From ed3156ecaec0f2472278b20aa754371e24fb4db1 Mon Sep 17 00:00:00 2001 From: taiwon1 Date: Wed, 18 Mar 2026 14:18:45 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20sprint=2010=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=A0=9C=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 10 + .gitignore | 5 +- README.md | 119 +- bun.lock | 505 + infra/ec2/ecosystem.config.js | 17 + infra/ec2/nginx.conf | 13 + infra/ec2/secure-group-inbound.png | Bin 0 -> 44393 bytes infra/ec2/secure-group-outbound.png | Bin 0 -> 33252 bytes infra/ec2/start.sh | 5 + infra/rds/secure-group-inbound.png | Bin 0 -> 37324 bytes infra/rds/secure-group-outbound.png | Bin 0 -> 39070 bytes infra/s3/policy.png | Bin 0 -> 70784 bytes jest.config.ts | 19 + package-lock.json | 15443 ++++++++++++++++ package.json | 37 +- .../migrations/20250429043356_/migration.sql | 15 + .../migrations/20250429061529_/migration.sql | 12 + .../20251127095400_init/migration.sql | 23 - .../migration.sql | 27 - .../migration.sql | 28 - .../20260106065635_init/migration.sql | 66 - .../migration.sql | 5 - prisma/migrations/migration_lock.toml | 2 +- prisma/prisma.js | 25 - prisma/schema.prisma | 122 +- prisma/seed.js | 59 - public/socket-client-test.html | 37 + src/app.js | 84 - src/app.ts | 33 + src/controllers/articlesController.js | 131 - src/controllers/articlesController.ts | 216 +- src/controllers/authController.ts | 86 +- src/controllers/commentsController.js | 26 - src/controllers/commentsController.ts | 49 +- src/controllers/errorController.js | 22 - src/controllers/errorController.ts | 62 +- src/controllers/imagesController.js | 41 - src/controllers/imagesController.ts | 104 +- src/controllers/likesController.js | 26 - src/controllers/notificationsController.ts | 10 + src/controllers/productsController.js | 122 - src/controllers/productsController.ts | 227 +- src/controllers/usersController.js | 92 - src/controllers/usersController.ts | 169 +- src/dto/userResponseDTO.ts | 8 + src/exceptions/errors.js | 29 - src/lib/authMiddleware.js | 18 - src/lib/constants.js | 7 - src/lib/constants.ts | 12 +- src/lib/errors/BadRequestError.js | 6 - src/lib/errors/BadRequestError.ts | 4 - src/lib/errors/ForbiddenError.ts | 4 - src/lib/errors/NotFoundError.js | 8 - src/lib/errors/NotFoundError.ts | 8 +- src/lib/errors/UnauthorizedError.ts | 4 - src/lib/prismaClient.js | 2 - src/lib/token.ts | 21 +- src/lib/withAsync.js | 9 - src/lib/withAsync.ts | 2 +- src/main.js | 30 - src/main.ts | 37 +- src/middlewares/authenticate.ts | 35 +- src/middlewares/validator.js | 283 - src/models/article.js | 12 - src/models/comment.js | 11 - src/models/index.js | 6 - src/models/product.js | 14 - src/repositories/articlesRepository.ts | 94 + src/repositories/commentsRepository.ts | 50 + src/repositories/favoritesRepository.ts | 29 + src/repositories/likesRepository.ts | 22 + src/repositories/notificationsRepository.ts | 60 + src/repositories/productsRepository.ts | 154 + src/repositories/usersRepository.ts | 37 + src/routers/articlesRouter.js | 19 - src/routers/commentsRouter.js | 11 - src/routers/imagesRouter.js | 9 - src/routers/likesRouter.js | 12 - src/routers/notificationsRouter.ts | 10 + src/routers/productsRouter.js | 19 - src/routers/productsRouter.ts | 8 +- src/routers/usersRouter.js | 20 - src/routers/usersRouter.ts | 6 +- src/routes/article.js | 134 - src/routes/articleComment.js | 169 - src/routes/comment.js | 25 - src/routes/product.js | 233 - src/routes/productImage.js | 169 - src/services/articleService.js | 64 - src/services/articlesService.ts | 59 + src/services/authService.ts | 102 + src/services/commentsService.ts | 122 + src/services/favoritesService.ts | 32 + src/services/likesService.ts | 32 + src/services/notificationsService.ts | 69 + src/services/productService.js | 69 - src/services/productsService.ts | 80 + src/services/socketService.ts | 39 + src/services/usersService.ts | 38 + src/structs/articlesStructs.js | 12 - src/structs/authStructs.ts | 3 +- src/structs/commentsStruct.js | 10 - src/structs/commentsStruct.ts | 6 +- src/structs/commonStructs.js | 22 - src/structs/productsStruct.js | 14 - src/structs/usersStructs.js | 13 - src/structs/usersStructs.ts | 7 +- src/tests/articles.auth.test.ts | 241 + src/tests/articles.public.test.ts | 136 + src/tests/auth.test.ts | 154 + src/tests/products.auth.test.ts | 241 + src/tests/products.public.test.ts | 146 + src/tests/productsService.unit.test.ts | 234 + src/tests/setup.ts | 3 + src/types/Article.ts | 13 + src/types/Comment.ts | 11 + src/types/Notification.ts | 29 + src/types/Product.ts | 15 + src/types/User.ts | 11 + src/types/express.d.ts | 8 +- src/types/pagination.ts | 21 + src/utils/cursorUtils.js | 79 - tests/test.http | 25 +- tests/websocket-test-scenario.http | 0 tsconfig.json | 154 +- 125 files changed, 19019 insertions(+), 3249 deletions(-) create mode 100644 .env.example create mode 100644 bun.lock create mode 100644 infra/ec2/ecosystem.config.js create mode 100644 infra/ec2/nginx.conf create mode 100644 infra/ec2/secure-group-inbound.png create mode 100644 infra/ec2/secure-group-outbound.png create mode 100644 infra/ec2/start.sh create mode 100644 infra/rds/secure-group-inbound.png create mode 100644 infra/rds/secure-group-outbound.png create mode 100644 infra/s3/policy.png create mode 100644 jest.config.ts create mode 100644 prisma/migrations/20250429043356_/migration.sql create mode 100644 prisma/migrations/20250429061529_/migration.sql delete mode 100644 prisma/migrations/20251127095400_init/migration.sql delete mode 100644 prisma/migrations/20251202044637_add_comment_tables/migration.sql delete mode 100644 prisma/migrations/20251204062130_set_product_image_onetoone/migration.sql delete mode 100644 prisma/migrations/20260106065635_init/migration.sql delete mode 100644 prisma/migrations/20260106141853_add_refresh_token/migration.sql delete mode 100644 prisma/prisma.js delete mode 100644 prisma/seed.js create mode 100644 public/socket-client-test.html delete mode 100644 src/app.js create mode 100644 src/app.ts delete mode 100644 src/controllers/articlesController.js delete mode 100644 src/controllers/commentsController.js delete mode 100644 src/controllers/errorController.js delete mode 100644 src/controllers/imagesController.js delete mode 100644 src/controllers/likesController.js create mode 100644 src/controllers/notificationsController.ts delete mode 100644 src/controllers/productsController.js delete mode 100644 src/controllers/usersController.js create mode 100644 src/dto/userResponseDTO.ts delete mode 100644 src/exceptions/errors.js delete mode 100644 src/lib/authMiddleware.js delete mode 100644 src/lib/constants.js delete mode 100644 src/lib/errors/BadRequestError.js delete mode 100644 src/lib/errors/NotFoundError.js delete mode 100644 src/lib/prismaClient.js delete mode 100644 src/lib/withAsync.js delete mode 100644 src/main.js delete mode 100644 src/middlewares/validator.js delete mode 100644 src/models/article.js delete mode 100644 src/models/comment.js delete mode 100644 src/models/index.js delete mode 100644 src/models/product.js create mode 100644 src/repositories/articlesRepository.ts create mode 100644 src/repositories/commentsRepository.ts create mode 100644 src/repositories/favoritesRepository.ts create mode 100644 src/repositories/likesRepository.ts create mode 100644 src/repositories/notificationsRepository.ts create mode 100644 src/repositories/productsRepository.ts create mode 100644 src/repositories/usersRepository.ts delete mode 100644 src/routers/articlesRouter.js delete mode 100644 src/routers/commentsRouter.js delete mode 100644 src/routers/imagesRouter.js delete mode 100644 src/routers/likesRouter.js create mode 100644 src/routers/notificationsRouter.ts delete mode 100644 src/routers/productsRouter.js delete mode 100644 src/routers/usersRouter.js delete mode 100644 src/routes/article.js delete mode 100644 src/routes/articleComment.js delete mode 100644 src/routes/comment.js delete mode 100644 src/routes/product.js delete mode 100644 src/routes/productImage.js delete mode 100644 src/services/articleService.js create mode 100644 src/services/articlesService.ts create mode 100644 src/services/authService.ts create mode 100644 src/services/commentsService.ts create mode 100644 src/services/favoritesService.ts create mode 100644 src/services/likesService.ts create mode 100644 src/services/notificationsService.ts delete mode 100644 src/services/productService.js create mode 100644 src/services/productsService.ts create mode 100644 src/services/socketService.ts create mode 100644 src/services/usersService.ts delete mode 100644 src/structs/articlesStructs.js delete mode 100644 src/structs/commentsStruct.js delete mode 100644 src/structs/commonStructs.js delete mode 100644 src/structs/productsStruct.js delete mode 100644 src/structs/usersStructs.js create mode 100644 src/tests/articles.auth.test.ts create mode 100644 src/tests/articles.public.test.ts create mode 100644 src/tests/auth.test.ts create mode 100644 src/tests/products.auth.test.ts create mode 100644 src/tests/products.public.test.ts create mode 100644 src/tests/productsService.unit.test.ts create mode 100644 src/tests/setup.ts create mode 100644 src/types/Article.ts create mode 100644 src/types/Comment.ts create mode 100644 src/types/Notification.ts create mode 100644 src/types/Product.ts create mode 100644 src/types/User.ts create mode 100644 src/types/pagination.ts delete mode 100644 src/utils/cursorUtils.js create mode 100644 tests/websocket-test-scenario.http diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..d2059f53 --- /dev/null +++ b/.env.example @@ -0,0 +1,10 @@ +DATABASE_URL=postgresql://postgres:postgres@localhost:5432/panda-market +PORT=3000 +JWT_ACCESS_TOKEN_SECRET=your-secret-key +JWT_REFRESH_TOKEN_SECRET=your-refresh-secret-key + +# AWS S3 +AWS_REGION=ap-northeast-2 +AWS_ACCESS_KEY_ID=your-access-key-id +AWS_SECRET_ACCESS_KEY=your-secret-access-key +AWS_S3_BUCKET_NAME=your-bucket-name \ No newline at end of file diff --git a/.gitignore b/.gitignore index b0fc192f..2d9bab17 100644 --- a/.gitignore +++ b/.gitignore @@ -3,8 +3,11 @@ node_modules/ .env* !.env.example +build/ +coverage/ +*.pem # Uploaded files public/* !public/.gitkeep - +!public/socket-client-test.html diff --git a/README.md b/README.md index 54c4b9d3..c12f850b 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,91 @@ -# 🚩 Sprint 5 λ―Έμ…˜ 체크리슀트 - -## βœ… κΈ°λ³Έ μš”κ΅¬ 사항 -- [x] μŠ€ν”„λ¦°νŠΈ λ―Έμ…˜ 4의 κ΅¬ν˜„ μ™„λ£Œ μƒνƒœμ—μ„œ μ§„ν–‰ -- [x] νƒ€μž…μŠ€ν¬λ¦½νŠΈ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ μ§„ν–‰ 및 λ―Έκ΅¬ν˜„ κΈ°λŠ₯ μΆ”κ°€ - -## πŸ› οΈ ν”„λ‘œμ νŠΈ μ„ΈνŒ… -- [x] `tsconfig.json` 파일 생성 및 ν•„μš”ν•œ μ˜΅μ…˜ μ„€μ • (예: `outDir`) -- [x] ν•„μš”ν•œ npm script μ„€μ • (λΉŒλ“œ 및 개발 μ„œλ²„ μ‹€ν–‰ λͺ…λ Ήμ–΄) - -## 🟦 νƒ€μž…μŠ€ν¬λ¦½νŠΈ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ -- [x] κΈ°μ‘΄ Express.js ν”„λ‘œμ νŠΈλ₯Ό νƒ€μž…μŠ€ν¬λ¦½νŠΈ ν”„λ‘œμ νŠΈλ‘œ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ -- [x] ν•„μš”ν•œ νƒ€μž… νŒ¨ν‚€μ§€ μ„€μΉ˜ (`@types/express`, `@types/node`, `@types/cookie-parser` λ“±) -- [x] `any` νƒ€μž… μ‚¬μš© μ΅œμ†Œν™” -- [x] λ³΅μž‘ν•œ 객체/λ°°μ—΄ ꡬ쑰에 μΈν„°νŽ˜μ΄μŠ€ λ˜λŠ” νƒ€μž… 별칭(Type Alias) μ‚¬μš© -- [x] νƒ€μž… 별칭 λ˜λŠ” μœ ν‹Έλ¦¬ν‹° νƒ€μž…μ„ μ‚¬μš©ν•΄ νƒ€μž… λ³΅μž‘μ„± κ°μ†Œ -- [x] `declare`λ₯Ό μ‚¬μš©ν•˜μ—¬ νƒ€μž…μ„ μ˜€λ²„λΌμ΄λ“œν•˜κ±°λ‚˜ ν™•μž₯ (예: `req.user`) - -## πŸ’» 개발 ν™˜κ²½ μ„€μ • -- [x] `ts-node`λ₯Ό μ‚¬μš©ν•΄ `.ts` μ½”λ“œλ₯Ό λ°”λ‘œ μ‹€ν–‰ν•  수 μžˆλŠ” npm script 생성 (`npm run dev`) -- [x] `nodemon`을 μ‚¬μš©ν•΄ μ½”λ“œκ°€ 변경될 λ•Œλ§ˆλ‹€ μ„œλ²„κ°€ λ‹€μ‹œ μ‹€ν–‰λ˜λ„λ‘ μ„€μ • - -## πŸš€ 심화 μš”κ΅¬ 사항 (μ§„ν–‰ 쀑) -- [ ] **Layered Architecture(κ³„μΈ΅ν˜• μ•„ν‚€ν…μ²˜) 적용** - - [ ] **Controller**: μš”μ²­ 검증 및 응닡 처리 계측 뢄리 - - [ ] **Service**: λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 및 μ—λŸ¬ 처리 계측 뢄리 - - [ ] **Repository**: λ°μ΄ν„°λ² μ΄μŠ€ μ•‘μ„ΈμŠ€ 둜직 뢄리 -- [ ] 계측 μ‚¬μ΄μ—μ„œ 데이터λ₯Ό 주고받을 λ•Œ **DTO(Data Transfer Object)** ν™œμš© +# 🐼 νŒλ‹€λ§ˆμΌ“ λ°±μ—”λ“œ μŠ€ν”„λ¦°νŠΈ λ―Έμ…˜ 10 + +이번 μŠ€ν”„λ¦°νŠΈμ—μ„œλŠ” **AWS**λ₯Ό ν™œμš©ν•˜μ—¬ νŒλ‹€λ§ˆμΌ“ λ°±μ—”λ“œ μ„œλΉ„μŠ€λ₯Ό ν”„λ‘œλ•μ…˜ ν™˜κ²½μ— λ°°ν¬ν–ˆμŠ΅λ‹ˆλ‹€. +S3λ₯Ό ν†΅ν•œ 파일 μ—…λ‘œλ“œ, RDSλ₯Ό ν†΅ν•œ λ°μ΄ν„°λ² μ΄μŠ€ 운영, EC2λ₯Ό ν†΅ν•œ μ„œλ²„ 배포λ₯Ό κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€. + +--- + +## πŸ› οΈ 기술 μŠ€νƒ + +- **Server:** Node.js, Express, TypeScript +- **Database:** PostgreSQL (AWS RDS) +- **File Storage:** AWS S3 +- **Deployment:** AWS EC2 (Ubuntu 24.04 LTS) +- **Process Manager:** pm2 +- **Reverse Proxy:** nginx + +--- + +## βœ… μš”κ΅¬μ‚¬ν•­ 이행 ν˜„ν™© + +### 1. κΈ°λ³Έ μš”κ΅¬μ‚¬ν•­ + +- [x] **ν™˜κ²½λ³€μˆ˜ μ„€μ •:** ν”„λ‘œλ•μ…˜ 배포λ₯Ό μœ„ν•œ ν™˜κ²½λ³€μˆ˜ 뢄리 ꡬ성 +- [x] **AWS S3 적용:** S3 버킷 생성 및 퍼블릭 μ•‘μ„ΈμŠ€ ν—ˆμš© +- [x] **S3 버킷 μ •μ±… μ„€μ •:** 일반 μ‚¬μš©μžκ°€ μ—…λ‘œλ“œ νŒŒμΌμ— μ ‘κ·Ό κ°€λŠ₯ν•˜λ„λ‘ μ„€μ • +- [x] **AWS IAM μ•‘μ„ΈμŠ€ ν‚€ λ°œκΈ‰:** EC2μ—μ„œ S3 μ‚¬μš©μ„ μœ„ν•œ ν‚€ λ°œκΈ‰ +- [x] **ν”„λ‘œλ•μ…˜ S3 μ—…λ‘œλ“œ:** `NODE_ENV=production` ν™˜κ²½μ—μ„œ S3 μ—…λ‘œλ“œλ‘œ μ „ν™˜ +- [x] **AWS RDS 적용:** PostgreSQL 프리티어 μΈμŠ€ν„΄μŠ€ 생성 및 λ³΄μ•ˆ κ·Έλ£Ή μ„€μ • +- [x] **AWS EC2 배포:** Ubuntu 프리티어 μΈμŠ€ν„΄μŠ€μ— Express μ„œλ²„ 배포 + +### 2. 심화 μš”κ΅¬μ‚¬ν•­ + +- [x] **pm2 ν”„λ‘œμ„ΈμŠ€ λ§€λ‹ˆμ €:** pm2λ₯Ό ν™œμš©ν•œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹€ν–‰ 및 μžλ™ μž¬μ‹œμž‘ μ„€μ • +- [x] **nginx λ¦¬λ²„μŠ€ ν”„λ‘μ‹œ:** nginxλ₯Ό 톡해 80번 포트둜 μ„œλΉ„μŠ€ 제곡 + +--- + +## 🌐 배포 정보 + +- **API μ—”λ“œν¬μΈνŠΈ:** `http://13.239.116.195` +- **μ˜ˆμ‹œ:** `http://13.239.116.195/products` + +--- + +## ☁️ AWS 인프라 ꡬ성 + +| μ„œλΉ„μŠ€ | λ‚΄μš© | +| ------- | ----------------------------------------- | +| **EC2** | Ubuntu 24.04 LTS, t2.micro (프리티어) | +| **RDS** | PostgreSQL, db.t3.micro (프리티어) | +| **S3** | ap-northeast-2 (μ„œμšΈ), 퍼블릭 μ•‘μ„ΈμŠ€ ν—ˆμš© | +| **IAM** | S3FullAccess κΆŒν•œμ˜ μ „μš© μ‚¬μš©μž 생성 | + +--- + +## πŸ’‘ μ£Όμš” κ΅¬ν˜„ 사항 및 νŠΈλŸ¬λΈ”μŠˆνŒ… + +### 1. ν™˜κ²½λ³„ 파일 μ—…λ‘œλ“œ λΆ„κΈ° 처리 + +- `NODE_ENV` 값에 따라 개발 ν™˜κ²½μ—μ„œλŠ” 둜컬 λ””μŠ€ν¬(`multer.diskStorage`), ν”„λ‘œλ•μ…˜ ν™˜κ²½μ—μ„œλŠ” AWS S3(`multer-s3`)λ₯Ό μ‚¬μš©ν•˜λ„λ‘ λΆ„κΈ° μ²˜λ¦¬ν–ˆμŠ΅λ‹ˆλ‹€. + +### 2. EC2 λ³΄μ•ˆ κ·Έλ£Ή 좩돌 ν•΄κ²° + +- EC2 μΈμŠ€ν„΄μŠ€ 생성 μ‹œ default λ³΄μ•ˆ κ·Έλ£Ήκ³Ό μƒˆλ‘œ μƒμ„±ν•œ λ³΄μ•ˆ 그룹이 쀑볡 μ μš©λ˜μ–΄ μΈλ°”μš΄λ“œ κ·œμΉ™ 좩돌이 λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. default λ³΄μ•ˆ 그룹을 μ œκ±°ν•˜μ—¬ ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€. + +### 3. nginx default μ„€μ • 좩돌 ν•΄κ²° + +- nginx μ„€μΉ˜ ν›„ κΈ°λ³Έ `default` μ„€μ • 파일이 80포트λ₯Ό μ„ μ ν•˜μ—¬ λ¦¬λ²„μŠ€ ν”„λ‘μ‹œκ°€ λ™μž‘ν•˜μ§€ μ•ŠλŠ” λ¬Έμ œκ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. `sites-enabled/default`λ₯Ό μ œκ±°ν•˜μ—¬ ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€. + +### 4. pm2 μžλ™ μ‹œμž‘ μ„€μ • + +- EC2 μΈμŠ€ν„΄μŠ€ μž¬μ‹œμž‘ μ‹œ μ„œλ²„κ°€ μžλ™μœΌλ‘œ μ‹€ν–‰λ˜λ„λ‘ `pm2 startup` 및 `pm2 save`λ₯Ό 톡해 systemd μ„œλΉ„μŠ€λ‘œ λ“±λ‘ν–ˆμŠ΅λ‹ˆλ‹€. + +--- + +## πŸ“ infra 파일 ꡬ쑰 + +``` +infra/ +β”œβ”€β”€ s3/ +β”‚ └── policy.png # S3 버킷 μ •μ±… μŠ€ν¬λ¦°μƒ· +β”œβ”€β”€ rds/ +β”‚ β”œβ”€β”€ secure-group-inbound.png # RDS λ³΄μ•ˆκ·Έλ£Ή μΈλ°”μš΄λ“œ +β”‚ └── secure-group-outbound.png # RDS λ³΄μ•ˆκ·Έλ£Ή μ•„μ›ƒλ°”μš΄λ“œ +└── ec2/ + β”œβ”€β”€ secure-group-inbound.png # EC2 λ³΄μ•ˆκ·Έλ£Ή μΈλ°”μš΄λ“œ + β”œβ”€β”€ secure-group-outbound.png # EC2 λ³΄μ•ˆκ·Έλ£Ή μ•„μ›ƒλ°”μš΄λ“œ + β”œβ”€β”€ start.sh # pm2 μ‹€ν–‰ λͺ…λ Ήμ–΄ + β”œβ”€β”€ ecosystem.config.js # pm2 μ„€μ • 파일 + └── nginx.conf # nginx μ„€μ • 파일 +``` diff --git a/bun.lock b/bun.lock new file mode 100644 index 00000000..e0df08fe --- /dev/null +++ b/bun.lock @@ -0,0 +1,505 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "codeit-panda-market-mission-3", + "dependencies": { + "@prisma/client": "^5.16.2", + "bcrypt": "^5.1.1", + "cookie-parser": "^1.4.7", + "cors": "^2.8.5", + "dotenv": "^16.4.5", + "express": "^4.19.2", + "jsonwebtoken": "^9.0.2", + "multer": "^1.4.5-lts.1", + "socket.io": "^4.8.1", + "superstruct": "^2.0.2", + "uuid": "^11.0.5", + }, + "devDependencies": { + "@types/bcrypt": "^5.0.2", + "@types/cookie-parser": "^1.4.8", + "@types/cors": "^2.8.17", + "@types/express": "^5.0.0", + "@types/jsonwebtoken": "^9.0.9", + "@types/multer": "^1.4.12", + "nodemon": "^3.1.9", + "prettier": "^3.3.2", + "prisma": "^5.16.2", + "ts-node": "^10.9.2", + "typescript": "^5.8.2", + }, + }, + }, + "packages": { + "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], + + "@mapbox/node-pre-gyp": ["@mapbox/node-pre-gyp@1.0.11", "", { "dependencies": { "detect-libc": "^2.0.0", "https-proxy-agent": "^5.0.0", "make-dir": "^3.1.0", "node-fetch": "^2.6.7", "nopt": "^5.0.0", "npmlog": "^5.0.1", "rimraf": "^3.0.2", "semver": "^7.3.5", "tar": "^6.1.11" }, "bin": { "node-pre-gyp": "bin/node-pre-gyp" } }, "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ=="], + + "@prisma/client": ["@prisma/client@5.16.2", "", { "peerDependencies": { "prisma": "*" } }, "sha512-+1lmkhR9gHWcTC5oghm2ZKpWljyWdzfazCVlLKUWXVmwHSf52g81aZ8qb6Km5Bs025yBi7puLp3qSLEvktoUtw=="], + + "@prisma/debug": ["@prisma/debug@5.16.2", "", {}, "sha512-ItzB4nR4O8eLzuJiuP3WwUJfoIvewMHqpGCad+64gvThcKEVOtaUza9AEJo2DPqAOa/AWkFyK54oM4WwHeew+A=="], + + "@prisma/engines": ["@prisma/engines@5.16.2", "", { "dependencies": { "@prisma/debug": "5.16.2", "@prisma/engines-version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", "@prisma/fetch-engine": "5.16.2", "@prisma/get-platform": "5.16.2" } }, "sha512-qUxwMtrwoG3byd4PbX6T7EjHJ8AUhzTuwniOGkh/hIznBfcE2QQnGakyEq4VnwNuttMqvh/GgPFapHQ3lCuRHg=="], + + "@prisma/engines-version": ["@prisma/engines-version@5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", "", {}, "sha512-HkT2WbfmFZ9WUPyuJHhkiADxazHg8Y4gByrTSVeb3OikP6tjQ7txtSUGu9OBOBH0C13dPKN2qqH12xKtHu/Hiw=="], + + "@prisma/fetch-engine": ["@prisma/fetch-engine@5.16.2", "", { "dependencies": { "@prisma/debug": "5.16.2", "@prisma/engines-version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", "@prisma/get-platform": "5.16.2" } }, "sha512-sq51lfHKfH2jjYSjBtMjP+AznFqOJzXpqmq6B9auWrlTJrMgZ7lPyhWUW7VU7LsQU48/TJ+DZeIz8s9bMYvcHg=="], + + "@prisma/get-platform": ["@prisma/get-platform@5.16.2", "", { "dependencies": { "@prisma/debug": "5.16.2" } }, "sha512-cXiHPgNLNyj22vLouPVNegklpRL/iX2jxTeap5GRO3DmCoVyIHmJAV1CgUMUJhHlcol9yYy7EHvsnXTDJ/PKEA=="], + + "@socket.io/component-emitter": ["@socket.io/component-emitter@3.1.2", "", {}, "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA=="], + + "@tsconfig/node10": ["@tsconfig/node10@1.0.11", "", {}, "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw=="], + + "@tsconfig/node12": ["@tsconfig/node12@1.0.11", "", {}, "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag=="], + + "@tsconfig/node14": ["@tsconfig/node14@1.0.3", "", {}, "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow=="], + + "@tsconfig/node16": ["@tsconfig/node16@1.0.4", "", {}, "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA=="], + + "@types/bcrypt": ["@types/bcrypt@5.0.2", "", { "dependencies": { "@types/node": "*" } }, "sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ=="], + + "@types/body-parser": ["@types/body-parser@1.19.5", "", { "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg=="], + + "@types/connect": ["@types/connect@3.4.38", "", { "dependencies": { "@types/node": "*" } }, "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug=="], + + "@types/cookie-parser": ["@types/cookie-parser@1.4.8", "", { "peerDependencies": { "@types/express": "*" } }, "sha512-l37JqFrOJ9yQfRQkljb41l0xVphc7kg5JTjjr+pLRZ0IyZ49V4BQ8vbF4Ut2C2e+WH4al3xD3ZwYwIUfnbT4NQ=="], + + "@types/cors": ["@types/cors@2.8.17", "", { "dependencies": { "@types/node": "*" } }, "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA=="], + + "@types/express": ["@types/express@5.0.1", "", { "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^5.0.0", "@types/serve-static": "*" } }, "sha512-UZUw8vjpWFXuDnjFTh7/5c2TWDlQqeXHi6hcN7F2XSVT5P+WmUnnbFS3KA6Jnc6IsEqI2qCVu2bK0R0J4A8ZQQ=="], + + "@types/express-serve-static-core": ["@types/express-serve-static-core@5.0.6", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA=="], + + "@types/http-errors": ["@types/http-errors@2.0.4", "", {}, "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA=="], + + "@types/jsonwebtoken": ["@types/jsonwebtoken@9.0.9", "", { "dependencies": { "@types/ms": "*", "@types/node": "*" } }, "sha512-uoe+GxEuHbvy12OUQct2X9JenKM3qAscquYymuQN4fMWG9DBQtykrQEFcAbVACF7qaLw9BePSodUL0kquqBJpQ=="], + + "@types/mime": ["@types/mime@1.3.5", "", {}, "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="], + + "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], + + "@types/multer": ["@types/multer@1.4.12", "", { "dependencies": { "@types/express": "*" } }, "sha512-pQ2hoqvXiJt2FP9WQVLPRO+AmiIm/ZYkavPlIQnx282u4ZrVdztx0pkh3jjpQt0Kz+YI0YhSG264y08UJKoUQg=="], + + "@types/node": ["@types/node@22.7.9", "", { "dependencies": { "undici-types": "~6.19.2" } }, "sha512-jrTfRC7FM6nChvU7X2KqcrgquofrWLFDeYC1hKfwNWomVvrn7JIksqf344WN2X/y8xrgqBd2dJATZV4GbatBfg=="], + + "@types/qs": ["@types/qs@6.9.18", "", {}, "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA=="], + + "@types/range-parser": ["@types/range-parser@1.2.7", "", {}, "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="], + + "@types/send": ["@types/send@0.17.4", "", { "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA=="], + + "@types/serve-static": ["@types/serve-static@1.15.7", "", { "dependencies": { "@types/http-errors": "*", "@types/node": "*", "@types/send": "*" } }, "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw=="], + + "abbrev": ["abbrev@1.1.1", "", {}, "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="], + + "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], + + "acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="], + + "acorn-walk": ["acorn-walk@8.3.4", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g=="], + + "agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + + "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], + + "append-field": ["append-field@1.0.0", "", {}, "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw=="], + + "aproba": ["aproba@2.0.0", "", {}, "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ=="], + + "are-we-there-yet": ["are-we-there-yet@2.0.0", "", { "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" } }, "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw=="], + + "arg": ["arg@4.1.3", "", {}, "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="], + + "array-flatten": ["array-flatten@1.1.1", "", {}, "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "base64id": ["base64id@2.0.0", "", {}, "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="], + + "bcrypt": ["bcrypt@5.1.1", "", { "dependencies": { "@mapbox/node-pre-gyp": "^1.0.11", "node-addon-api": "^5.0.0" } }, "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww=="], + + "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], + + "body-parser": ["body-parser@1.20.2", "", { "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" } }, "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA=="], + + "brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], + + "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], + + "busboy": ["busboy@1.6.0", "", { "dependencies": { "streamsearch": "^1.1.0" } }, "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA=="], + + "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], + + "call-bind": ["call-bind@1.0.7", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.1" } }, "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w=="], + + "chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], + + "chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="], + + "color-support": ["color-support@1.1.3", "", { "bin": { "color-support": "bin.js" } }, "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg=="], + + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + + "concat-stream": ["concat-stream@1.6.2", "", { "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" } }, "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw=="], + + "console-control-strings": ["console-control-strings@1.1.0", "", {}, "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="], + + "content-disposition": ["content-disposition@0.5.4", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ=="], + + "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], + + "cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], + + "cookie-parser": ["cookie-parser@1.4.7", "", { "dependencies": { "cookie": "0.7.2", "cookie-signature": "1.0.6" } }, "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw=="], + + "cookie-signature": ["cookie-signature@1.0.6", "", {}, "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="], + + "core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="], + + "cors": ["cors@2.8.5", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g=="], + + "create-require": ["create-require@1.1.1", "", {}, "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="], + + "debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], + + "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="], + + "delegates": ["delegates@1.0.0", "", {}, "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="], + + "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="], + + "destroy": ["destroy@1.2.0", "", {}, "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="], + + "detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="], + + "diff": ["diff@4.0.2", "", {}, "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="], + + "dotenv": ["dotenv@16.4.5", "", {}, "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg=="], + + "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], + + "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], + + "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="], + + "engine.io": ["engine.io@6.6.4", "", { "dependencies": { "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "2.0.0", "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", "ws": "~8.17.1" } }, "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g=="], + + "engine.io-parser": ["engine.io-parser@5.2.3", "", {}, "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q=="], + + "es-define-property": ["es-define-property@1.0.0", "", { "dependencies": { "get-intrinsic": "^1.2.4" } }, "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ=="], + + "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + + "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], + + "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], + + "express": ["express@4.19.2", "", { "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "1.2.0", "fresh": "0.5.2", "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", "qs": "6.11.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.18.0", "serve-static": "1.15.0", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "finalhandler": ["finalhandler@1.2.0", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", "statuses": "2.0.1", "unpipe": "~1.0.0" } }, "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg=="], + + "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], + + "fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], + + "fs-minipass": ["fs-minipass@2.1.0", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg=="], + + "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "gauge": ["gauge@3.0.2", "", { "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.2", "console-control-strings": "^1.0.0", "has-unicode": "^2.0.1", "object-assign": "^4.1.1", "signal-exit": "^3.0.0", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", "wide-align": "^1.1.2" } }, "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q=="], + + "get-intrinsic": ["get-intrinsic@1.2.4", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" } }, "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ=="], + + "glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + + "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "gopd": ["gopd@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.1.3" } }, "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA=="], + + "has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], + + "has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="], + + "has-proto": ["has-proto@1.0.3", "", {}, "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q=="], + + "has-symbols": ["has-symbols@1.0.3", "", {}, "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="], + + "has-unicode": ["has-unicode@2.0.1", "", {}, "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="], + + "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + + "http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="], + + "https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], + + "iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], + + "ignore-by-default": ["ignore-by-default@1.0.1", "", {}, "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA=="], + + "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="], + + "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + + "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], + + "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="], + + "jsonwebtoken": ["jsonwebtoken@9.0.2", "", { "dependencies": { "jws": "^3.2.2", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", "lodash.isnumber": "^3.0.3", "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", "ms": "^2.1.1", "semver": "^7.5.4" } }, "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ=="], + + "jwa": ["jwa@1.4.1", "", { "dependencies": { "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA=="], + + "jws": ["jws@3.2.2", "", { "dependencies": { "jwa": "^1.4.1", "safe-buffer": "^5.0.1" } }, "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA=="], + + "lodash.includes": ["lodash.includes@4.3.0", "", {}, "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="], + + "lodash.isboolean": ["lodash.isboolean@3.0.3", "", {}, "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="], + + "lodash.isinteger": ["lodash.isinteger@4.0.4", "", {}, "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="], + + "lodash.isnumber": ["lodash.isnumber@3.0.3", "", {}, "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="], + + "lodash.isplainobject": ["lodash.isplainobject@4.0.6", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="], + + "lodash.isstring": ["lodash.isstring@4.0.1", "", {}, "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="], + + "lodash.once": ["lodash.once@4.1.1", "", {}, "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="], + + "make-dir": ["make-dir@3.1.0", "", { "dependencies": { "semver": "^6.0.0" } }, "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw=="], + + "make-error": ["make-error@1.3.6", "", {}, "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="], + + "media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="], + + "merge-descriptors": ["merge-descriptors@1.0.1", "", {}, "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="], + + "methods": ["methods@1.1.2", "", {}, "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="], + + "mime": ["mime@1.6.0", "", { "bin": "cli.js" }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], + + "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + + "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], + + "minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="], + + "minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="], + + "mkdirp": ["mkdirp@0.5.6", "", { "dependencies": { "minimist": "^1.2.6" }, "bin": "bin/cmd.js" }, "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "multer": ["multer@1.4.5-lts.1", "", { "dependencies": { "append-field": "^1.0.0", "busboy": "^1.0.0", "concat-stream": "^1.5.2", "mkdirp": "^0.5.4", "object-assign": "^4.1.1", "type-is": "^1.6.4", "xtend": "^4.0.0" } }, "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ=="], + + "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], + + "node-addon-api": ["node-addon-api@5.1.0", "", {}, "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA=="], + + "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], + + "nodemon": ["nodemon@3.1.10", "", { "dependencies": { "chokidar": "^3.5.2", "debug": "^4", "ignore-by-default": "^1.0.1", "minimatch": "^3.1.2", "pstree.remy": "^1.1.8", "semver": "^7.5.3", "simple-update-notifier": "^2.0.0", "supports-color": "^5.5.0", "touch": "^3.1.0", "undefsafe": "^2.0.5" }, "bin": { "nodemon": "bin/nodemon.js" } }, "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw=="], + + "nopt": ["nopt@5.0.0", "", { "dependencies": { "abbrev": "1" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ=="], + + "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], + + "npmlog": ["npmlog@5.0.1", "", { "dependencies": { "are-we-there-yet": "^2.0.0", "console-control-strings": "^1.1.0", "gauge": "^3.0.0", "set-blocking": "^2.0.0" } }, "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw=="], + + "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + + "object-inspect": ["object-inspect@1.13.2", "", {}, "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g=="], + + "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="], + + "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], + + "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], + + "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], + + "path-to-regexp": ["path-to-regexp@0.1.7", "", {}, "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="], + + "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "prettier": ["prettier@3.3.2", "", { "bin": "bin/prettier.cjs" }, "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA=="], + + "prisma": ["prisma@5.16.2", "", { "dependencies": { "@prisma/engines": "5.16.2" }, "bin": "build/index.js" }, "sha512-rFV/xoBR2hBGGlu4LPLQd4U8WVA+tSAmYyFWGPRVfj+xg7N4kiZV4lSk38htSpF+/IuHKzlrbh4SFk8Z18cI8A=="], + + "process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="], + + "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="], + + "pstree.remy": ["pstree.remy@1.1.8", "", {}, "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w=="], + + "qs": ["qs@6.11.0", "", { "dependencies": { "side-channel": "^1.0.4" } }, "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q=="], + + "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], + + "raw-body": ["raw-body@2.5.2", "", { "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } }, "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA=="], + + "readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], + + "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], + + "rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="], + + "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + + "semver": ["semver@7.6.3", "", { "bin": "bin/semver.js" }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + + "send": ["send@0.18.0", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", "http-errors": "2.0.0", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "2.4.1", "range-parser": "~1.2.1", "statuses": "2.0.1" } }, "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg=="], + + "serve-static": ["serve-static@1.15.0", "", { "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "0.18.0" } }, "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g=="], + + "set-blocking": ["set-blocking@2.0.0", "", {}, "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="], + + "set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="], + + "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], + + "side-channel": ["side-channel@1.0.6", "", { "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4", "object-inspect": "^1.13.1" } }, "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA=="], + + "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + + "simple-update-notifier": ["simple-update-notifier@2.0.0", "", { "dependencies": { "semver": "^7.5.3" } }, "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w=="], + + "socket.io": ["socket.io@4.8.1", "", { "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.3.2", "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" } }, "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg=="], + + "socket.io-adapter": ["socket.io-adapter@2.5.5", "", { "dependencies": { "debug": "~4.3.4", "ws": "~8.17.1" } }, "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg=="], + + "socket.io-parser": ["socket.io-parser@4.2.4", "", { "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" } }, "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew=="], + + "statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="], + + "streamsearch": ["streamsearch@1.1.0", "", {}, "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="], + + "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], + + "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "superstruct": ["superstruct@2.0.2", "", {}, "sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A=="], + + "supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], + + "tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], + + "touch": ["touch@3.1.1", "", { "bin": { "nodetouch": "bin/nodetouch.js" } }, "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA=="], + + "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], + + "ts-node": ["ts-node@10.9.2", "", { "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", "@tsconfig/node16": "^1.0.2", "acorn": "^8.4.1", "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "peerDependencies": { "@swc/core": ">=1.2.50", "@swc/wasm": ">=1.2.50", "@types/node": "*", "typescript": ">=2.7" }, "optionalPeers": ["@swc/core", "@swc/wasm"], "bin": { "ts-node": "dist/bin.js", "ts-script": "dist/bin-script-deprecated.js", "ts-node-cwd": "dist/bin-cwd.js", "ts-node-esm": "dist/bin-esm.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js" } }, "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ=="], + + "type-is": ["type-is@1.6.18", "", { "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="], + + "typedarray": ["typedarray@0.0.6", "", {}, "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="], + + "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], + + "undefsafe": ["undefsafe@2.0.5", "", {}, "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA=="], + + "undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], + + "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="], + + "uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], + + "v8-compile-cache-lib": ["v8-compile-cache-lib@3.0.1", "", {}, "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="], + + "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], + + "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], + + "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], + + "wide-align": ["wide-align@1.1.5", "", { "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } }, "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg=="], + + "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], + + "ws": ["ws@8.17.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ=="], + + "xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="], + + "yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "yn": ["yn@3.1.1", "", {}, "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="], + + "are-we-there-yet/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], + + "body-parser/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "express/cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="], + + "express/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "make-dir/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], + + "send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "string_decoder/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], + + "tar/mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], + + "body-parser/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + + "express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + + "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + + "send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + } +} diff --git a/infra/ec2/ecosystem.config.js b/infra/ec2/ecosystem.config.js new file mode 100644 index 00000000..53cecd3b --- /dev/null +++ b/infra/ec2/ecosystem.config.js @@ -0,0 +1,17 @@ +module.exports = { + apps: [ + { + name: 'panda-market', + script: './build/main.js', + instances: 1, + autorestart: true, + watch: false, + env: { + NODE_ENV: 'development', + }, + env_production: { + NODE_ENV: 'production', + }, + }, + ], +}; diff --git a/infra/ec2/nginx.conf b/infra/ec2/nginx.conf new file mode 100644 index 00000000..35247e2c --- /dev/null +++ b/infra/ec2/nginx.conf @@ -0,0 +1,13 @@ +server { + listen 80; + server_name _; + + location / { + proxy_pass http://localhost:3000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } +} diff --git a/infra/ec2/secure-group-inbound.png b/infra/ec2/secure-group-inbound.png new file mode 100644 index 0000000000000000000000000000000000000000..5300a494fa5f8160a10f0eeb1c17e6d74ea0f460 GIT binary patch literal 44393 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 literal 0 HcmV?d00001 diff --git a/infra/rds/secure-group-outbound.png b/infra/rds/secure-group-outbound.png new file mode 100644 index 0000000000000000000000000000000000000000..6c706d8de75314d64142ffd704dc3a0fc56b48e2 GIT binary patch literal 39070 zcmeEuWmFtX*Deqw1Pu}#5;S;lhY;M|g6rV!PDmg)1os4j1$VdLI#_TYm9tHnqqft4lTu^DFPT(Y5fnSK9 z7dj~{?9KMAzxLVLE9W(p*c(rt%Y2ak;7G8<(=B1cm?@Mw@@_`eSAr(tBs{Pil9MUq z(FGZY1y5ezd5sMZ^S+|};|OWh9K?S9#{qMA?MnAYgKb)(mOmapcYFS9_46M`%TqLG z=|2vmk0=6vh|_Ys3#0f`p5$9k+#lkfW7Icg{}At&`G0PBX3c;rN?x0&RU#@azu5<7 zvJ0^hQ<|7byer11Yx$m`m$?8W4j#RhANfS)sQGJc9!E5Ks*l|@hPN&OV1_nMTo zwQlsqWJ*TaP+*4YjR`bZBzQpGQ%QcSf2%yO{f-60GS<3@TVA0>)hdUNA^D57Q8B*7 zHq854r%Nm_j>s}o!#^6vm#nxbnK}fB#pXMKPLRYg(1vgvczrvCGz-SNEDaX3zv?HC zamEzzIc_%5dKS<*aRgqM8!^AnX%`G~pjJmqPLp$A{P=&5>kbsfNMhlP6i_*o{%A%iD5`Ll|` zP-g|r`Ys#R`}5P&f`W9BEmjlj(-|z+M^gTdC4NBoi`vMAH<0@3CBiJLjh4+VnKgdk z>9&%Xt;uu~(#zcbMfztm-*=C9Bby_+76vmf$Kl5nTmsF}PGr0_46Wm4XT7;{#3 zO6|X1GKT^6j6oBY2K_=eb))Dl&!%lWfo}61nnh19n6d8Y zn4vPl+8j#1KZ=y*);Afvql7+W_xEeHnl4oT5J~pGIaTaCze2N0{E{eZgp8tSJ?6Iw zF&NBnq6-728v)X}L`Vek{JBG&g9ii8;jsrKd5|;9shSuXIqGsVElu9&yNqZfC~jew zxXbutC75SCYbNfkW$=66m2QK+gm!OtVgB5H)YB`sp~p#YPv7qtz=rB~COQu`#McjQ z40e!&nxK>C@g=BJZ3AMwE}MX6m&ygScIe8w%tdDBtW6mum2B|fsV-7`#{B&g{^_Ks z1KH``7PIHCyH1#MPdnQMb8W|)PpecSbx#`$Jswl>`KjXgE08u3W?{#yGm@)ZAZkCT z)UXkb!c?saFX}A)4Kn%cpiUW(#s&yryJ-$d3v;5(P00}&%fegmATPb^XT2!3WaDHJ zI^ilkz|XTg%+pHgNWv6@)JB>`aAqqe9AbG*3d8I!`dLLarB6C<;yVN3{4rI@&6y!F z7oEeK-^MVjFWF+i*Yv|J75~gIi*6%5Du+!59qIw%L zEb;qpnk!GM<#=v9Jf`{!-@mD(Sm>d6xr>5v9gz_(U*y2!dhD6k*n!96P-yya?p#r4 z_j@>@_N=eTjhi_>!^)#(WMgP1V=kDK)%1sEk8C}KUI&gebHyY4SprRykQHmdDbxX3 zbW=t=EE~00H5y=nt=@_aTK1o!6&Xw%2dnPzCIJ zIfmMw8M#W#>mlXB)q0I^GOx@b3DsSsw{0VV@bnLFT?9P*tks(0I>M6~L|v1ER1vQ- ziTts0D^>5YZ;uzrr-L;h^9iP%LO*>*c8%EnJq^_6>g6!wsZmOFz#~yf!$-j{6%aoq z*R@)D++fixfsh(JZr_cyWD=UPOsWo{PMa5|`Qx0f$*S9_^fRtZr8-RHI;fw)n?SkG zY)N6+IcA@w8uP5D;rxz1p2t4^on^f}XtR4;PPqL>w^vTGLAh$1V7LG{!p~B?$*bfm zLSpwkP$km6YRIp9P-S#=pn*xkOv?rbo#W;+z+pLs%A|kRav|AP6kvtnc|QAPp_>dy zH;T__XlX=aDOwvkUfN!4N4E zU{Gh@?PiU|x!-g$PKPI?7UwQjx>d<@Qe zr8nbiJ3<^A{&UxzIhB|T$y)zXSBKH7tY6EiVh@)Q2g^)H3W+fL@pW6c;{v17RI$Io zyGP^P{7Cfky|*5>u-q&ozvb1e5LYdNgE&^hxvtq;cQ;s}TEz zg!1hVq_9`%?r99+{xgjMYHjfb`3^TVi+rGQ>$Rb?OJXIYukF@;*%ymnnb{=Ltn?{p zn9JgEY~S{lZ+wlo%OB4*Ni>u$Y`C zxBypK;=zl-t^30f)KZm1rzv#7P9LVIP@m-6tGo3=Ld&=XPq~HbL3TSWX~}Gh^fdYL z)Rx1yUgl{0llLNJ^6{_!lfEPoOzxrxl!Tbb32ts!ib75Hd&94NY&KKKIu?=S7Y7pp z;v9%N`=$Hd*kwdYMK_FRZyQead!}A#yLG-&KjxmuW#H_bMYScTyE{g)HU5~N5 zdpqR7H)G5CurF?_HD4Ix@tQLN`eOrxLK~kvF}O=32@(sN(iZQwGFpGxlZ!EmZ1u)M zmk8=T-j4rXHi!@u7->vni*p^V?Yr_Ffs_ zo?Yq`=!b8hJM9@QHH}l9j0WH6UG;TSewR4{j4U!&)b0tr=(6B_^3XZm5u((donCnu z86x8&@8jtmW4Xc)JrEOg7w*g79}Z6t9lLwnx1(;VGSbRxM5W2IGc#Iv2}K!`crS&G ze>3ixjkHEe&C6kE(Ly-)gAQ-qMIMI@kkYZ;CeCL&T~WsH>)VgDGR{!hv_UAYSBE1O zW%=Tlut5hCJf+jpL;?XPtK{84vib*yCP@6fkk>85v@YQO&>&yrw?6N-etjTayj)2P z=mry7h+1jL+sMgs6yJQ7<(&L8{)h?Zsr}O2-er$sl`r8}5Lca;fvi;|S^i|EV|{@Wkilz6qUGzR@LkAh;!T?HuPX)4+cchQZ2Q}J zKYQhlVUQB-o&<=NZ#}wTPuJtkkCTm{5i!tAekG9(l`2D0FSsymSXEbe>>81zDK#Wl z_=UWfU4O(|VegGNg#wUHuekY51iormhGJD@KH^{$Iu@8_?nzVMM6^m|99R^h!(@nz z)TX3z?NEDyaj9#VhgZ|@eG2bH$jCER&f6NduF8FU`>}?xw}#l$pjWAv<3`TMOTX8^ z#9cQw)~Zq`b*bYXg7mtyQBg>IhXMR^KctL9tt9r}e<1d|v{jB-930n^t>1}-iHdjp z8aX`ZAIA&XX>t2R0Fdy&=y;ot9JBc3qiKy1hT_uo^s4wB+AX$kB;WI%^-n@#dAFTC z8+UPZfVPt5iyGcMyp9tf7Txz;gURgr>nA3ty3h~bjg|cmD1LgNb$KX>UeVYDQ{WWc zpI#%YK180eMvL2$cUf?IBp5tC+iHLjnWuFmhz%iqu$!A=lrRM>)r(-3zKi6K-|uxg zj*n*G%wYJB1Gy6-9B8&B47N9VN@d6nl|`yuS-cPlrJ2aym2i~Z&NNQja^bJLk4={I z3dxqsN9LS@BVn23I$EB`ck)A(+%+;fAI6x2cS^p_Pdu!syl^ZIWB*h zeVX55N4J8kcv6STW?}|*;V(y~H#NJ9mQnU?#Y@1+8%Ti6o|P`eT}x2N9P}q19!QT+ zvrMqW^|QM58!6D^d{$8I>#ie-J7#-}|JB{lq=CZz=<&Du68TgAFaa!X?PZt?sUsx^ za0@P^`hCF7bwC8$_mV;t@F66DEAVWZRrL3h9D~VCWSUd2(qu_4o>|PtvnS{Y#(jIr zrFVzzfm~G->pgo#)!b&c{IoGUDXEitE*s`^GxeLZNf?I6()EGGDrU?V6+%z-52&+9 z7-w9~#3W3R?Y*{o;r`&Z0(P3kpzB%3gY77qOjv%dzA!t9;$bSBX8s=_-%8wSv{}4e z7__JHTo8&=eL;}@|cuZF_zUPR%PtYRA1 z5bct*)rTl0GS{oSm=rQEai+LdhKidH>|H_t0DV{1#%fOU-?qsJAoJettx~aYs*2u5NVy`g07Mp4Zu$6 zgIg+P*~rq0ch;m;Mz}?=vvzE|s?~>9ITb}sl#Qy-Uyn)l`nO~^AS`uFtrYYCZg*WG z6%rF0Xk0^oYiv%$UJfsi5_=P6Y$ywg-T}vB4C?r(U^yNFY^181E@$o|VcYHIk>je7 z15n%PP&|${+TE)I{4Zz*Dmc^Xeis#|3F#=3O9=ZkU~666X?VEe3Er%5K=C!4gwMW) zzcp?8jvsHhd`Iz1pjkR!+_FrEFMDd)`Ez53*Uer196JsIYVXztb4~$zkZuEQG1~ye z*^tE+0=a^-??xQCvlR37Ol(vM_PrOr9^&OB*u||RQ^9lW+}c@B>=fqw!5ia`w!)nA z*jp_V>Rx}r#!=4oZ*qLuyPf+}!T}kLO%2Yv7zrQsF&0`rl)m!-i846ZL%7CucpV12 zdo0CFHz$hZK96{oIG>cU`Ij;KHd-IT&%oE@?J;VmL19&5re;6!(gxuT_3)c5LG+8` zzRjif&m$jug#rL%%re+l-32Ig1TXcI=wL+-S_bAJ&RPmoga3$7IR<=0#_({mO@AzGLVhIf0#xL0kPfOnwGDV(x zKc+1~z%5)d%0`9&GWF)ztRyd#1%aG z2WFFzxb<9hF17cZr<+(qR|&#ts1nomEB+cp97em3NDCeHi5 zdA$G1e866Pw)xS8bY;DzF}oQ6lziXp>^$D(r;%=Vc|wHi?_YD@i8NMYK^EA)NzkeK zcB4zjV3{#9Ga2LyeRe^mo?Mjn>I&%GCOyR7I&!Bxl@J>@$IM11L*6gXf0{?)h%y&)*(P>2()f_)LXP?%rPkM$(T0cm(h6W%lp4 z+1hqL?s{mixiC4G=g2A{qiv*?2Ex2?NmN#n({V)8tJ$yP?{DlsgeR!f>9+7Gf$bPvzA36hN zCWwOu`~fh}9^0-iluEg3tMl-*mo`^IbBOE{49p;<0Ema&A#4u-=S9y$`TvHWc@aY4 z=V`u&6vZm01JnnJp1by^!=+~(>s%!y#a?$!kmml+_4K#%Jy19Y?#@bO@iX>gJdU(i znb8LUqw6JpPxmDvFq(rC?^g2{8i8ODcTcB@UAO=?bz6>WyF;PIq}SwCP=ByUe0NB2 zL=U<#>CN)vnHk^HjrN$?DE!6mba5=jgk47xk5DPOL|OgoTNz%Y3X~SnH6ZxT!Z43pS^}^4*6m9}1|8vKv)^nFsdLL$SN|{B;5B z=C#$D#61kFHK6j+JnNf&UaTn}vPYN)Q=%5lWq8{3Fl4I+u?614`fKpP#<&n$aDRI)toeZ^m z8@^v~7XZ?o>99=%G);)X)!lh(4RlI>6A$Gvj4e@PdFA_lq8@ldsdUDN&+z6f*SC03 za-++qra{HvbKAJoNl}eZId6WKRvhHs{R34~7{ySIaa0-~8;Sk+Gi!&1a%qo{P;5^N%UYzr2HauerwWlJgKOChBd=_v;*$pj$WT;JMk|R&-`>3l*&8?o zt&)$`_9KEyTShvz4e|AT?s-j!9a0InO4L}AjK~r*XxLmr5m;YVP^IM`3y(Hw4d@bj zwn{p7t}D9neBeeb_rZ)Gy>9Z`YU%loED^Jxe^YlnfW~Mq+aQ1p z^tN(&y4BK&MYy#I{6%e(k)0WHbnyJr72||%R=A@i6@-L`WVg3z4qY>i0(-Vb&w06u zE+WR|#zbKiAwA$_&!S;UumYR(>2#>7frC!jyvC3frgK!Q{;AX|{$Wwoj2}a04gC^Euy!Q^z)%gi0;&9IfC(UA=(K1A(b!?+W94 zQPM=jP@TOx} zk~R{)Su+e{y@wzAm+jEBD7-p1Vo5S6dRk!+_7=m*&5ZE7n-AR-xvP@E^UR!Co&mSb zL0Z1dVJj_FSB7fq7z6K}S6PQ9-8^6ab44D+UB*@1T)c7Sw#D{9+~tvc?De z(eiF5`3)*szK*xSrI&1kB2LybGg!V7=eXr^%j2+Qsus6ZTNh&3r7e13@QbJ50Zs(_ z@hU>;N%p--H$}BX)}8GHt7~!^k=&QFv5BSxvU_kXQ~q@bPxM^?tx(iriYF5uhG18* zl~Vo1OV%S9nfz6zzMp8$?*7JM6MUqInISv+5iYte*A%$!qM;-_mIZs<8iF>3`}yJf znwpxNED^alAThw6j!7)Z()0OR>En@;6}Cl^oLwwl(hFm%Qo?ebFoTom|bLw-7W8TS2aCBpD=}V5&OGD1n>);3>HY0U)9E^Oj zP-)eZCe@}~AK|={M9He5YHRDJ%hysb@iWbEmr?oIhNim&PKlh|X{Br!rtG~bE#s|7 zl{}OLfSH7uW|+%FQ%m`lrDu~m_H5lr)Ax_kJ}K^`4ahA-S(6Y9s2VHB4t0DLz5I$; z400a?vC{CO7JcUU}KhLedddlh)uy*wllUvou1Esz?ba4^H|=q8Lqdb&01ljgCko<1{kzSm4j zW+5I)6~mo|G}RIbYd_G~&_}^Y@9G_^UjDwtd3GHP_ITL1o3Knk;8sR>2`0ZYiAKc&v6F**hJo-+# zU0{PlE;u@WWJ291EdK?zG45;B0)9B%ZiG44Ev>aof%VOLq%d)}{hQ96OJ2WT!F6X1 zmU*Ut${DTC%A*C2LU?ddr^r(lvxMvmRB%vE&#*_DRJReCIF(KmG^cC8n+Y@{QPZgdH#-{zPF^zXJlP2UQOb#4F7jQGKL9FTR zBD11B`t~}aodq|9T_q@&(Qbp&Tt;k^M&Xn=_34~Yw-?%M3#O2t>0P6n!~%;VgTf1O zM{mM2+cU0qFdRo4$lh0y5?$9qwDY8jhy$J98V+2p$owZ9`hT?qZ!&&mPFT(5fq8Ne zuW;L%jiIP98YlLstm6bM;>;4Z2MEQ4#PDz=H3x3ghYzx&IX~<1+hk;54$GC(TIvvp z%M7tXq;cBpV?QG7E|#tGV(Q6l`q36x@SZ~047wcqo<=i zqr4b`KA%XMiN2B~Qe|J}s&5X~B6#1MJEm8gvnc?KtM5|TS=x0e#$wH>eEDpUA?Tj3 zgkWB3p&>XAI;c^2&Hkcgt4B1Cx;shQb=B7Ra}UmU!dB~7gkVSd)hW;*DCsOvV#c7q z5q|*n_0vt_JTltVYZN@D)rUSu_&E`FY! z2xH;pia7?>IHg(nUz!DM>+^uoz|>D32dV6g*%vZj8k!9~f|hizHYAsUTE2&U_fz}C zUHNlMfz-9QmAb7M(5{abP-{_3U_mW?t@=UNXXSbuCpl@e7tgBPxMZ1j?JYm)Wnezxv^)YLa83o3I| zav{JVDln*i8I~QmyI~2oVRi*66AbB%TP%lM6YjZ^Qu}Ia-vdu5iEl0935kA z^1^j!YzPZa?ruR>vKk9_a@xBy;#^%57>9OzzxO-KVCsI~cI_SWgM)hQ$m+oNAqlf~ zE(sEeJlJm@6JAt|#~(1K8^U<85=RJ2;Kd=%xZ6K__wIM@YdvvZbvtmuOy#A_hMIdv ziEPv`6~CIW`_eJAilOd6`i0NBLE2kRCN;&95`3~uN%USnK;wY^R)KT9<5U;f5RSPA0EpB226S*f+mU zx5M^j9x)#pELnJR`%8H!C5Yp^WN9D27SB~~L0rXS9QEEUdh(KYILv<2!GR`UjF2qW z-?2q$e;c^(6*%<_>AknR8zLsUXxrSR%>8RU?CZ%9^QjK(I-$@$+|csIXQPR)%0yeM zMmST-b~ie4_P8ej;g{hM&Q_4l^w<;+@C-89RV;8QU)bRfTmNn$arNw{ziNY+TJ%4= ziCR?@ElC6;4CJ48(h4kDT$Uvm!n>GY<-ZpR|KmW+e&<=9Qh!u4NIyvL|7(%Ilj?2S zIne)IxkGbota37!){f0Rz=y!4G7h9@kyb1J{VhvC`gZ5g{Y^K&$sp}N{`~xTl3^N( zfF>IXlacn6tn+*86HRH=D(CSR|83A}ZCA?s-z&tIzv?rHVy>yL3+tM3Ia}T4zs>yb z7jkA2;L~14?3%|J{DTqxK3Noc9e@YfN}O5#N9hQyjGU!G)IZAm>-7I?MgF%crKSI0 ztCU&g=H^xz94|=A%v3NkLczq0GV0D#wznrIBO^;;(TT38U;}Oc={6j_6~(z+(m949y}Zz zfAqBdMVXP1j4Tr|-uSO_H)$DTaJ&f1b5dW7-O*G&j^Ms%c2`1b>fYTky)xr=##9!V z#*Y+P>wlv5FYiw>l+x9Gp;tZVc6I1?+)_v&DfuflW;Kx(ZnEW)|LmhXy{!D2_dh!=*PkXa-FWsf zQjRp{*-r5j0mSe|U4f}teC6aZe|o612%m%Q?)h%H0I$`u3WhVn8d~k%DvGIXdn$j% zb&7A1Vrqf+QI@o<3IB`TgW>}A%*@Qcx>QVs$IATi{Bk-3%sF)zxNAqr`pwuHB|pjv9=IkRkkNlYwV|MNX)akYQ!$h~`4z$K#Qj4(c< zrHv$&h<9`Z&cXJv$)G;{e}{F~3Kq}&nZWdADTpIgYnseRg&R*md!(HAvOMM6L~fqw zObsO--)je>Mt!4J0x8c6;_Yn$dBrwWe}7@dSsa1tG+$?D=a%+%(5?=(gapkG?K0)v z(TBl-=ud@~bO%@WEd5cM&LL~CpDbcx;e<@8vn_5xmPuLy#4StRkFP7=^9@W)O#Jx^ zNr7G32M`{>zj$-i}+mj_?wf%cdV!Gk=sJ1q?yW$SI1)S#?n+`WmFMLwE^aZH#jWJ zWU&8N3!1ifKW9l{D%jn*3TQ7|qD92A(;;EE)^c-@_TA6OFqZNJ?R-M7u6|8S1;3)VbMPQ+1CeZ3NBr< z;!a9S8*Fq?FzO^9D^k*+XE4V2Y9S**E>M+FU7g_8NKtnZNM0RG)rUJ)tI-`T0wj%( zn-SpS`n(#=U4IB9F{SC4WFCWUcM0bOUc^dV&#`4eWlX$}SJe*YC*qd=ezBAFz6Lw3 zQxaDHEw)1_>Z}?Pj;VFuXxJP##~1e08|b$~as1J;4Ilh3sGCx*E4p((bQ4ss=ld3B zTU56`u^+1~7|4Y&#y$iyOWBjB*Q6>2dJ>t-#S^4aRa_SZuN2Sy*zU_;F)#OZx(8rI zR3Q6Ce~M(B8BsTBxo7-Wm(5v^$7cD#kYqUpN{AXlV-seNSIACS!6|pU+jBM%w>EiHnJnl$NG1QO$kDyeEusFJ71R zkBIxRF~reFe=Em@WE)}T_gw-}J_|!0Kb`_fU@)yG0t4$HM&^`C3aKaz(eU@vWq!m` zZ|HJbbCmQOH2IN z<*FyuNO{}kV;+0)cgY>?^*1xYe+h}NTgS8A0 zx7sky<_qhV@#uQ}`6s%w(G@oSO&LCMvUEa=~XJ@y|JY3gmhzvLv7%Utb3yO$WjT)xpQfA`kA&Xa2Vv&{jMlU2(~6=+7^SDLtd-K#!bVB#T|^t`p}b+ zFjfiR=0LhBVAURq_O++3sutF_;CHq=0_Xgx|N38F3@HxUvJ-9ZUwtESY;G!kWO(xx z=dGQC&!}eg(3;pzR_EcS(AF%z?y(S zF{t|)tA68}Go1{}Ve*!;gu_GkN#U%J=N7GbBrg7!TvdFZEhMD?LlnVjR#KjgbFv3E z9qOHMU`21G=uCJ1PjaSfHp@lXA3tKB&nR^Q2JP=EEKN@ZMT1}!}I@A4hrFcG=G6W}`SSIPu68C#g3Wp$z>BIqEf z_@m_E_%g3|KJq;!?El<+D@=_(QU5F3y%)wDMxFlR^rOX9Mi8&_-cBOZ6jM6#QeOYWt*jp?5bW8 zArOU-`%4_QQni%2%fNPsf+%zL^-C>LNJbyr&Q9q`%I^YPstrX!h#bJ|7RSp!F?gJ{ zFRrRHL|mRLHJc(5kKS|f^yA{M>~*p#S-gL(QHUNselmXZLWD2mj?X(sp(vQx2mHA9 zu=rXrJMEK}7hFbs@>dMfu;MH33zo436N^*GbLmq#$Eym>5tSK0O|V0>UUGL%J! zjrmjQp{mq3X$AvmIg#UJuF>Qf^eX197xnMJ5|xKwaldP&c`DVfftCChL6sttoYfDj z8@1G~aYx;GZ(jV1iih*fuBySZGf``SM-g&LK;G%CK6&xQjL;EO;M&2!ey@+Kog$9K zM)inGHO9HOfa#Ch6q_xVsD|9Qe#g>-)RZI$7JKyFz-rONs4KHun`(PDFqy+cPRsy#8N?@)Wz_e&pf>s}p zM~y~_7Ftl?$1BofPRr1XC^TU9>0x>mF`dkz>8vT5z@bzCSyW{b+h+Ah5T%Pfab zDdm`_KFOYt{N6DGfMByOwJJ&|;qjH&X{M;Wq5nh}Sykh|K&(pxr04FH-uc7}-DtNE zOu{w-(sK9qGcaL9`#lOO&Ij3Se{rKZiW$D|s<7+TY4>uL-O~hvu(LtO)!y}yfk{{* zH4Enht8xptO>wt6wzJ=&Vcjb}>Qg<&mFdB>hj&q;CM$&U4EvjmX&lB$$-%;k+AQkD z&vH%P%MagvLlwdLnB$vJ#Sg9b%+GYd?His!dWCzwyiu@-vsAgvhh0mr<)6 zemHt)*t_S}0(1j0EFUMIT;97iv-7{+Xm}<0_BM(zhwHzdC0~0BvwFrPAfC6;H-o6KpBQ|O%toc2S(1e)XDs0j-c_8gYGOL^yaqK3pp2Djg}^sKXs-2CD=0)4E#Tzk#&r5@0C zu1aDV=djDZM&LU_rZH)viTyk&iGS|{%qs9N#K4GNLetJ2-}4GIc$My%WF|xPooH zm&eneE7JQdKYbZETX)WcOC=(?Q}m<)rssol{_Jg{y?~37_VFY)|GP|h2E*_y0MmT_ zko)p?_x{UBUDfY;ga^H;^~MLUG@7o0upb?nlKjxVJXn|mD#ObCQM1Frt=1p8eRd9W zfO!3!{_zjxE)5eAwW;_*rOO*95cmu<>VNKF1YvB`e?LrRraIC-BFCu=lVTK3$wMR%f@p8svxw` zA3Bxw!W;DY#TP-Aq%Iv?u>$MA)gV6x(Xg|`%njxx{hOG<4@iEtb8%bM*iA}m0(BeB ztvl}_;!**I)3wKX2f>pumv{byu8ymphfR}VY-H~}E9KAc8b2TDMbwS#VLx(J56hCF zumjigZ|FV|x+(M**(83+khapM9aGIJ2{9csN|fvR^o{LL2&a;&-i`ZcYdL--Ex-yj21@5V|NOmNB~Q z_&7dcr!F15uqg`Fya-sndJGdKO_By$mmTs}?VJFD)g}~^zC1Ofog5p>(F3luT&UDj zyPye~5;bRw)jenkiI|~W3 zf@=B0rZ^TQE^&H(O$_)UBK3*O6)pK&vzKp)V9Ip=r2u3cuZ29?r=CRgjKhx>-ehhL z+;#YU%>&KXDuZftUl@NlN^f>vxqa^!6~mJds)c~HmKvDunMX<_Tt4gmsz}qd3&=E% z**c(vpnT&8K;3`rT5nl+`sHRzo>4tw+IT#Pw7bcAPw&|zwc5y9ADtl?^&w=afU!uh zRv=0CvE$vqGzs%{0;_f|CGb>>@qI&O&qGPvRs&mFWfQhulQ4V2ks-pWN@VaiT$aZ& z`+;Uu`-imb8y)?H7)UNY5sht2_v%m6xdoB%)dwY!n8I^Q*et(&Dy|(-5M!%YPFU#Y z9m)p8p&`-NAIBV2OmfTd%vZ*lw@#@0$dtW7@FbdGBk~skSlt|kz8jr2hR@_%G zbl4bS#x?b2$tqP+Yq%rWsq9^7t;urPyXp`_|4U{6#8CF+x=5*drR#>GODVkB5ynR6 zBePZ;_Kcc=8*&?m$VLPxLY_(H7Ym^j>i)QnYqDTKUN_pd-HhEmlmj?EBAS>H_j>9m z_OU3fUaPWKDRUhp&Iqqdd`QERnHyBNuwBhBdOm+dr0iY?>nVMIWb;H|_p~ktS|$C$ zai0EPev6sBq+r5HG_HIZFW;SZMzm^Sb|UAx>9z5*vDt^KJ;>J8k<7f4p(!h;g2DoF zsrnXUB)Cpd@Mkm`4UgsE(0Ilf6-Fg2YREv$1>?#Roj6rlQ%h4pMU^h~Af-zEd9}N^ z_Bjs+z|D>|rfvg-XkXiyv9326+;|M>5ES8m#+lq=g(LtUHGr<#>0`EJ*%5Y(TKshE zqvSj8>Uh(@I6{Mte^)(fG^(m2|4{nk?hXcmeD%8TM;mjsCaH4=0;GiR2O~lJv>&|E za(b?Qwet36?@cIb@lOiR88D{9N8dbHQdly1D` z_URIw+E#4DdmsS<00`X(HE{(vZ$ zt#nvY(L>jkJbJeTb(Hv z-7FLgV)rvwK+^d=eJ8G@K-~5afYtsOl;0{+65<0s+!&cjKc@SNJx9)$^zh5QDY^SK zEe9FY*~lzZ0%=c%i0a?%h@=m#Syt5B712I+?eM8FaN1^*&pMp)#eWRDw+CLhJUxB$ zVlBg+&(`ZP2!8Z%ce8Ro;o|(Xt{k)fiS?-P5|aS}BQfC9_~dF6z9o2mr<(M>=y_#U z3S@j9q>q6Pb%K-jneNF-tz6z87_OHvG?pi<&CSU4w3$}k32{!w#}$0}g6W(7)B9s} z1mEcCZ{wn}Bfr#O1m>$R)+;Q%0kUdOs7|NUv*#08&(;sx+|(smA6;`HIX85aV{y(2#L}?6X!}A(0#?5A_q1@$CamnZU;VSX7wt!>=i;~$4 zVLKXmNpPy93_yrcen#HjzBz-R0yo%xGw5L_>lr+H@jVEP;OG(yyChPrC z(gG~PWw-)A{+A#pXW z*RzLf>R+jouN}>Oore67q$#bBOqkC0e|yC~3^hw5Bde*I-xkJ4ek}j>L&S%KWmrRA z;hWS2X9vpnyh9lXO{Ebdk>=KC-G{r#(A0yf^e$J0;9aZHkbvxA`+hS(e4EK4V*LUK9xI?|HIL zCLkbS>Gq1!{8wz{$2;DllSI`WUWiPc+m-<3cjll-ZL1-~gN4I>iq7oi%A=_;myB9w zf(;unvekiJ5ZFLY|7=T_64y~{kPvw8k@#KMG8ZS*j}Lqa%#_>cm~8v%ZbYv2=^pFn;h4fs z4+rRtJ(;p;+Ndgx4_N%zoaFRd4#rwGtY)MoS4o36E9++z<9bF!8;_+XTOnsVv@gfr zbEtUL+tAN$JI=0DD5uHJK=3}Ef~01lx*6o>tl4DzeN_+bMC1Ih=RI3HQy5vYWoD?z zScLA@p2#SYUC#XxOZWod?5E)`yJncE7r&K3nt(Gy?>Q_EW^Z_N?OFStP=i2VBQH$?4E;=`iB|Y zf2TML&0QLjmYfWQ{uFZUM$9SCY?_ILp=5(=cj7iamPJwx2}&h!ty;m}dJCmQN6KuC z70&O~E#s`;ArMqgN*D}M`Ms!Ux=2Y*R4i94$_PKrOzzX|#qTwA;4qIglO);WxzYVD zgyPw%G`u5&II>#nsMq|$$(#*sn4Xyfa|L|EZ6fZw6wCYKY)n&E5NlQ2sc$o0{G+U4 z1ea2q@(uCRef;62A{oLK1r?RubknA-t*u@uJTLASD{kJ7tBHl_ubW@ud>B3N3$4q! z7tZTtQW0Gf2z6Obx6b9-+*TLO56bITl~7}pFdo^GSD8PGr2zv^-@ZI2#|zHc7j*?q z>3E!O$Jga#k|vg8C{EX*YdNmZc0FB9`#xLaAQLa)oJaWDP#67s$@9!Z`kcg^-l79W zI10S<$cb(ICBv&!!FG*=)l(?5+R|Z9&Tjn*x^vIj-MDVUT{&V-`^n82BUsJWh`%Q?ti5*|bmsrDEy(J)}Su0UcJ#@y1ZhfY+)SUs%>ED^+LHV*g z1M*JLdnEXG1^Cy5ls!9~y?ZO&eH?a4j>PV;i05JRH=fwuwa(LmEH?&{mpt2FW}Xjh zO3{%x++1K6S@gO^UnXGx;k7@qNpd^eCp;$2QFL|=?G-pebw~>tm~l$-mdp+`UY;nZ z4hAo|`1JXIhJR_TCM1g$4P zS4KuRduYhuuKa{!wx+69T)UQIiS{%lFG>X_imfABy^M6qxO3KAf7uKRN@bDDjTxLN zKjo@=svc1%Zi0I2=LU}~Z@76G@1p4x&X44*ed$IwH8i0h7vo9YNLAo0P3lZXfCJrL z%|S$Cbhgq}3zrguBZ#0FXxtmYgTLC!*(Znn-N9+a_8RA+1=IL#$yKtTBdq@517YB0 z!z+JVrqo1s3ZYc9@#bBn`^oF)hpBp;#4-61pzGCUq>I~gS}Yp$0s*d|W#ONp?-RO4 zeoy*&3e*~0MKqEQ=RBwa&zBIPS#aV8D!u-~v(P*Vn2T1oh5Lw8tq=DF|WOF4)I_tQKg$@j%krV$uZLW^!Z zRlj^9tD!qT$5K3eK>Z)>=gxt4o>blZ@nsa-e)p0zHlnFMAmACOL@X;4p4q7{h6K^0yh>;7cwF;7Vm822Ga4O8#WLf8>tHMW&=K%Ngcis3utleAIG1 zMn*sz!NSnwhzF%DH-_8Jm3GxG#@Abd2CWm_Uxj&*)V($=W5b(=PU7P3Y=9Uub6KmV z9-7&D;sAF#76yi#pm*Qt8J|N+li!m0pmb{GT#?s?-1Ba4&nPhKWWA-48w$cM9Ac^) z&p1-1bK$r|6usnThv%{RUA7?0cOEwkO)TMXHEe(#OB*O*CoXgccWe_B_oFlGRpZ_C-^KHk@DWOud*Nr?h{%Or$Bx^2$MWwpdGb3f-)4ivJ>` zJ^VEY#+=R6d+h@`qxNI)m;y)W_$5yBl<)w+7aigJ8IW%VspaX4uV$-kLAo(2Zy`zJ zwSi3?Gdp=`G}Kjrvk~Bt)k)Kx*xH&mw3F_P#4UxdRHB=x|79QL#i{LVsnL(J!_&4} z*^Vzb`@YLf#9ab|+&-DU(>xq?auUoOk72b$x>>Lc_Lih@Y;p>!?9eXLBnwqacWyce zFS?E~u0u!sdxmP0nB_*SEPHi^?u2Bbk@X-9s*=JaD}hgG=e!+2_{KrpKd|re?sgdg z=Ucc_Dz|{MPOP(QjJ6i8Z!%69cxN9WpAu$wfjpJ zvV&=Z`IXf|dcE_e6Etu})cs$KpB_rKDkF5|Oj`G(?Mp6h2HyYT?JWbM>bkIDR1if{ zLTL*S1(9w>1SACkkp^Mt?q(?IlJ1Z$>F$#5?g56LfuUi5f$wnN&;7*r{dj-9-=B#y zGw1BHXYaMwTGzF%Z7ty$YZc4%{!1BVTf8t8%{jrr{7fpm1L511U5Esl2XDC zzWqEBv$kEK;l_$^3{N^IPMV>h82Uv!Rc1GcpHW042fd81aKJezfe!y@n#vZ;pZvw& z26K;1#2<)jRWbrd~*6zzubetHaOF~DGj6$z~T{3 z%p(>rF4tY7w$9Stay+ow?EK+<0`Q-wQ(n>2k7kGw7bw|sMD-3zEceK%Kg`BYp&il_ zdA?E0_}(;}65Raz<4G!GA`Le{>7e4VBC)h&xjwBCVE8?>ftY!166WgJ$-a_iEfeTd z4$*glNz&3UD0-EvN+K2rhf66*$%i8BZ5iZ|^)*HnS#q7@v1(z^#k0WT!8RM5g=yA^M~oA`Vp5|PK?WaD^K z$AortG;zNBim+Vwu}D|Za_Q&rBsEL3m5~`2UUJ``mKg2yR*K)nNT?W@Hq+Ki@E2N7 zc8|!bm`KiC{r3-!@IwD!S%s0p3@Ui5`Q&6FK6^1C>;IsC3JbSPg16d#2sQqsfQbv_ z=a_SEaTicaIQXIqvpl)-d+a+bFyH0jUS_k?Oi{A2cURQQ2Z6GNT9zJKdn%=<(2n+Z zR>xbCjg5UrH7!*ggM%A*q>TMmCVN`vE~M5a0Wb8O)3OB)PU^}=e*z#^%XNKJRu-JY zc+69+3Wsa^5=f{xt+%jFl&lUN984m-ZNz#7Iuj@%LZ`OHS+BJG54)UI%(57WrRWG&^grt$7iwv(OZ!izFL5P$M$iGJQi!$~Br z+Q5CotBt^{T0Pi6o&97q83Og=({oS)bx+6f(mgGE73#=OJRZyp{b#Do_OyeR8ZG@&6CK_|?kFlRHME8H|$!SWln4{rML&fONjp*ygflz&q|nontfD`?c9}&T(g;Wea$K zDKGfR%Y0RK*Vt$O7%!rTkERNfK7L+%MM8Ed?wjN1$Y%JtYfOf5mA4?e+0F8?2O#c3 zDVy`95AWN8-b*uIoFyk$S0YmTg!6Mufa|fpZEpZeyq9wt47 z@JHc%up)JI;bIxSchWyrTfnc>D1DDGCBC;zdfQAWrkxwRg!pj^{)bDx)PcQi?X8v3 z zmC^97Q1}xUCl15Y6gk*r33x__mkYowH_1E7ex>s0MknZdG@oBA+smpBJvo~^Sj#lL z3O0A*Q1{)n{%O%7q>F5So#_T+zg^UW)c|J!>q(!kQvN6Gw-shyp# zz!6V@?z7%Z;mlVm^efAg7=S`TXVq~aW&uw*A6OZ#p-G+UL=KW!sO0}kDa_&_C{1Ri zo46Mt6xWx(gqwMyi+{J1;kxQaxI=PT^Iy3KOiyzTAldqGbhR$(}7y}vAPGL4@h9d`+^ zjQ%=V53__<(t-vT&fy@pX>T9fLHna&Yh)91zQ(M!@U1*sggU_G%Fff6O>;$>_da3~ z5dRh%XxXf4sv+~YDO;;vj*R%J4VnE240pTT3r}y(+b*byP{@`Vt%BeCnzwx0JXW&5 zZYv;Q;ZWn<8-ShIJ6o}0w|&SBj<{{e0)4$5iqde{58weA|3hA^%Lb~+H_i{D01A|- z;9qf-1^AXw=zK&^1%izIL!7gbwyoQe0BAoZ)6L_56WeMM=Bkjd1gl5!a_hhm_Gsv39jRad$iEm&9IC_8VfMlT;o~?`rXaV`(KyL z>Xi8W83z0-V240^fG3)tZ`@@Tceo;c#OwObFf9!S?ZZpUQmNiG3EU<9+qZB(KS^nc z+O7fBBa~aO%_%L9jE37?>w|{~kX8Kf6Bh6kLQX>B^@sO#w9}67bO8Pe<(O*`pT6cQ zW)g%)+RqW|lGIBYZg6xu{fn1eeEOhw!xn>TwmEFyj&{LT>b8W$!W8Je7jNJ8|BL;n z@FFWG=WyP##rEnvUtO2O>vr<-SO-BNmnjnyU%?03^vujD;UHAVboW)%4djGbXJr#0 z*}}S!ExNlk{TMvxZu09I1L~4+6vHEs`p)55qHp-m+C1Mh=5;-Z*MoZ&14)_U?@c#I z3ZMk(WX#-TY1RrdN^E`Suw6IH%%|t#D}+|Mi#)+pKwgEpwwOZ zVw%V0oGQk2vVVxz_Tp{~C0D0^aIyfN{m%WF-~T06NGAtyiCfUsaq#IVM(t**J9iwP zK4D~I`~{ESpFm@Bo3{O6?i$M=eyZYoxZZD#c3}g)Jgx7t(}74Z*0+&0wy z&X!PH;!e4+xCop@;H=W@lbRZzt&mpFuMTll)T9ZSd-Fssd7O zo+Ns8@#n5msVj}4*IELCf+4|+ja#2XoYV2WcKzQwy1tet8Wkl4i$9fiM6?D_OxGd2Um-tlo(=T6YhKSA5>|PUMToNS4H5se2nx*oGQ&**CT80KAcwM|R z#pOz2qPQ{eiOj~u_Fe?agncC|%55=`v@fA>J%IlLuU{GQtkFP_V&O5=@85USv%4+# zXb$6*Z#h4Qr!1O*Ei1IF)Tvf&-=Kpf>5kJ*uedYh`>h7o8v;l7pWE!4hcaox0^^2+ z?1qDxV1I{3PM23KxGrJc^^SBeUq+pPu5}lZ`)lbwVm%p3>c%e8VjfY6W=;>Pd#mO& z;|!MnMMtIHU0IV;MrZX5iEk#c?x*Qw-19+;V$84g7>C2$jDJm)jX`<9fLD-wgg#-= zv?l5&7L{OIZz92d-%qcFC-D~KY@h!&Dz}eP86ZxhdtYo{tFs{V1_yo#eC=0JanoRQ zvNinu45RsGg&{2M!JTCoD(&E?iy2sR0kw+mVal5QgR5Z-9=ElpAd4AH&)nSH!B~xc zW}@1%K0t}nU|pBZfaI$SE(3Ro!A2)Hs(X6W&I$YmdCGNM6nHy9<}lSa8YIJK1{sK< z8&LsVjY5@l)T!Gd<41+4?sha4ue(>@3EUX+ABoKf^;V!hqZT4a4vHh9~)esHWAnD>`ucSmyQw%~?T(Zae z`_4-Pr48%-aj+%VB+4f!MYn@>kJ&0$78;s80aRxuMx_yi8>1vNwKcxX^4>_fFE28m zfi_zvfz528GDiPxbMY_3I>dftC^m211qb z;QyX&0TPm{QnoE5xghsb8@6tutHj{w{aCe&Zqb9sD6}xCGN&t^m8Z5TKsZ z{aF~eC=9)A8_?|L`^NF>#^C77{e%4P8Uy))N7{y?I$(>if<@@+V)wm}Sy@deUz&Ui zr{2ZPWu4bG=r3oiarMglZ(^`QvVx-GY@IDF;L{t=0n{qt$j>jG5qXdygl%G%UY`3k<<^$J!1(b(-h_}yq+$^Jq`)7C^; ziuGSJ%leM0s;b-Z=v^(>UH!j3!T^cDpNWZ5qM{^Krr6}cQd#VV?Ri>)r9IwUB*M#G zTfR@U*ELjXHMN@R?a$X>B-pNzU{T6ZGJV>Oad3a_~`a=0Q6I#)Ph_$wVHx1hW z(2iv|yrb!iY}euThgo_k^cfoP8Ar1F(f<_H)rpbVhf^wlU3FdHFq!ZKNYjxqG5UY` zvJvy5KoJo(0Zq32%jpy*g}+yiES_3GEJ>~E1K^Xd#%V)1$!>k}9`oDR*$%tU3X~pk z{B;O8x-bR^e%-shoJK=zj~`yru9q zxSh_%U0q*7iZue|32)O6Yh=;DZ-CJA_NdS$LRu=uCev`Z`=5{?V1evk1zX+#{`haJa~qFZL9iCh04qf8UhFOMb^amQ$V%ZS(&i zZ~fT+qXaEgaLd7W_@DB^i22a}S3LFqw>K8zhIZLx4whIATjCk2STZ4QC zM8OonR6udhi?fCCWPlb=9-KT^XAAO_cGHST;sjVE7>x&A@4*p0=5i+@oxGC-M4Mkh zqREPALTlN-57fmV7V6TbekV~@q`Wy0vGdj?w4WGwvJ7*(@pH9DdaT&j8N!WDZ-e)n72sjDZ;||a|I-T7JBJp0Ix#)Iz z5h^yM65h~W^irV+kZcKk*_F6D9{Om;)@9GmrkFJ1MYQZWQhm0T7io7DWGxt>uD<3- zygg}2nAsA{MkZ_%iMoh2@^F7!eMv*)6R+7HF9ZWOUv{_@$*wg#fGLD+^TepjQFU`$ z>cfyvBr5t_B3uJ0RmHQGrLMjhvm3a%bu6yqR22J3MX5{5J8&)vS`vZ5B_8#eKD zFTxT9&e~q3<{8*hLAjHaN*3-Rbay(CWd}nLCary3;aT|88oep&3EfZkA?8ARW>Z9r zc^SWHC8@MepDTXbdpUMp{IG8_eI8Eybdj+&lBj#{PyY%h$(}H_7_7=eo$0|;A%|Dg3^my;^$<}AcLb4k3OAG9unNdVCHyiOE`453gnM!K zf;qn9$WiU4`NN1OFH`l>nV!~iLk+`GFH(Ls)Q5(%fz^I0xN`s9vU~UfSx^z=6$4R} zF6A@3?)mQEo|p|-#ZjlF^IkG)rmD%3v)^4?SQt4h79<}r8EzI9eu8kDcMXJsvZsqu zs^2D&BfITyo@3d~y1>hrUJjp4F^fVT1JZHRv9W~WGUa7|244(P5th9b zJZ3~|q2fO_>K2E*zJLbg8 zy&^CME%1U$cfPU+Y>coD{7^C1y=TH0szVdc`a@}4NN=Z-0Hx>elY3xOCe##hBpQ8U zEM!a37Qjf$?mGKT_K8^#3yNKJ_-s~CJ>z_jb_!_$Or)l^TJp4VGx4FpMtQZ5RIJLn zk^_}`di2&OQdF!Dhg@HM#W4{}iv4XwjF6j);n7vNGF}) z$E;n;HxZ9nVoQNfnl6=(EEAdenY%BvxGXqshGx$%wH(rdsv97BX*bl_JE@%-fv|#= zK#wDPdg`0+*l?bD2fh0747ok1@YJya11QN?ET|)NGQ6@=MYp(9C-1Irbo8PK$EeNX z0h74~efKsCJ^SU^>nnZ&y`2VNgyu5RY)-RZ?4CG-Jn3zG+LgnzmD7Z|jF}2?W-9z< zQ~=(VsD)T>;6`;+F93}za>q&Qu)%64| z9NZ)}CDrddKydo#`@rLmhSgI&r=reu4=&<8Y_|60!PO}(_9nxf2jGxd)SEsAvO}b= z_h6Lac2U|$(sm2>i0KeR<5%d_tGUgRkngi~-#-;6``vgaxo33ujuTJuZLIjVgg2ny ze4CZ~Op@vhnmMcOU0Gucaf3J6Hzn_?rETcar;0VDIQsTrpth+0DpJ4?vP?1 z4Jms6UCLi_)t>eDHfBzwD*Eg-*7*#QsgN^F>PO^cEIZ;~4zV1Nd?LCCSs~TZ;HTp7 z9_C-769gG5Cw3U0)K!n$Moxx3Wv=jXS9c6b4j|ng+bmJ2@Cm z)HIfUYk-Pcepw=DI#lJ@S$3AD!(6m}o_EVuqa*YbyNlqJ>nZk@qh*!54g=GS6H&iJ z86Tc>xFpw*SH+K-GirnIt-O&3Emfc(WEMr{;oJ3L* z=+YpR1yj?8FUH75C`*FN^tYTFBrf3}FFf&p%BHyY*O2lhu;JO2V`*4`mpMBAY6vt5 z%gGARK(iJe?)*-P6_pWv&~R)1ui0PC39&^di^`ZiHct3pL(=VNu74KDbEGJiu>I=V z`bTI|IAJRM;aAgHp)m19Kn_7+AhKAS+hF}MIl1}3MX;0nS@SzPxQWDIhzOo2kuCYN z_^uOX)ojx*C0rW}GiLQYX357SDYVz6TWMOgh0=R8+*1=Hm-o{k4Ij=`J^3(sO^$h7 z;_qP~z%{)0-NwD|59q+;pyk$!x;bYB_Yw@xuLk9Kzwahk2ftN4>Bzf3>|PqL)ZeVv zL}z8=GFu?f)fuV}*Xq`}Ya%Wk=*sLkrBLOI#X)>2T^B*0O z8+?&!jFbo6HCpI=RNLAWqrM9%$r7VpIYJIJy@yX$*M;e6eV@&XbJ`5no~ia=X{d1@ zJSOT$sDIfzHl8l)){^2h1f@-|hPD`fE#YlHLMi}a(&S<|_jmZ0nBC+jTS8z(E#?=%y~vZaqu?X$ex zJx2xxn=PCMS=Lo85@LLK6b5xOvsnygsgd{7?+aJmIW4ocP3C>;@MQkO z25H&0dXu{f>>?n&_-EZzkWYm(nuyXDFT5WDw zh4*yXkhQ@_NDUB=4TlTg8KJ?fNW!9_Ti*R60eKNy7E{^k(5Kc^(8j367Nj0*W-(iQ= zuJ7!x#TzqK2#m6$12H7{+i$q$hl3-Wx}ouWmaP3 zUyQ7Z1D~^*r<5ORdV^~k zFG4LQsx<4Ky~udbAr$b~R`)HXobn3qykCGa^>Hovf@kO8CDrlQU|4OoSGy{o1J-NG z{_VjjzaSoG1n4IZ z9cLWDZ4*XI@UIT2U*2yVLipsLUy{`;eUyrStO$~tUJmqNF+g*(#|xcuYVC~sGTg@n zFEos+oVJvxTuCWjes?-a#Jt0r8y26Yu~aqe)=Yr&%&gcVIqSRBC$t3jaAw4JXKzqL zoc`l!wmXdn&%)xJu+IoT_@*})k1kjjD38|KK{5g=g)qA$uMHClhZDc0U<82Y?_OR3 zeXh6T$go@es<=dNf}kIHm>GMy+7lHEgV05p**tU3p6dWmUMKP5E6wsA_D@7 z&MhUw=yRQd%eRB%mw1&zN>&fsmwMRgui2rRK+mc^E$FVlJ|FOqeCgZ-eJvaLn8 zRR5f@umf>Tz5o03WM_xjf=m3<1+PaxeCOXW6nDB<^P{^}V@t05SmH`vFkQJhWIJNf z2muD(fq`C+rQr;i?|#}UEeFcBNYCJWK&(GAvSu)uEry@^FMdXs}1CGXlP}^b1Ar~|Aq>5Aj8^CWVdsO7o z;WiFMqBUQ|o@O4w(M+5BcX7-}F=DVw)8Cl?1PpMQFsdY_mrc>E}RDiMsk(i*0HZj(AFf)RX{KnXPw>S!q8 z_yfMl-C&4gK!4O5w2+})iskCChrPnu+&Q^-%Gxme%w=%S@S6QHf2b^0Czd(1+ft2! z0M}u-JSBeaCsi@*)xNIeO+N%bml+1Rh&_SE(=yqnHtV75EmH=d48=nyaDO__+Buu= zYOdpkH+}>A}F{dOxvAmDECeo)byI^jth2LZ|nef-@!gYpw0!ozjsX0PllU0buDMR$1bEjT(-vJzyjnB*c~FK z%1O=Drm`aKvt70AtoF1A3RpcVaK%+3J}|V=5UF!hG}_&68Ai_j$mAbI5p-@MD-1@N znqKf8zPDhU8o!zYDp~COb_W6RAcS$z%h%X4jB!~ECRp(uJg5*y2P22(u}zAIbyXQs z`V+3+pRH|9Nv;hFTQ(;Ex z0<$;`arS(l3x2EYIb~e>>fgsyA6rK0u-wC;2|UqK>1RLkaVZN8wY)JqGT7qE$AS_b0@HOw34vgms(rVdE8JCi7Y8a0+ExI!ljx z>QD&mcuHI4Y+ehWD*OeJoK$-jdxl8W5TMOBbQsDErNT$`!ZP1VnFJJ6!QY|9EQcTaIHlC)JA>6)BuD&zu| z=C_x~YqSe=LTs2$)UEpggPeP!>;4QEA&J8LN>N|x`-xAdoroJS-~nY-Ifq(lg2 z?Uqey46#Em$!Q=5wMR7lRey5CbIvp?dxzknh8_3b&@5HYSJ*+BH_gxZPFs5KI<@Nz z-?OD~rxX;hd273SVGTyW{bA9Dfa2!?(>&Kz`vo)qVCJKloW+)MNC%7AWye_fMzKZR zCK~tF3MVRXD>p?(W&xhrV#R&^;Wz;_=<=|odk}Z!sLkgopE)_4Kx{?6fz+JBIl^g8 zId+f&hbYG9 zTTa;1&M&!wTw*p8P5l-|MR(=@$|MK~S`6UzvqD3&rv;>yE&CNGur~y{w~$c}cGyG7 zj zb%EqcQm=vGmwBD*3UW8K`@qnhxm)g0?{0@a+&`u&RWA+usE}bQ7u{sUZt^&D-r(%z zGoVl-N9MwJ-_uZKUksGXt@Ywtu^Pzcrnyh#i{-{u1GP?YT-jhTi??)=z4^4L zMUP6oGf)>mDtua6& z!Il7C+8w(7^u$A#qEM?0lY&{6g{EyJ=84hKhO*3VvYeG-r!R14Ckt@-Q36YU%iq+Q zalpM{R-9aCF(ZpygTt!fdVcR+TUDBacRMHSON?g>dZ&j{E-g!FxMSWZt*!o%?n1a} zHaZ1L#b~@#Te+DDK4x2>ta2)UVlVj2ZC%CXguFlQ0KzLmwUAC$A_LZw2I-!94BGX_ zPmU|^RoNX7D}Mu)k(|#7JqUsu_wgr98Ft$ltlex0Ne4N-37w#sCg(!^kMbgXD^BgQ z$cDMG-==YQbGy14iV>1)W{Rvs!C&~oa}6wYBhNcQ4hd;H{1jM|-p=i8;X}JUN^o)c zQrE|GT(d)zF}bh9$l>1{aC&X?2TD;Q7-a=umccG;)>=Suhql!JqN+zH=kX zxUZWr#LxGFe^Z6OpAL@?AmoCSg@h`5UfAauHUvo!G5!bA*cw}h6e!muWz6OWKVdoO zXHhqrEhqn+#KlI&{}ssj;dC5k3F)Kvha6w0e3X!VK~E<*T{~lQ`Fe+e4Ci-%OACn< zQIo+h*M&8@lHAiZmZP}o@Q>CGSE^|^wXnCzNg z%;EeE?=8mO^HI!+Jm+w8_uoM3(QZBW8rU6rX=?0 z*FDI1jm`B=!r0H3KUqAumpp2Toh&W8!rlEoabIf`FMI-^&zw$di&9L>(_Q|a$-*v% zHmbtE!K21jVan@*)=&vn#+^snfy-7sY_`(}cLja*^dGuy$V`|fd^rDf_tz94cZ-Or z^^Q~mS*)HD*WD4*0*yrmNJ`a^UlWY2!XyUXw4!F~i+$0UJ1;z%UzE_ksQIa$0pV## z%X0!B-BOoSCe=A18fUuUkv5{eV`^10PUo%sQ!oaSc7x&KYPG3 z(*LijslrFb{}KNDKQki#RxzzeKSl6LG&nGa&T`WMGJw)?8G*sl@BcwVZ*j4JXrABd z+}sAd>o)(hk8FhcAHZBZBCQ?$V*DQr9^hyG-^LUFKP~sDe<>bTVF?v3)(QnsJD{{g zY_Bet_phn&-v}Q`0zhaOueY}aS1Zy9S=p}jSOer>(YSYKiU80DE)#jeq6J{W)g$Hl z>{yn6!>oTjX3darSt+jiOU>6HzyI>)!T{jGY=GPeV3z4+5~5in8TiHE-PkV*Ay^(c zAx5W6kZ_`smhN_+(JqCGfXpII+vwNe=D#`ksJ$z$5uIv39B zFT#|CfFvcElMyEo%JdIX>%+|{^Mj(%pUeJ!6;_tsn$CT*_90GrSXCwy&uiT+>93Zb zSw%#&u8?MKPZVJhS3iC9e7zILPhi4(nZiDA5&>~(Z0MzLjgXp29JMo<`q@gsY;-j7 zYU*`nZzd1H--0W(&5q6Syl-h z;#6)B&zETs50#aNxF(!xuUEH_br)EzBhkn(4J^@`Jv@N<9SVuK=E)}^(Hz5 z^OT9=bNK00x&O9c$D#V#w><3^vc46iay0fG&(4s0)G}6IY7mf)u9-9_Kc2dHQcD1MErfFp=2 z_?(9Q+y!dbnfKCf|I(_Jq@qO>v8_w%n3o5*vn#owuynG+Sh3=H zN>|Z_6`(QKMOiX}Ww*cTDu`ezLSiP`sD-}4$jGlk6m`9+&M;xbL>jqPzceX8~5P5!9pEMypX6r0G3 z(@zWAMs%ba3+7Flih21!F!X+~o&7m5v$takjwTUPqNPF^^FUI_2n_~U6jlb@bFje> z%f2lSmi0n9#dx8td-9v+87#jZZOzqUgB`F~&$VffCi}>N4Z(T~p3D&mm=VtsL{kit z+PGFU35C}ZyhtApNQPS@FFuS3(N|hZOndBQn}sV6>ci4vG-Bz;pBwSIhrGpOT;n) znrmbFwza7&<#sHHR#eLIUszi9{V1u~ha)UXbszlJhOX6GkZd&RA-+$JeN{U{STrj$ zO@Uf*#I}7qNo_X9n4Ue;C5qK_1QUkdtAIA;cl1N?I+`VWmTV> znR60k=Za3?@pJT0ak8Wr%pOQBp~2(ve3Gc%%2AG58_w}%T5~ckGnSh7Ss{XSS!gyc40nb zy(M8InU#d0D`|*&#)6Mz&&)k)do8(`9@^lS012uXvTZkG{|uZkn(B!GU*&GV zwuVMf?=kFsl;yfkPFlz#RRqm^>lJSZmaO*l>I6ehn3v{fYW{ERsOEB329J3j#SiP< zpVPD|HD^9e*o?zsZVWD#qk+&iYzchZCw(Ld@Ta!cAbfVz9Ar4`^rqT62LmS5)7{If z`MFuMK2dFxFIG(Ir}vb|T`RiB1k@ zSaEO8#|f5*$Htk)R_hx%9@OtQDA$h~=JnVT#^e$seFB#g=lJCY zmys$(`?&!?57)`zj`?0~+Cy7$VvQ>NDvEGhwyP=mY72irNo4-`Fz;ioKRlw`o%Z>U z3PbTXcLZtaW(}TLJfR$+?LL1yI7ZVb5%K!##e~o2Y+dN zQjTrk_>IHw^k4YV2p)iNf$FYjWELsX%BKG5KpC;4xW~6U&ym#~$grJrym`zIJq&^m zisr+LMJ~rrQvEPnnnx{M9U`0chcYl}XgPnX`MvNjF^wVWJAOjHa(1mi4{QO-cLnED z;5*J1=e)c!Q`#X$koOhPeypg-c;_q9k;4l$+`3yol_&DM%Y6IzgY8{froG&)8@)-N zJh9h0E2B(^Zz-+Z=KhJn2HT2$jU%(TPSbI`H_pKg=CLGobb8a+M``kf{)BFZB6G)- zvLz094~u4f>ZZoUZmmzT$ZrQU`Jsp0NWL}oCo^0_i`*Tc(f4F!GG=cp*TFoLr2_Vg zMfg=T2(gmxIV-~o8aoq>l;@xX?k8MlkSo5=x_doj=ZmvHm#z7qy^PLwR|A$t9Tz;f zTyB^BgK8nAoplimtMj}l)L;g8xe31=HD~lP+o@PHK}%nNOFq+8pIb2*W3qdZTH=S+ zewKsUgT&+~BIw7AWo!x<+E<6X*GCtNcpEGCr<><|2nvSvhs6mZD|qGH@aDsU9{Bs6 zAojRLHRRg%LT%R^OUzjiXVh6=og-=R%-QCbx?u?L@SP-q*K4kl`oLam`$mp5XBi_% zY0UHr#!Pje=)i9d>s4zN{=Fwpu68s5$u2~n7NuZ zXEANx95F%p#>~TZS-I?}vZu>tul?_6vs|W2&$4~kVr=Ibd=CDCm5$pg-;Tqk{h`yj z{XzTDDh|DXeT#F5X#=ZW(n$TiABed)_9DFepLeJp4nBNw?f@Q2CH_Ih_hF`v6ZcG` z&6AM}Z;$Bh7RZXWqb2pDsmMzjBI&0G7sf8XLExo01`plJO&ofbL1RtHS)RlOY>4#i zeWidoR}RB~BLB_Dj?Rotp360kj~!7jtZ6|;OB>~8 zG$x2E&{sP&cbfk_iv7r1v`eVVE=jb9_|d}#JHMY`!+?1`#s<2q$K@_q&+T#*=ieM} zITJAUPnS*Bd%OV3hg}IfuvNW-$SVzFNT5BWoC+RDq_?pcU3+r`ubTLXL zr-sJaH8bwln9u!X3G05dcy;Ma$rWvWi7R=)>+W5ee@0ZbhW9DiB?xbmY4h~tC1b;} zAXy4_!ST9}$D&A2<>f=OsU#v>ZX#VuGmvYv;6$dqqBsHG1Z@e{CrguWl6uJ{}odek&s{lw-4$s5!xCa)LU#z@~vMOW@!oC6>sQ@W2W z=Z6dFqsn7kyIqxIZo?q%*PfnyR_8~vOoB#rvyArup_;{&{myY-Id7LG;qP<}F?Wm> zGx^(;-1bjSewmrvl^-4D?X@V5*0tLpdH$n(=jaO{w)6A%+fB9?M*f3O>jCYGYtg-H zW1gxVH48#hj;tHLXL(XXZp<-vACz8KA2<46-!n^lfMd9K6H0G#^+d+VLi4%!M3+6{ zz~iT^@ImabmhUo|)p^f0LVxvPhWJgh-EZ3AL=OQOtA0uR)Wp7sa?_WtPC?gAHV~%E zZ`OxKx?T7=EfwL*Wg^>pwRMAVdqu9WoawP4CiFSuCG9@O4`PSADmC6pc7}Ur(6SwE zg2?h72-R9o#jj4K?V*6w(w#**s?!r+r~bjS=1Hc|lI{Tc#e=G57JqIiU2hF;nT)r3 zp$YYzOz`Fbmg3er)*W~31E(FFsXaCp@+u2XR}&%05S7$Ol%wYE9KXul~5|W}8S`+n?hy#Rl34Rw)7bm~GA-CZu zZtu_N`hYRwaYvNaqw4pYOD{v5^RT=)X$(3EMnB*j)VWNPw8mOva$7`1rD}Xs8BE+* zNvFbkE#Q8TN#Azji7PIg`sSQ0%Q^$1=$+pkz)MU%_KW5Y9uj=+U59%h(5DPi-O+FQ zWhUt8`TJ4Md-n~6YCkGH9m7`Wbk1e9;5>tOyAXN%k3tbtdQC~)0n&sD!&*5rP|iF0 z+$cb`Ex?~9CyMU#jJmHZ^NxWfOZt(-#z68=a)Ryb{=8lNCzkIQ6yj;~OmEt+o<&7K!Du3hC;5o@Ny41WaOoazPdzZHZnW&ah z8cgq7JB9}`p{E5qOH>SLD3G15#}I0IGtHiTVd7aU1a5*H@`rcxR1j??mu7o&mTLPwZAZ?nAjdYXU`GcT=vkZn#$BUe z!TC$1rt7tpjI*3zF_q+y<8)!=hHO*io-FUK!z?28tZTcpf8zmK5Tjjv3)Z&1zkp9X z;ipP(T3%#g6wLw4<*O_dovTxDM1QWgk*dyL;th9aQ~D#j>*3H;fQZa7G_5WvM$hQ;vlxH6uWSikV-pzXOsPEm z%+6Oj(*5Lp&L4f#wn$W;r0lo85Y(FsRbQ?($NYjR+uX}9Xp3+?W-ax-ZJ5P;<^^== z?flf|f`^T^W9CYehjcDlEfd%2`4gU2ob6=?Kf$}-RcB`-=WTU@RD=EqyrHqsEGoEK zWYv#}c|9D*(e84mWAtlTDb!hIs9Trmnbi?9ym5wY87856L!9$rCU|J7Px&dytMt|s(Bj{WS5gvpQ!H{; zw(`^Q*LpMkv)A}J40$#gBBNsH3T54Bev%nS{CQD#mp|CLH?e6;nDkwrlGL&ME|h`v z9d6aTur({5th&@HH3}hqI!?>+NZzINiF++dK1FXlmbsWAyG06PY*}0D1$-+hhuxPm z6?~!%-w!kxmrMxI__ffXsUcFo~S{FcN;n=JA3q?go{vzR>AV1VY zsE{yA+mtIb5(FEQWn|r-A8zd}6A8#bi z3z%ACfE9p&H13x$rz4)r7xO#WIMstW7*Zg}pf+*QGWo{DOr$^s7~!C3+Dt4m2Q3f?J#P7Woq*w%_9$T_CWxx*kDH89Q|(hCXUXfzC!f!rs76T z|AQ07%8XM_nL}wZd0pfQI0ctVo90HvKf0(g)wZ%1*0;`(juGNnA+zu-9(o+>wH^^JSY<16O`Np1F5 z8~^T;b3I+>DVJZr%uuQvt58{46_?hVJ+l==iw_^G4YBiA=>%)?g0zGhWi=Ok-nd8< zpeBP0&hV$GJQfP1Tyt=qI73=fHh;UDHq;Ikn4C~d>Ir0S-ktU_E*gJcnESH@ALRBy zHIl4FcZX`?MuE3)%FjiP;rYfMc2(<1Jy)YkbqN^m;G7$5o4>Nf$cb7qt&wKnHvbx0 zuH@#ih5u<_k-)?Y-^6yEk#{jt!-4wZb?FgY>8$=u;=L*P14`W%#k3J3MgQD-6$R^< z|EIVs4`(yo;!&!jQ_NIN)6#M89kkTiM3gG+l&Z#3Bz9F4CDan3s4_ak6q(vuT8dIz ziP(ckXceu!A|euru>@&FMIyD7`Fdyc&foWW?sLyy-}`;%yyy3x?Vt0!=ZmzG@?Y!h z%fdt#=U4K{TG>c>SDDMQnj?EGoYC_qyIalXSVPtsiZKDgQr;DohDD3W|6W&huhkjq zEH07qmb#<7a4XF5Uhk<0ROfRV(xZ*3WciN$R#1gP2$WcQ*!WOY&UO;Ad~(C;7b?1+ zNEC1$2G#i(6}}9#m~_u?va++}Ys^VhZyq|LspmqS;=AJ>;fl=BbGL(@}m<85K*jI;w2^VmiW~M(|26oOt81UVqTpy1l%suW9j0 z{k&61#5gsaX;_!y8?XD?|7?lmPFAlLoeSgYH;yC_(IuV&A~gv4X{A1PDN>~NAba_t zuTj;@15pVu6whuYNw$I;dH-Zzj9<&Z_qTdvzR6EiR5&Ap>Xdtj@TS&uPyE)3RgaAz z9A##FcedKD?>uhv%~b;?i)^zFqx%|FJV2j~te_gXmP%vtV`ZHWTO>sUW-bjLl;7)q z2og>LO(p&w;h|eCTzRptC$+ta&)<(8slocXg3Pf(2;~5L8sWXsUy-PyJ8)v0-(o@# z;u^czL-{Dn0@ApXdrPO2iT1#226OgJATwZArSwQ8n-|kGtk}Id#P)VNNZGodkbVE? z6ET(Tt?vEa(dV`W$i|DP;B#W_kyxtu5}|$&mrg-?yOz{oh zjTN`pKDd%?v-JhRac{xa*an z${)<%FX_D)nu*DouxG|gE@*!Yztcu_`gVBv!)+T9ycnnP7#)-zE=^T-m?rr$J!(rH3fum;_Xh|N2F%|Tf~AeejQLw4X}DMV zN+P~FDiDTlv|Um-%!mO0a?k%FXVsh}bz!uGhOUzT^kPw)?e`&CtiwqN#MnlcqhyR_ z2oVqFTpJ9b(v)azQH0#gb|k)?d|~h2okD@Ywcq(}fPYJ&_`Yp(6_uUqgL`!LSSQUV z&w%@`Q9_)M+joDNSY1dm6kJ~*no3e9Ra^-W!5ugEI)l9AdkWXKS)Tm1hhXQMzb&^{ zCyUnQgKT@_NHhwHDAl~rf8XoMNF_RQmlFm>uPlCVwfv!5-$kR{z zyt*)WW%-GATw3huV-W_`PFZ2AAci=&r)|k=7Sz*@Ujm;9KEWfYlS&Y}M3;uBbOXvO znv6`1l3&s!nz{&ziUqU;8P<|4yX3XxNdh>~8nvGLSwl88o)8B`>_~t;Bo`sFnZXA- zYww2or`6WhGfHw!QzDILofs;9kqur6`QB+{X99e%d0}eB?bp`RDENbopAqXmJ_~BZ z3u9k{x=UqEwoId<&;xJ&iCym)@GJOKV7xy2GmjYjd(B;aP0hoC!86N?YmE6DV^xnh zfuLdxr)KR;J;u?uP9xntpxnK(YbcM37H%S7!xJD7$j!WICdnr^16MVB-I*D2Y@)#q zel@p*D>vt&$i4moGi6losF3fDPc|g_1z40CN`OH6ibQp#W~=rbByKDYVnde(&CsL| zH>c|ZqbbHi8wnn#{G@O6W=Twj_P8a$I)q`qWe&!5SA#dk_Fl@xWAJUy=T~P2RK!5d zygc)(qtkJ$(oC759o-gq<2w5!;!w?ZJVGy3B^UCzvP}$tI3*c+LGmW>@F%@|dr4gX zTMhu^FWLfrAM}~;-}IH7#NSvYep1-|5U+E7N^*Dc56l0Vi0+FevR95=QYCr2na}6s zWPX8m^A>QWbYr2|=0UbTEl+-=oY#CWH5GdN3&XjQ2PYjbD#DK-r&J9$&Ty1>;esxO zwUECL)$l>smpn0`RQ30}LPMub(GNXrZ0<)avvBZiEq{8Q&t*$X=wT^4N5`_nL`e(= z^QeAzhYqm3k`g{IPjPO3KDWL*tEmYF%+G~ONlCf1hF5rbdk>gxXh0urqxnp`z^6@0{_>zRY@&Bx2bEWl!0EFwdY>#EKc{+In7DNgWySvi@S* z8Pn+K*5s6wfj8dWFYfNcOuv${utOlSzSD9mXENQ;x>h+l=N;Z>& z2k~cb>FImu9Iq@ZGuPA8GYpxEH@N}HYHc+H+J}EpDq2%h6VL}ae&2#bB7Now2nZOZ zP~@^AgiJUoCu`>{~)G*vwW0@!CVoDxZ;%m~Va0>O>VwI#zyp4%1rQz#UglexQR z$7v|bYtQ`P6Uy2WgE}^*8nxWy9~5M7HQtYiFO?-<1gEb__hT(5-Wtrn2r>WI%%^pk`)f zk5Z)7jPG10?B8{Ie67Dxw?t7<5uoJxufKk!r`LEw%|BVyDp~ii!brI|p#9OK(y=j^ zJNZ2#FtEx2=ThPtOrp94UNJB*_)m!F$Y2RM9XJB(IkM70O-;=L=9=3|)IJG;47de4 zk<&Y{%2v4#D=1~{X??;*z~M*);#opMf+ssRv!DPk5QL*o?Vbs2K0={9C@2WF{yq~x zhPZO2u&C%?U0q!j#hp(%oUb3lG%0T3S%@f4`QZse&&ydX1Rci1@p(xev#H_TmLZDBq z4ud%WsZvLu7-il*Pp8{sC|04Ify5;RY38Moxjt(>SU%FrE5XiAQg&n)G$<7*r)oJ2 zbegH7qeVPkAAoZ8@mQmj0K4zz?ZN!B_>{v8A!*s?jaSQ?yf6OKQC;5y!{LGqfhzRu znHsIF6idf^&3qjrvO>Kxb8j23ZfH0JWWXUgIov(D_SzE67lmYb66t2F5P5%sp%FZ1p>sK)`1-Yl6jO)FR8A^k5bUiS~OZ1agyWpMch;E)G52SZ`rni@0GiH z;v6%N_n@X<-Q#!_ui^ey!*rk=ja`$0{_oZ8zo?-rJ6g81gz&uHA3q=6!pz#V`p0Vt Fe*g;H4qgBN literal 0 HcmV?d00001 diff --git a/infra/s3/policy.png b/infra/s3/policy.png new file mode 100644 index 0000000000000000000000000000000000000000..418f117e3c42294ba269f6d0b19d5685ce56d648 GIT binary patch literal 70784 zcmaI82RxhI`#iA`HA zB}R=1VpQ$KDqm9e2N3o|z}6B82) z;Ql>RCZRG{;e+t=>=PZC5eO& zkWR|M&K!Bkv+UQ{eihrBXK==)lIO4FrDUu8=Z%}UjK82P6)jHu&kIcDm&CQt{QH~f z@%1N;=Z-I!wExt-Z*M!Th@Dm996l|P5Od?Yu%-a+ zGdDVjy++8^?AgTxLRbi<;=(Z@<9E*B%HNzg&FV!N<^?qb7hk-{{LijZfT4hez43E{ zROuAGJK3nc=#tT`x}s73SY(ⅈaL3%^ua>!)%mL$)FFev+>W?_9ML?Tq~q{eNyO) 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%0DT!&F0W{qL94P3w zg0C^Xp>Do-HMUQA9y#RAEADJ`ap}rwrPY`6F zBh`GF_?iE$3Vek#&?MYspC3EKW@}xwXD`Ek4N#q)&fFR?$ihW4EyZPogLB@#R*JHfHmE^Um~NOilKHW444*cV&QD7=)i# z6vexx>h2`4n)R@S274Upa7(>zwG|JU;S5jD6p^XRmR%&w>ex?}JHBDQLPcXCQRcc* zHf}qSImo~`oW8UMwOgFGt)2M!uS`jCnk*ZtQ$e5R*;l`&739zkk)@Kksv!a&2B~#d zlJ6dZ13xy_M#a>o3*tvO&t=dW!bP9#X~{Vlu4c@q8$sSmsT1%Yk-?Xkp9xR)J2qZ& z+0Z}B_}2XoX#%HAkEGUduvdv>6AWrPI$RBcko+7AO=|VJhe6|tM_UsQE^E)-8Jbv| ze#qtQ3mC7kNrgr&;^Q=N1gyaV2}Xq@_WUls=W5X%g=Z*D4oHJNr5+=kL@9M;=AEWM%M1q@}qv8UHPa}SpxqPgzqINRV0&EiLm zpVD7TYD-JclU+^OUmhljk=y zLs6B7_(nD`D~rb=O5yZP$?wX}46eto7R1wd#_y8~rIiz@l+Bsy5waaleY@K4Tsu#B zt6j8uBU0V?2W%sIJ{`jsqHmaa$xP22q$U%Qp@}b(gHsb-$p^{OZ#B?RaonX}x&NsF zJj%pQyEgGG!mB2A1uDwm`JT4YU~aT-_3Qawy(4j_0kQH8+)h?Z_lV|yw8vRT%YrsJq>Q!xvz|OX}x<^Uyp~4AaAWAT?^h1 zjXmc32EeNcd_%F^pm~kjzE*|-Ei*dgu0^z66@1UxUwpCz+xHI$d7zeE8Yb_~R%#?d zM~k?>QY%{EEdT%I;rJu6&J$hv^g!rj2L-ElupB>D;GWONHs`fzqqCKBJ$Xi@Mvu~wcNfsZKgmc43JV1&(DFVJ zoi3Zn)#tpu5n#E(C)iOLr=;oDeFw@CU`ZB4@2<4CriYzpS~@eB0A6N}`cpa(P&tOr zyr8n))$Chf+!FHKG=yxdhxV9>n8yx{G=2CDK~5@j4dsR~?_^{;1cK=1Yf>oZNLSL^ zhtxC+Xfw||jYC@cTj)zFR>VY#W)|Nr5>`ytyFKn2#_iQCfJ=No2-P5N2gy({L^IY2aMP$e8eis z^Cu?rF%M~G>gFq()TU?%o;-Bsvj{``2;-xDJuh&jRFvaVPB10>@SS@qU0 z^8{WQ%=TzC283H`sKj!HxPhXUm#}>TV-c>fGGE+&Y&u+F`*q2y9M+RZKKg(zIp?@oVSxIsWwt{`Nq6qQlw4Cr|em;_47S>ZC1N7RC~@%6<_UHdv0D=ND|~0a zC9T7$0<&{D6XctReW*6LzvcbRK^<9p!IjSGI<9fn)Ym7CQ6jwzRpfR|_IY4#?vrx9 zvxW+zn)iH@T;Iyo`TSokdfkjbtqGpz-|Jv{sG4@}Df+y&w18RrP1i$G3gJG@`tu#x zp7i)PH#HkjXio!e0L38(y^Z^m-qs;n5{jUMPHpp&J)EnzbNMpxzf?Y5_+_`rnFV zk4_V&cFu0McIoi~N$Lw#rz-iHIW8+~Ow9l*OAEG#n;WKz51G+M)n|l5-`6(~I65orUd)kC z@L7PHv`KoZ0#;L+yk-SzC*6_0uUutp#NTJiapa>l2&q2s1umk}OkYU(I|=gtVua9% zi0x<8H0me*5qbT1nt)NR4u7P$XD@>p>_RE{vxT=b*ZFh|c3)#54Z^z^C$p*H=i#R7 z1`<+r>(}zC>8ykOwO{IwbrM_Lb2B9mE64I5(EJcqbt;cJ8 z%lwyAHY)#xYa}{;0eoGeCI!8tgAckazlAg^{V&}9e~6J^Te1)ntQ?hgW+h8y`&WFp zf=ryuehJ$PiKb^|p*x(BZp$3Bea_`0kXfhm40D@I_UZ?I$DnraqD5`E&y%!$l?K-6 zqmX`PUiA-cZ}f*`9b9$7(SBF|nengkI$S#5C`j49fh#2STceCyDI#}%lnqXmyYLh= zVR!Q__hyJo5Uzbe$08KGhFjt(6w5~MO7nX1_3BM%PaqLEJFzZ6H&vlcu~@ z$G)ujL9d5^Gaa&Y0tcn^KVE{_;&&t;47BV(?|-HdIh6y@hhV=`0v zr}c-(yO{w$YeMwWe*w1U)Klh~_bRK}W?VoQul=uiO<~P*7pglLlPP6t#_Y4uMe%T$ zlMV1#nowGVf*9>jhuiIV(?cyOVKKO!}+T@;mzbv~*klRy4x@~~~ zf=yV}H>;a|k{Xc!%-qj&gW5zCX9nJttb^?yzfq}CQRYmvYm??EvyG*~-dK-}y;*nT z^H!BO&RB>m$qaEFdX_+KAtL5DoxLZhi~RN(a$%458zW49M0JmMnyo`HNKB9>VP-eO z-p4daoP=+$^eW)>(XyEffxPTu?cTK>slw7f(y~n~pBHN(g@spy(PEr0stz#nC3EKnJ5i7f86I=TBgzUG97X zEPjhbCJR)bZI@^zmbl`M<~CHVidOR;?z$R!UD|&={Ortn%8Ws&_+AXSFexwv`?J_n zh1P^L$3=XeWWYU(7paF8Y7H*~1kv-$j-$Ltf2>4q64(^2b zdK1u3F62vMNRU$VGrxjwIS^*mTYUdvd2MvDo#|#ncG)qquigj=HKmMRQN0 zMRvVD>wKg8L$5)<9#=8S8-jy_*IDcNxMjf)qu!INro+l1?@G`jjQ+ZS6Dxx%(Dw4_ z*Te*T?q&S0*@VYqEWT0HSsm7=#$R?7J;RxJha`q1VBV@?_wPD#i_&e3T;4x#0nlM= zQTy9o@mN_|KQ=v5y(A&vPcP4lr$57KtCb?B2q&ie%+Jci4`M)D@A`xO!#5A@M`pLC zC^Y)6mERpPw+Aj*>3U7R*c{CE*d7g>(%Tqp2kpGC6(R{MCaA1_h+-Q{!^i@Oaky-^$jI=@_As%E3$Th%=*#iZb!(07B8PN7=S)_Xqlq|xi2T|<6xWptvcB++r8 zDe>T33_g4$^yOP{e@R1Mam0U=u_t$<1CwQ;AvvsYouJAK#v~!RV4}P53Q)5)f3)KZ z$wYcBYm5RR4hLQy6VR zbC-bCUBSaJt@--5x00azf0Aw|iF4m2*cgzdJCA2e3J>_Bde7L969PySN1hq4kd$Ah zEO+Q`g8t-@@y(-s+3F2t#b)0y1Et-~M1VemC_X^6-^zs_{RFAp*!e?dx_=I{QH%d( z<^hSk0@Y8`wkgfOW>fs98lzZPHEZ{u(|H=x*MeT1++ETucNza#zWT2!zTyli-6%7Z zAe+&mG3I;n>wSoSjw<9FhWe*XsOXP*UXs?VS9WXuVS1kZD*g|FOZ>M}AnFa_sGj%K z2mU=Qqj`{+kpzhubw|-{X?aC3mbMt;$p1{W1XsOkP0$sfYM0i!W9x2tu`-=t?oZnP z2hS^^jr7~>0=B9oO~T|;f8>RNtK|Q0021#!DTPUexdrX>gZ?mR!!%gI^+>TWob@}rCL?}uu zTBT#`j(E~;U~G*cl48qvdi;>39zy;0$`&fFdH)qDkS1Be!YZl!3+5a?HjbBn7#eo3 zn*{-?^{z}a5ThVf$G&; zii`%lw`EqOaG5;DNxK*UG9J2R&GR6X5bO=|HX@7$nY^^g z>lqFT?;V}eJrIKf*3G8oUm>wxS64W#C_`#E2Togq6B!L@#0)pZq&Tb>R)u33N*heW zrDPiAVo7p2F%kdETL*@F*^>4mgUGOO3Z*^@ik^sKdM3+ixiXV>3uand9hq3`f=Z+6 zxN=uV(awavyyhb94+arMCKpBE`x!H`$4eVA^TVQ!TGeh?v?b2g@kya4y(|@^CAR{( z=(+}|nmz8uqG(1+6+9e%Yjx2QOF}VM`3}$BKq5scvNwFIeD8p4z{8r`xCW{pjyjWZ z!aE6`9&}ck$eKNwvb?a%U|aZWd4a#p&o4W*_7#Lh`6?Li=X%iHKI$HAa4Dv3-*jbZ zebyNg3@+qOg*jsvpd$G(!T7b1+Oft<0dBoE^vLe#Gx8TZ@oRf0oM~B+G`II}j~+JN zmm+X(E`LLJr{DStGgm6>rR9T`5jovJp{mORvKY0E3Q1b%q5~oSV!HInLOaGbl~h8$ z9j=I#L2s8<^wmYgQ+R^r*Ai^&+4h1@B#eab)-ei-t_SKF;-XRsr8A;`{AkJQV0GTR z9Ck4F@F(!@7FYr0+Iik#+<)7MGvgL`!E5WCDe^WZVcx;^`EJcM&Nfx+515K{i|upT z=G7ii3@ho@T2IOuzMf_=BtDI>tg&KrrRWe53O|ZCfN^(pCl3C_dR;O z8l3qA1nJ^W54Zf#-$3BN_?BQ;Ea8eQMB);U0X&(|^{UhalM5h@xh)pAC2aG|aE(AV zRT#=Q|EGvW&~zL|ux0v;)KoablH`tkmoMVQGuHNH7#)15UjLv9$tj&*S~;?D$Ig#g zifl7g9K5ShtmoJD5>8=9e^ycwsU$uwG1F0!`zI_oo!wSfl!~Qn(ODeVeeS+@w{%US=G^HQwZi#)Q+> z*RYnM@s^DW0t^@$|BZn9G$o)<*Hd_6Jyz5nleYB9OyucIzDeW@lM73or+lHGR|Pvz zj}O6eoyWE_$pkp)m#VKwmHFLxsf%8d^1r>GnNT;F`~;C&9p_z*Bq1NYYjC4SgNiC% z;3r}|`Wv-h1zNt)6C*rKlVk-v7$@fTJOh93HdXaFL+Q+<`eNMw@=b~`baL@efj>jW zON!34X2&)Ww>&|DQ#w5WB1w4~eKc7Zl_=;&FDsX0zm@!<{P#Rb!NZxyUcx*4_=m$ZDmVjz>sM z%htBur02m+EXI$sba0U&anF^t9d@h+<^+&FU-NUdmWU)(RHz5oeaEDJCD3?v@^p9v z+m@sIaS$@u(nYfr*ql-C6-iY-eYvb#es10dlM+f0@YH-?7eP5^cR;SaiqT|&5rSb! zAYWflp^WNA;bB?bu{I?z{)O3_;P@9GT>QD2?Vo6Y>YlEln2m{;rzkqszPM4IsL;dM z(`jn~^xt?wP#785>YYBKkU^Rz0T(wG$A@uIy!QBLU9y_btEbzOv7cFy3;Ha*T3q5U z+pK&RL8UD>t01;KO?B@=)uTt#@V(!;@E4#scwFM@utwD$t`pJBk4eaAd_Wb^42+M* zqF8Gdh}dd0-tRA6%6?`iaO*J>wBFw!OtjP@9^3+azFa$)UuRSbvROI`=6wFbe4g>w zFj+#zYqeZQg=H$@qT81O5k4BMA%#U(czBMPe*J0?PMaKmMYV}Zq@jl;Px26njTGSqJL?!W`S zKm_3&)vQ!5jqW(}ou6QLG!UfHk{aR*ZgDOv&rz->W_e7EZ}q&aHrI7UMcngOjC877 z{9Y3`^>>ie1shD4yqRyt4f?EB^K77MM4G!7$b)QKE8fxQf#H+_vNf1_h z%*Q$-E#evUJdhbDg1!4pCrZiM`MDnUDXmu?;GN|8^#PC{*)!x99W@2oM&ctKrqSZ*`7AZA1qm>&gZ1>!o-=k`4DH_dnjOf>dru zTY8@8tFR4ied%ozIy);}hZ}Ws8z)2{4yD`KbV30*aY{#Zs*1}bIuf}OKt~#5N-2s5 zCrqqxX$TK%q}$scrHi{#Q`o)tSRiBo4YeorT%cavlfv{uM@rZ2af{df9Qu59nDJAS zHoCBCHrhOm2eg1UA#)q+Po5&JLE~cxm|rl~iZxxpH)?Unz2%9jkfFdW_+x~ho4eP; zWg5oE$oUviEw7QaXSiVlRS3ka<+nX|n-o>jJX3)=CmUBj*F?w-U=v~-Zcp3ZJ#Z*V z?(gyu=?%95Z1`@2v^sudAQ{%+ryB~=?uYKiVBOv6nYq!ny>IWpo^J&fBSF)e3vMOi zh0~#eDc4Usc9L1x}n_cWZu5}&)m6mxm4W3 zPOiO-L`)ymQ%4cO2~Dp*W6O|PS9Wp2*%w?omS3_l?@APu^13WqJ!T!XR~X3Cop-JyBd_@{Uf-B|H~p$%T>PinzpJvQf;4pO9`4Y$1PCk9+3Oj5x0xLsN^jP>2EXspN16by5{l#&v!x09^VXe59B5xn=rNFTK*jBZ~CW zI{Ce9aCTG*37Y7-88L%I{Fm_?!rZ0kLq@^vjL1PEa{Nk~%+McBOy{j6JfxFQjT@eU znB4`m2OtC%mvEN_& z<__qdcNMi7?svClIlvRK)j0p1_6*Z27;Ym0^E6~#=kvjgsSVFXC*gKPw+aYZ5zT}0nG3Gg z)>92=v>!S!pP6EMn;O|3vGLelmM5+9l1Qa5!z9x~?0|*~VRl%#txkz3>lt`TZ-koD zwZBx7_PCNda!)ViM0xACXa!v-a^m1P>^uu-Wd%7!F4BoS-{mwU~IP`-I==tRu=%wZ1SeW!Eot)yrL>QM!1w`XNt zO|64_y!zyU+B7+eOb?Z|KE7Uc4I*HYVu+t6sn9zwUy&E^&M$p0Z)V+Z2lkR$*g4WU z96|r+_c;e}R;A_)XeovH97DM@o1`*vyga*E zyR~;*rb0_1Ct~kUWCm0Vh!0 z)_t87HcUi7MHr*;_)BB#7uQz(3kqtztf=lLq0*9{P$O^%3p5QdMaxdn-o;`GrIezl zgr}yD-{_OH-JKBn_W-Cq)mvCZwIK2~ZrFr(R@anhh0+&TD$efne871V$qc$G(^%3B za8>uWpUO5EJ^MM|Uvio*eaCQ4&OMl}Z4PB=QB3qk=g-a3`bOwJV)#6RVcwC`XHwF2 zQ+D<%>$gmo4VWGWSf&lbEvs(5=P%TokDA&hrQeoCMWp$xAi;Y?CM$VH?_TuWCQ1wS z9#m)_HL+~2(f`%>jEL5M$$X(PWzl3YHYa`!VC;jP>hht3-l$SUvB2l@Co?k+Q$F-< zf-cA4I^VUFynDvzkO1_hjjg;^eljR&*n|6zvCSmJ1-L;$l`EffCYF9SrIy(vNMT=I zQb*+r?z`g^;Cs&olv)Rg2MiR>HRKQ;d3tuASA%8FclIp6$;`evDakXXEVFsqZ7`kAQ4* zk@o(?AE{ML4aI(=^^b1arygb?mMt3r!8(y5GbW-|Y2Lz;lfOXTxINe}l%u?d)&0Bs z7FD?^=WpB!bmU}pSAyc1Ckr!p-RzRJ2rConlI8SORF`Y@_A^WmYbrG-%Be16U+Y&c@(gbI`JblkO22I)IBAUa52pyHo3lMKN?A^fWHw(z(zf z>9WYtf0zZ4oH;QNTHzU=e~wBZ;?WJ5;M}g64QG6JadbR);Zko%4e+wUYA+D@P2=ut zqJ(-bG&zmEESAA1`zjn2Z)8-+fOo?5>JfHK`n*j_Xa&@G_a~F(nzSR&-RF5(An@)p zpeS8?e0E=ke(eN7>j4&J?xb73qs6W~6r|yK1XpsJLO4ODYz$tLej+P^GtJJ6RlQ z{YqD{Cyl_zTiez5YE+WSL+3x3LL8E#J4Hg$`UQ`6#Yt8L-?rd4eHvAj<9ic+9oDl~ z^0^U96^$v+`@TA3r)@I(V4JYIBjGDvlX3B;wMydp;>}-cY2PDY`*gHiK~lG4Fz2_9 zph?pOmmVL0W_qU%o~YikxYJgCPCm3o{49&^n45eICqt$Q>6s@*_b16aA`lWvvA;*< zasiP}tBDmIBw$e6OR;L4&n|#0?5YZB|9^I^biorbljs2dmXOPZG933C7~XvA40}4WGb>qoecftk)WhQR7Le+O-)mrq$MO&TO zBUg&4ALQLHelS!5Vxl>w`m24pPuQsIqzkfgkDX@BMxc;f>6s24e*Zqm;EG_Z0f}Jl zu~OH_fP^s^Y8pQy@TLXNKG3Q2IY4i*%vy3ZT3AXEXS4Gh^I!2f)Wa?kCa04b^{#Pm zkIb9ys8uVk$G?m%wT6*U6>;Rz^frvT`IxG!olGk0&1>1N&I5Rsk;61lcUupgdN0Ky25KwQey8Sylk0!-!j!$vrP$5yU|-h$b8p#Z$Gsr z$Us{HTo=VLOOg&Y<3T(3uq1Wp)J8$HY5m2we^<5RU&?1*t9pE|H8VnjFP0k98s*S# zM6F3ciDr2UDUBt0szna{AqPG0=4}i+ka7uO=7P?_9uHX}Df`5|z0esE?(oO=T-!zi zoF^i@tGLZuiu}|K5w2IRvH4cz-IdVI`Nm3Lxh4HD}RH2lQ z_EVtuFDq`ji87c*6gC2O>kcjQS-4*84MXz%VH@!k_#F;EWdboo$K#oo)7aJ)I+wY~3)Y zQtbbLc0|ng^h=Nb(tF5ZfOUE-Be9I51C`h^l7^!Lu;bF*#dEV_{>vrkr&PTw?|7+< zQ~0-UndvYc#+QZs2Gn=;n&(^1hJDFkgPU0K9Y*HTqEDhQsg!&4y$86> z-}~nbb0^>;JkOd1pS`RCpor-6Gu2>G+X`RuioOii_;9sm2RiYWUSXjHqx-j~4w+~a zAd;N7v}D69MVyH9Y|rTk`rh{yB*>h2Hu~vIjpk&&-j?|dv#(b`fzB7%M^;tw3JW)z z?c$n2CL?BCl6iVpEUrK9oba9I(8`203=bpeizrg*b)$w6;ScI~oh zdXK!pj;g>>uEFYgx3kX-$^s;GOs+bsXBVEK(UxZ8QM~zn;W6@VujsraLvV61evyeI z=ai&$U`p8~`(~}DxN`1-K3!@8?d~QV)G7z<3cB;QDMcsrS=tDc@q|AUbIlh80Fr-* z4CwN>#I1JNR2fMg6l(wCj9#Prxwi|02Rk&YPsU+BVN>|jKY$jP4fi*v?ksv6ktc@` z#8~+qrQcR%VxT&QqQy}w#5yg^%B;pMau_?rYjSHp5<69c^C!}w+%Q@#%Ng0XbdM4I zHFQF`Ljvan5s>Rs(Z%iJ2V8AO(1CDRQ z0E&|YaGDtjHIA!21iilsJ!=9WxuxRs4ms=_iTCCI0Q@aMZu`ve080)Hw{tZCVGM~} zhIKk`2fuY@w=P}y{6kn+W3_-ccl*t5i(XKPXD|NTj-cQJh4v8~0|VJ(g}PwswyEiC zECr!N4iExxPUa*8VAk2z5ajY83|jPts#B~_m#0x&pXeLTpU_NgQv_>ANLeHeT^ppE zg;-x#$-&Pcpy7>ppuk*oWF-8nj$X5c?F#P3dHLkpoF$wlIS+jaogCwch!{Ap*2_?q z)NQP%zqgLSL*Xvga;JcgI@&CFl=UVbhn?GOqVj9rhS5Cg?t5TJ_nP2(4%d!79T2f_ zlW?@4Abr3^ak$*f?oXNw|945X9UlM>tSVAMt*=ifi+H`7dHnk0&B&GK?R|qr0C5FD zXX$qaF{R6%NF?KH`lLei3O3VQ6WS9ff&eh*DTsds|H99Z0P*rropb$ak%DO`dqcq| z#R)5e937)`(BYVGuwiRf024ZM2rSWLvZ@y8#5g+ZPzqt%1@> z2YPlw!~Y5^x!D*7b$`&?>MncHrE%Y{KdX{)L^RlzEs_Jn(TD^m)s z7|$$~sGgqdAyl)*Z%r$ul2tWG_KCehZ&j}e{`y+lGavwPiK<4)6Vg2|BRD7ogd7wy zonTGQf|A%oJHjEcjh)SAL!yAsmIJ%aqdwfiLb=yC1f30*#=gu*JSWCj_6v%m$Gi3_ zKbPopRZPtdf0;V~=m%PvM@^27nUzFJ3pGb!HxH_XBonA|@Rm(`jkx#_%%n$a6hXtv zjc|1~yGZeCWOolqK(}iyvE7<3&dImS`6*XujhO2*dwnnx)7D&)bQ@@O|2tD2bvt}l}JXD2y_^MVY+|2xV{;F!mPe|~MsStoh9gD;dpuqOkE%(znf{%x7c1OodHeg)ZH#l?g= zuVYccriRd_S8E@#d3?Y<{5Mqq)cG%w+GPJ*$2J{kjf}oiQ9=KYJY`Xh_2wPR z?{r+-lJ}fXRsM;1MA`#EEI&1VR$9b&+P@x)>;MCvJsryxaJ&969h?0%!ygF7@U5|A ziO=)5j>_R+hs7!vWke;4p&37Oupiz|tqqWPSEhO#vJsW&e-)Teg!4DsknUl$1>=dz z`=z(-6ea+=4Iz8Ma~DHNxYEW2E6@0{oP7+=32Up>aHYN+E=Ss25>zFe|KKj<`C`bB z&hp7m(Os$L=I7f{x?NfNz7;?4Ijx>y){q5}wpyENVe?eYz(prb4e^d|6hAiz7Mvl= zV7U~O)E5V(PO8yD+A(EVmJx+D4aQBg71kYwX?si*CUyb@W|$@kYe@^N%K{6BG-h;R zu};z_af^S)^F`l?(6KvW03DRTU_OWn&V`{1CJrIp*Mi5F=V`LG-`LV{rR0EDq79|Q zZkWhsmz%9YCU1}XI|`b|MO#u!Z!v@3hfF`OXI-m%aK$=BdAqrjjjg0~WAD#1Fe1y3 z2}wzn?>P6|adT_IPd*Qo9_EVROy=Lb7{(P4V+vsb1A9*}>Lvq-(`*7RKXP9VEnj*5{!`eSL83wk$gx%t|vzE!S zF;ujW3(wfL$~++D!$f@(lZ`Rff}mD^(jfw50fb#uHP+cQF^E+ z2Y*biChkqwEIQkLk@0)gcwkEWy(N!kp!^S)jFUccF#=?wi?^oSDy{GO;kvLd?mXn2 zyPK4>PI9QXNdVbbr*oSE0?-Fm*=5v%Xawp*6Pa->)a?9YPHwAj$v^!`CS^oS&L~} zJ!HB-v3lc{-G7C=h7?&bIOwr4Fl9waY&yE4X=O7N;#K|%t~xp(zvXGre(_Bx$xyzJF5m%^G~kfyx<(Z> z;=Y9rQe$oHA5zZ^cOg{%v;xO+^VeS2#uAnsAXEKNh$xg(eGZ8H%0S^WBNOTzttO#i z<<)EIAQV!ZW$Glgo zQhi5FE$sDp5(<9%9sUq}cOw9$8=r@|dUa?&I?Hh|OPgAq?qDN;7%?rOgG7wfL_gnI zHcw96kABY0!vV_+cQUOYCcz&{@}6GSJ*q6N`_S}4_sLvkij~2#0EtMrK|Z!0e10g2 z7B*2xJ#23SqBB1n$Ij(qj1Ilq8}>gb%8IXh7S-wA(W}iK57{TqI&=*i;tnGegTT*}@n$5dC9S$mXtGUn6hb8Huidv(?^1%(nvOb$4M1wVF(s^#T}uU}J#TlbXj zM~5K`hZCkMD|&Y7;-A!~!CurepfX+i%LJB&#loC8-EuL4tDZ$ityX-f1f!ietJKJA zl%QdhiGa}M>NrYD zrw&D8C5JMIY3j69!DE>S0@&{VYzI;(P$78*g`ys8ZRY=DGUUay<(Q(vz_>8RFD+322gdP^VlQx}O&b_NU!}(tj_%4A$RvV0)DR=Mi z+;eRl6TV(l)WXNCC9UZ)wJHJu>ruE@K|*3M)Ce}ap^xPK#L;q)+Z6D_&cJGxca<^R zlH=|*uOPOa-?(WzaTIr*91h@N+Q2Qej;kNu_sqEi@O0cbK-;)amgB*{)`hM+JT6q= zX+E6wc*S%QbD#7zNBj)2<&ZPC;M@)a&S8PAOPd9ty5Dj8Vo@{_4sV!)cqqo>=wfx8 z#e0~TE#4?hmelg(9voH_G3Qc0dUW@iLG@YnkzIX;OmSv@Eq^n zv;x5wTEvm5-$f3=ucW-U%@%KjI`pctP@6oM28f9d>s85K9+x`=RrdmO0Szm+Kb%bA z*|T#5IaHm;jCp&$gGH%2z-G!!B&)m)^r=~8d0d%5Qgf3GbdEkmG|5gb-!0r%^WG*+ zyy6h|3`Fhw-=Gxk3jd5!wCbR>A<1Dl7a7XZ zc~PWj3Skl=Izr%0SHYzb^x^YMo2_D?j%)K1^-*30*KAixCa*IrO+(K3_@B=SX;d_a7p z?w5Sf<_yCg2^a>q??FS5D3Iq8=J06$@~G%kcH)bYt(3ZLY_}Wb0Vq5RTX<=CE!Okp<>yT`{I^Wd!4h6gY&Fm>8kXsF-;o0+zF6sxu`Q zF$mqxhDkk;JKk-#!A*1m?&j~-liY|$cim||A#T01eOTCd zX6JIF<-=G`g|W3sRnair_DpjQ63~=8tj%TB++4__hKZ@*;9>buN6sSDLn-!kUPsmQ zf=q0+^{i$=L5KEo^`kX=D%Q2u!Dj`-(N~9+Yk8i7T-nFb`R$oti7D~3IKU?}rtr&` zv~tFz)EXX_BVpv=I%`L$MuqK@eeBG72KKA6Ff}EWyyVC1VP&ngd_fMiJP{Yul5&)8 zmwyd}72_y~t1%;2hr-t^#wPL@HV4foi06&Q9D(RaE;m>AVYA#GNgOUt?sANdNWIHb z2Bms!#?fTcb+l8WZ7-sPx763?Yn=1r9^@X(cp47pBSolM!40+m6(5TDUAlV3xinCxfpWdj6!fN!ko9d0)=uq`vbrenFF$qI zQBYTfe`2pd@p9<4vIMnFUq8uQvQw4>757B1jTR?#ZgU%3F^;@WV%b&8L(F2@J%%#p zFJ29_n3U8<1SG{hRc!5j?B=8fqg3MOqe_+0jPjbC0jq=};lt%9C&T8i_AV=SiI#K=L;5HMwo*}oWJnTx~L1kpF=XQ*Q{b9~%rJbo*zGh5VPsZYrZ0~$> zO$;m8#RXZXCCsVZcD+0u@vY6?S}h9CDRX@e79wS9UL_uvIrI5B6pa#enXd;!_j=dN z*Saz_qiJfp5zD)C)`s7g0@2)Jp<`LdS*MggOt9rv%W@Bz=fcq&$sl0wXuvdQ?_$ZKsRQpaVoZ~I_K6N(0b zMRS0Y(|Dv(uUB{ouQTs$_NOX4A^Kj!Hxw4@%nbHpB_XWqi}E`j;z?GTF>5)G-0PD1 zunBF*`Z^a)q#(&5{dh$^Bo921YrB51Y42i-L5{ir|CvP~UVj9g=PR@`*r%#>nF8HT z%|QfX8L4F|3?~J1`s@d{EZl1ag_T@q6Y`E5dndSH9!4FT_0itcb1L;nV+`c-vWnB` zuv47BucF9B;-G1Au^@SFw~7=rWBaYHjtAtqwzG})luD}eU{+Y0j8&th_yahWEF~&V>yCA#A{(n5m3k2MZTS@Funm3DpOL#U%BCJ5^ltkqIg8-mT`N zM=P&}EUOT+_9u%)|9X^+!AkQIW4{5Shi+~@3G`gMPEVHBg}HgWJo&)m8&kMp;~`pk z%%8bgwixWpY--sXwUY`Pf0ZuvZvR!^5G;nEb4Esm?z2hyPzsA0gukmjEp5Ple>5Rv zAmAyTc=t@^NLxQ8C9Tr9w}7>P2C~-huG-l3XC~J(t4LJp3Xr$$Ua_HMG{*|mxBK0q z1Z4#HhZ4&#D@(dEW0te9xryP*V~@}}0kQ(c@5?Bw_!A?ihDwu1jGHXpuMbUZuUmH! z;_nw*?aJ*4zfg8bzAd8ydZzryZ3U7Px&K(kJZrQUB0?LrlmB1_BTgf=KQle+B=7~^ z?U&^5A*t`4s_fPUX>3YGfmI9$$yE=$m&pHOI(-J+|*9(BO0;hy4gz=^}@mdBHh zTL_U}fSWi8w6-M;B#WqR`lLMiW}Q_MO|V!ywbY$x(4U556>OXwsZq-LPl1I9Y6P9-q@EJh}9S@q*^b7o011M@|M1 z&ie~ZC-1<)c|ckoe@1$AvpNa+U0PQGj`sg7efpF=qXi#R6?n5ech!|c8HU<(pTi$y zKS^sCCD818lkYyQw%)E?kGwN9CwGKMUCXvQeT|LkZ@HgdV)HKiLS&{aYaZ45%Hh{t z0t@|ne}JJpF4IHX2hj-r$27Pni4ZT~cB(%(z`I)Kt-uoS{dvj7?6A{%_1qbGdA>I0 zXq`newVErnvZ_q%+{r^COn+D5m-9EqQeC4`a^jw`p1#*Nwjyz`Cc_w~dYR#PCmFAg&*r@Wfonty-Y$_3vWp z_skql2MzD4FIUgxe%%eJ4cM--?$C3@p9TG!QS~ns$UL9Yl}lN&RFuTiL17>LJmB=H zlDI-a#A~CuJoDmNtRxU8TOXS|$aj*~z{z6KEvPMQ+}tXTjKNqdFBKRe)|Srycrg0! z>fimGX4O=Izwgtf)4PmW_09A5SK^Sm>&mp6)wi5L)mdVv?H2Fgn+G*p7+)MOXI-ZC z;Om{J&HX)TsTVE>jx}0c6*lhhULrloPj82;{50d=n?FzVv(z(XJHQ@%{-a$>q6-Cw zS71@Sj@(MU(gjASk0c0g^zdohU1R{NHM}#A0UtV^Kbo&yan^g_aPcHtUULFX`)}S4 zOs(^{PjBwB`nw7CZ}$8@^;u>5HwsK)Rr~e`6e$bcn^%4w$1@TsOWUzgZVA%OyX^3dQy*UU0bMCffhOV9--tT3yZK=4&H3 zH5MCk`^U$VxHQY3#U;%6<~5a-x^o&B7z`Snl!a}m<&&V0P;BfqQJZ3JpLGBHUPY?8@SRxBxK#^*rna1I%QTC z+m)o&`R!xdXQtD)v@U*7)rGH{z-nFqi4Vv5od`6qd-)L}5UilRz{-;y?@nZ9(2KUP zP~)klz36fytLlH=#z6eC;k2EbGof9nARgrWU|-({y%Wppaad7N(G3u+9Vm!^wT{w2 zq7Td+8K6&??-E(>VeFB|*+pacIWOYd*?F5|~}stO;!ed0bfL%Uo;Wthrd=O@xu5VQCf7N!fW3p&=oeWez$HF68>==d~S24{k{A-*uooN!9BScir~U0xm9X zF#~(^i_%y6ODOb@-o~-lsXg+%#`Qv7JLUdJ;$0e=V7rB{`smTqBE`S|_GqAo_o66 zzS%4(1AeBit@SJ|Tmedu1ghssP7W5}-OzD3bq{zEL_{@lKpqL8`aCf)ze1FKp~dJR zC9PC!VFH&X&l5Nl@~PbaJvoaBR#trI&fa^(Vz#4dWY z8f{(TzE`~TO1^2Rx8q>XQln^kYz0<3obY1~LHL2(s-4!mgRTyz^s`)0{%K=%i8@*^ zuh&(x5?|uCsnsh+_C{$!}G8y3!J9NKki1RiuyPE^TXWJt` z?tS+$prnyZk@@&!@^m!lseT?bGqp^P>*P*KeGq&t^P|C&7cX9XPD&R3(+6|Utvam` qPD$k7S>^wxmwKAlziYBhVR3KkXv/src/tests/setup.ts'], +}; + +export default config; diff --git a/package-lock.json b/package-lock.json index e69de29b..c9871422 100644 --- a/package-lock.json +++ b/package-lock.json @@ -0,0 +1,15443 @@ +{ + "name": "7-sprint-mission", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "dependencies": { + "@aws-sdk/client-s3": "^3.1008.0", + "@prisma/client": "^5.16.2", + "bcrypt": "^5.1.1", + "cookie-parser": "^1.4.7", + "cors": "^2.8.5", + "dotenv": "^16.4.5", + "express": "^4.19.2", + "jsonwebtoken": "^9.0.2", + "multer": "^1.4.5-lts.1", + "multer-s3": "^3.0.1", + "socket.io": "^4.8.1", + "superstruct": "^2.0.2", + "uuid": "^11.0.5" + }, + "devDependencies": { + "@types/bcrypt": "^5.0.2", + "@types/cookie-parser": "^1.4.8", + "@types/cors": "^2.8.17", + "@types/express": "^5.0.0", + "@types/jest": "^30.0.0", + "@types/jsonwebtoken": "^9.0.9", + "@types/multer": "^1.4.12", + "@types/multer-s3": "^3.0.3", + "@types/supertest": "^7.2.0", + "jest": "^30.2.0", + "nodemon": "^3.1.9", + "prettier": "^3.3.2", + "prisma": "^5.16.2", + "supertest": "^7.2.2", + "ts-jest": "^29.4.6", + "ts-node": "^10.9.2", + "typescript": "^5.8.2" + } + }, + "node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/crc32c": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", + "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha1-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz", + "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-s3": { + "version": "3.1008.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.1008.0.tgz", + "integrity": "sha512-w/SIRD25v2zVMbkn8CYIxUsac8yf5Jghkhw5j7EsNWdJhl56m/nWpUX7t1etFUW1cnzpFjZV0lXt0dNFSnbXwA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha1-browser": "5.2.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/credential-provider-node": "^3.972.20", + "@aws-sdk/middleware-bucket-endpoint": "^3.972.7", + "@aws-sdk/middleware-expect-continue": "^3.972.7", + "@aws-sdk/middleware-flexible-checksums": "^3.973.5", + "@aws-sdk/middleware-host-header": "^3.972.7", + "@aws-sdk/middleware-location-constraint": "^3.972.7", + "@aws-sdk/middleware-logger": "^3.972.7", + "@aws-sdk/middleware-recursion-detection": "^3.972.7", + "@aws-sdk/middleware-sdk-s3": "^3.972.19", + "@aws-sdk/middleware-ssec": "^3.972.7", + "@aws-sdk/middleware-user-agent": "^3.972.20", + "@aws-sdk/region-config-resolver": "^3.972.7", + "@aws-sdk/signature-v4-multi-region": "^3.996.7", + "@aws-sdk/types": "^3.973.5", + "@aws-sdk/util-endpoints": "^3.996.4", + "@aws-sdk/util-user-agent-browser": "^3.972.7", + "@aws-sdk/util-user-agent-node": "^3.973.6", + "@smithy/config-resolver": "^4.4.10", + "@smithy/core": "^3.23.9", + "@smithy/eventstream-serde-browser": "^4.2.11", + "@smithy/eventstream-serde-config-resolver": "^4.3.11", + "@smithy/eventstream-serde-node": "^4.2.11", + "@smithy/fetch-http-handler": "^5.3.13", + "@smithy/hash-blob-browser": "^4.2.12", + "@smithy/hash-node": "^4.2.11", + "@smithy/hash-stream-node": "^4.2.11", + "@smithy/invalid-dependency": "^4.2.11", + "@smithy/md5-js": "^4.2.11", + "@smithy/middleware-content-length": "^4.2.11", + "@smithy/middleware-endpoint": "^4.4.23", + "@smithy/middleware-retry": "^4.4.40", + "@smithy/middleware-serde": "^4.2.12", + "@smithy/middleware-stack": "^4.2.11", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/node-http-handler": "^4.4.14", + "@smithy/protocol-http": "^5.3.11", + "@smithy/smithy-client": "^4.12.3", + "@smithy/types": "^4.13.0", + "@smithy/url-parser": "^4.2.11", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-body-length-browser": "^4.2.2", + "@smithy/util-body-length-node": "^4.2.3", + "@smithy/util-defaults-mode-browser": "^4.3.39", + "@smithy/util-defaults-mode-node": "^4.2.42", + "@smithy/util-endpoints": "^3.3.2", + "@smithy/util-middleware": "^4.2.11", + "@smithy/util-retry": "^4.2.11", + "@smithy/util-stream": "^4.5.17", + "@smithy/util-utf8": "^4.2.2", + "@smithy/util-waiter": "^4.2.12", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.973.19", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.19.tgz", + "integrity": "sha512-56KePyOcZnKTWCd89oJS1G6j3HZ9Kc+bh/8+EbvtaCCXdP6T7O7NzCiPuHRhFLWnzXIaXX3CxAz0nI5My9spHQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@aws-sdk/xml-builder": "^3.972.10", + "@smithy/core": "^3.23.9", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/property-provider": "^4.2.11", + "@smithy/protocol-http": "^5.3.11", + "@smithy/signature-v4": "^5.3.11", + "@smithy/smithy-client": "^4.12.3", + "@smithy/types": "^4.13.0", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-middleware": "^4.2.11", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/crc64-nvme": { + "version": "3.972.4", + "resolved": "https://registry.npmjs.org/@aws-sdk/crc64-nvme/-/crc64-nvme-3.972.4.tgz", + "integrity": "sha512-HKZIZLbRyvzo/bXZU7Zmk6XqU+1C9DjI56xd02vwuDIxedxBEqP17t9ExhbP9QFeNq/a3l9GOcyirFXxmbDhmw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.972.17", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.17.tgz", + "integrity": "sha512-MBAMW6YELzE1SdkOniqr51mrjapQUv8JXSGxtwRjQV0mwVDutVsn22OPAUt4RcLRvdiHQmNBDEFP9iTeSVCOlA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/types": "^3.973.5", + "@smithy/property-provider": "^4.2.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.972.19", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.19.tgz", + "integrity": "sha512-9EJROO8LXll5a7eUFqu48k6BChrtokbmgeMWmsH7lBb6lVbtjslUYz/ShLi+SHkYzTomiGBhmzTW7y+H4BxsnA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/types": "^3.973.5", + "@smithy/fetch-http-handler": "^5.3.13", + "@smithy/node-http-handler": "^4.4.14", + "@smithy/property-provider": "^4.2.11", + "@smithy/protocol-http": "^5.3.11", + "@smithy/smithy-client": "^4.12.3", + "@smithy/types": "^4.13.0", + "@smithy/util-stream": "^4.5.17", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.972.19", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.19.tgz", + "integrity": "sha512-pVJVjWqVrPqjpFq7o0mCmeZu1Y0c94OCHSYgivdCD2wfmYVtBbwQErakruhgOD8pcMcx9SCqRw1pzHKR7OGBcA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/credential-provider-env": "^3.972.17", + "@aws-sdk/credential-provider-http": "^3.972.19", + "@aws-sdk/credential-provider-login": "^3.972.19", + "@aws-sdk/credential-provider-process": "^3.972.17", + "@aws-sdk/credential-provider-sso": "^3.972.19", + "@aws-sdk/credential-provider-web-identity": "^3.972.19", + "@aws-sdk/nested-clients": "^3.996.9", + "@aws-sdk/types": "^3.973.5", + "@smithy/credential-provider-imds": "^4.2.11", + "@smithy/property-provider": "^4.2.11", + "@smithy/shared-ini-file-loader": "^4.4.6", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login": { + "version": "3.972.19", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.19.tgz", + "integrity": "sha512-jOXdZ1o+CywQKr6gyxgxuUmnGwTTnY2Kxs1PM7fI6AYtDWDnmW/yKXayNqkF8KjP1unflqMWKVbVt5VgmE3L0g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/nested-clients": "^3.996.9", + "@aws-sdk/types": "^3.973.5", + "@smithy/property-provider": "^4.2.11", + "@smithy/protocol-http": "^5.3.11", + "@smithy/shared-ini-file-loader": "^4.4.6", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.972.20", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.20.tgz", + "integrity": "sha512-0xHca2BnPY0kzjDYPH7vk8YbfdBPpWVS67rtqQMalYDQUCBYS37cZ55K6TuFxCoIyNZgSCFrVKr9PXC5BVvQQw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "^3.972.17", + "@aws-sdk/credential-provider-http": "^3.972.19", + "@aws-sdk/credential-provider-ini": "^3.972.19", + "@aws-sdk/credential-provider-process": "^3.972.17", + "@aws-sdk/credential-provider-sso": "^3.972.19", + "@aws-sdk/credential-provider-web-identity": "^3.972.19", + "@aws-sdk/types": "^3.973.5", + "@smithy/credential-provider-imds": "^4.2.11", + "@smithy/property-provider": "^4.2.11", + "@smithy/shared-ini-file-loader": "^4.4.6", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.972.17", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.17.tgz", + "integrity": "sha512-c8G8wT1axpJDgaP3xzcy+q8Y1fTi9A2eIQJvyhQ9xuXrUZhlCfXbC0vM9bM1CUXiZppFQ1p7g0tuUMvil/gCPg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/types": "^3.973.5", + "@smithy/property-provider": "^4.2.11", + "@smithy/shared-ini-file-loader": "^4.4.6", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.972.19", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.19.tgz", + "integrity": "sha512-kVjQsEU3b///q7EZGrUzol9wzwJFKbEzqJKSq82A9ShrUTEO7FNylTtby3sPV19ndADZh1H3FB3+5ZrvKtEEeg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/nested-clients": "^3.996.9", + "@aws-sdk/token-providers": "3.1008.0", + "@aws-sdk/types": "^3.973.5", + "@smithy/property-provider": "^4.2.11", + "@smithy/shared-ini-file-loader": "^4.4.6", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.972.19", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.19.tgz", + "integrity": "sha512-BV1BlTFdG4w4tAihxN7iXDBoNcNewXD4q8uZlNQiUrnqxwGWUhKHODIQVSPlQGxXClEj+63m+cqZskw+ESmeZg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/nested-clients": "^3.996.9", + "@aws-sdk/types": "^3.973.5", + "@smithy/property-provider": "^4.2.11", + "@smithy/shared-ini-file-loader": "^4.4.6", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/lib-storage": { + "version": "3.1008.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.1008.0.tgz", + "integrity": "sha512-SWIzixPt9VG6jz8+tR8VklOi3FXY1J6WMfd1JEtY9gVtJaLGF5tWexIkjUnGHP8B6M6Uk+qC5zdr2Caome5Gfg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/abort-controller": "^4.2.11", + "@smithy/middleware-endpoint": "^4.4.23", + "@smithy/smithy-client": "^4.12.3", + "buffer": "5.6.0", + "events": "3.3.0", + "stream-browserify": "3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-s3": "^3.1008.0" + } + }, + "node_modules/@aws-sdk/middleware-bucket-endpoint": { + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.972.7.tgz", + "integrity": "sha512-goX+axlJ6PQlRnzE2bQisZ8wVrlm6dXJfBzMJhd8LhAIBan/w1Kl73fJnalM/S+18VnpzIHumyV6DtgmvqG5IA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@aws-sdk/util-arn-parser": "^3.972.3", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "@smithy/util-config-provider": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-expect-continue": { + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.972.7.tgz", + "integrity": "sha512-mvWqvm61bmZUKmmrtl2uWbokqpenY3Mc3Jf4nXB/Hse6gWxLPaCQThmhPBDzsPSV8/Odn8V6ovWt3pZ7vy4BFQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.973.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.973.5.tgz", + "integrity": "sha512-Dp3hqE5W6hG8HQ3Uh+AINx9wjjqYmFHbxede54sGj3akx/haIQrkp85lNdTdC+ouNUcSYNiuGkzmyDREfHX1Gg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-crypto/util": "5.2.0", + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/crc64-nvme": "^3.972.4", + "@aws-sdk/types": "^3.973.5", + "@smithy/is-array-buffer": "^4.2.2", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "@smithy/util-middleware": "^4.2.11", + "@smithy/util-stream": "^4.5.17", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.972.7.tgz", + "integrity": "sha512-aHQZgztBFEpDU1BB00VWCIIm85JjGjQW1OG9+98BdmaOpguJvzmXBGbnAiYcciCd+IS4e9BEq664lhzGnWJHgQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-location-constraint": { + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.972.7.tgz", + "integrity": "sha512-vdK1LJfffBp87Lj0Bw3WdK1rJk9OLDYdQpqoKgmpIZPe+4+HawZ6THTbvjhJt4C4MNnRrHTKHQjkwBiIpDBoig==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.972.7.tgz", + "integrity": "sha512-LXhiWlWb26txCU1vcI9PneESSeRp/RYY/McuM4SpdrimQR5NgwaPb4VJCadVeuGWgh6QmqZ6rAKSoL1ob16W6w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.972.7.tgz", + "integrity": "sha512-l2VQdcBcYLzIzykCHtXlbpiVCZ94/xniLIkAj0jpnpjY4xlgZx7f56Ypn+uV1y3gG0tNVytJqo3K9bfMFee7SQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@aws/lambda-invoke-store": "^0.2.2", + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.972.19", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.19.tgz", + "integrity": "sha512-/CtOHHVFg4ZuN6CnLnYkrqWgVEnbOBC4kNiKa+4fldJ9cioDt3dD/f5vpq0cWLOXwmGL2zgVrVxNhjxWpxNMkg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/types": "^3.973.5", + "@aws-sdk/util-arn-parser": "^3.972.3", + "@smithy/core": "^3.23.9", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/protocol-http": "^5.3.11", + "@smithy/signature-v4": "^5.3.11", + "@smithy/smithy-client": "^4.12.3", + "@smithy/types": "^4.13.0", + "@smithy/util-config-provider": "^4.2.2", + "@smithy/util-middleware": "^4.2.11", + "@smithy/util-stream": "^4.5.17", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-ssec": { + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.972.7.tgz", + "integrity": "sha512-G9clGVuAml7d8DYzY6DnRi7TIIDRvZ3YpqJPz/8wnWS5fYx/FNWNmkO6iJVlVkQg9BfeMzd+bVPtPJOvC4B+nQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.972.20", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.20.tgz", + "integrity": "sha512-3kNTLtpUdeahxtnJRnj/oIdLAUdzTfr9N40KtxNhtdrq+Q1RPMdCJINRXq37m4t5+r3H70wgC3opW46OzFcZYA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/types": "^3.973.5", + "@aws-sdk/util-endpoints": "^3.996.4", + "@smithy/core": "^3.23.9", + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "@smithy/util-retry": "^4.2.11", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/nested-clients": { + "version": "3.996.9", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.996.9.tgz", + "integrity": "sha512-+RpVtpmQbbtzFOKhMlsRcXM/3f1Z49qTOHaA8gEpHOYruERmog6f2AUtf/oTRLCWjR9H2b3roqryV/hI7QMW8w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/middleware-host-header": "^3.972.7", + "@aws-sdk/middleware-logger": "^3.972.7", + "@aws-sdk/middleware-recursion-detection": "^3.972.7", + "@aws-sdk/middleware-user-agent": "^3.972.20", + "@aws-sdk/region-config-resolver": "^3.972.7", + "@aws-sdk/types": "^3.973.5", + "@aws-sdk/util-endpoints": "^3.996.4", + "@aws-sdk/util-user-agent-browser": "^3.972.7", + "@aws-sdk/util-user-agent-node": "^3.973.6", + "@smithy/config-resolver": "^4.4.10", + "@smithy/core": "^3.23.9", + "@smithy/fetch-http-handler": "^5.3.13", + "@smithy/hash-node": "^4.2.11", + "@smithy/invalid-dependency": "^4.2.11", + "@smithy/middleware-content-length": "^4.2.11", + "@smithy/middleware-endpoint": "^4.4.23", + "@smithy/middleware-retry": "^4.4.40", + "@smithy/middleware-serde": "^4.2.12", + "@smithy/middleware-stack": "^4.2.11", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/node-http-handler": "^4.4.14", + "@smithy/protocol-http": "^5.3.11", + "@smithy/smithy-client": "^4.12.3", + "@smithy/types": "^4.13.0", + "@smithy/url-parser": "^4.2.11", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-body-length-browser": "^4.2.2", + "@smithy/util-body-length-node": "^4.2.3", + "@smithy/util-defaults-mode-browser": "^4.3.39", + "@smithy/util-defaults-mode-node": "^4.2.42", + "@smithy/util-endpoints": "^3.3.2", + "@smithy/util-middleware": "^4.2.11", + "@smithy/util-retry": "^4.2.11", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.972.7.tgz", + "integrity": "sha512-/Ev/6AI8bvt4HAAptzSjThGUMjcWaX3GX8oERkB0F0F9x2dLSBdgFDiyrRz3i0u0ZFZFQ1b28is4QhyqXTUsVA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@smithy/config-resolver": "^4.4.10", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.996.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.7.tgz", + "integrity": "sha512-mYhh7FY+7OOqjkYkd6+6GgJOsXK1xBWmuR+c5mxJPj2kr5TBNeZq+nUvE9kANWAux5UxDVrNOSiEM/wlHzC3Lg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-sdk-s3": "^3.972.19", + "@aws-sdk/types": "^3.973.5", + "@smithy/protocol-http": "^5.3.11", + "@smithy/signature-v4": "^5.3.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.1008.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1008.0.tgz", + "integrity": "sha512-TulwlHQBWcJs668kNUDMZHN51DeLrDsYT59Ux4a/nbvr025gM6HjKJJ3LvnZccam7OS/ZKUVkWomCneRQKJbBg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/nested-clients": "^3.996.9", + "@aws-sdk/types": "^3.973.5", + "@smithy/property-provider": "^4.2.11", + "@smithy/shared-ini-file-loader": "^4.4.6", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.973.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.973.5.tgz", + "integrity": "sha512-hl7BGwDCWsjH8NkZfx+HgS7H2LyM2lTMAI7ba9c8O0KqdBLTdNJivsHpqjg9rNlAlPyREb6DeDRXUl0s8uFdmQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/util-arn-parser": { + "version": "3.972.3", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.972.3.tgz", + "integrity": "sha512-HzSD8PMFrvgi2Kserxuff5VitNq2sgf3w9qxmskKDiDTThWfVteJxuCS9JXiPIPtmCrp+7N9asfIaVhBFORllA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.996.4", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.996.4.tgz", + "integrity": "sha512-Hek90FBmd4joCFj+Vc98KLJh73Zqj3s2W56gjAcTkrNLMDI5nIFkG9YpfcJiVI1YlE2Ne1uOQNe+IgQ/Vz2XRA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@smithy/types": "^4.13.0", + "@smithy/url-parser": "^4.2.11", + "@smithy/util-endpoints": "^3.3.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.965.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.965.5.tgz", + "integrity": "sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.972.7.tgz", + "integrity": "sha512-7SJVuvhKhMF/BkNS1n0QAJYgvEwYbK2QLKBrzDiwQGiTRU6Yf1f3nehTzm/l21xdAOtWSfp2uWSddPnP2ZtsVw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.5", + "@smithy/types": "^4.13.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.973.6", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.6.tgz", + "integrity": "sha512-iF7G0prk7AvmOK64FcLvc/fW+Ty1H+vttajL7PvJFReU8urMxfYmynTTuFKDTA76Wgpq3FzTPKwabMQIXQHiXQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-user-agent": "^3.972.20", + "@aws-sdk/types": "^3.973.5", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/types": "^4.13.0", + "@smithy/util-config-provider": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.972.10", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.10.tgz", + "integrity": "sha512-OnejAIVD+CxzyAUrVic7lG+3QRltyja9LoNqCE/1YVs8ichoTbJlVSaZ9iSMcnHLyzrSNtvaOGjSDRP+d/ouFA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.0", + "fast-xml-parser": "5.4.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws/lambda-invoke-store": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.4.tgz", + "integrity": "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", + "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@emnapi/core": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz", + "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.2.0.tgz", + "integrity": "sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/core": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.2.0.tgz", + "integrity": "sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.2.0", + "@jest/pattern": "30.0.1", + "@jest/reporters": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-changed-files": "30.2.0", + "jest-config": "30.2.0", + "jest-haste-map": "30.2.0", + "jest-message-util": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-resolve-dependencies": "30.2.0", + "jest-runner": "30.2.0", + "jest-runtime": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "jest-watcher": "30.2.0", + "micromatch": "^4.0.8", + "pretty-format": "30.2.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/diff-sequences": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", + "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/environment": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.2.0.tgz", + "integrity": "sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-mock": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "30.2.0", + "jest-snapshot": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", + "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.2.0.tgz", + "integrity": "sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@sinonjs/fake-timers": "^13.0.0", + "@types/node": "*", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/get-type": { + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz", + "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.2.0.tgz", + "integrity": "sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/expect": "30.2.0", + "@jest/types": "30.2.0", + "jest-mock": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/pattern": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", + "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-regex-util": "30.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.2.0.tgz", + "integrity": "sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@jridgewell/trace-mapping": "^0.3.25", + "@types/node": "*", + "chalk": "^4.1.2", + "collect-v8-coverage": "^1.0.2", + "exit-x": "^0.2.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^5.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "jest-worker": "30.2.0", + "slash": "^3.0.0", + "string-length": "^4.0.2", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/reporters/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/snapshot-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.2.0.tgz", + "integrity": "sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "natural-compare": "^1.4.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz", + "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "callsites": "^3.1.0", + "graceful-fs": "^4.2.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/source-map/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/test-result": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.2.0.tgz", + "integrity": "sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.2.0", + "@jest/types": "30.2.0", + "@types/istanbul-lib-coverage": "^2.0.6", + "collect-v8-coverage": "^1.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.2.0.tgz", + "integrity": "sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.2.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.2.0.tgz", + "integrity": "sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/types": "30.2.0", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.1", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-util": "30.2.0", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/types": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", + "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.5", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@paralleldrive/cuid2": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", + "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.1.5" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@prisma/client": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.16.2.tgz", + "integrity": "sha512-+1lmkhR9gHWcTC5oghm2ZKpWljyWdzfazCVlLKUWXVmwHSf52g81aZ8qb6Km5Bs025yBi7puLp3qSLEvktoUtw==", + "hasInstallScript": true, + "engines": { + "node": ">=16.13" + }, + "peerDependencies": { + "prisma": "*" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + } + } + }, + "node_modules/@prisma/debug": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.16.2.tgz", + "integrity": "sha512-ItzB4nR4O8eLzuJiuP3WwUJfoIvewMHqpGCad+64gvThcKEVOtaUza9AEJo2DPqAOa/AWkFyK54oM4WwHeew+A==", + "devOptional": true + }, + "node_modules/@prisma/engines": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.16.2.tgz", + "integrity": "sha512-qUxwMtrwoG3byd4PbX6T7EjHJ8AUhzTuwniOGkh/hIznBfcE2QQnGakyEq4VnwNuttMqvh/GgPFapHQ3lCuRHg==", + "devOptional": true, + "hasInstallScript": true, + "dependencies": { + "@prisma/debug": "5.16.2", + "@prisma/engines-version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", + "@prisma/fetch-engine": "5.16.2", + "@prisma/get-platform": "5.16.2" + } + }, + "node_modules/@prisma/engines-version": { + "version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303.tgz", + "integrity": "sha512-HkT2WbfmFZ9WUPyuJHhkiADxazHg8Y4gByrTSVeb3OikP6tjQ7txtSUGu9OBOBH0C13dPKN2qqH12xKtHu/Hiw==", + "devOptional": true + }, + "node_modules/@prisma/fetch-engine": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.16.2.tgz", + "integrity": "sha512-sq51lfHKfH2jjYSjBtMjP+AznFqOJzXpqmq6B9auWrlTJrMgZ7lPyhWUW7VU7LsQU48/TJ+DZeIz8s9bMYvcHg==", + "devOptional": true, + "dependencies": { + "@prisma/debug": "5.16.2", + "@prisma/engines-version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", + "@prisma/get-platform": "5.16.2" + } + }, + "node_modules/@prisma/get-platform": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.16.2.tgz", + "integrity": "sha512-cXiHPgNLNyj22vLouPVNegklpRL/iX2jxTeap5GRO3DmCoVyIHmJAV1CgUMUJhHlcol9yYy7EHvsnXTDJ/PKEA==", + "devOptional": true, + "dependencies": { + "@prisma/debug": "5.16.2" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.34.48", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.48.tgz", + "integrity": "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@smithy/abort-controller": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.12.tgz", + "integrity": "sha512-xolrFw6b+2iYGl6EcOL7IJY71vvyZ0DJ3mcKtpykqPe2uscwtzDZJa1uVQXyP7w9Dd+kGwYnPbMsJrGISKiY/Q==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.2.2.tgz", + "integrity": "sha512-St+kVicSyayWQca+I1rGitaOEH6uKgE8IUWoYnnEX26SWdWQcL6LvMSD19Lg+vYHKdT9B2Zuu7rd3i6Wnyb/iw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader-native": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.2.3.tgz", + "integrity": "sha512-jA5k5Udn7Y5717L86h4EIv06wIr3xn8GM1qHRi/Nf31annXcXHJjBKvgztnbn2TxH3xWrPBfgwHsOwZf0UmQWw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-base64": "^4.3.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "4.4.11", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.11.tgz", + "integrity": "sha512-YxFiiG4YDAtX7WMN7RuhHZLeTmRRAOyCbr+zB8e3AQzHPnUhS8zXjB1+cniPVQI3xbWsQPM0X2aaIkO/ME0ymw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.12", + "@smithy/types": "^4.13.1", + "@smithy/util-config-provider": "^4.2.2", + "@smithy/util-endpoints": "^3.3.3", + "@smithy/util-middleware": "^4.2.12", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/core": { + "version": "3.23.11", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.23.11.tgz", + "integrity": "sha512-952rGf7hBRnhUIaeLp6q4MptKW8sPFe5VvkoZ5qIzFAtx6c/QZ/54FS3yootsyUSf9gJX/NBqEBNdNR7jMIlpQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "@smithy/url-parser": "^4.2.12", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-body-length-browser": "^4.2.2", + "@smithy/util-middleware": "^4.2.12", + "@smithy/util-stream": "^4.5.19", + "@smithy/util-utf8": "^4.2.2", + "@smithy/uuid": "^1.1.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.12.tgz", + "integrity": "sha512-cr2lR792vNZcYMriSIj+Um3x9KWrjcu98kn234xA6reOAFMmbRpQMOv8KPgEmLLtx3eldU6c5wALKFqNOhugmg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.12", + "@smithy/property-provider": "^4.2.12", + "@smithy/types": "^4.13.1", + "@smithy/url-parser": "^4.2.12", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-codec": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.2.12.tgz", + "integrity": "sha512-FE3bZdEl62ojmy8x4FHqxq2+BuOHlcxiH5vaZ6aqHJr3AIZzwF5jfx8dEiU/X0a8RboyNDjmXjlbr8AdEyLgiA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.13.1", + "@smithy/util-hex-encoding": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-browser": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.12.tgz", + "integrity": "sha512-XUSuMxlTxV5pp4VpqZf6Sa3vT/Q75FVkLSpSSE3KkWBvAQWeuWt1msTv8fJfgA4/jcJhrbrbMzN1AC/hvPmm5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/eventstream-serde-universal": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "4.3.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.12.tgz", + "integrity": "sha512-7epsAZ3QvfHkngz6RXQYseyZYHlmWXSTPOfPmXkiS+zA6TBNo1awUaMFL9vxyXlGdoELmCZyZe1nQE+imbmV+Q==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-node": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.12.tgz", + "integrity": "sha512-D1pFuExo31854eAvg89KMn9Oab/wEeJR6Buy32B49A9Ogdtx5fwZPqBHUlDzaCDpycTFk2+fSQgX689Qsk7UGA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/eventstream-serde-universal": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.12.tgz", + "integrity": "sha512-+yNuTiyBACxOJUTvbsNsSOfH9G9oKbaJE1lNL3YHpGcuucl6rPZMi3nrpehpVOVR2E07YqFFmtwpImtpzlouHQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/eventstream-codec": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "5.3.15", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.15.tgz", + "integrity": "sha512-T4jFU5N/yiIfrtrsb9uOQn7RdELdM/7HbyLNr6uO/mpkj1ctiVs7CihVr51w4LyQlXWDpXFn4BElf1WmQvZu/A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.12", + "@smithy/querystring-builder": "^4.2.12", + "@smithy/types": "^4.13.1", + "@smithy/util-base64": "^4.3.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-blob-browser": { + "version": "4.2.13", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.2.13.tgz", + "integrity": "sha512-YrF4zWKh+ghLuquldj6e/RzE3xZYL8wIPfkt0MqCRphVICjyyjH8OwKD7LLlKpVEbk4FLizFfC1+gwK6XQdR3g==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/chunked-blob-reader": "^5.2.2", + "@smithy/chunked-blob-reader-native": "^4.2.3", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-node": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.12.tgz", + "integrity": "sha512-QhBYbGrbxTkZ43QoTPrK72DoYviDeg6YKDrHTMJbbC+A0sml3kSjzFtXP7BtbyJnXojLfTQldGdUR0RGD8dA3w==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "@smithy/util-buffer-from": "^4.2.2", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-stream-node": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.2.12.tgz", + "integrity": "sha512-O3YbmGExeafuM/kP7Y8r6+1y0hIh3/zn6GROx0uNlB54K9oihAL75Qtc+jFfLNliTi6pxOAYZrRKD9A7iA6UFw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.12.tgz", + "integrity": "sha512-/4F1zb7Z8LOu1PalTdESFHR0RbPwHd3FcaG1sI3UEIriQTWakysgJr65lc1jj6QY5ye7aFsisajotH6UhWfm/g==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.2.tgz", + "integrity": "sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/md5-js": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.2.12.tgz", + "integrity": "sha512-W/oIpHCpWU2+iAkfZYyGWE+qkpuf3vEXHLxQQDx9FPNZTTdnul0dZ2d/gUFrtQ5je1G2kp4cjG0/24YueG2LbQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.12.tgz", + "integrity": "sha512-YE58Yz+cvFInWI/wOTrB+DbvUVz/pLn5mC5MvOV4fdRUc6qGwygyngcucRQjAhiCEbmfLOXX0gntSIcgMvAjmA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "4.4.25", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.25.tgz", + "integrity": "sha512-dqjLwZs2eBxIUG6Qtw8/YZ4DvzHGIf0DA18wrgtfP6a50UIO7e2nY0FPdcbv5tVJKqWCCU5BmGMOUwT7Puan+A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.23.11", + "@smithy/middleware-serde": "^4.2.14", + "@smithy/node-config-provider": "^4.3.12", + "@smithy/shared-ini-file-loader": "^4.4.7", + "@smithy/types": "^4.13.1", + "@smithy/url-parser": "^4.2.12", + "@smithy/util-middleware": "^4.2.12", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "4.4.42", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.42.tgz", + "integrity": "sha512-vbwyqHRIpIZutNXZpLAozakzamcINaRCpEy1MYmK6xBeW3xN+TyPRA123GjXnuxZIjc9848MRRCugVMTXxC4Eg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.12", + "@smithy/protocol-http": "^5.3.12", + "@smithy/service-error-classification": "^4.2.12", + "@smithy/smithy-client": "^4.12.5", + "@smithy/types": "^4.13.1", + "@smithy/util-middleware": "^4.2.12", + "@smithy/util-retry": "^4.2.12", + "@smithy/uuid": "^1.1.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "4.2.14", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.14.tgz", + "integrity": "sha512-+CcaLoLa5apzSRtloOyG7lQvkUw2ZDml3hRh4QiG9WyEPfW5Ke/3tPOPiPjUneuT59Tpn8+c3RVaUvvkkwqZwg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.23.11", + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-stack": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.12.tgz", + "integrity": "sha512-kruC5gRHwsCOuyCd4ouQxYjgRAym2uDlCvQ5acuMtRrcdfg7mFBg6blaxcJ09STpt3ziEkis6bhg1uwrWU7txw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-config-provider": { + "version": "4.3.12", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.12.tgz", + "integrity": "sha512-tr2oKX2xMcO+rBOjobSwVAkV05SIfUKz8iI53rzxEmgW3GOOPOv0UioSDk+J8OpRQnpnhsO3Af6IEBabQBVmiw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^4.2.12", + "@smithy/shared-ini-file-loader": "^4.4.7", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "4.4.16", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.16.tgz", + "integrity": "sha512-ULC8UCS/HivdCB3jhi+kLFYe4B5gxH2gi9vHBfEIiRrT2jfKiZNiETJSlzRtE6B26XbBHjPtc8iZKSNqMol9bw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/abort-controller": "^4.2.12", + "@smithy/protocol-http": "^5.3.12", + "@smithy/querystring-builder": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/property-provider": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.12.tgz", + "integrity": "sha512-jqve46eYU1v7pZ5BM+fmkbq3DerkSluPr5EhvOcHxygxzD05ByDRppRwRPPpFrsFo5yDtCYLKu+kreHKVrvc7A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "5.3.12", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.12.tgz", + "integrity": "sha512-fit0GZK9I1xoRlR4jXmbLhoN0OdEpa96ul8M65XdmXnxXkuMxM0Y8HDT0Fh0Xb4I85MBvBClOzgSrV1X2s1Hxw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/querystring-builder": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.12.tgz", + "integrity": "sha512-6wTZjGABQufekycfDGMEB84BgtdOE/rCVTov+EDXQ8NHKTUNIp/j27IliwP7tjIU9LR+sSzyGBOXjeEtVgzCHg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "@smithy/util-uri-escape": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/querystring-parser": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.12.tgz", + "integrity": "sha512-P2OdvrgiAKpkPNKlKUtWbNZKB1XjPxM086NeVhK+W+wI46pIKdWBe5QyXvhUm3MEcyS/rkLvY8rZzyUdmyDZBw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/service-error-classification": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.12.tgz", + "integrity": "sha512-LlP29oSQN0Tw0b6D0Xo6BIikBswuIiGYbRACy5ujw/JgWSzTdYj46U83ssf6Ux0GyNJVivs2uReU8pt7Eu9okQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.7.tgz", + "integrity": "sha512-HrOKWsUb+otTeo1HxVWeEb99t5ER1XrBi/xka2Wv6NVmTbuCUC1dvlrksdvxFtODLBjsC+PHK+fuy2x/7Ynyiw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "5.3.12", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.12.tgz", + "integrity": "sha512-B/FBwO3MVOL00DaRSXfXfa/TRXRheagt/q5A2NM13u7q+sHS59EOVGQNfG7DkmVtdQm5m3vOosoKAXSqn/OEgw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^4.2.2", + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "@smithy/util-hex-encoding": "^4.2.2", + "@smithy/util-middleware": "^4.2.12", + "@smithy/util-uri-escape": "^4.2.2", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/smithy-client": { + "version": "4.12.5", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.12.5.tgz", + "integrity": "sha512-UqwYawyqSr/aog8mnLnfbPurS0gi4G7IYDcD28cUIBhsvWs1+rQcL2IwkUQ+QZ7dibaoRzhNF99fAQ9AUcO00w==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.23.11", + "@smithy/middleware-endpoint": "^4.4.25", + "@smithy/middleware-stack": "^4.2.12", + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "@smithy/util-stream": "^4.5.19", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.13.1.tgz", + "integrity": "sha512-787F3yzE2UiJIQ+wYW1CVg2odHjmaWLGksnKQHUrK/lYZSEcy1msuLVvxaR/sI2/aDe9U+TBuLsXnr3vod1g0g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.12.tgz", + "integrity": "sha512-wOPKPEpso+doCZGIlr+e1lVI6+9VAKfL4kZWFgzVgGWY2hZxshNKod4l2LXS3PRC9otH/JRSjtEHqQ/7eLciRA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/querystring-parser": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-base64": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.3.2.tgz", + "integrity": "sha512-XRH6b0H/5A3SgblmMa5ErXQ2XKhfbQB+Fm/oyLZ2O2kCUrwgg55bU0RekmzAhuwOjA9qdN5VU2BprOvGGUkOOQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.2", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.2.tgz", + "integrity": "sha512-JKCrLNOup3OOgmzeaKQwi4ZCTWlYR5H4Gm1r2uTMVBXoemo1UEghk5vtMi1xSu2ymgKVGW631e2fp9/R610ZjQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-body-length-node": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.3.tgz", + "integrity": "sha512-ZkJGvqBzMHVHE7r/hcuCxlTY8pQr1kMtdsVPs7ex4mMU+EAbcXppfo5NmyxMYi2XU49eqaz56j2gsk4dHHPG/g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.2.2.tgz", + "integrity": "sha512-FDXD7cvUoFWwN6vtQfEta540Y/YBe5JneK3SoZg9bThSoOAC/eGeYEua6RkBgKjGa/sz6Y+DuBZj3+YEY21y4Q==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-config-provider": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.2.2.tgz", + "integrity": "sha512-dWU03V3XUprJwaUIFVv4iOnS1FC9HnMHDfUrlNDSh4315v0cWyaIErP8KiqGVbf5z+JupoVpNM7ZB3jFiTejvQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "4.3.41", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.41.tgz", + "integrity": "sha512-M1w1Ux0rSVvBOxIIiqbxvZvhnjQ+VUjJrugtORE90BbadSTH+jsQL279KRL3Hv0w69rE7EuYkV/4Lepz/NBW9g==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^4.2.12", + "@smithy/smithy-client": "^4.12.5", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "4.2.44", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.44.tgz", + "integrity": "sha512-YPze3/lD1KmWuZsl9JlfhcgGLX7AXhSoaCDtiPntUjNW5/YY0lOHjkcgxyE9x/h5vvS1fzDifMGjzqnNlNiqOQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/config-resolver": "^4.4.11", + "@smithy/credential-provider-imds": "^4.2.12", + "@smithy/node-config-provider": "^4.3.12", + "@smithy/property-provider": "^4.2.12", + "@smithy/smithy-client": "^4.12.5", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-endpoints": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.3.3.tgz", + "integrity": "sha512-VACQVe50j0HZPjpwWcjyT51KUQ4AnsvEaQ2lKHOSL4mNLD0G9BjEniQ+yCt1qqfKfiAHRAts26ud7hBjamrwig==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.2.tgz", + "integrity": "sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-middleware": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.12.tgz", + "integrity": "sha512-Er805uFUOvgc0l8nv0e0su0VFISoxhJ/AwOn3gL2NWNY2LUEldP5WtVcRYSQBcjg0y9NfG8JYrCJaYDpupBHJQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-retry": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.12.tgz", + "integrity": "sha512-1zopLDUEOwumjcHdJ1mwBHddubYF8GMQvstVCLC54Y46rqoHwlIU+8ZzUeaBcD+WCJHyDGSeZ2ml9YSe9aqcoQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/service-error-classification": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-stream": { + "version": "4.5.19", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.19.tgz", + "integrity": "sha512-v4sa+3xTweL1CLO2UP0p7tvIMH/Rq1X4KKOxd568mpe6LSLMQCnDHs4uv7m3ukpl3HvcN2JH6jiCS0SNRXKP/w==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/fetch-http-handler": "^5.3.15", + "@smithy/node-http-handler": "^4.4.16", + "@smithy/types": "^4.13.1", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-buffer-from": "^4.2.2", + "@smithy/util-hex-encoding": "^4.2.2", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-uri-escape": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.2.tgz", + "integrity": "sha512-2kAStBlvq+lTXHyAZYfJRb/DfS3rsinLiwb+69SstC9Vb0s9vNWkRwpnj918Pfi85mzi42sOqdV72OLxWAISnw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.2.tgz", + "integrity": "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-waiter": { + "version": "4.2.13", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.13.tgz", + "integrity": "sha512-2zdZ9DTHngRtcYxJK1GUDxruNr53kv5W2Lupe0LMU+Imr6ohQg8M2T14MNkj1Y0wS3FFwpgpGQyvuaMF7CiTmQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/abort-controller": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/uuid": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@smithy/uuid/-/uuid-1.1.2.tgz", + "integrity": "sha512-O/IEdcCUKkubz60tFbGA7ceITTAJsty+lBjNoorP4Z6XRqaFb/OjQjZODophEcuq68nKm6/0r+6/lLQ+XVpk8g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/bcrypt": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz", + "integrity": "sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookie-parser": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.8.tgz", + "integrity": "sha512-l37JqFrOJ9yQfRQkljb41l0xVphc7kg5JTjjr+pLRZ0IyZ49V4BQ8vbF4Ut2C2e+WH4al3xD3ZwYwIUfnbT4NQ==", + "dev": true, + "peerDependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/cookiejar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", + "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz", + "integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.6.tgz", + "integrity": "sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz", + "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^30.0.0", + "pretty-format": "^30.0.0" + } + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.9.tgz", + "integrity": "sha512-uoe+GxEuHbvy12OUQct2X9JenKM3qAscquYymuQN4fMWG9DBQtykrQEFcAbVACF7qaLw9BePSodUL0kquqBJpQ==", + "dev": true, + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/methods": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", + "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true + }, + "node_modules/@types/multer": { + "version": "1.4.12", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.12.tgz", + "integrity": "sha512-pQ2hoqvXiJt2FP9WQVLPRO+AmiIm/ZYkavPlIQnx282u4ZrVdztx0pkh3jjpQt0Kz+YI0YhSG264y08UJKoUQg==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/multer-s3": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/multer-s3/-/multer-s3-3.0.3.tgz", + "integrity": "sha512-VgWygI9UwyS7loLithUUi0qAMIDWdNrERS2Sb06UuPYiLzKuIFn2NgL7satyl4v8sh/LLoU7DiPanvbQaRg9Yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@aws-sdk/client-s3": "^3.0.0", + "@types/multer": "*", + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "22.13.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.9.tgz", + "integrity": "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==", + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/@types/qs": { + "version": "6.9.18", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", + "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/superagent": { + "version": "8.1.9", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.9.tgz", + "integrity": "sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/cookiejar": "^2.1.5", + "@types/methods": "^1.1.4", + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/@types/supertest": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-7.2.0.tgz", + "integrity": "sha512-uh2Lv57xvggst6lCqNdFAmDSvoMG7M/HDtX4iUCquxQ5EGPtaPM5PL5Hmi7LCvOG8db7YaCPNJEeoI8s/WzIQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/methods": "^1.1.4", + "@types/superagent": "^8.1.0" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/babel-jest": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.2.0.tgz", + "integrity": "sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "30.2.0", + "@types/babel__core": "^7.20.5", + "babel-plugin-istanbul": "^7.0.1", + "babel-preset-jest": "30.2.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0 || ^8.0.0-0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz", + "integrity": "sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==", + "dev": true, + "license": "BSD-3-Clause", + "workspaces": [ + "test/babel-8" + ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.2.0.tgz", + "integrity": "sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/babel__core": "^7.20.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.2.0.tgz", + "integrity": "sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "30.2.0", + "babel-preset-current-node-syntax": "^1.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0 || ^8.0.0-beta.1" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "license": "MIT", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", + "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bowser": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz", + "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "license": "MIT", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001776", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001776.tgz", + "integrity": "sha512-sg01JDPzZ9jGshqKSckOQthXnYwOEP50jeVFhaSFbZcOy05TiuuaffDOfcwtCisJ9kNQuLBFibYywv2Bgm9osw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz", + "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/dedent": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz", + "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "license": "ISC", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.307", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz", + "integrity": "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/engine.io": { + "version": "6.6.5", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.5.tgz", + "integrity": "sha512-2RZdgEbXmp5+dVbRm0P7HQUImZpICccJy7rN7Tv+SFa55pH+lxnuw6/K1ZxxBfHoYpSkHLAO92oa8O4SwFXA2A==", + "license": "MIT", + "dependencies": { + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.7.2", + "cors": "~2.8.5", + "debug": "~4.4.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.18.3" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit-x": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", + "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "30.2.0", + "@jest/get-type": "30.1.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-xml-builder": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.3.tgz", + "integrity": "sha512-1o60KoFw2+LWKQu3IdcfcFlGTW4dpqEWmjhYec6H82AYZU2TVBXep6tMl8Z1Y+wM+ZrzCwe3BZ9Vyd9N2rIvmg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "path-expression-matcher": "^1.1.3" + } + }, + "node_modules/fast-xml-parser": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.4.1.tgz", + "integrity": "sha512-BQ30U1mKkvXQXXkAGcuyUA/GA26oEB7NzOtsxCDtyu62sjGw5QraKFhx2Em3WQNjPw9PG6MQ9yuIIgkSDfGu5A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "fast-xml-builder": "^1.0.0", + "strnum": "^2.1.2" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formidable": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", + "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@paralleldrive/cuid2": "^2.2.2", + "dezalgo": "^1.0.4", + "once": "^1.4.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", + "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", + "license": "MIT" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.2.0.tgz", + "integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "30.2.0", + "@jest/types": "30.2.0", + "import-local": "^3.2.0", + "jest-cli": "30.2.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.2.0.tgz", + "integrity": "sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.1.1", + "jest-util": "30.2.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-circus": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.2.0.tgz", + "integrity": "sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/expect": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "co": "^4.6.0", + "dedent": "^1.6.0", + "is-generator-fn": "^2.1.0", + "jest-each": "30.2.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-runtime": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "p-limit": "^3.1.0", + "pretty-format": "30.2.0", + "pure-rand": "^7.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-cli": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.2.0.tgz", + "integrity": "sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "exit-x": "^0.2.2", + "import-local": "^3.2.0", + "jest-config": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "yargs": "^17.7.2" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.2.0.tgz", + "integrity": "sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/get-type": "30.1.0", + "@jest/pattern": "30.0.1", + "@jest/test-sequencer": "30.2.0", + "@jest/types": "30.2.0", + "babel-jest": "30.2.0", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "deepmerge": "^4.3.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-circus": "30.2.0", + "jest-docblock": "30.2.0", + "jest-environment-node": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-runner": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "micromatch": "^4.0.8", + "parse-json": "^5.2.0", + "pretty-format": "30.2.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "esbuild-register": ">=3.4.0", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "esbuild-register": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/jest-config/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/jest-diff": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", + "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.2.0.tgz", + "integrity": "sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-each": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.2.0.tgz", + "integrity": "sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "jest-util": "30.2.0", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.2.0.tgz", + "integrity": "sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/fake-timers": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-mock": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.2.0.tgz", + "integrity": "sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.2.0", + "jest-worker": "30.2.0", + "micromatch": "^4.0.8", + "walker": "^1.0.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.3" + } + }, + "node_modules/jest-leak-detector": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.2.0.tgz", + "integrity": "sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", + "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "jest-diff": "30.2.0", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", + "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.2.0", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.2.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-mock": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", + "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-util": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.2.0.tgz", + "integrity": "sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-pnp-resolver": "^1.2.3", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "slash": "^3.0.0", + "unrs-resolver": "^1.7.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.2.0.tgz", + "integrity": "sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "30.0.1", + "jest-snapshot": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runner": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.2.0.tgz", + "integrity": "sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.2.0", + "@jest/environment": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-docblock": "30.2.0", + "jest-environment-node": "30.2.0", + "jest-haste-map": "30.2.0", + "jest-leak-detector": "30.2.0", + "jest-message-util": "30.2.0", + "jest-resolve": "30.2.0", + "jest-runtime": "30.2.0", + "jest-util": "30.2.0", + "jest-watcher": "30.2.0", + "jest-worker": "30.2.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.2.0.tgz", + "integrity": "sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/fake-timers": "30.2.0", + "@jest/globals": "30.2.0", + "@jest/source-map": "30.0.1", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "cjs-module-lexer": "^2.1.0", + "collect-v8-coverage": "^1.0.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runtime/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-runtime/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-runtime/node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/jest-snapshot": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.2.0.tgz", + "integrity": "sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.2.0", + "@jest/get-type": "30.1.0", + "@jest/snapshot-utils": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "babel-preset-current-node-syntax": "^1.2.0", + "chalk": "^4.1.2", + "expect": "30.2.0", + "graceful-fs": "^4.2.11", + "jest-diff": "30.2.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "pretty-format": "30.2.0", + "semver": "^7.7.2", + "synckit": "^0.11.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", + "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-util/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-validate": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.2.0.tgz", + "integrity": "sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "@jest/types": "30.2.0", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", + "leven": "^3.1.0", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.2.0.tgz", + "integrity": "sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "jest-util": "30.2.0", + "string-length": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-worker": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.2.0.tgz", + "integrity": "sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.2.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lru-cache/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/multer-s3": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/multer-s3/-/multer-s3-3.0.1.tgz", + "integrity": "sha512-BFwSO80a5EW4GJRBdUuSHblz2jhVSAze33ZbnGpcfEicoT0iRolx4kWR+AJV07THFRCQ78g+kelKFdjkCCaXeQ==", + "license": "MIT", + "dependencies": { + "@aws-sdk/lib-storage": "^3.46.0", + "file-type": "^3.3.0", + "html-comment-regex": "^1.1.2", + "run-parallel": "^1.1.6" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-s3": "^3.0.0" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nodemon": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.9.tgz", + "integrity": "sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-expression-matcher": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.1.3.tgz", + "integrity": "sha512-qdVgY8KXmVdJZRSS1JdEPOKPdTiEK/pi0RkcT2sw1RhXxohdujUlJFPuS1TSkevZ9vzd3ZlL7ULl1MHGTApKzQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/prettier": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-format": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", + "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prisma": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.16.2.tgz", + "integrity": "sha512-rFV/xoBR2hBGGlu4LPLQd4U8WVA+tSAmYyFWGPRVfj+xg7N4kiZV4lSk38htSpF+/IuHKzlrbh4SFk8Z18cI8A==", + "devOptional": true, + "hasInstallScript": true, + "dependencies": { + "@prisma/engines": "5.16.2" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "node_modules/pure-rand": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", + "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/socket.io": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.3.tgz", + "integrity": "sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.4.1", + "engine.io": "~6.6.0", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.6.tgz", + "integrity": "sha512-DkkO/dz7MGln0dHn5bmN3pPy+JmywNICWrJqVWiVOyvXjWQFIv9c2h24JrQLLFJ2aQVQf/Cvl1vblnd4r2apLQ==", + "license": "MIT", + "dependencies": { + "debug": "~4.4.1", + "ws": "~8.18.3" + } + }, + "node_modules/socket.io-adapter/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-adapter/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/socket.io-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.5.tgz", + "integrity": "sha512-bPMmpy/5WWKHea5Y/jYAP6k74A+hvmRCQaJuJB6I/ML5JZq/KfNieUVo/3Mh7SAqn7TyFdIo6wqYHInG1MU1bQ==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/socket.io/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "license": "MIT", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/stream-browserify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strnum": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.0.tgz", + "integrity": "sha512-Y7Bj8XyJxnPAORMZj/xltsfo55uOiyHcU2tnAVzHUnSJR/KsEX+9RoDeXEnsXtl/CX4fAcrt64gZ13aGaWPeBg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/superagent": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.3.0.tgz", + "integrity": "sha512-B+4Ik7ROgVKrQsXTV0Jwp2u+PXYLSlqtDAhYnkkD+zn3yg8s/zjA2MeGayPoY/KICrbitwneDHrjSotxKL+0XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "component-emitter": "^1.3.1", + "cookiejar": "^2.1.4", + "debug": "^4.3.7", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.5", + "formidable": "^3.5.4", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.14.1" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/superagent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/superagent/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/superagent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/superagent/node_modules/qs": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/superstruct": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-2.0.2.tgz", + "integrity": "sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/supertest": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.2.2.tgz", + "integrity": "sha512-oK8WG9diS3DlhdUkcFn4tkNIiIbBx9lI2ClF8K+b2/m8Eyv47LSawxUzZQSNKUrVb2KsqeTDCcjAAVPYaSLVTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cookie-signature": "^1.2.2", + "methods": "^1.1.2", + "superagent": "^10.3.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/supertest/node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/synckit": { + "version": "0.11.12", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", + "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/ts-jest": { + "version": "29.4.6", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.6.tgz", + "integrity": "sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bs-logger": "^0.2.6", + "fast-json-stable-stringify": "^2.1.0", + "handlebars": "^4.7.8", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.7.3", + "type-fest": "^4.41.0", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0 || ^30.0.0", + "@jest/types": "^29.0.0 || ^30.0.0", + "babel-jest": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-util": "^29.0.0 || ^30.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jest-util": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "node_modules/typescript": { + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", + "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.5.tgz", + "integrity": "sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "requires": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "@aws-crypto/crc32c": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", + "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==", + "requires": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "@aws-crypto/sha1-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz", + "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==", + "requires": { + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "requires": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "requires": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + } + } + } + }, + "@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "requires": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "requires": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "requires": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + } + } + } + }, + "@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "requires": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "requires": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "requires": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "requires": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + } + } + } + }, + "@aws-sdk/client-s3": { + "version": "3.1008.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.1008.0.tgz", + "integrity": "sha512-w/SIRD25v2zVMbkn8CYIxUsac8yf5Jghkhw5j7EsNWdJhl56m/nWpUX7t1etFUW1cnzpFjZV0lXt0dNFSnbXwA==", + "requires": { + "@aws-crypto/sha1-browser": "5.2.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/credential-provider-node": "^3.972.20", + "@aws-sdk/middleware-bucket-endpoint": "^3.972.7", + "@aws-sdk/middleware-expect-continue": "^3.972.7", + "@aws-sdk/middleware-flexible-checksums": "^3.973.5", + "@aws-sdk/middleware-host-header": "^3.972.7", + "@aws-sdk/middleware-location-constraint": "^3.972.7", + "@aws-sdk/middleware-logger": "^3.972.7", + "@aws-sdk/middleware-recursion-detection": "^3.972.7", + "@aws-sdk/middleware-sdk-s3": "^3.972.19", + "@aws-sdk/middleware-ssec": "^3.972.7", + "@aws-sdk/middleware-user-agent": "^3.972.20", + "@aws-sdk/region-config-resolver": "^3.972.7", + "@aws-sdk/signature-v4-multi-region": "^3.996.7", + "@aws-sdk/types": "^3.973.5", + "@aws-sdk/util-endpoints": "^3.996.4", + "@aws-sdk/util-user-agent-browser": "^3.972.7", + "@aws-sdk/util-user-agent-node": "^3.973.6", + "@smithy/config-resolver": "^4.4.10", + "@smithy/core": "^3.23.9", + "@smithy/eventstream-serde-browser": "^4.2.11", + "@smithy/eventstream-serde-config-resolver": "^4.3.11", + "@smithy/eventstream-serde-node": "^4.2.11", + "@smithy/fetch-http-handler": "^5.3.13", + "@smithy/hash-blob-browser": "^4.2.12", + "@smithy/hash-node": "^4.2.11", + "@smithy/hash-stream-node": "^4.2.11", + "@smithy/invalid-dependency": "^4.2.11", + "@smithy/md5-js": "^4.2.11", + "@smithy/middleware-content-length": "^4.2.11", + "@smithy/middleware-endpoint": "^4.4.23", + "@smithy/middleware-retry": "^4.4.40", + "@smithy/middleware-serde": "^4.2.12", + "@smithy/middleware-stack": "^4.2.11", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/node-http-handler": "^4.4.14", + "@smithy/protocol-http": "^5.3.11", + "@smithy/smithy-client": "^4.12.3", + "@smithy/types": "^4.13.0", + "@smithy/url-parser": "^4.2.11", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-body-length-browser": "^4.2.2", + "@smithy/util-body-length-node": "^4.2.3", + "@smithy/util-defaults-mode-browser": "^4.3.39", + "@smithy/util-defaults-mode-node": "^4.2.42", + "@smithy/util-endpoints": "^3.3.2", + "@smithy/util-middleware": "^4.2.11", + "@smithy/util-retry": "^4.2.11", + "@smithy/util-stream": "^4.5.17", + "@smithy/util-utf8": "^4.2.2", + "@smithy/util-waiter": "^4.2.12", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/core": { + "version": "3.973.19", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.19.tgz", + "integrity": "sha512-56KePyOcZnKTWCd89oJS1G6j3HZ9Kc+bh/8+EbvtaCCXdP6T7O7NzCiPuHRhFLWnzXIaXX3CxAz0nI5My9spHQ==", + "requires": { + "@aws-sdk/types": "^3.973.5", + "@aws-sdk/xml-builder": "^3.972.10", + "@smithy/core": "^3.23.9", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/property-provider": "^4.2.11", + "@smithy/protocol-http": "^5.3.11", + "@smithy/signature-v4": "^5.3.11", + "@smithy/smithy-client": "^4.12.3", + "@smithy/types": "^4.13.0", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-middleware": "^4.2.11", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/crc64-nvme": { + "version": "3.972.4", + "resolved": "https://registry.npmjs.org/@aws-sdk/crc64-nvme/-/crc64-nvme-3.972.4.tgz", + "integrity": "sha512-HKZIZLbRyvzo/bXZU7Zmk6XqU+1C9DjI56xd02vwuDIxedxBEqP17t9ExhbP9QFeNq/a3l9GOcyirFXxmbDhmw==", + "requires": { + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-env": { + "version": "3.972.17", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.17.tgz", + "integrity": "sha512-MBAMW6YELzE1SdkOniqr51mrjapQUv8JXSGxtwRjQV0mwVDutVsn22OPAUt4RcLRvdiHQmNBDEFP9iTeSVCOlA==", + "requires": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/types": "^3.973.5", + "@smithy/property-provider": "^4.2.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-http": { + "version": "3.972.19", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.19.tgz", + "integrity": "sha512-9EJROO8LXll5a7eUFqu48k6BChrtokbmgeMWmsH7lBb6lVbtjslUYz/ShLi+SHkYzTomiGBhmzTW7y+H4BxsnA==", + "requires": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/types": "^3.973.5", + "@smithy/fetch-http-handler": "^5.3.13", + "@smithy/node-http-handler": "^4.4.14", + "@smithy/property-provider": "^4.2.11", + "@smithy/protocol-http": "^5.3.11", + "@smithy/smithy-client": "^4.12.3", + "@smithy/types": "^4.13.0", + "@smithy/util-stream": "^4.5.17", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-ini": { + "version": "3.972.19", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.19.tgz", + "integrity": "sha512-pVJVjWqVrPqjpFq7o0mCmeZu1Y0c94OCHSYgivdCD2wfmYVtBbwQErakruhgOD8pcMcx9SCqRw1pzHKR7OGBcA==", + "requires": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/credential-provider-env": "^3.972.17", + "@aws-sdk/credential-provider-http": "^3.972.19", + "@aws-sdk/credential-provider-login": "^3.972.19", + "@aws-sdk/credential-provider-process": "^3.972.17", + "@aws-sdk/credential-provider-sso": "^3.972.19", + "@aws-sdk/credential-provider-web-identity": "^3.972.19", + "@aws-sdk/nested-clients": "^3.996.9", + "@aws-sdk/types": "^3.973.5", + "@smithy/credential-provider-imds": "^4.2.11", + "@smithy/property-provider": "^4.2.11", + "@smithy/shared-ini-file-loader": "^4.4.6", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-login": { + "version": "3.972.19", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.19.tgz", + "integrity": "sha512-jOXdZ1o+CywQKr6gyxgxuUmnGwTTnY2Kxs1PM7fI6AYtDWDnmW/yKXayNqkF8KjP1unflqMWKVbVt5VgmE3L0g==", + "requires": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/nested-clients": "^3.996.9", + "@aws-sdk/types": "^3.973.5", + "@smithy/property-provider": "^4.2.11", + "@smithy/protocol-http": "^5.3.11", + "@smithy/shared-ini-file-loader": "^4.4.6", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-node": { + "version": "3.972.20", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.20.tgz", + "integrity": "sha512-0xHca2BnPY0kzjDYPH7vk8YbfdBPpWVS67rtqQMalYDQUCBYS37cZ55K6TuFxCoIyNZgSCFrVKr9PXC5BVvQQw==", + "requires": { + "@aws-sdk/credential-provider-env": "^3.972.17", + "@aws-sdk/credential-provider-http": "^3.972.19", + "@aws-sdk/credential-provider-ini": "^3.972.19", + "@aws-sdk/credential-provider-process": "^3.972.17", + "@aws-sdk/credential-provider-sso": "^3.972.19", + "@aws-sdk/credential-provider-web-identity": "^3.972.19", + "@aws-sdk/types": "^3.973.5", + "@smithy/credential-provider-imds": "^4.2.11", + "@smithy/property-provider": "^4.2.11", + "@smithy/shared-ini-file-loader": "^4.4.6", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-process": { + "version": "3.972.17", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.17.tgz", + "integrity": "sha512-c8G8wT1axpJDgaP3xzcy+q8Y1fTi9A2eIQJvyhQ9xuXrUZhlCfXbC0vM9bM1CUXiZppFQ1p7g0tuUMvil/gCPg==", + "requires": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/types": "^3.973.5", + "@smithy/property-provider": "^4.2.11", + "@smithy/shared-ini-file-loader": "^4.4.6", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-sso": { + "version": "3.972.19", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.19.tgz", + "integrity": "sha512-kVjQsEU3b///q7EZGrUzol9wzwJFKbEzqJKSq82A9ShrUTEO7FNylTtby3sPV19ndADZh1H3FB3+5ZrvKtEEeg==", + "requires": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/nested-clients": "^3.996.9", + "@aws-sdk/token-providers": "3.1008.0", + "@aws-sdk/types": "^3.973.5", + "@smithy/property-provider": "^4.2.11", + "@smithy/shared-ini-file-loader": "^4.4.6", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-web-identity": { + "version": "3.972.19", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.19.tgz", + "integrity": "sha512-BV1BlTFdG4w4tAihxN7iXDBoNcNewXD4q8uZlNQiUrnqxwGWUhKHODIQVSPlQGxXClEj+63m+cqZskw+ESmeZg==", + "requires": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/nested-clients": "^3.996.9", + "@aws-sdk/types": "^3.973.5", + "@smithy/property-provider": "^4.2.11", + "@smithy/shared-ini-file-loader": "^4.4.6", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/lib-storage": { + "version": "3.1008.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.1008.0.tgz", + "integrity": "sha512-SWIzixPt9VG6jz8+tR8VklOi3FXY1J6WMfd1JEtY9gVtJaLGF5tWexIkjUnGHP8B6M6Uk+qC5zdr2Caome5Gfg==", + "requires": { + "@smithy/abort-controller": "^4.2.11", + "@smithy/middleware-endpoint": "^4.4.23", + "@smithy/smithy-client": "^4.12.3", + "buffer": "5.6.0", + "events": "3.3.0", + "stream-browserify": "3.0.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-bucket-endpoint": { + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.972.7.tgz", + "integrity": "sha512-goX+axlJ6PQlRnzE2bQisZ8wVrlm6dXJfBzMJhd8LhAIBan/w1Kl73fJnalM/S+18VnpzIHumyV6DtgmvqG5IA==", + "requires": { + "@aws-sdk/types": "^3.973.5", + "@aws-sdk/util-arn-parser": "^3.972.3", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "@smithy/util-config-provider": "^4.2.2", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-expect-continue": { + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.972.7.tgz", + "integrity": "sha512-mvWqvm61bmZUKmmrtl2uWbokqpenY3Mc3Jf4nXB/Hse6gWxLPaCQThmhPBDzsPSV8/Odn8V6ovWt3pZ7vy4BFQ==", + "requires": { + "@aws-sdk/types": "^3.973.5", + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-flexible-checksums": { + "version": "3.973.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.973.5.tgz", + "integrity": "sha512-Dp3hqE5W6hG8HQ3Uh+AINx9wjjqYmFHbxede54sGj3akx/haIQrkp85lNdTdC+ouNUcSYNiuGkzmyDREfHX1Gg==", + "requires": { + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-crypto/util": "5.2.0", + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/crc64-nvme": "^3.972.4", + "@aws-sdk/types": "^3.973.5", + "@smithy/is-array-buffer": "^4.2.2", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "@smithy/util-middleware": "^4.2.11", + "@smithy/util-stream": "^4.5.17", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-host-header": { + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.972.7.tgz", + "integrity": "sha512-aHQZgztBFEpDU1BB00VWCIIm85JjGjQW1OG9+98BdmaOpguJvzmXBGbnAiYcciCd+IS4e9BEq664lhzGnWJHgQ==", + "requires": { + "@aws-sdk/types": "^3.973.5", + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-location-constraint": { + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.972.7.tgz", + "integrity": "sha512-vdK1LJfffBp87Lj0Bw3WdK1rJk9OLDYdQpqoKgmpIZPe+4+HawZ6THTbvjhJt4C4MNnRrHTKHQjkwBiIpDBoig==", + "requires": { + "@aws-sdk/types": "^3.973.5", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-logger": { + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.972.7.tgz", + "integrity": "sha512-LXhiWlWb26txCU1vcI9PneESSeRp/RYY/McuM4SpdrimQR5NgwaPb4VJCadVeuGWgh6QmqZ6rAKSoL1ob16W6w==", + "requires": { + "@aws-sdk/types": "^3.973.5", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-recursion-detection": { + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.972.7.tgz", + "integrity": "sha512-l2VQdcBcYLzIzykCHtXlbpiVCZ94/xniLIkAj0jpnpjY4xlgZx7f56Ypn+uV1y3gG0tNVytJqo3K9bfMFee7SQ==", + "requires": { + "@aws-sdk/types": "^3.973.5", + "@aws/lambda-invoke-store": "^0.2.2", + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-sdk-s3": { + "version": "3.972.19", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.19.tgz", + "integrity": "sha512-/CtOHHVFg4ZuN6CnLnYkrqWgVEnbOBC4kNiKa+4fldJ9cioDt3dD/f5vpq0cWLOXwmGL2zgVrVxNhjxWpxNMkg==", + "requires": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/types": "^3.973.5", + "@aws-sdk/util-arn-parser": "^3.972.3", + "@smithy/core": "^3.23.9", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/protocol-http": "^5.3.11", + "@smithy/signature-v4": "^5.3.11", + "@smithy/smithy-client": "^4.12.3", + "@smithy/types": "^4.13.0", + "@smithy/util-config-provider": "^4.2.2", + "@smithy/util-middleware": "^4.2.11", + "@smithy/util-stream": "^4.5.17", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-ssec": { + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.972.7.tgz", + "integrity": "sha512-G9clGVuAml7d8DYzY6DnRi7TIIDRvZ3YpqJPz/8wnWS5fYx/FNWNmkO6iJVlVkQg9BfeMzd+bVPtPJOvC4B+nQ==", + "requires": { + "@aws-sdk/types": "^3.973.5", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-user-agent": { + "version": "3.972.20", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.20.tgz", + "integrity": "sha512-3kNTLtpUdeahxtnJRnj/oIdLAUdzTfr9N40KtxNhtdrq+Q1RPMdCJINRXq37m4t5+r3H70wgC3opW46OzFcZYA==", + "requires": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/types": "^3.973.5", + "@aws-sdk/util-endpoints": "^3.996.4", + "@smithy/core": "^3.23.9", + "@smithy/protocol-http": "^5.3.11", + "@smithy/types": "^4.13.0", + "@smithy/util-retry": "^4.2.11", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/nested-clients": { + "version": "3.996.9", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.996.9.tgz", + "integrity": "sha512-+RpVtpmQbbtzFOKhMlsRcXM/3f1Z49qTOHaA8gEpHOYruERmog6f2AUtf/oTRLCWjR9H2b3roqryV/hI7QMW8w==", + "requires": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/middleware-host-header": "^3.972.7", + "@aws-sdk/middleware-logger": "^3.972.7", + "@aws-sdk/middleware-recursion-detection": "^3.972.7", + "@aws-sdk/middleware-user-agent": "^3.972.20", + "@aws-sdk/region-config-resolver": "^3.972.7", + "@aws-sdk/types": "^3.973.5", + "@aws-sdk/util-endpoints": "^3.996.4", + "@aws-sdk/util-user-agent-browser": "^3.972.7", + "@aws-sdk/util-user-agent-node": "^3.973.6", + "@smithy/config-resolver": "^4.4.10", + "@smithy/core": "^3.23.9", + "@smithy/fetch-http-handler": "^5.3.13", + "@smithy/hash-node": "^4.2.11", + "@smithy/invalid-dependency": "^4.2.11", + "@smithy/middleware-content-length": "^4.2.11", + "@smithy/middleware-endpoint": "^4.4.23", + "@smithy/middleware-retry": "^4.4.40", + "@smithy/middleware-serde": "^4.2.12", + "@smithy/middleware-stack": "^4.2.11", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/node-http-handler": "^4.4.14", + "@smithy/protocol-http": "^5.3.11", + "@smithy/smithy-client": "^4.12.3", + "@smithy/types": "^4.13.0", + "@smithy/url-parser": "^4.2.11", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-body-length-browser": "^4.2.2", + "@smithy/util-body-length-node": "^4.2.3", + "@smithy/util-defaults-mode-browser": "^4.3.39", + "@smithy/util-defaults-mode-node": "^4.2.42", + "@smithy/util-endpoints": "^3.3.2", + "@smithy/util-middleware": "^4.2.11", + "@smithy/util-retry": "^4.2.11", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/region-config-resolver": { + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.972.7.tgz", + "integrity": "sha512-/Ev/6AI8bvt4HAAptzSjThGUMjcWaX3GX8oERkB0F0F9x2dLSBdgFDiyrRz3i0u0ZFZFQ1b28is4QhyqXTUsVA==", + "requires": { + "@aws-sdk/types": "^3.973.5", + "@smithy/config-resolver": "^4.4.10", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/signature-v4-multi-region": { + "version": "3.996.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.7.tgz", + "integrity": "sha512-mYhh7FY+7OOqjkYkd6+6GgJOsXK1xBWmuR+c5mxJPj2kr5TBNeZq+nUvE9kANWAux5UxDVrNOSiEM/wlHzC3Lg==", + "requires": { + "@aws-sdk/middleware-sdk-s3": "^3.972.19", + "@aws-sdk/types": "^3.973.5", + "@smithy/protocol-http": "^5.3.11", + "@smithy/signature-v4": "^5.3.11", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/token-providers": { + "version": "3.1008.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1008.0.tgz", + "integrity": "sha512-TulwlHQBWcJs668kNUDMZHN51DeLrDsYT59Ux4a/nbvr025gM6HjKJJ3LvnZccam7OS/ZKUVkWomCneRQKJbBg==", + "requires": { + "@aws-sdk/core": "^3.973.19", + "@aws-sdk/nested-clients": "^3.996.9", + "@aws-sdk/types": "^3.973.5", + "@smithy/property-provider": "^4.2.11", + "@smithy/shared-ini-file-loader": "^4.4.6", + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/types": { + "version": "3.973.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.973.5.tgz", + "integrity": "sha512-hl7BGwDCWsjH8NkZfx+HgS7H2LyM2lTMAI7ba9c8O0KqdBLTdNJivsHpqjg9rNlAlPyREb6DeDRXUl0s8uFdmQ==", + "requires": { + "@smithy/types": "^4.13.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/util-arn-parser": { + "version": "3.972.3", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.972.3.tgz", + "integrity": "sha512-HzSD8PMFrvgi2Kserxuff5VitNq2sgf3w9qxmskKDiDTThWfVteJxuCS9JXiPIPtmCrp+7N9asfIaVhBFORllA==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@aws-sdk/util-endpoints": { + "version": "3.996.4", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.996.4.tgz", + "integrity": "sha512-Hek90FBmd4joCFj+Vc98KLJh73Zqj3s2W56gjAcTkrNLMDI5nIFkG9YpfcJiVI1YlE2Ne1uOQNe+IgQ/Vz2XRA==", + "requires": { + "@aws-sdk/types": "^3.973.5", + "@smithy/types": "^4.13.0", + "@smithy/url-parser": "^4.2.11", + "@smithy/util-endpoints": "^3.3.2", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/util-locate-window": { + "version": "3.965.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.965.5.tgz", + "integrity": "sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@aws-sdk/util-user-agent-browser": { + "version": "3.972.7", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.972.7.tgz", + "integrity": "sha512-7SJVuvhKhMF/BkNS1n0QAJYgvEwYbK2QLKBrzDiwQGiTRU6Yf1f3nehTzm/l21xdAOtWSfp2uWSddPnP2ZtsVw==", + "requires": { + "@aws-sdk/types": "^3.973.5", + "@smithy/types": "^4.13.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/util-user-agent-node": { + "version": "3.973.6", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.6.tgz", + "integrity": "sha512-iF7G0prk7AvmOK64FcLvc/fW+Ty1H+vttajL7PvJFReU8urMxfYmynTTuFKDTA76Wgpq3FzTPKwabMQIXQHiXQ==", + "requires": { + "@aws-sdk/middleware-user-agent": "^3.972.20", + "@aws-sdk/types": "^3.973.5", + "@smithy/node-config-provider": "^4.3.11", + "@smithy/types": "^4.13.0", + "@smithy/util-config-provider": "^4.2.2", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/xml-builder": { + "version": "3.972.10", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.10.tgz", + "integrity": "sha512-OnejAIVD+CxzyAUrVic7lG+3QRltyja9LoNqCE/1YVs8ichoTbJlVSaZ9iSMcnHLyzrSNtvaOGjSDRP+d/ouFA==", + "requires": { + "@smithy/types": "^4.13.0", + "fast-xml-parser": "5.4.1", + "tslib": "^2.6.2" + } + }, + "@aws/lambda-invoke-store": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.4.tgz", + "integrity": "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==" + }, + "@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + } + }, + "@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true + }, + "@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "dependencies": { + "debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "requires": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + } + } + }, + "@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true + }, + "@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "requires": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + } + }, + "@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true + }, + "@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true + }, + "@babel/helpers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "dev": true, + "requires": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + } + }, + "@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "dev": true, + "requires": { + "@babel/types": "^7.29.0" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-import-attributes": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", + "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.28.6" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.28.6" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.28.6" + } + }, + "@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + } + }, + "@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "dependencies": { + "debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + } + }, + "@emnapi/core": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz", + "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==", + "dev": true, + "optional": true, + "requires": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "@emnapi/runtime": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "dev": true, + "optional": true, + "requires": { + "tslib": "^2.4.0" + } + }, + "@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "dev": true, + "optional": true, + "requires": { + "tslib": "^2.4.0" + } + }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "requires": { + "ansi-regex": "^6.2.2" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true + }, + "@jest/console": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.2.0.tgz", + "integrity": "sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==", + "dev": true, + "requires": { + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "slash": "^3.0.0" + } + }, + "@jest/core": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.2.0.tgz", + "integrity": "sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==", + "dev": true, + "requires": { + "@jest/console": "30.2.0", + "@jest/pattern": "30.0.1", + "@jest/reporters": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-changed-files": "30.2.0", + "jest-config": "30.2.0", + "jest-haste-map": "30.2.0", + "jest-message-util": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-resolve-dependencies": "30.2.0", + "jest-runner": "30.2.0", + "jest-runtime": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "jest-watcher": "30.2.0", + "micromatch": "^4.0.8", + "pretty-format": "30.2.0", + "slash": "^3.0.0" + } + }, + "@jest/diff-sequences": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", + "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "dev": true + }, + "@jest/environment": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.2.0.tgz", + "integrity": "sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==", + "dev": true, + "requires": { + "@jest/fake-timers": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-mock": "30.2.0" + } + }, + "@jest/expect": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==", + "dev": true, + "requires": { + "expect": "30.2.0", + "jest-snapshot": "30.2.0" + } + }, + "@jest/expect-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", + "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", + "dev": true, + "requires": { + "@jest/get-type": "30.1.0" + } + }, + "@jest/fake-timers": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.2.0.tgz", + "integrity": "sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==", + "dev": true, + "requires": { + "@jest/types": "30.2.0", + "@sinonjs/fake-timers": "^13.0.0", + "@types/node": "*", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" + } + }, + "@jest/get-type": { + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz", + "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", + "dev": true + }, + "@jest/globals": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.2.0.tgz", + "integrity": "sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==", + "dev": true, + "requires": { + "@jest/environment": "30.2.0", + "@jest/expect": "30.2.0", + "@jest/types": "30.2.0", + "jest-mock": "30.2.0" + } + }, + "@jest/pattern": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", + "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", + "dev": true, + "requires": { + "@types/node": "*", + "jest-regex-util": "30.0.1" + } + }, + "@jest/reporters": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.2.0.tgz", + "integrity": "sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==", + "dev": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@jridgewell/trace-mapping": "^0.3.25", + "@types/node": "*", + "chalk": "^4.1.2", + "collect-v8-coverage": "^1.0.2", + "exit-x": "^0.2.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^5.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "jest-worker": "30.2.0", + "slash": "^3.0.0", + "string-length": "^4.0.2", + "v8-to-istanbul": "^9.0.1" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + } + }, + "minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.2" + } + }, + "minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true + } + } + }, + "@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "dev": true, + "requires": { + "@sinclair/typebox": "^0.34.0" + } + }, + "@jest/snapshot-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.2.0.tgz", + "integrity": "sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==", + "dev": true, + "requires": { + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "natural-compare": "^1.4.0" + } + }, + "@jest/source-map": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz", + "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.25", + "callsites": "^3.1.0", + "graceful-fs": "^4.2.11" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + } + } + }, + "@jest/test-result": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.2.0.tgz", + "integrity": "sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==", + "dev": true, + "requires": { + "@jest/console": "30.2.0", + "@jest/types": "30.2.0", + "@types/istanbul-lib-coverage": "^2.0.6", + "collect-v8-coverage": "^1.0.2" + } + }, + "@jest/test-sequencer": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.2.0.tgz", + "integrity": "sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==", + "dev": true, + "requires": { + "@jest/test-result": "30.2.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "slash": "^3.0.0" + } + }, + "@jest/transform": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.2.0.tgz", + "integrity": "sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==", + "dev": true, + "requires": { + "@babel/core": "^7.27.4", + "@jest/types": "30.2.0", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.1", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-util": "30.2.0", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + } + } + }, + "@jest/types": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", + "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", + "dev": true, + "requires": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.5", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "requires": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + } + } + }, + "@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + } + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "requires": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + } + }, + "@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "optional": true, + "requires": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "dev": true + }, + "@paralleldrive/cuid2": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", + "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==", + "dev": true, + "requires": { + "@noble/hashes": "^1.1.5" + } + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true + }, + "@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true + }, + "@prisma/client": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.16.2.tgz", + "integrity": "sha512-+1lmkhR9gHWcTC5oghm2ZKpWljyWdzfazCVlLKUWXVmwHSf52g81aZ8qb6Km5Bs025yBi7puLp3qSLEvktoUtw==", + "requires": {} + }, + "@prisma/debug": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.16.2.tgz", + "integrity": "sha512-ItzB4nR4O8eLzuJiuP3WwUJfoIvewMHqpGCad+64gvThcKEVOtaUza9AEJo2DPqAOa/AWkFyK54oM4WwHeew+A==", + "devOptional": true + }, + "@prisma/engines": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.16.2.tgz", + "integrity": "sha512-qUxwMtrwoG3byd4PbX6T7EjHJ8AUhzTuwniOGkh/hIznBfcE2QQnGakyEq4VnwNuttMqvh/GgPFapHQ3lCuRHg==", + "devOptional": true, + "requires": { + "@prisma/debug": "5.16.2", + "@prisma/engines-version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", + "@prisma/fetch-engine": "5.16.2", + "@prisma/get-platform": "5.16.2" + } + }, + "@prisma/engines-version": { + "version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303.tgz", + "integrity": "sha512-HkT2WbfmFZ9WUPyuJHhkiADxazHg8Y4gByrTSVeb3OikP6tjQ7txtSUGu9OBOBH0C13dPKN2qqH12xKtHu/Hiw==", + "devOptional": true + }, + "@prisma/fetch-engine": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.16.2.tgz", + "integrity": "sha512-sq51lfHKfH2jjYSjBtMjP+AznFqOJzXpqmq6B9auWrlTJrMgZ7lPyhWUW7VU7LsQU48/TJ+DZeIz8s9bMYvcHg==", + "devOptional": true, + "requires": { + "@prisma/debug": "5.16.2", + "@prisma/engines-version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", + "@prisma/get-platform": "5.16.2" + } + }, + "@prisma/get-platform": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.16.2.tgz", + "integrity": "sha512-cXiHPgNLNyj22vLouPVNegklpRL/iX2jxTeap5GRO3DmCoVyIHmJAV1CgUMUJhHlcol9yYy7EHvsnXTDJ/PKEA==", + "devOptional": true, + "requires": { + "@prisma/debug": "5.16.2" + } + }, + "@sinclair/typebox": { + "version": "0.34.48", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.48.tgz", + "integrity": "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==", + "dev": true + }, + "@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "dev": true, + "requires": { + "@sinonjs/commons": "^3.0.1" + } + }, + "@smithy/abort-controller": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.12.tgz", + "integrity": "sha512-xolrFw6b+2iYGl6EcOL7IJY71vvyZ0DJ3mcKtpykqPe2uscwtzDZJa1uVQXyP7w9Dd+kGwYnPbMsJrGISKiY/Q==", + "requires": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/chunked-blob-reader": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.2.2.tgz", + "integrity": "sha512-St+kVicSyayWQca+I1rGitaOEH6uKgE8IUWoYnnEX26SWdWQcL6LvMSD19Lg+vYHKdT9B2Zuu7rd3i6Wnyb/iw==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/chunked-blob-reader-native": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.2.3.tgz", + "integrity": "sha512-jA5k5Udn7Y5717L86h4EIv06wIr3xn8GM1qHRi/Nf31annXcXHJjBKvgztnbn2TxH3xWrPBfgwHsOwZf0UmQWw==", + "requires": { + "@smithy/util-base64": "^4.3.2", + "tslib": "^2.6.2" + } + }, + "@smithy/config-resolver": { + "version": "4.4.11", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.11.tgz", + "integrity": "sha512-YxFiiG4YDAtX7WMN7RuhHZLeTmRRAOyCbr+zB8e3AQzHPnUhS8zXjB1+cniPVQI3xbWsQPM0X2aaIkO/ME0ymw==", + "requires": { + "@smithy/node-config-provider": "^4.3.12", + "@smithy/types": "^4.13.1", + "@smithy/util-config-provider": "^4.2.2", + "@smithy/util-endpoints": "^3.3.3", + "@smithy/util-middleware": "^4.2.12", + "tslib": "^2.6.2" + } + }, + "@smithy/core": { + "version": "3.23.11", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.23.11.tgz", + "integrity": "sha512-952rGf7hBRnhUIaeLp6q4MptKW8sPFe5VvkoZ5qIzFAtx6c/QZ/54FS3yootsyUSf9gJX/NBqEBNdNR7jMIlpQ==", + "requires": { + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "@smithy/url-parser": "^4.2.12", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-body-length-browser": "^4.2.2", + "@smithy/util-middleware": "^4.2.12", + "@smithy/util-stream": "^4.5.19", + "@smithy/util-utf8": "^4.2.2", + "@smithy/uuid": "^1.1.2", + "tslib": "^2.6.2" + } + }, + "@smithy/credential-provider-imds": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.12.tgz", + "integrity": "sha512-cr2lR792vNZcYMriSIj+Um3x9KWrjcu98kn234xA6reOAFMmbRpQMOv8KPgEmLLtx3eldU6c5wALKFqNOhugmg==", + "requires": { + "@smithy/node-config-provider": "^4.3.12", + "@smithy/property-provider": "^4.2.12", + "@smithy/types": "^4.13.1", + "@smithy/url-parser": "^4.2.12", + "tslib": "^2.6.2" + } + }, + "@smithy/eventstream-codec": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.2.12.tgz", + "integrity": "sha512-FE3bZdEl62ojmy8x4FHqxq2+BuOHlcxiH5vaZ6aqHJr3AIZzwF5jfx8dEiU/X0a8RboyNDjmXjlbr8AdEyLgiA==", + "requires": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.13.1", + "@smithy/util-hex-encoding": "^4.2.2", + "tslib": "^2.6.2" + } + }, + "@smithy/eventstream-serde-browser": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.12.tgz", + "integrity": "sha512-XUSuMxlTxV5pp4VpqZf6Sa3vT/Q75FVkLSpSSE3KkWBvAQWeuWt1msTv8fJfgA4/jcJhrbrbMzN1AC/hvPmm5A==", + "requires": { + "@smithy/eventstream-serde-universal": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/eventstream-serde-config-resolver": { + "version": "4.3.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.12.tgz", + "integrity": "sha512-7epsAZ3QvfHkngz6RXQYseyZYHlmWXSTPOfPmXkiS+zA6TBNo1awUaMFL9vxyXlGdoELmCZyZe1nQE+imbmV+Q==", + "requires": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/eventstream-serde-node": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.12.tgz", + "integrity": "sha512-D1pFuExo31854eAvg89KMn9Oab/wEeJR6Buy32B49A9Ogdtx5fwZPqBHUlDzaCDpycTFk2+fSQgX689Qsk7UGA==", + "requires": { + "@smithy/eventstream-serde-universal": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/eventstream-serde-universal": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.12.tgz", + "integrity": "sha512-+yNuTiyBACxOJUTvbsNsSOfH9G9oKbaJE1lNL3YHpGcuucl6rPZMi3nrpehpVOVR2E07YqFFmtwpImtpzlouHQ==", + "requires": { + "@smithy/eventstream-codec": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/fetch-http-handler": { + "version": "5.3.15", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.15.tgz", + "integrity": "sha512-T4jFU5N/yiIfrtrsb9uOQn7RdELdM/7HbyLNr6uO/mpkj1ctiVs7CihVr51w4LyQlXWDpXFn4BElf1WmQvZu/A==", + "requires": { + "@smithy/protocol-http": "^5.3.12", + "@smithy/querystring-builder": "^4.2.12", + "@smithy/types": "^4.13.1", + "@smithy/util-base64": "^4.3.2", + "tslib": "^2.6.2" + } + }, + "@smithy/hash-blob-browser": { + "version": "4.2.13", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.2.13.tgz", + "integrity": "sha512-YrF4zWKh+ghLuquldj6e/RzE3xZYL8wIPfkt0MqCRphVICjyyjH8OwKD7LLlKpVEbk4FLizFfC1+gwK6XQdR3g==", + "requires": { + "@smithy/chunked-blob-reader": "^5.2.2", + "@smithy/chunked-blob-reader-native": "^4.2.3", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/hash-node": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.12.tgz", + "integrity": "sha512-QhBYbGrbxTkZ43QoTPrK72DoYviDeg6YKDrHTMJbbC+A0sml3kSjzFtXP7BtbyJnXojLfTQldGdUR0RGD8dA3w==", + "requires": { + "@smithy/types": "^4.13.1", + "@smithy/util-buffer-from": "^4.2.2", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + } + }, + "@smithy/hash-stream-node": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.2.12.tgz", + "integrity": "sha512-O3YbmGExeafuM/kP7Y8r6+1y0hIh3/zn6GROx0uNlB54K9oihAL75Qtc+jFfLNliTi6pxOAYZrRKD9A7iA6UFw==", + "requires": { + "@smithy/types": "^4.13.1", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + } + }, + "@smithy/invalid-dependency": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.12.tgz", + "integrity": "sha512-/4F1zb7Z8LOu1PalTdESFHR0RbPwHd3FcaG1sI3UEIriQTWakysgJr65lc1jj6QY5ye7aFsisajotH6UhWfm/g==", + "requires": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/is-array-buffer": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.2.tgz", + "integrity": "sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/md5-js": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.2.12.tgz", + "integrity": "sha512-W/oIpHCpWU2+iAkfZYyGWE+qkpuf3vEXHLxQQDx9FPNZTTdnul0dZ2d/gUFrtQ5je1G2kp4cjG0/24YueG2LbQ==", + "requires": { + "@smithy/types": "^4.13.1", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-content-length": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.12.tgz", + "integrity": "sha512-YE58Yz+cvFInWI/wOTrB+DbvUVz/pLn5mC5MvOV4fdRUc6qGwygyngcucRQjAhiCEbmfLOXX0gntSIcgMvAjmA==", + "requires": { + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-endpoint": { + "version": "4.4.25", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.25.tgz", + "integrity": "sha512-dqjLwZs2eBxIUG6Qtw8/YZ4DvzHGIf0DA18wrgtfP6a50UIO7e2nY0FPdcbv5tVJKqWCCU5BmGMOUwT7Puan+A==", + "requires": { + "@smithy/core": "^3.23.11", + "@smithy/middleware-serde": "^4.2.14", + "@smithy/node-config-provider": "^4.3.12", + "@smithy/shared-ini-file-loader": "^4.4.7", + "@smithy/types": "^4.13.1", + "@smithy/url-parser": "^4.2.12", + "@smithy/util-middleware": "^4.2.12", + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-retry": { + "version": "4.4.42", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.42.tgz", + "integrity": "sha512-vbwyqHRIpIZutNXZpLAozakzamcINaRCpEy1MYmK6xBeW3xN+TyPRA123GjXnuxZIjc9848MRRCugVMTXxC4Eg==", + "requires": { + "@smithy/node-config-provider": "^4.3.12", + "@smithy/protocol-http": "^5.3.12", + "@smithy/service-error-classification": "^4.2.12", + "@smithy/smithy-client": "^4.12.5", + "@smithy/types": "^4.13.1", + "@smithy/util-middleware": "^4.2.12", + "@smithy/util-retry": "^4.2.12", + "@smithy/uuid": "^1.1.2", + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-serde": { + "version": "4.2.14", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.14.tgz", + "integrity": "sha512-+CcaLoLa5apzSRtloOyG7lQvkUw2ZDml3hRh4QiG9WyEPfW5Ke/3tPOPiPjUneuT59Tpn8+c3RVaUvvkkwqZwg==", + "requires": { + "@smithy/core": "^3.23.11", + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-stack": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.12.tgz", + "integrity": "sha512-kruC5gRHwsCOuyCd4ouQxYjgRAym2uDlCvQ5acuMtRrcdfg7mFBg6blaxcJ09STpt3ziEkis6bhg1uwrWU7txw==", + "requires": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/node-config-provider": { + "version": "4.3.12", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.12.tgz", + "integrity": "sha512-tr2oKX2xMcO+rBOjobSwVAkV05SIfUKz8iI53rzxEmgW3GOOPOv0UioSDk+J8OpRQnpnhsO3Af6IEBabQBVmiw==", + "requires": { + "@smithy/property-provider": "^4.2.12", + "@smithy/shared-ini-file-loader": "^4.4.7", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/node-http-handler": { + "version": "4.4.16", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.16.tgz", + "integrity": "sha512-ULC8UCS/HivdCB3jhi+kLFYe4B5gxH2gi9vHBfEIiRrT2jfKiZNiETJSlzRtE6B26XbBHjPtc8iZKSNqMol9bw==", + "requires": { + "@smithy/abort-controller": "^4.2.12", + "@smithy/protocol-http": "^5.3.12", + "@smithy/querystring-builder": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/property-provider": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.12.tgz", + "integrity": "sha512-jqve46eYU1v7pZ5BM+fmkbq3DerkSluPr5EhvOcHxygxzD05ByDRppRwRPPpFrsFo5yDtCYLKu+kreHKVrvc7A==", + "requires": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/protocol-http": { + "version": "5.3.12", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.12.tgz", + "integrity": "sha512-fit0GZK9I1xoRlR4jXmbLhoN0OdEpa96ul8M65XdmXnxXkuMxM0Y8HDT0Fh0Xb4I85MBvBClOzgSrV1X2s1Hxw==", + "requires": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/querystring-builder": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.12.tgz", + "integrity": "sha512-6wTZjGABQufekycfDGMEB84BgtdOE/rCVTov+EDXQ8NHKTUNIp/j27IliwP7tjIU9LR+sSzyGBOXjeEtVgzCHg==", + "requires": { + "@smithy/types": "^4.13.1", + "@smithy/util-uri-escape": "^4.2.2", + "tslib": "^2.6.2" + } + }, + "@smithy/querystring-parser": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.12.tgz", + "integrity": "sha512-P2OdvrgiAKpkPNKlKUtWbNZKB1XjPxM086NeVhK+W+wI46pIKdWBe5QyXvhUm3MEcyS/rkLvY8rZzyUdmyDZBw==", + "requires": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/service-error-classification": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.12.tgz", + "integrity": "sha512-LlP29oSQN0Tw0b6D0Xo6BIikBswuIiGYbRACy5ujw/JgWSzTdYj46U83ssf6Ux0GyNJVivs2uReU8pt7Eu9okQ==", + "requires": { + "@smithy/types": "^4.13.1" + } + }, + "@smithy/shared-ini-file-loader": { + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.7.tgz", + "integrity": "sha512-HrOKWsUb+otTeo1HxVWeEb99t5ER1XrBi/xka2Wv6NVmTbuCUC1dvlrksdvxFtODLBjsC+PHK+fuy2x/7Ynyiw==", + "requires": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/signature-v4": { + "version": "5.3.12", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.12.tgz", + "integrity": "sha512-B/FBwO3MVOL00DaRSXfXfa/TRXRheagt/q5A2NM13u7q+sHS59EOVGQNfG7DkmVtdQm5m3vOosoKAXSqn/OEgw==", + "requires": { + "@smithy/is-array-buffer": "^4.2.2", + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "@smithy/util-hex-encoding": "^4.2.2", + "@smithy/util-middleware": "^4.2.12", + "@smithy/util-uri-escape": "^4.2.2", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + } + }, + "@smithy/smithy-client": { + "version": "4.12.5", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.12.5.tgz", + "integrity": "sha512-UqwYawyqSr/aog8mnLnfbPurS0gi4G7IYDcD28cUIBhsvWs1+rQcL2IwkUQ+QZ7dibaoRzhNF99fAQ9AUcO00w==", + "requires": { + "@smithy/core": "^3.23.11", + "@smithy/middleware-endpoint": "^4.4.25", + "@smithy/middleware-stack": "^4.2.12", + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "@smithy/util-stream": "^4.5.19", + "tslib": "^2.6.2" + } + }, + "@smithy/types": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.13.1.tgz", + "integrity": "sha512-787F3yzE2UiJIQ+wYW1CVg2odHjmaWLGksnKQHUrK/lYZSEcy1msuLVvxaR/sI2/aDe9U+TBuLsXnr3vod1g0g==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/url-parser": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.12.tgz", + "integrity": "sha512-wOPKPEpso+doCZGIlr+e1lVI6+9VAKfL4kZWFgzVgGWY2hZxshNKod4l2LXS3PRC9otH/JRSjtEHqQ/7eLciRA==", + "requires": { + "@smithy/querystring-parser": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/util-base64": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.3.2.tgz", + "integrity": "sha512-XRH6b0H/5A3SgblmMa5ErXQ2XKhfbQB+Fm/oyLZ2O2kCUrwgg55bU0RekmzAhuwOjA9qdN5VU2BprOvGGUkOOQ==", + "requires": { + "@smithy/util-buffer-from": "^4.2.2", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + } + }, + "@smithy/util-body-length-browser": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.2.tgz", + "integrity": "sha512-JKCrLNOup3OOgmzeaKQwi4ZCTWlYR5H4Gm1r2uTMVBXoemo1UEghk5vtMi1xSu2ymgKVGW631e2fp9/R610ZjQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-body-length-node": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.3.tgz", + "integrity": "sha512-ZkJGvqBzMHVHE7r/hcuCxlTY8pQr1kMtdsVPs7ex4mMU+EAbcXppfo5NmyxMYi2XU49eqaz56j2gsk4dHHPG/g==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.2.2.tgz", + "integrity": "sha512-FDXD7cvUoFWwN6vtQfEta540Y/YBe5JneK3SoZg9bThSoOAC/eGeYEua6RkBgKjGa/sz6Y+DuBZj3+YEY21y4Q==", + "requires": { + "@smithy/is-array-buffer": "^4.2.2", + "tslib": "^2.6.2" + } + }, + "@smithy/util-config-provider": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.2.2.tgz", + "integrity": "sha512-dWU03V3XUprJwaUIFVv4iOnS1FC9HnMHDfUrlNDSh4315v0cWyaIErP8KiqGVbf5z+JupoVpNM7ZB3jFiTejvQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-defaults-mode-browser": { + "version": "4.3.41", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.41.tgz", + "integrity": "sha512-M1w1Ux0rSVvBOxIIiqbxvZvhnjQ+VUjJrugtORE90BbadSTH+jsQL279KRL3Hv0w69rE7EuYkV/4Lepz/NBW9g==", + "requires": { + "@smithy/property-provider": "^4.2.12", + "@smithy/smithy-client": "^4.12.5", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/util-defaults-mode-node": { + "version": "4.2.44", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.44.tgz", + "integrity": "sha512-YPze3/lD1KmWuZsl9JlfhcgGLX7AXhSoaCDtiPntUjNW5/YY0lOHjkcgxyE9x/h5vvS1fzDifMGjzqnNlNiqOQ==", + "requires": { + "@smithy/config-resolver": "^4.4.11", + "@smithy/credential-provider-imds": "^4.2.12", + "@smithy/node-config-provider": "^4.3.12", + "@smithy/property-provider": "^4.2.12", + "@smithy/smithy-client": "^4.12.5", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/util-endpoints": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.3.3.tgz", + "integrity": "sha512-VACQVe50j0HZPjpwWcjyT51KUQ4AnsvEaQ2lKHOSL4mNLD0G9BjEniQ+yCt1qqfKfiAHRAts26ud7hBjamrwig==", + "requires": { + "@smithy/node-config-provider": "^4.3.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/util-hex-encoding": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.2.tgz", + "integrity": "sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-middleware": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.12.tgz", + "integrity": "sha512-Er805uFUOvgc0l8nv0e0su0VFISoxhJ/AwOn3gL2NWNY2LUEldP5WtVcRYSQBcjg0y9NfG8JYrCJaYDpupBHJQ==", + "requires": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/util-retry": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.12.tgz", + "integrity": "sha512-1zopLDUEOwumjcHdJ1mwBHddubYF8GMQvstVCLC54Y46rqoHwlIU+8ZzUeaBcD+WCJHyDGSeZ2ml9YSe9aqcoQ==", + "requires": { + "@smithy/service-error-classification": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/util-stream": { + "version": "4.5.19", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.19.tgz", + "integrity": "sha512-v4sa+3xTweL1CLO2UP0p7tvIMH/Rq1X4KKOxd568mpe6LSLMQCnDHs4uv7m3ukpl3HvcN2JH6jiCS0SNRXKP/w==", + "requires": { + "@smithy/fetch-http-handler": "^5.3.15", + "@smithy/node-http-handler": "^4.4.16", + "@smithy/types": "^4.13.1", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-buffer-from": "^4.2.2", + "@smithy/util-hex-encoding": "^4.2.2", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + } + }, + "@smithy/util-uri-escape": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.2.tgz", + "integrity": "sha512-2kAStBlvq+lTXHyAZYfJRb/DfS3rsinLiwb+69SstC9Vb0s9vNWkRwpnj918Pfi85mzi42sOqdV72OLxWAISnw==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-utf8": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.2.tgz", + "integrity": "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw==", + "requires": { + "@smithy/util-buffer-from": "^4.2.2", + "tslib": "^2.6.2" + } + }, + "@smithy/util-waiter": { + "version": "4.2.13", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.13.tgz", + "integrity": "sha512-2zdZ9DTHngRtcYxJK1GUDxruNr53kv5W2Lupe0LMU+Imr6ohQg8M2T14MNkj1Y0wS3FFwpgpGQyvuaMF7CiTmQ==", + "requires": { + "@smithy/abort-controller": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + } + }, + "@smithy/uuid": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@smithy/uuid/-/uuid-1.1.2.tgz", + "integrity": "sha512-O/IEdcCUKkubz60tFbGA7ceITTAJsty+lBjNoorP4Z6XRqaFb/OjQjZODophEcuq68nKm6/0r+6/lLQ+XVpk8g==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + }, + "@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "optional": true, + "requires": { + "tslib": "^2.4.0" + } + }, + "@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "requires": { + "@babel/types": "^7.28.2" + } + }, + "@types/bcrypt": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz", + "integrity": "sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/cookie-parser": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.8.tgz", + "integrity": "sha512-l37JqFrOJ9yQfRQkljb41l0xVphc7kg5JTjjr+pLRZ0IyZ49V4BQ8vbF4Ut2C2e+WH4al3xD3ZwYwIUfnbT4NQ==", + "dev": true, + "requires": {} + }, + "@types/cookiejar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", + "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", + "dev": true + }, + "@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "requires": { + "@types/node": "*" + } + }, + "@types/express": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz", + "integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.6.tgz", + "integrity": "sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz", + "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==", + "dev": true, + "requires": { + "expect": "^30.0.0", + "pretty-format": "^30.0.0" + } + }, + "@types/jsonwebtoken": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.9.tgz", + "integrity": "sha512-uoe+GxEuHbvy12OUQct2X9JenKM3qAscquYymuQN4fMWG9DBQtykrQEFcAbVACF7qaLw9BePSodUL0kquqBJpQ==", + "dev": true, + "requires": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "@types/methods": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", + "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", + "dev": true + }, + "@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true + }, + "@types/multer": { + "version": "1.4.12", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.12.tgz", + "integrity": "sha512-pQ2hoqvXiJt2FP9WQVLPRO+AmiIm/ZYkavPlIQnx282u4ZrVdztx0pkh3jjpQt0Kz+YI0YhSG264y08UJKoUQg==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, + "@types/multer-s3": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/multer-s3/-/multer-s3-3.0.3.tgz", + "integrity": "sha512-VgWygI9UwyS7loLithUUi0qAMIDWdNrERS2Sb06UuPYiLzKuIFn2NgL7satyl4v8sh/LLoU7DiPanvbQaRg9Yg==", + "dev": true, + "requires": { + "@aws-sdk/client-s3": "^3.0.0", + "@types/multer": "*", + "@types/node": "*" + } + }, + "@types/node": { + "version": "22.13.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.9.tgz", + "integrity": "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==", + "requires": { + "undici-types": "~6.20.0" + } + }, + "@types/qs": { + "version": "6.9.18", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", + "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "requires": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, + "@types/superagent": { + "version": "8.1.9", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.9.tgz", + "integrity": "sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==", + "dev": true, + "requires": { + "@types/cookiejar": "^2.1.5", + "@types/methods": "^1.1.4", + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "@types/supertest": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-7.2.0.tgz", + "integrity": "sha512-uh2Lv57xvggst6lCqNdFAmDSvoMG7M/HDtX4iUCquxQ5EGPtaPM5PL5Hmi7LCvOG8db7YaCPNJEeoI8s/WzIQw==", + "dev": true, + "requires": { + "@types/methods": "^1.1.4", + "@types/superagent": "^8.1.0" + } + }, + "@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true + }, + "@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "dev": true, + "optional": true + }, + "@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "dev": true, + "optional": true + }, + "@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "dev": true, + "optional": true + }, + "@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "dev": true, + "optional": true + }, + "@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "dev": true, + "optional": true + }, + "@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "dev": true, + "optional": true + }, + "@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "dev": true, + "optional": true + }, + "@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "dev": true, + "optional": true + }, + "@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "dev": true, + "optional": true + }, + "@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "dev": true, + "optional": true + }, + "@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "dev": true, + "optional": true + }, + "@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "dev": true, + "optional": true + }, + "@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "dev": true, + "optional": true + }, + "@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "dev": true, + "optional": true + }, + "@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "dev": true, + "optional": true + }, + "@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "dev": true, + "optional": true, + "requires": { + "@napi-rs/wasm-runtime": "^0.2.11" + } + }, + "@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "dev": true, + "optional": true + }, + "@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "dev": true, + "optional": true + }, + "@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "dev": true, + "optional": true + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "acorn": { + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "dev": true + }, + "acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "requires": { + "acorn": "^8.11.0" + } + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "babel-jest": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.2.0.tgz", + "integrity": "sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==", + "dev": true, + "requires": { + "@jest/transform": "30.2.0", + "@types/babel__core": "^7.20.5", + "babel-plugin-istanbul": "^7.0.1", + "babel-preset-jest": "30.2.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "slash": "^3.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz", + "integrity": "sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" + } + }, + "babel-plugin-jest-hoist": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.2.0.tgz", + "integrity": "sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==", + "dev": true, + "requires": { + "@types/babel__core": "^7.20.5" + } + }, + "babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dev": true, + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + } + }, + "babel-preset-jest": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.2.0.tgz", + "integrity": "sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "30.2.0", + "babel-preset-current-node-syntax": "^1.2.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" + }, + "baseline-browser-mapping": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", + "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", + "dev": true + }, + "bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + } + }, + "binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true + }, + "body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + } + }, + "bowser": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz", + "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "requires": { + "fill-range": "^7.1.1" + } + }, + "browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "requires": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + } + }, + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "2.x" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "requires": { + "streamsearch": "^1.1.0" + } + }, + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + } + }, + "call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001776", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001776.tgz", + "integrity": "sha512-sg01JDPzZ9jGshqKSckOQthXnYwOEP50jeVFhaSFbZcOy05TiuuaffDOfcwtCisJ9kNQuLBFibYywv2Bgm9osw==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true + }, + "chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, + "ci-info": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", + "dev": true + }, + "cjs-module-lexer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz", + "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==", + "dev": true + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true + }, + "collect-v8-coverage": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "requires": { + "safe-buffer": "5.2.1" + } + }, + "content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" + }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==" + }, + "cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "requires": { + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "dependencies": { + "cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==" + } + } + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "dedent": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz", + "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==", + "dev": true, + "requires": {} + }, + "deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==" + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true + }, + "dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==" + }, + "dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "requires": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + } + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "electron-to-chromium": { + "version": "1.5.307", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz", + "integrity": "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==", + "dev": true + }, + "emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "engine.io": { + "version": "6.6.5", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.5.tgz", + "integrity": "sha512-2RZdgEbXmp5+dVbRm0P7HQUImZpICccJy7rN7Tv+SFa55pH+lxnuw6/K1ZxxBfHoYpSkHLAO92oa8O4SwFXA2A==", + "requires": { + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.7.2", + "cors": "~2.8.5", + "debug": "~4.4.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.18.3" + }, + "dependencies": { + "cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==" + }, + "debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==" + }, + "error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, + "es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "requires": { + "es-errors": "^1.3.0" + } + }, + "es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + } + }, + "escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "exit-x": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", + "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", + "dev": true + }, + "expect": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", + "dev": true, + "requires": { + "@jest/expect-utils": "30.2.0", + "@jest/get-type": "30.1.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" + } + }, + "express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, + "fast-xml-builder": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.3.tgz", + "integrity": "sha512-1o60KoFw2+LWKQu3IdcfcFlGTW4dpqEWmjhYec6H82AYZU2TVBXep6tMl8Z1Y+wM+ZrzCwe3BZ9Vyd9N2rIvmg==", + "requires": { + "path-expression-matcher": "^1.1.3" + } + }, + "fast-xml-parser": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.4.1.tgz", + "integrity": "sha512-BQ30U1mKkvXQXXkAGcuyUA/GA26oEB7NzOtsxCDtyu62sjGw5QraKFhx2Em3WQNjPw9PG6MQ9yuIIgkSDfGu5A==", + "requires": { + "fast-xml-builder": "^1.0.0", + "strnum": "^2.1.2" + } + }, + "fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "requires": { + "bser": "2.1.1" + } + }, + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==" + }, + "fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + } + } + }, + "form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + } + }, + "formidable": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", + "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", + "dev": true, + "requires": { + "@paralleldrive/cuid2": "^2.2.2", + "dezalgo": "^1.0.4", + "once": "^1.4.0" + } + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + } + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + } + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, + "get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "requires": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" + }, + "has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.3" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "requires": { + "function-bind": "^1.1.2" + } + }, + "html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", + "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==" + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "requires": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + } + }, + "istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "requires": { + "semver": "^7.5.3" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, + "jest": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.2.0.tgz", + "integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==", + "dev": true, + "requires": { + "@jest/core": "30.2.0", + "@jest/types": "30.2.0", + "import-local": "^3.2.0", + "jest-cli": "30.2.0" + } + }, + "jest-changed-files": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.2.0.tgz", + "integrity": "sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==", + "dev": true, + "requires": { + "execa": "^5.1.1", + "jest-util": "30.2.0", + "p-limit": "^3.1.0" + } + }, + "jest-circus": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.2.0.tgz", + "integrity": "sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==", + "dev": true, + "requires": { + "@jest/environment": "30.2.0", + "@jest/expect": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "co": "^4.6.0", + "dedent": "^1.6.0", + "is-generator-fn": "^2.1.0", + "jest-each": "30.2.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-runtime": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "p-limit": "^3.1.0", + "pretty-format": "30.2.0", + "pure-rand": "^7.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + } + }, + "jest-cli": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.2.0.tgz", + "integrity": "sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==", + "dev": true, + "requires": { + "@jest/core": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "exit-x": "^0.2.2", + "import-local": "^3.2.0", + "jest-config": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "yargs": "^17.7.2" + } + }, + "jest-config": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.2.0.tgz", + "integrity": "sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==", + "dev": true, + "requires": { + "@babel/core": "^7.27.4", + "@jest/get-type": "30.1.0", + "@jest/pattern": "30.0.1", + "@jest/test-sequencer": "30.2.0", + "@jest/types": "30.2.0", + "babel-jest": "30.2.0", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "deepmerge": "^4.3.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-circus": "30.2.0", + "jest-docblock": "30.2.0", + "jest-environment-node": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-runner": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "micromatch": "^4.0.8", + "parse-json": "^5.2.0", + "pretty-format": "30.2.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + } + }, + "minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.2" + } + }, + "minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true + } + } + }, + "jest-diff": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", + "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "dev": true, + "requires": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.2.0" + } + }, + "jest-docblock": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.2.0.tgz", + "integrity": "sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==", + "dev": true, + "requires": { + "detect-newline": "^3.1.0" + } + }, + "jest-each": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.2.0.tgz", + "integrity": "sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==", + "dev": true, + "requires": { + "@jest/get-type": "30.1.0", + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "jest-util": "30.2.0", + "pretty-format": "30.2.0" + } + }, + "jest-environment-node": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.2.0.tgz", + "integrity": "sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==", + "dev": true, + "requires": { + "@jest/environment": "30.2.0", + "@jest/fake-timers": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-mock": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0" + } + }, + "jest-haste-map": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.2.0.tgz", + "integrity": "sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==", + "dev": true, + "requires": { + "@jest/types": "30.2.0", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "fsevents": "^2.3.3", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.2.0", + "jest-worker": "30.2.0", + "micromatch": "^4.0.8", + "walker": "^1.0.8" + } + }, + "jest-leak-detector": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.2.0.tgz", + "integrity": "sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==", + "dev": true, + "requires": { + "@jest/get-type": "30.1.0", + "pretty-format": "30.2.0" + } + }, + "jest-matcher-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", + "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "dev": true, + "requires": { + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "jest-diff": "30.2.0", + "pretty-format": "30.2.0" + } + }, + "jest-message-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", + "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.2.0", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.2.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + } + }, + "jest-mock": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", + "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", + "dev": true, + "requires": { + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-util": "30.2.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "requires": {} + }, + "jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "dev": true + }, + "jest-resolve": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.2.0.tgz", + "integrity": "sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==", + "dev": true, + "requires": { + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-pnp-resolver": "^1.2.3", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "slash": "^3.0.0", + "unrs-resolver": "^1.7.11" + } + }, + "jest-resolve-dependencies": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.2.0.tgz", + "integrity": "sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==", + "dev": true, + "requires": { + "jest-regex-util": "30.0.1", + "jest-snapshot": "30.2.0" + } + }, + "jest-runner": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.2.0.tgz", + "integrity": "sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==", + "dev": true, + "requires": { + "@jest/console": "30.2.0", + "@jest/environment": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-docblock": "30.2.0", + "jest-environment-node": "30.2.0", + "jest-haste-map": "30.2.0", + "jest-leak-detector": "30.2.0", + "jest-message-util": "30.2.0", + "jest-resolve": "30.2.0", + "jest-runtime": "30.2.0", + "jest-util": "30.2.0", + "jest-watcher": "30.2.0", + "jest-worker": "30.2.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + } + }, + "jest-runtime": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.2.0.tgz", + "integrity": "sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==", + "dev": true, + "requires": { + "@jest/environment": "30.2.0", + "@jest/fake-timers": "30.2.0", + "@jest/globals": "30.2.0", + "@jest/source-map": "30.0.1", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "cjs-module-lexer": "^2.1.0", + "collect-v8-coverage": "^1.0.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + } + }, + "minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.2" + } + }, + "minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true + } + } + }, + "jest-snapshot": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.2.0.tgz", + "integrity": "sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==", + "dev": true, + "requires": { + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.2.0", + "@jest/get-type": "30.1.0", + "@jest/snapshot-utils": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "babel-preset-current-node-syntax": "^1.2.0", + "chalk": "^4.1.2", + "expect": "30.2.0", + "graceful-fs": "^4.2.11", + "jest-diff": "30.2.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "pretty-format": "30.2.0", + "semver": "^7.7.2", + "synckit": "^0.11.8" + } + }, + "jest-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", + "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "dev": true, + "requires": { + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" + }, + "dependencies": { + "picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true + } + } + }, + "jest-validate": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.2.0.tgz", + "integrity": "sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==", + "dev": true, + "requires": { + "@jest/get-type": "30.1.0", + "@jest/types": "30.2.0", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", + "leven": "^3.1.0", + "pretty-format": "30.2.0" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + } + } + }, + "jest-watcher": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.2.0.tgz", + "integrity": "sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==", + "dev": true, + "requires": { + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "jest-util": "30.2.0", + "string-length": "^4.0.2" + } + }, + "jest-worker": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.2.0.tgz", + "integrity": "sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==", + "dev": true, + "requires": { + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.2.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, + "jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + }, + "dependencies": { + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "requires": { + "tmpl": "1.0.5" + } + }, + "math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "requires": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "requires": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + } + }, + "multer-s3": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/multer-s3/-/multer-s3-3.0.1.tgz", + "integrity": "sha512-BFwSO80a5EW4GJRBdUuSHblz2jhVSAze33ZbnGpcfEicoT0iRolx4kWR+AJV07THFRCQ78g+kelKFdjkCCaXeQ==", + "requires": { + "@aws-sdk/lib-storage": "^3.46.0", + "file-type": "^3.3.0", + "html-comment-regex": "^1.1.2", + "run-parallel": "^1.1.6" + } + }, + "napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node-releases": { + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "dev": true + }, + "nodemon": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.9.tgz", + "integrity": "sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==", + "dev": true, + "requires": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "dependencies": { + "debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "requires": { + "abbrev": "1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==" + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + }, + "dependencies": { + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + } + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-expression-matcher": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.1.3.tgz", + "integrity": "sha512-qdVgY8KXmVdJZRSS1JdEPOKPdTiEK/pi0RkcT2sw1RhXxohdujUlJFPuS1TSkevZ9vzd3ZlL7ULl1MHGTApKzQ==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "requires": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + } + } + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "prettier": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "dev": true + }, + "pretty-format": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", + "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "dev": true, + "requires": { + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "prisma": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.16.2.tgz", + "integrity": "sha512-rFV/xoBR2hBGGlu4LPLQd4U8WVA+tSAmYyFWGPRVfj+xg7N4kiZV4lSk38htSpF+/IuHKzlrbh4SFk8Z18cI8A==", + "devOptional": true, + "requires": { + "@prisma/engines": "5.16.2" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "pure-rand": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", + "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", + "dev": true + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==" + }, + "send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + } + }, + "side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + } + }, + "side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + } + }, + "side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + } + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "requires": { + "semver": "^7.5.3" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "socket.io": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.3.tgz", + "integrity": "sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A==", + "requires": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.4.1", + "engine.io": "~6.6.0", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "dependencies": { + "debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "socket.io-adapter": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.6.tgz", + "integrity": "sha512-DkkO/dz7MGln0dHn5bmN3pPy+JmywNICWrJqVWiVOyvXjWQFIv9c2h24JrQLLFJ2aQVQf/Cvl1vblnd4r2apLQ==", + "requires": { + "debug": "~4.4.1", + "ws": "~8.18.3" + }, + "dependencies": { + "debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "socket.io-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.5.tgz", + "integrity": "sha512-bPMmpy/5WWKHea5Y/jYAP6k74A+hvmRCQaJuJB6I/ML5JZq/KfNieUVo/3Mh7SAqn7TyFdIo6wqYHInG1MU1bQ==", + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1" + }, + "dependencies": { + "debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, + "stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "requires": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "strnum": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.0.tgz", + "integrity": "sha512-Y7Bj8XyJxnPAORMZj/xltsfo55uOiyHcU2tnAVzHUnSJR/KsEX+9RoDeXEnsXtl/CX4fAcrt64gZ13aGaWPeBg==" + }, + "superagent": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.3.0.tgz", + "integrity": "sha512-B+4Ik7ROgVKrQsXTV0Jwp2u+PXYLSlqtDAhYnkkD+zn3yg8s/zjA2MeGayPoY/KICrbitwneDHrjSotxKL+0XQ==", + "dev": true, + "requires": { + "component-emitter": "^1.3.1", + "cookiejar": "^2.1.4", + "debug": "^4.3.7", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.5", + "formidable": "^3.5.4", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.14.1" + }, + "dependencies": { + "debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "requires": { + "ms": "^2.1.3" + } + }, + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "qs": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", + "dev": true, + "requires": { + "side-channel": "^1.1.0" + } + } + } + }, + "superstruct": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-2.0.2.tgz", + "integrity": "sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==" + }, + "supertest": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.2.2.tgz", + "integrity": "sha512-oK8WG9diS3DlhdUkcFn4tkNIiIbBx9lI2ClF8K+b2/m8Eyv47LSawxUzZQSNKUrVb2KsqeTDCcjAAVPYaSLVTA==", + "dev": true, + "requires": { + "cookie-signature": "^1.2.2", + "methods": "^1.1.2", + "superagent": "^10.3.0" + }, + "dependencies": { + "cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "dev": true + } + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "synckit": { + "version": "0.11.12", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", + "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", + "dev": true, + "requires": { + "@pkgr/core": "^0.2.9" + } + }, + "tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + } + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "ts-jest": { + "version": "29.4.6", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.6.tgz", + "integrity": "sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==", + "dev": true, + "requires": { + "bs-logger": "^0.2.6", + "fast-json-stable-stringify": "^2.1.0", + "handlebars": "^4.7.8", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.7.3", + "type-fest": "^4.41.0", + "yargs-parser": "^21.1.1" + }, + "dependencies": { + "type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true + } + } + }, + "ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + } + }, + "tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "typescript": { + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", + "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", + "dev": true + }, + "uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "optional": true + }, + "undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "requires": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1", + "napi-postinstall": "^0.3.0" + } + }, + "update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "requires": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + }, + "uuid": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.5.tgz", + "integrity": "sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==" + }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + } + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "requires": { + "makeerror": "1.0.12" + } + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + } + } + }, + "ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/package.json b/package.json index e16c084e..cf6b0a87 100644 --- a/package.json +++ b/package.json @@ -1,34 +1,43 @@ { - "type": "module", "scripts": { - "dev": "nodemon --watch 'src/**/*.ts' --exec 'tsx' src/main.ts", + "start": "node ./build/main.js", "build": "tsc", - "start": "node dist/main.js" + "dev": "nodemon ./src/main.ts --watch ./src", + "test": "jest", + "test:coverage": "jest --coverage", + "test:watch": "jest --watch" }, "devDependencies": { - "@types/bcrypt": "^6.0.0", - "@types/cookie-parser": "^1.4.10", - "@types/cors": "^2.8.19", - "@types/express": "^5.0.6", - "@types/jsonwebtoken": "^9.0.10", - "@types/multer": "^2.0.0", - "@types/node": "^25.0.8", - "nodemon": "^3.1.11", + "@types/bcrypt": "^5.0.2", + "@types/cookie-parser": "^1.4.8", + "@types/cors": "^2.8.17", + "@types/express": "^5.0.0", + "@types/jest": "^30.0.0", + "@types/jsonwebtoken": "^9.0.9", + "@types/multer": "^1.4.12", + "@types/multer-s3": "^3.0.3", + "@types/supertest": "^7.2.0", + "jest": "^30.2.0", + "nodemon": "^3.1.9", "prettier": "^3.3.2", "prisma": "^5.16.2", + "supertest": "^7.2.2", + "ts-jest": "^29.4.6", "ts-node": "^10.9.2", - "tsx": "^4.21.0", - "typescript": "^5.9.3" + "typescript": "^5.8.2" }, "dependencies": { + "@aws-sdk/client-s3": "^3.1008.0", "@prisma/client": "^5.16.2", "bcrypt": "^5.1.1", "cookie-parser": "^1.4.7", "cors": "^2.8.5", "dotenv": "^16.4.5", - "express": "^4.22.1", + "express": "^4.19.2", "jsonwebtoken": "^9.0.2", "multer": "^1.4.5-lts.1", + "multer-s3": "^3.0.1", + "socket.io": "^4.8.1", "superstruct": "^2.0.2", "uuid": "^11.0.5" } diff --git a/prisma/migrations/20250429043356_/migration.sql b/prisma/migrations/20250429043356_/migration.sql new file mode 100644 index 00000000..ea1d6546 --- /dev/null +++ b/prisma/migrations/20250429043356_/migration.sql @@ -0,0 +1,15 @@ +-- CreateTable +CREATE TABLE "Notification" ( + "id" SERIAL NOT NULL, + "userId" INTEGER NOT NULL, + "type" TEXT NOT NULL, + "payload" JSONB NOT NULL, + "read" BOOLEAN NOT NULL DEFAULT false, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Notification_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "Notification" ADD CONSTRAINT "Notification_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20250429061529_/migration.sql b/prisma/migrations/20250429061529_/migration.sql new file mode 100644 index 00000000..ef0d145a --- /dev/null +++ b/prisma/migrations/20250429061529_/migration.sql @@ -0,0 +1,12 @@ +/* + Warnings: + + - Changed the type of `type` on the `Notification` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required. + +*/ +-- CreateEnum +CREATE TYPE "NotificationType" AS ENUM ('PRICE_CHANGED', 'NEW_COMMENT'); + +-- AlterTable +ALTER TABLE "Notification" DROP COLUMN "type", +ADD COLUMN "type" "NotificationType" NOT NULL; diff --git a/prisma/migrations/20251127095400_init/migration.sql b/prisma/migrations/20251127095400_init/migration.sql deleted file mode 100644 index decf85e3..00000000 --- a/prisma/migrations/20251127095400_init/migration.sql +++ /dev/null @@ -1,23 +0,0 @@ --- CreateTable -CREATE TABLE "product" ( - "id" BIGSERIAL NOT NULL, - "name" TEXT NOT NULL, - "description" TEXT, - "price" INTEGER NOT NULL, - "tags" TEXT[] DEFAULT ARRAY[]::TEXT[], - "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updated_at" TIMESTAMPTZ(6), - - CONSTRAINT "product_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "article" ( - "id" BIGSERIAL NOT NULL, - "title" TEXT NOT NULL, - "content" TEXT NOT NULL, - "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updated_at" TIMESTAMPTZ(6), - - CONSTRAINT "article_pkey" PRIMARY KEY ("id") -); diff --git a/prisma/migrations/20251202044637_add_comment_tables/migration.sql b/prisma/migrations/20251202044637_add_comment_tables/migration.sql deleted file mode 100644 index 8e89f0f3..00000000 --- a/prisma/migrations/20251202044637_add_comment_tables/migration.sql +++ /dev/null @@ -1,27 +0,0 @@ --- CreateTable -CREATE TABLE "product_comment" ( - "id" BIGSERIAL NOT NULL, - "content" TEXT NOT NULL, - "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updated_at" TIMESTAMPTZ(6), - "product_id" BIGINT NOT NULL, - - CONSTRAINT "product_comment_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "article_comment" ( - "id" BIGSERIAL NOT NULL, - "content" TEXT NOT NULL, - "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updated_at" TIMESTAMPTZ(6), - "article_id" BIGINT NOT NULL, - - CONSTRAINT "article_comment_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "product_comment" ADD CONSTRAINT "product_comment_product_id_fkey" FOREIGN KEY ("product_id") REFERENCES "product"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "article_comment" ADD CONSTRAINT "article_comment_article_id_fkey" FOREIGN KEY ("article_id") REFERENCES "article"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20251204062130_set_product_image_onetoone/migration.sql b/prisma/migrations/20251204062130_set_product_image_onetoone/migration.sql deleted file mode 100644 index 2f62270d..00000000 --- a/prisma/migrations/20251204062130_set_product_image_onetoone/migration.sql +++ /dev/null @@ -1,28 +0,0 @@ -/* - Warnings: - - - A unique constraint covering the columns `[image_id]` on the table `product` will be added. If there are existing duplicate values, this will fail. - -*/ --- AlterTable -ALTER TABLE "product" ADD COLUMN "image_id" BIGINT; - --- CreateTable -CREATE TABLE "product_image" ( - "id" BIGSERIAL NOT NULL, - "name" TEXT NOT NULL, - "path" TEXT NOT NULL, - "size" INTEGER NOT NULL, - "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "product_image_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "product_image_name_key" ON "product_image"("name"); - --- CreateIndex -CREATE UNIQUE INDEX "product_image_id_key" ON "product"("image_id"); - --- AddForeignKey -ALTER TABLE "product" ADD CONSTRAINT "product_image_id_fkey" FOREIGN KEY ("image_id") REFERENCES "product_image"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20260106065635_init/migration.sql b/prisma/migrations/20260106065635_init/migration.sql deleted file mode 100644 index 2d1b91b6..00000000 --- a/prisma/migrations/20260106065635_init/migration.sql +++ /dev/null @@ -1,66 +0,0 @@ -/* - Warnings: - - - Added the required column `userId` to the `Article` table without a default value. This is not possible if the table is not empty. - - Added the required column `userId` to the `Comment` table without a default value. This is not possible if the table is not empty. - - Added the required column `userId` to the `Product` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "Article" ADD COLUMN "userId" INTEGER NOT NULL; - --- AlterTable -ALTER TABLE "Comment" ADD COLUMN "userId" INTEGER NOT NULL; - --- AlterTable -ALTER TABLE "Product" ADD COLUMN "userId" INTEGER NOT NULL; - --- CreateTable -CREATE TABLE "User" ( - "id" SERIAL NOT NULL, - "email" TEXT NOT NULL, - "nickname" TEXT NOT NULL, - "image" TEXT, - "password" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "User_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Like" ( - "id" SERIAL NOT NULL, - "userId" INTEGER NOT NULL, - "productId" INTEGER, - "articleId" INTEGER, - - CONSTRAINT "Like_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); - --- CreateIndex -CREATE UNIQUE INDEX "Like_userId_productId_key" ON "Like"("userId", "productId"); - --- CreateIndex -CREATE UNIQUE INDEX "Like_userId_articleId_key" ON "Like"("userId", "articleId"); - --- AddForeignKey -ALTER TABLE "Article" ADD CONSTRAINT "Article_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Product" ADD CONSTRAINT "Product_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Comment" ADD CONSTRAINT "Comment_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Like" ADD CONSTRAINT "Like_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Like" ADD CONSTRAINT "Like_productId_fkey" FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Like" ADD CONSTRAINT "Like_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "Article"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20260106141853_add_refresh_token/migration.sql b/prisma/migrations/20260106141853_add_refresh_token/migration.sql deleted file mode 100644 index 788ebae8..00000000 --- a/prisma/migrations/20260106141853_add_refresh_token/migration.sql +++ /dev/null @@ -1,5 +0,0 @@ --- AlterTable -ALTER TABLE "Like" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; - --- AlterTable -ALTER TABLE "User" ADD COLUMN "refreshToken" TEXT; diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml index 99e4f200..fbffa92c 100644 --- a/prisma/migrations/migration_lock.toml +++ b/prisma/migrations/migration_lock.toml @@ -1,3 +1,3 @@ # Please do not edit this file manually # It should be added in your version-control system (i.e. Git) -provider = "postgresql" +provider = "postgresql" \ No newline at end of file diff --git a/prisma/prisma.js b/prisma/prisma.js deleted file mode 100644 index 33c37681..00000000 --- a/prisma/prisma.js +++ /dev/null @@ -1,25 +0,0 @@ -import dotenv from "dotenv"; -import path from "path"; -import { fileURLToPath } from "url"; -import { createRequire } from "module"; -import { PrismaPg } from "@prisma/adapter-pg"; -import pkg from "pg"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -dotenv.config({ path: path.resolve(__dirname, "../.env") }); - -const require = createRequire(import.meta.url); -const { PrismaClient } = require("../generated/prisma/index.js"); - -const connectionString = process.env.DATABASE_URL; - -if (!connectionString) { - throw new Error("DATABASE_URL이 μ„€μ •λ˜μ–΄ μžˆμ§€ μ•ŠμŠ΅λ‹ˆλ‹€. .env 파일 확인 ν•„μš”"); -} - -const pool = new pkg.Pool({ connectionString }); -const adapter = new PrismaPg(pool); - -export const prisma = new PrismaClient({ adapter }); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 970681b5..f3fab9d3 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1,3 +1,9 @@ +// This is your Prisma schema file, +// learn more about it in the docs: https://pris.ly/d/prisma-schema + +// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? +// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init + generator client { provider = "prisma-client-js" } @@ -7,72 +13,96 @@ datasource db { url = env("DATABASE_URL") } +enum NotificationType { + PRICE_CHANGED + NEW_COMMENT +} + model Article { - id Int @id @default(autoincrement()) - title String - content String - image String? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - userId Int - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - comments Comment[] - likes Like[] + id Int @id @default(autoincrement()) + title String + content String + image String? + comments Comment[] + user User @relation(fields: [userId], references: [id]) + userId Int + likes Like[] + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } model Product { - id Int @id @default(autoincrement()) - name String - description String - price Int - tags String[] - images String[] - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - userId Int - comments Comment[] - likes Like[] - user User @relation(fields: [userId], references: [id], onDelete: Cascade) + id Int @id @default(autoincrement()) + name String + description String + price Int + tags String[] + images String[] + comments Comment[] + user User @relation(fields: [userId], references: [id]) + userId Int + favorites Favorite[] + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } model Comment { id Int @id @default(autoincrement()) content String + product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) productId Int? + article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) articleId Int? + user User @relation(fields: [userId], references: [id]) + userId Int createdAt DateTime @default(now()) updatedAt DateTime @updatedAt - userId Int - article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) - product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) - user User @relation(fields: [userId], references: [id], onDelete: Cascade) } model User { - id Int @id @default(autoincrement()) - email String @unique - nickname String - image String? - password String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - refreshToken String? - articles Article[] - comments Comment[] - likes Like[] - products Product[] + id Int @id @default(autoincrement()) + email String @unique + nickname String + image String? + password String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + articles Article[] + products Product[] + comments Comment[] + favorites Favorite[] + likes Like[] + notifications Notification[] +} + +model Favorite { + id Int @id @default(autoincrement()) + product Product @relation(fields: [productId], references: [id]) + productId Int + user User @relation(fields: [userId], references: [id]) + userId Int + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } model Like { id Int @id @default(autoincrement()) + article Article @relation(fields: [articleId], references: [id]) + articleId Int + user User @relation(fields: [userId], references: [id]) userId Int - productId Int? - articleId Int? createdAt DateTime @default(now()) - article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade) - product Product? @relation(fields: [productId], references: [id], onDelete: Cascade) // πŸ‘ˆ 'Product'μ—μ„œ 'product'둜 λ³€κ²½ - user User @relation(fields: [userId], references: [id], onDelete: Cascade) + updatedAt DateTime @updatedAt +} + +model Notification { + id Int @id @default(autoincrement()) + user User @relation(fields: [userId], references: [id]) + userId Int + type NotificationType + payload Json + read Boolean @default(false) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} - @@unique([userId, articleId]) - @@unique([userId, productId]) -} \ No newline at end of file diff --git a/prisma/seed.js b/prisma/seed.js deleted file mode 100644 index c94b4acb..00000000 --- a/prisma/seed.js +++ /dev/null @@ -1,59 +0,0 @@ -import { prisma } from "./prisma.js"; - -async function main() { - console.log("Seeding μ‹œμž‘..."); - - // 1. κΈ°μ‘΄ 데이터 μ‚­μ œ (μ΄ˆκΈ°ν™”) - await prisma.product.deleteMany(); - await prisma.article.deleteMany(); - console.log("κΈ°μ‘΄ product 및 article 데이터 μ‚­μ œ μ™„λ£Œ."); - - // 2. 더미 데이터 생성 - Article - const article1 = await prisma.article.create({ - data: { - title: "Prisma둜 CRUD κ΅¬ν˜„ν•˜κΈ°", - content: - "μ„œλΉ„μŠ€ 계측, 컨트둀러 계측 λΆ„λ¦¬ν•˜μ—¬ κΉ”λ”ν•˜κ²Œ μ½”λ“œλ₯Ό μž‘μ„±ν•΄λ³΄μ„Έμš”.", - }, - }); - - const article2 = await prisma.article.create({ - data: { - title: "λ°°μ—΄ νƒ€μž… ν•„λ“œ μ‚¬μš©λ²•", - content: "PostgreSQLμ—μ„œ String[] νƒ€μž…μ„ ν™œμš©ν•˜λŠ” 방법을 μ•Œμ•„λ΄…μ‹œλ‹€.", - }, - }); - - // 3. 더미 데이터 생성 - Product - const product1 = await prisma.product.create({ - data: { - name: "프리미엄 기계식 ν‚€λ³΄λ“œ", - description: "개발 생산성을 κ·ΉλŒ€ν™”ν•΄μ£ΌλŠ” 졜고의 ν‚€λ³΄λ“œμž…λ‹ˆλ‹€.", - price: 189000, - tags: ["재고있음", "μΈκΈ°μƒν’ˆ", "할인쀑"], - }, - }); - - const product2 = await prisma.product.create({ - data: { - name: "μ΄ˆκ²½λŸ‰ 무선 마우슀", - price: 45000, - tags: ["μ‹ μ œν’ˆ", "μ‚¬λ¬΄μš©"], - }, - }); - - console.log("βœ… Article 더미 데이터:", article1.id, article2.id); - console.log("βœ… Product 더미 데이터:", product1.id, product2.id); - - console.log("πŸŽ‰ Seeding μ™„λ£Œ."); -} - -main() - .then(async () => { - await prisma.$disconnect(); - }) - .catch(async (e) => { - console.error("❌ Seeding 쀑 였λ₯˜ λ°œμƒ:", e); - await prisma.$disconnect(); - process.exit(1); - }); diff --git a/public/socket-client-test.html b/public/socket-client-test.html new file mode 100644 index 00000000..2dad3fc0 --- /dev/null +++ b/public/socket-client-test.html @@ -0,0 +1,37 @@ + + + + + + Document + + +

Socket.IO client test

+
+ + +
+ + + + + diff --git a/src/app.js b/src/app.js deleted file mode 100644 index 3093a130..00000000 --- a/src/app.js +++ /dev/null @@ -1,84 +0,0 @@ -import express from "express"; -import cors from "cors"; -import productRouter from "./routes/product.js"; -import articleRouter from "./routes/article.js"; -import dotenv from "dotenv"; -import path from "path"; -import { fileURLToPath } from "url"; -import { ValidationError } from "./middlewares/validator.js"; -import productImageRouter from "./routes/productImage.js"; -import { HttpError, NotFoundError } from "./exceptions/errors.js"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -dotenv.config({ path: path.resolve(__dirname, "../.env") }); - -const app = express(); - -const bigIntToStringOrBypass = (_, value) => { - if (typeof value === "bigint") { - return value.toString(); - } - return value; -}; - -app.use(express.json()); -app.use(cors()); -app.use("json replacer", bigIntToStringOrBypass); - -// λΌμš°ν„° mount -app.use("/products", productRouter); -app.use("/articles", articleRouter); - -app.use("/profile", productImageRouter); -app.use("/uploads", productImageRouter); - -// κΈ°λ³Έ 라우트 -app.get("/", (req, res) => { - res.json({ - message: "API Server", - endpoints: ["/products", "/articles"], - }); -}); - -// 404 처리 미듀웨어: λͺ¨λ“  λΌμš°νŠΈκ°€ μ²˜λ¦¬λ˜μ§€ μ•Šμ•˜μ„ λ•Œ μ‹€ν–‰ -app.use((req, res, next) => { - next( - new NotFoundError( - `μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” μ—”λ“œν¬μΈνŠΈ: ${req.method} ${req.originalUrl}` - ) - ); -}); - -// μ΅œμ’… μ—λŸ¬ 처리 미듀웨어 (HTTP Error 반영) -app.use((err, req, res, next) => { - console.error("🚨 μ—λŸ¬ λ°œμƒ:", err.stack); - - // 1. ValidationError (μœ νš¨μ„± 검증 μ‹€νŒ¨, 400) - if (err instanceof ValidationError) { - return res.status(err.status).json({ - error: err.name, - message: err.message, - }); - } - - // 2. HttpError 계열 - if (err instanceof HttpError) { - return res.status(err.statusCode).json({ - error: err.name, - message: err.message, - }); - } - // 3. κ·Έ μ™Έ μ˜ˆμƒμΉ˜ λͺ»ν•œ μ„œλ²„ μ—λŸ¬λŠ” 500 Error 처리 - return res.status(500).json({ - error: "InternalServerError", - message: "μ„œλ²„μ—μ„œ μ•Œ 수 μ—†λŠ” μ—λŸ¬κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.", - }); -}); - -// 포트 κΈ°λ³Έκ°’ μ„€μ • μΆ”κ°€ -const apiPort = process.env.API_PORT || 3000; -app.listen(apiPort, () => { - console.log(`Server running on port ${apiPort}`); -}); diff --git a/src/app.ts b/src/app.ts new file mode 100644 index 00000000..5acfaf04 --- /dev/null +++ b/src/app.ts @@ -0,0 +1,33 @@ +import express from 'express'; +import cors from 'cors'; +import path from 'path'; +import cookieParser from 'cookie-parser'; +import { PUBLIC_PATH, STATIC_PATH } from './lib/constants'; +import articlesRouter from './routers/articlesRouter'; +import productsRouter from './routers/productsRouter'; +import commentsRouter from './routers/commentsRouter'; +import imagesRouter from './routers/imagesRouter'; +import authRouter from './routers/authRouter'; +import usersRouter from './routers/usersRouter'; +import { defaultNotFoundHandler, globalErrorHandler } from './controllers/errorController'; +import notificationsRouter from './routers/notificationsRouter'; + +const app = express(); + +app.use(cors()); +app.use(express.json()); +app.use(cookieParser()); +app.use(STATIC_PATH, express.static(path.resolve(process.cwd(), PUBLIC_PATH))); + +app.use('/articles', articlesRouter); +app.use('/products', productsRouter); +app.use('/comments', commentsRouter); +app.use('/images', imagesRouter); +app.use('/auth', authRouter); +app.use('/users', usersRouter); +app.use('/notifications', notificationsRouter); + +app.use(defaultNotFoundHandler); +app.use(globalErrorHandler); + +export default app; \ No newline at end of file diff --git a/src/controllers/articlesController.js b/src/controllers/articlesController.js deleted file mode 100644 index a32e212f..00000000 --- a/src/controllers/articlesController.js +++ /dev/null @@ -1,131 +0,0 @@ -import { create } from 'superstruct'; -import { prismaClient } from '../lib/prismaClient.js'; -import NotFoundError from '../lib/errors/NotFoundError.js'; -import { IdParamsStruct } from '../structs/commonStructs.js'; -import { CreateArticleBodyStruct, UpdateArticleBodyStruct, GetArticleListParamsStruct } from '../structs/articlesStructs.js'; -import { CreateCommentBodyStruct, GetCommentListParamsStruct } from '../structs/commentsStruct.js'; - -export const createArticle = async (req, res) => { - const data = create(req.body, CreateArticleBodyStruct); - const article = await prismaClient.article.create({ - data: { ...data, user: { connect: { id: req.user.id } } }, - }); - res.status(201).json(article); -}; - -export const getArticle = async (req, res) => { - const { id } = create(req.params, IdParamsStruct); - const article = await prismaClient.article.findUnique({ - where: { id }, - include: { _count: { select: { likes: true } } }, - }); - if (!article) throw new NotFoundError('article', id); - - let isLiked = false; - if (req.user) { - const like = await prismaClient.like.findUnique({ - where: { - userId_articleId: { - userId: req.user.id, - articleId: id - }, - }, - }); - isLiked = !!like; - } - - res.json({ - ...article, - likeCount: article._count.likes, - isLiked - }); -}; - -export const updateArticle = async (req, res) => { - const { id } = create(req.params, IdParamsStruct); - const data = create(req.body, UpdateArticleBodyStruct); - const article = await prismaClient.article.findUnique({ where: { id } }); - if (!article) throw new NotFoundError('article', id); - if (article.userId !== req.user.id) return res.status(403).json({ message: 'κΆŒν•œμ΄ μ—†μŠ΅λ‹ˆλ‹€.' }); - - const updated = await prismaClient.article.update({ where: { id }, data }); - res.json(updated); -}; - -export const deleteArticle = async (req, res) => { - const { id } = create(req.params, IdParamsStruct); - const article = await prismaClient.article.findUnique({ where: { id } }); - if (!article) throw new NotFoundError('article', id); - if (article.userId !== req.user.id) return res.status(403).json({ message: 'κΆŒν•œμ΄ μ—†μŠ΅λ‹ˆλ‹€.' }); - - await prismaClient.article.delete({ where: { id } }); - res.status(204).send(); -}; - -export const getArticleList = async (req, res) => { - const { page, pageSize, orderBy, keyword } = create(req.query, GetArticleListParamsStruct); - const where = keyword ? { title: { contains: keyword } } : {}; - const [totalCount, list] = await Promise.all([ - prismaClient.article.count({ where }), - prismaClient.article.findMany({ - skip: (page - 1) * pageSize, - take: pageSize, - orderBy: orderBy === 'recent' ? { createdAt: 'desc' } : { id: 'asc' }, - where, - }), - ]); - res.json({ list, totalCount }); -}; - -export const toggleArticleLike = async (req, res) => { - const { id: articleId } = create(req.params, IdParamsStruct); - const where = { userId_articleId: { userId: req.user.id, articleId } }; - const existing = await prismaClient.like.findUnique({ where }); - - if (existing) { - await prismaClient.like.delete({ where }); - res.json({ isLiked: false }); - } else { - await prismaClient.like.create({ - data: { user: { connect: { id: req.user.id } }, article: { connect: { id: articleId } } }, - }); - res.json({ isLiked: true }); - } -}; - -export const createComment = async (req, res) => { - const { id: articleId } = create(req.params, IdParamsStruct); - const { content } = create(req.body, CreateCommentBodyStruct); - - const article = await prismaClient.article.findUnique({ where: { id: articleId } }); - if (!article) throw new NotFoundError('article', articleId); - - const comment = await prismaClient.comment.create({ - data: { - content, - article: { connect: { id: articleId } }, - user: { connect: { id: req.user.id } }, - }, - }); - res.status(201).json(comment); -}; - -export const getCommentList = async (req, res) => { - const { id: articleId } = create(req.params, IdParamsStruct); - const { cursor, limit } = create(req.query, GetCommentListParamsStruct); - - const article = await prismaClient.article.findUnique({ where: { id: articleId } }); - if (!article) throw new NotFoundError('article', articleId); - - const commentsWithCursor = await prismaClient.comment.findMany({ - cursor: cursor ? { id: cursor } : undefined, - take: limit + 1, - where: { articleId }, - orderBy: { createdAt: 'desc' }, - }); - - const list = commentsWithCursor.slice(0, limit); - const nextCursor = commentsWithCursor.length > limit ? commentsWithCursor[limit].id : null; - - res.json({ list, nextCursor }); -}; \ No newline at end of file diff --git a/src/controllers/articlesController.ts b/src/controllers/articlesController.ts index 460f800b..84339f2e 100644 --- a/src/controllers/articlesController.ts +++ b/src/controllers/articlesController.ts @@ -1,7 +1,5 @@ -import type { Request, Response } from 'express'; +import { Request, Response } from 'express'; import { create } from 'superstruct'; -import { prismaClient } from '../lib/prismaClient'; -import NotFoundError from '../lib/errors/NotFoundError'; import { IdParamsStruct } from '../structs/commonStructs'; import { CreateArticleBodyStruct, @@ -9,227 +7,73 @@ import { GetArticleListParamsStruct, } from '../structs/articlesStructs'; import { CreateCommentBodyStruct, GetCommentListParamsStruct } from '../structs/commentsStruct'; -import UnauthorizedError from '../lib/errors/UnauthorizedError'; -import ForbiddenError from '../lib/errors/ForbiddenError'; -import BadRequestError from '../lib/errors/BadRequestError'; +import * as articlesService from '../services/articlesService'; +import * as commentsService from '../services/commentsService'; +import * as likesService from '../services/likesService'; export async function createArticle(req: Request, res: Response) { - if (!req.user) { - throw new UnauthorizedError('Unauthorized'); - } - const data = create(req.body, CreateArticleBodyStruct); - - const article = await prismaClient.article.create({ - data: { - ...data, - userId: req.user.id, - }, + const article = await articlesService.createArticle({ + ...data, + userId: req.user.id, }); - - return res.status(201).send(article); + res.status(201).send(article); } export async function getArticle(req: Request, res: Response) { const { id } = create(req.params, IdParamsStruct); - - const article = await prismaClient.article.findUnique({ - where: { id: Number(id) }, - include: { - likes: true, - }, - }); - if (!article) { - throw new NotFoundError('article', id.toString()); - } - - const currentUser = req.user; - - const articleWithLikes = { - ...article, - likes: undefined, - likeCount: article.likes.length, - isLiked: currentUser ? article.likes.some((like) => like.userId === currentUser.id) : undefined, - }; - - return res.send(articleWithLikes); + const article = await articlesService.getArticle(id); + res.send(article); } export async function updateArticle(req: Request, res: Response) { - if (!req.user) { - throw new UnauthorizedError('Unauthorized'); - } - const { id } = create(req.params, IdParamsStruct); const data = create(req.body, UpdateArticleBodyStruct); - - const existingArticle = await prismaClient.article.findUnique({ where: { id: Number(id) } }); - if (!existingArticle) { - throw new NotFoundError('article', id.toString()); - } - - if (existingArticle.userId !== req.user.id) { - throw new ForbiddenError('Should be the owner of the article'); - } - - const updatedArticle = await prismaClient.article.update({ - where: { id: Number(id) }, - data: { - ...(data.title !== undefined && { title: data.title }), - ...(data.content !== undefined && { content: data.content }), - ...(data.image !== undefined && { image: data.image }), - }, + const updatedArticle = await articlesService.updateArticle(id, { + ...data, + userId: req.user.id, }); - - return res.send(updatedArticle); + res.send(updatedArticle); } export async function deleteArticle(req: Request, res: Response) { - if (!req.user) { - throw new UnauthorizedError('Unauthorized'); - } - const { id } = create(req.params, IdParamsStruct); - - const existingArticle = await prismaClient.article.findUnique({ where: { id: Number(id) } }); - if (!existingArticle) { - throw new NotFoundError('article', id.toString()); - } - - if (existingArticle.userId !== req.user.id) { - throw new ForbiddenError('Should be the owner of the article'); - } - - await prismaClient.article.delete({ where: { id: Number(id) } }); - return res.status(204).send(); + await articlesService.deleteArticle(id, req.user.id); + res.status(204).send(); } export async function getArticleList(req: Request, res: Response) { - const { page, pageSize, orderBy, keyword } = create(req.query, GetArticleListParamsStruct); - - const where = keyword ? { title: { contains: keyword } } : {}; - - const totalCount = await prismaClient.article.count({ where }); - const articles = await prismaClient.article.findMany({ - skip: (page - 1) * pageSize, - take: pageSize, - orderBy: orderBy === 'recent' ? { createdAt: 'desc' } : { id: 'asc' }, - where, - include: { - likes: true, - }, - }); - - const articlesWithLikes = articles.map((article) => ({ - ...article, - likes: undefined, - likeCount: article.likes.length, - isLiked: req.user ? article.likes.some((like) => like.userId === req.user?.id) : undefined, - })); - - return res.send({ - list: articlesWithLikes, - totalCount, - }); + const params = create(req.query, GetArticleListParamsStruct); + const result = await articlesService.getArticleList(params); + res.send(result); } export async function createComment(req: Request, res: Response) { - if (!req.user) { - throw new UnauthorizedError('Unauthorized'); - } - const { id: articleId } = create(req.params, IdParamsStruct); const { content } = create(req.body, CreateCommentBodyStruct); - - const existingArticle = await prismaClient.article.findUnique({ - where: { id: Number(articleId) }, - }); - if (!existingArticle) { - throw new NotFoundError('article', articleId.toString()); - } - - const createdComment = await prismaClient.comment.create({ - data: { - articleId: Number(articleId), - content, - userId: req.user.id, - }, + const createdComment = await commentsService.createComment({ + articleId, + content, + userId: req.user.id, }); - - return res.status(201).send(createdComment); + res.status(201).send(createdComment); } export async function getCommentList(req: Request, res: Response) { const { id: articleId } = create(req.params, IdParamsStruct); const { cursor, limit } = create(req.query, GetCommentListParamsStruct); - - const article = await prismaClient.article.findUnique({ where: { id: Number(articleId) } }); - if (!article) { - throw new NotFoundError('article', articleId.toString()); - } - - const commentsWithCursor = await prismaClient.comment.findMany({ - where: { articleId: Number(articleId) }, - orderBy: { createdAt: 'desc' }, - take: limit + 1, - ...(cursor ? { cursor: { id: Number(cursor) } } : {}), - }); - - const comments = commentsWithCursor.slice(0, limit); - const nextCursor = - commentsWithCursor.length > limit ? comments[comments.length - 1]?.id ?? null : null; - return res.send({ - list: comments, - nextCursor, - }); + const result = await commentsService.getCommentListByArticleId(articleId, { cursor, limit }); + res.send(result); } export async function createLike(req: Request, res: Response) { - if (!req.user) { - throw new UnauthorizedError('Unauthorized'); - } - const { id: articleId } = create(req.params, IdParamsStruct); - - const existingArticle = await prismaClient.article.findUnique({ - where: { id: Number(articleId) }, - }); - if (!existingArticle) { - throw new NotFoundError('article', articleId.toString()); - } - - const existingLike = await prismaClient.like.findFirst({ - where: { articleId: Number(articleId), userId: req.user.id }, - }); - if (existingLike) { - throw new BadRequestError('Already liked'); - } - - await prismaClient.like.create({ data: { articleId: Number(articleId), userId: req.user.id } }); - return res.status(201).send(); + await likesService.createLike(articleId, req.user.id); + res.status(201).send(); } export async function deleteLike(req: Request, res: Response) { - if (!req.user) { - throw new UnauthorizedError('Unauthorized'); - } - const { id: articleId } = create(req.params, IdParamsStruct); - - const existingArticle = await prismaClient.article.findUnique({ - where: { id: Number(articleId) }, - }); - if (!existingArticle) { - throw new NotFoundError('article', articleId.toString()); - } - - const existingLike = await prismaClient.like.findFirst({ - where: { articleId: Number(articleId), userId: req.user.id }, - }); - if (!existingLike) { - throw new BadRequestError('Not liked'); - } - - await prismaClient.like.delete({ where: { id: existingLike.id } }); - return res.status(204).send(); + await likesService.deleteLike(articleId, req.user.id); + res.status(204).send(); } diff --git a/src/controllers/authController.ts b/src/controllers/authController.ts index 836b9131..ed29f511 100644 --- a/src/controllers/authController.ts +++ b/src/controllers/authController.ts @@ -1,98 +1,50 @@ -import type { Request, Response } from 'express'; -import * as bcrypt from 'bcrypt'; +import { Request, Response } from 'express'; import { create } from 'superstruct'; -import { prismaClient } from '../lib/prismaClient'; -import { generateTokens, verifyRefreshToken } from '../lib/token'; import { ACCESS_TOKEN_COOKIE_NAME, REFRESH_TOKEN_COOKIE_NAME, NODE_ENV } from '../lib/constants'; import { LoginBodyStruct, RegisterBodyStruct } from '../structs/authStructs'; -import BadRequestError from '../lib/errors/BadRequestError'; -import UnauthorizedError from '../lib/errors/UnauthorizedError'; +import * as authService from '../services/authService'; +import userResponseDTO from '../dto/userResponseDTO'; export async function register(req: Request, res: Response) { - const { email, nickname, password } = create(req.body, RegisterBodyStruct); - - const salt = await bcrypt.genSalt(10); - const hashedPassword = await bcrypt.hash(password, salt); - - const isExist = await prismaClient.user.findUnique({ where: { email } }); - if (isExist) { - throw new BadRequestError('User already exists'); - } - - const user = await prismaClient.user.create({ - data: { email, nickname, password: hashedPassword }, - }); - - const { accessToken, refreshToken } = generateTokens(user.id); - setTokenCookies(res, accessToken, refreshToken); - - const { password: _, ...userWithoutPassword } = user; - return res.status(201).send(userWithoutPassword); + const data = create(req.body, RegisterBodyStruct); + const user = await authService.register(data); + res.status(201).json(userResponseDTO(user)); } export async function login(req: Request, res: Response) { - const { email, password } = create(req.body, LoginBodyStruct); - - const user = await prismaClient.user.findUnique({ where: { email } }); - if (!user) { - throw new UnauthorizedError('Invalid credentials'); - } - - const isPasswordValid = await bcrypt.compare(password, user.password); - if (!isPasswordValid) { - throw new UnauthorizedError('Invalid credentials'); - } - - const { accessToken, refreshToken } = generateTokens(user.id); + const data = create(req.body, LoginBodyStruct); + const { accessToken, refreshToken } = await authService.login(data); setTokenCookies(res, accessToken, refreshToken); - - const { password: _, ...userWithoutPassword } = user; - return res.status(200).send(userWithoutPassword); + res.status(200).send(); } export async function logout(req: Request, res: Response) { clearTokenCookies(res); - return res.status(200).send(); + res.status(200).send(); } export async function refreshToken(req: Request, res: Response) { - const token = req.cookies[REFRESH_TOKEN_COOKIE_NAME]; - if (!token) { - throw new UnauthorizedError('Invalid refresh token'); - } - - try { - const { userId } = verifyRefreshToken(token); - - const user = await prismaClient.user.findUnique({ where: { id: userId } }); - if (!user) { - throw new UnauthorizedError('Invalid refresh token'); - } - - const { accessToken, refreshToken: newRefreshToken } = generateTokens(userId); - setTokenCookies(res, accessToken, newRefreshToken); - return res.status(200).send(); - } catch (error) { - throw new UnauthorizedError('Invalid refresh token'); - } + const refreshToken = req.cookies[REFRESH_TOKEN_COOKIE_NAME]; + const { accessToken, refreshToken: newRefreshToken } = await authService.refreshToken(refreshToken); + setTokenCookies(res, accessToken, newRefreshToken); + res.status(200).send(); } function setTokenCookies(res: Response, accessToken: string, refreshToken: string) { res.cookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, { httpOnly: true, secure: NODE_ENV === 'production', - maxAge: 1 * 60 * 60 * 1000, - path: '/', + maxAge: 1 * 60 * 60 * 1000, // 1 hour }); res.cookie(REFRESH_TOKEN_COOKIE_NAME, refreshToken, { httpOnly: true, secure: NODE_ENV === 'production', - maxAge: 7 * 24 * 60 * 60 * 1000, - path: '/', + maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days + path: '/auth/refresh', }); } function clearTokenCookies(res: Response) { - res.clearCookie(ACCESS_TOKEN_COOKIE_NAME, { path: '/' }); - res.clearCookie(REFRESH_TOKEN_COOKIE_NAME, { path: '/' }); + res.clearCookie(ACCESS_TOKEN_COOKIE_NAME); + res.clearCookie(REFRESH_TOKEN_COOKIE_NAME); } diff --git a/src/controllers/commentsController.js b/src/controllers/commentsController.js deleted file mode 100644 index 92291ba5..00000000 --- a/src/controllers/commentsController.js +++ /dev/null @@ -1,26 +0,0 @@ -import { create } from 'superstruct'; -import { prismaClient } from '../lib/prismaClient.js'; -import { UpdateCommentBodyStruct } from '../structs/commentsStruct.js'; -import NotFoundError from '../lib/errors/NotFoundError.js'; -import { IdParamsStruct } from '../structs/commonStructs.js'; - -export const updateComment = async (req, res) => { - const { id } = create(req.params, IdParamsStruct); - const { content } = create(req.body, UpdateCommentBodyStruct); - const comment = await prismaClient.comment.findUnique({ where: { id } }); - if (!comment) throw new NotFoundError('comment', id); - if (comment.userId !== req.user.id) return res.status(403).json({ message: 'κΆŒν•œμ΄ μ—†μŠ΅λ‹ˆλ‹€.' }); - - const updated = await prismaClient.comment.update({ where: { id }, data: { content } }); - res.json(updated); -}; - -export const deleteComment = async (req, res) => { - const { id } = create(req.params, IdParamsStruct); - const comment = await prismaClient.comment.findUnique({ where: { id } }); - if (!comment) throw new NotFoundError('comment', id); - if (comment.userId !== req.user.id) return res.status(403).json({ message: 'κΆŒν•œμ΄ μ—†μŠ΅λ‹ˆλ‹€.' }); - - await prismaClient.comment.delete({ where: { id } }); - res.status(204).send(); -}; \ No newline at end of file diff --git a/src/controllers/commentsController.ts b/src/controllers/commentsController.ts index 6bbeec25..3551cc97 100644 --- a/src/controllers/commentsController.ts +++ b/src/controllers/commentsController.ts @@ -1,55 +1,18 @@ -import type { Request, Response } from 'express'; +import { Request, Response } from 'express'; import { create } from 'superstruct'; -import { prismaClient } from '../lib/prismaClient'; import { UpdateCommentBodyStruct } from '../structs/commentsStruct'; -import NotFoundError from '../lib/errors/NotFoundError'; import { IdParamsStruct } from '../structs/commonStructs'; -import UnauthorizedError from '../lib/errors/UnauthorizedError'; -import ForbiddenError from '../lib/errors/ForbiddenError'; +import * as commentsService from '../services/commentsService'; export async function updateComment(req: Request, res: Response) { - if (!req.user) { - throw new UnauthorizedError('Unauthorized'); - } - const { id } = create(req.params, IdParamsStruct); const { content } = create(req.body, UpdateCommentBodyStruct); - - const existingComment = await prismaClient.comment.findUnique({ where: { id: Number(id) } }); - if (!existingComment) { - throw new NotFoundError('comment', id.toString()); - } - - if (existingComment.userId !== req.user.id) { - throw new ForbiddenError('Should be the owner of the comment'); - } - - const updatedComment = await prismaClient.comment.update({ - where: { id: Number(id) }, - data: { - ...(content !== undefined ? { content } : {}), - }, - }); - - return res.send(updatedComment); + const updatedComment = await commentsService.updateComment(id, req.user.id, content); + res.send(updatedComment); } export async function deleteComment(req: Request, res: Response) { - if (!req.user) { - throw new UnauthorizedError('Unauthorized'); - } - const { id } = create(req.params, IdParamsStruct); - - const existingComment = await prismaClient.comment.findUnique({ where: { id: Number(id) } }); - if (!existingComment) { - throw new NotFoundError('comment', id.toString()); - } - - if (existingComment.userId !== req.user.id) { - throw new ForbiddenError('Should be the owner of the comment'); - } - - await prismaClient.comment.delete({ where: { id: Number(id) } }); - return res.status(204).send(); + await commentsService.deleteComment(id, req.user.id); + res.status(204).send(); } diff --git a/src/controllers/errorController.js b/src/controllers/errorController.js deleted file mode 100644 index 309dbc6b..00000000 --- a/src/controllers/errorController.js +++ /dev/null @@ -1,22 +0,0 @@ -import { StructError } from 'superstruct'; -import { BadRequestError } from '../lib/errors/BadRequestError.js'; -import NotFoundError from '../lib/errors/NotFoundError.js'; - -export const defaultNotFoundHandler = (req, res) => { - res.status(404).json({ message: 'Not found' }); -}; - -export const globalErrorHandler = (err, req, res, next) => { - if (err instanceof StructError || err instanceof BadRequestError) { - return res.status(400).json({ message: err.message }); - } - if (err instanceof NotFoundError) { - return res.status(404).json({ message: err.message }); - } - if (err instanceof SyntaxError && err.status === 400 && 'body' in err) { - return res.status(400).json({ message: 'Invalid JSON' }); - } - - console.error(err); - res.status(500).json({ message: 'Internal server error' }); -}; \ No newline at end of file diff --git a/src/controllers/errorController.ts b/src/controllers/errorController.ts index b58136b8..c3a9fd78 100644 --- a/src/controllers/errorController.ts +++ b/src/controllers/errorController.ts @@ -1,40 +1,50 @@ -import type { NextFunction, Request, Response } from 'express'; +import { Request, Response, NextFunction } from 'express'; import { StructError } from 'superstruct'; import BadRequestError from '../lib/errors/BadRequestError'; import NotFoundError from '../lib/errors/NotFoundError'; import UnauthorizedError from '../lib/errors/UnauthorizedError'; import ForbiddenError from '../lib/errors/ForbiddenError'; -export function defaultNotFoundHandler(req: Request, res: Response) { - return res.status(404).send({ message: 'Not found' }); +export function defaultNotFoundHandler(req: Request, res: Response, next: NextFunction) { + res.status(404).send({ message: 'Not found' }); } -export function globalErrorHandler(err: unknown, req: Request, res: Response, next: NextFunction) { - if (err instanceof StructError) { - return res.status(400).send({ - message: `Invalid ${err.path.join('.')}: ${err.message}`, - }); +export function globalErrorHandler(err: Error, req: Request, res: Response, next: NextFunction) { + /** From superstruct or application error */ + if (err instanceof StructError || err instanceof BadRequestError) { + res.status(400).send({ message: err.message }); + return; } - if ( - err instanceof BadRequestError || - err instanceof UnauthorizedError || - err instanceof ForbiddenError || - err instanceof NotFoundError - ) { - return res - .status( - err instanceof BadRequestError - ? 400 - : err instanceof UnauthorizedError - ? 401 - : err instanceof ForbiddenError - ? 403 - : 404, - ) - .send({ message: err.message }); + /** From express.json middleware */ + if (err instanceof SyntaxError && 'body' in err) { + res.status(400).send({ message: 'Invalid JSON' }); + return; + } + + /** Prisma error codes */ + if ('code' in err) { + console.error(err); + res.status(500).send({ message: 'Failed to process data' }); + return; + } + + /** Application errors */ + if (err instanceof NotFoundError) { + res.status(404).send({ message: err.message }); + return; + } + + if (err instanceof UnauthorizedError) { + res.status(401).send({ message: err.message }); + return; + } + + if (err instanceof ForbiddenError) { + res.status(403).send({ message: err.message }); + return; } console.error(err); - return res.status(500).send({ message: 'Internal server error' }); + res.status(500).send({ message: 'Internal server error' }); } diff --git a/src/controllers/imagesController.js b/src/controllers/imagesController.js deleted file mode 100644 index 84600deb..00000000 --- a/src/controllers/imagesController.js +++ /dev/null @@ -1,41 +0,0 @@ -import multer from 'multer'; -import path from 'path'; -import { v4 as uuidv4 } from 'uuid'; -import { PUBLIC_PATH, STATIC_PATH } from '../lib/constants.js'; -import {BadRequestError} from '../lib/errors/BadRequestError.js'; - -const ALLOWED_MIME_TYPES = ['image/png', 'image/jpeg', 'image/jpg']; -const FILE_SIZE_LIMIT = 5 * 1024 * 1024; - -export const upload = multer({ - storage: multer.diskStorage({ - destination(req, file, cb) { - cb(null, PUBLIC_PATH); - }, - filename(req, file, cb) { - const ext = path.extname(file.originalname); - const filename = `${uuidv4()}${ext}`; - cb(null, filename); - }, - }), - - limits: { - fileSize: FILE_SIZE_LIMIT, - }, - - fileFilter: function (req, file, cb) { - if (!ALLOWED_MIME_TYPES.includes(file.mimetype)) { - const err = new BadRequestError('Only png, jpeg, and jpg are allowed'); - return cb(err); - } - - cb(null, true); - }, -}); - -export async function uploadImage(req, res) { - const host = req.get('host'); - const filePath = path.join(host, STATIC_PATH, req.file.filename); - const url = `http://${filePath}`; - return res.send({ url }); -} diff --git a/src/controllers/imagesController.ts b/src/controllers/imagesController.ts index e41041d1..fee1098a 100644 --- a/src/controllers/imagesController.ts +++ b/src/controllers/imagesController.ts @@ -1,64 +1,86 @@ -import * as multerModule from 'multer'; -import type { Request, Response } from 'express'; +import { Request, Response } from 'express'; +import multer from 'multer'; +import multerS3 from 'multer-s3'; +import { S3Client } from '@aws-sdk/client-s3'; import path from 'path'; import { v4 as uuidv4 } from 'uuid'; -import { PUBLIC_PATH, STATIC_PATH } from '../lib/constants'; +import { + PUBLIC_PATH, + STATIC_PATH, + NODE_ENV, + AWS_REGION, + AWS_ACCESS_KEY_ID, + AWS_SECRET_ACCESS_KEY, + AWS_S3_BUCKET_NAME, +} from '../lib/constants'; import BadRequestError from '../lib/errors/BadRequestError'; -const multer = (multerModule as any).default || multerModule; - const ALLOWED_MIME_TYPES = ['image/png', 'image/jpeg', 'image/jpg']; const FILE_SIZE_LIMIT = 5 * 1024 * 1024; -export const upload = (multer as any)({ - storage: (multer as any).diskStorage({ - destination( - req: Request, - file: Express.Multer.File, - cb: (error: Error | null, destination: string) => void, - ) { - cb(null, PUBLIC_PATH); - }, - filename( - req: Request, - file: Express.Multer.File, - cb: (error: Error | null, filename: string) => void, - ) { - const ext = path.extname(file.originalname); - const filename = `${uuidv4()}${ext}`; - cb(null, filename); - }, - }), +const isProduction = NODE_ENV === 'production'; - limits: { - fileSize: FILE_SIZE_LIMIT, - }, +// S3 ν΄λΌμ΄μ–ΈνŠΈ (ν”„λ‘œλ•μ…˜ μ „μš©) +const s3 = isProduction + ? new S3Client({ + region: AWS_REGION, + credentials: { + accessKeyId: AWS_ACCESS_KEY_ID, + secretAccessKey: AWS_SECRET_ACCESS_KEY, + }, + }) + : null; + +// ν™˜κ²½μ— 따라 storage λΆ„κΈ° +const storage = isProduction + ? multerS3({ + s3: s3!, + bucket: AWS_S3_BUCKET_NAME, + contentType: multerS3.AUTO_CONTENT_TYPE, + key(req, file, cb) { + const ext = path.extname(file.originalname); + const filename = `uploads/${uuidv4()}${ext}`; + cb(null, filename); + }, + }) + : multer.diskStorage({ + destination(req, file, cb) { + cb(null, PUBLIC_PATH); + }, + filename(req, file, cb) { + const ext = path.extname(file.originalname); + const filename = `${uuidv4()}${ext}`; + cb(null, filename); + }, + }); - fileFilter: function ( - req: Request, - file: Express.Multer.File, - cb: (error: Error | null, acceptFile: boolean) => void, - ) { +export const upload = multer({ + storage, + limits: { fileSize: FILE_SIZE_LIMIT }, + fileFilter(req, file, cb) { if (!ALLOWED_MIME_TYPES.includes(file.mimetype)) { const err = new BadRequestError('Only png, jpeg, and jpg are allowed'); - return cb(err, false); + return cb(err); } - cb(null, true); }, }); export async function uploadImage(req: Request, res: Response) { - // req.file 쑴재 μ—¬λΆ€ 확인 (νƒ€μž… κ°€λ“œ) if (!req.file) { - throw new BadRequestError('파일이 μ—…λ‘œλ“œλ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.'); + throw new BadRequestError('File is required'); } - const host = req.get('host'); + let url: string; - // hostκ°€ undefined일 수 μžˆμœΌλ―€λ‘œ ?? '' 처리 - const filePath = path.join(host ?? '', STATIC_PATH, req.file.filename); - const url = `http://${filePath}`; + if (isProduction) { + // multer-s3κ°€ location ν•„λ“œμ— S3 URL을 λ„£μ–΄μ€Œ + url = (req.file as Express.MulterS3.File).location; + } else { + const host = req.get('host'); + if (!host) throw new BadRequestError('Host is required'); + url = `http://${path.join(host, STATIC_PATH, req.file.filename)}`; + } - return res.send({ url }); + res.send({ url }); } diff --git a/src/controllers/likesController.js b/src/controllers/likesController.js deleted file mode 100644 index 704c51c9..00000000 --- a/src/controllers/likesController.js +++ /dev/null @@ -1,26 +0,0 @@ -import { prismaClient } from '../lib/prismaClient.js'; - -export const toggleProductLike = async (req, res) => { - const { productId } = req.params; - const where = { userId_productId: { userId: req.user.id, productId: Number(productId) } }; - const existing = await prismaClient.like.findUnique({ where }); - - if (existing) { - await prismaClient.like.delete({ where }); - res.json({ isLiked: false }); - } else { - await prismaClient.like.create({ - data: { user: { connect: { id: req.user.id } }, product: { connect: { id: Number(productId) } } }, - }); - res.json({ isLiked: true }); - } -}; - -export const getMyLikedProducts = async (req, res) => { - const likedData = await prismaClient.like.findMany({ - where: { userId: req.user.id, productId: { not: null } }, - include: { product: true }, - orderBy: { createdAt: 'desc' }, - }); - res.json(likedData.map((item) => item.product)); -}; \ No newline at end of file diff --git a/src/controllers/notificationsController.ts b/src/controllers/notificationsController.ts new file mode 100644 index 00000000..8b3f5feb --- /dev/null +++ b/src/controllers/notificationsController.ts @@ -0,0 +1,10 @@ +import { Request, Response } from 'express'; +import { create } from 'superstruct'; +import { IdParamsStruct } from '../structs/commonStructs'; +import * as notificationsService from '../services/notificationsService'; + +export async function readNotification(req: Request, res: Response) { + const { id } = create(req.params, IdParamsStruct); + await notificationsService.readNotificationById(req.user?.id, id); + res.status(200).send(); +} diff --git a/src/controllers/productsController.js b/src/controllers/productsController.js deleted file mode 100644 index 6e3c42b4..00000000 --- a/src/controllers/productsController.js +++ /dev/null @@ -1,122 +0,0 @@ -import { create } from 'superstruct'; -import { prismaClient } from '../lib/prismaClient.js'; -import NotFoundError from '../lib/errors/NotFoundError.js'; -import { BadRequestError } from '../lib/errors/BadRequestError.js'; -import { IdParamsStruct } from '../structs/commonStructs.js'; -import { CreateProductBodyStruct, GetProductListParamsStruct, UpdateProductBodyStruct } from '../structs/productsStruct.js'; -import { CreateCommentBodyStruct, GetCommentListParamsStruct } from '../structs/commentsStruct.js'; - -export const createProduct = async (req, res) => { - const data = create(req.body, CreateProductBodyStruct); - const product = await prismaClient.product.create({ - data: { ...data, user: { connect: { id: req.user.id } } }, - }); - res.status(201).json(product); -}; - -export const getProduct = async (req, res) => { - const { id } = create(req.params, IdParamsStruct); - const product = await prismaClient.product.findUnique({ - where: { id }, - include: { _count: { select: { likes: true } } }, - }); - if (!product) throw new NotFoundError('product', id); - - let isLiked = false; - if (req.user) { - const like = await prismaClient.like.findUnique({ - where: { userId_productId: { userId: req.user.id, productId: id } }, - }); - isLiked = !!like; - } - res.json({ ...product, likeCount: product._count.likes, isLiked }); -}; - -export const updateProduct = async (req, res) => { - const { id } = create(req.params, IdParamsStruct); - const data = create(req.body, UpdateProductBodyStruct); - const product = await prismaClient.product.findUnique({ where: { id } }); - if (!product) throw new NotFoundError('product', id); - if (product.userId !== req.user.id) throw new BadRequestError('κΆŒν•œμ΄ μ—†μŠ΅λ‹ˆλ‹€.'); - - const updated = await prismaClient.product.update({ where: { id }, data }); - res.json(updated); -}; - -export const deleteProduct = async (req, res) => { - const { id } = create(req.params, IdParamsStruct); - const product = await prismaClient.product.findUnique({ where: { id } }); - if (!product) throw new NotFoundError('product', id); - if (product.userId !== req.user.id) throw new BadRequestError('κΆŒν•œμ΄ μ—†μŠ΅λ‹ˆλ‹€.'); - - await prismaClient.product.delete({ where: { id } }); - res.status(204).send(); -}; - -export const getProductList = async (req, res) => { - const { page, pageSize, orderBy, keyword } = create(req.query, GetProductListParamsStruct); - const where = keyword ? { OR: [{ name: { contains: keyword } }, { description: { contains: keyword } }] } : {}; - const [totalCount, list] = await Promise.all([ - prismaClient.product.count({ where }), - prismaClient.product.findMany({ - skip: (page - 1) * pageSize, - take: pageSize, - orderBy: orderBy === 'recent' ? { createdAt: 'desc' } : { id: 'asc' }, - where, - }), - ]); - res.json({ list, totalCount }); -}; - -export const toggleProductLike = async (req, res) => { - const { id: productId } = create(req.params, IdParamsStruct); - const where = { userId_productId: { userId: req.user.id, productId } }; - const existing = await prismaClient.like.findUnique({ where }); - - if (existing) { - await prismaClient.like.delete({ where }); - res.json({ isLiked: false }); - } else { - await prismaClient.like.create({ - data: { user: { connect: { id: req.user.id } }, product: { connect: { id: productId } } }, - }); - res.json({ isLiked: true }); - } -}; - -export const createComment = async (req, res) => { - const { id: productId } = create(req.params, IdParamsStruct); - const { content } = create(req.body, CreateCommentBodyStruct); - - const product = await prismaClient.product.findUnique({ where: { id: productId } }); - if (!product) throw new NotFoundError('product', productId); - - const comment = await prismaClient.comment.create({ - data: { - content, - product: { connect: { id: productId } }, - user: { connect: { id: req.user.id } }, - }, - }); - res.status(201).json(comment); -}; - -export const getCommentList = async (req, res) => { - const { id: productId } = create(req.params, IdParamsStruct); - const { cursor, limit } = create(req.query, GetCommentListParamsStruct); - - const product = await prismaClient.product.findUnique({ where: { id: productId } }); - if (!product) throw new NotFoundError('product', productId); - - const commentsWithCursor = await prismaClient.comment.findMany({ - cursor: cursor ? { id: cursor } : undefined, - take: limit + 1, - where: { productId }, - orderBy: { createdAt: 'desc' }, - }); - - const list = commentsWithCursor.slice(0, limit); - const nextCursor = commentsWithCursor.length > limit ? commentsWithCursor[limit].id : null; - - res.json({ list, nextCursor }); -}; \ No newline at end of file diff --git a/src/controllers/productsController.ts b/src/controllers/productsController.ts index c86a4404..a713a6c9 100644 --- a/src/controllers/productsController.ts +++ b/src/controllers/productsController.ts @@ -1,7 +1,5 @@ -import type { Request, Response } from 'express'; +import { Request, Response } from 'express'; import { create } from 'superstruct'; -import { prismaClient } from '../lib/prismaClient'; -import NotFoundError from '../lib/errors/NotFoundError'; import { IdParamsStruct } from '../structs/commonStructs'; import { CreateProductBodyStruct, @@ -9,230 +7,73 @@ import { UpdateProductBodyStruct, } from '../structs/productsStruct'; import { CreateCommentBodyStruct, GetCommentListParamsStruct } from '../structs/commentsStruct'; -import UnauthorizedError from '../lib/errors/UnauthorizedError'; -import ForbiddenError from '../lib/errors/ForbiddenError'; -import BadRequestError from '../lib/errors/BadRequestError'; +import * as productsService from '../services/productsService'; +import * as commentsService from '../services/commentsService'; +import * as favoritesService from '../services/favoritesService'; export async function createProduct(req: Request, res: Response) { - if (!req.user) { - throw new UnauthorizedError('Unauthorized'); - } - const data = create(req.body, CreateProductBodyStruct); - - const createdProduct = await prismaClient.product.create({ - data: { - ...data, - userId: req.user.id, - }, + const createdProduct = await productsService.createProduct({ + ...data, + userId: req.user.id, }); - res.status(201).send(createdProduct); } export async function getProduct(req: Request, res: Response) { const { id } = create(req.params, IdParamsStruct); - - const product = await prismaClient.product.findUnique({ - where: { id: Number(id) }, - include: { likes: true }, - }); - - if (!product) { - throw new NotFoundError('product', id.toString()); - } - - const productWithLikes = { - ...product, - likes: undefined, - likeCount: product.likes.length, - isLiked: req.user ? product.likes.some((like) => like.userId === req.user?.id) : false, - }; - - return res.send(productWithLikes); + const product = await productsService.getProduct(id); + res.send(product); } export async function updateProduct(req: Request, res: Response) { - if (!req.user) { - throw new UnauthorizedError('Unauthorized'); - } - const { id } = create(req.params, IdParamsStruct); - const { name, description, price, tags, images } = create(req.body, UpdateProductBodyStruct); - - const existingProduct = await prismaClient.product.findUnique({ - where: { id: Number(id) }, + const data = create(req.body, UpdateProductBodyStruct); + const updatedProduct = await productsService.updateProduct(id, { + ...data, + userId: req.user.id, }); - - if (!existingProduct) { - throw new NotFoundError('product', id.toString()); - } - - if (existingProduct.userId !== req.user.id) { - throw new ForbiddenError('Should be the owner of the product'); - } - - const updatedProduct = await prismaClient.product.update({ - where: { id: Number(id) }, - data: { - ...(name !== undefined && { name }), - ...(description !== undefined && { description }), - ...(price !== undefined && { price }), - ...(tags !== undefined && { tags }), - ...(images !== undefined && { images }), - }, - }); - - return res.send(updatedProduct); + res.send(updatedProduct); } export async function deleteProduct(req: Request, res: Response) { - if (!req.user) { - throw new UnauthorizedError('Unauthorized'); - } - const { id } = create(req.params, IdParamsStruct); - const existingProduct = await prismaClient.product.findUnique({ - where: { id: Number(id) }, - }); - - if (!existingProduct) { - throw new NotFoundError('product', id.toString()); - } - - if (existingProduct.userId !== req.user.id) { - throw new ForbiddenError('Should be the owner of the product'); - } - - await prismaClient.product.delete({ where: { id: Number(id) } }); - return res.status(204).send(); + await productsService.deleteProduct(id, req.user.id); + res.status(204).send(); } export async function getProductList(req: Request, res: Response) { - const { page, pageSize, orderBy, keyword } = create(req.query, GetProductListParamsStruct); - - const where = keyword - ? { - OR: [{ name: { contains: keyword } }, { description: { contains: keyword } }], - } - : undefined; - - const totalCount = await prismaClient.product.count({ - ...(where && { where }), - }); - const products = await prismaClient.product.findMany({ - skip: (page - 1) * pageSize, - take: pageSize, - orderBy: orderBy === 'recent' ? { id: 'desc' } : { id: 'asc' }, - ...(where && { where }), - include: { - likes: true, - }, - }); - - const productsWithLikes = products.map((product) => ({ - ...product, - likes: undefined, - likeCount: product.likes.length, - isLiked: req.user ? product.likes.some((like) => like.userId === req.user?.id) : false, - })); - - return res.send({ - list: productsWithLikes, - totalCount, + const params = create(req.query, GetProductListParamsStruct); + const result = await productsService.getProductList(params, { + userId: req.user?.id, }); + res.send(result); } export async function createComment(req: Request, res: Response) { - if (!req.user) { - throw new UnauthorizedError('Unauthorized'); - } - - const { id: productId } = create(req.params, IdParamsStruct); - const { content } = create(req.body, CreateCommentBodyStruct); - - const existingProduct = await prismaClient.product.findUnique({ - where: { id: Number(productId) }, - }); - if (!existingProduct) { - throw new NotFoundError('product', productId.toString()); - } - - const createdComment = await prismaClient.comment.create({ - data: { productId: Number(productId), content, userId: req.user.id }, + const data = create(req.body, CreateCommentBodyStruct); + const createdComment = await commentsService.createComment({ + ...data, + userId: req.user.id, }); - - return res.status(201).send(createdComment); + res.status(201).send(createdComment); } export async function getCommentList(req: Request, res: Response) { const { id: productId } = create(req.params, IdParamsStruct); - const { cursor, limit } = create(req.query, GetCommentListParamsStruct); - - const existingProduct = await prismaClient.product.findUnique({ - where: { id: Number(productId) }, - }); - if (!existingProduct) { - throw new NotFoundError('product', productId.toString()); - } - - const commentsWithCursor = await prismaClient.comment.findMany({ - where: { productId: Number(productId) }, - orderBy: { createdAt: 'desc' }, - take: limit + 1, - ...(cursor ? { cursor: { id: Number(cursor) } } : {}), - }); - - const comments = commentsWithCursor.slice(0, limit); - const nextCursor = - commentsWithCursor.length > limit ? comments[comments.length - 1]?.id ?? null : null; - return res.send({ - list: comments, - nextCursor, - }); + const params = create(req.query, GetCommentListParamsStruct); + const result = await commentsService.getCommentListByProductId(productId, params); + res.send(result); } -export async function createLike(req: Request, res: Response) { - if (!req.user) { - throw new UnauthorizedError('Unauthorized'); - } - +export async function createFavorite(req: Request, res: Response) { const { id: productId } = create(req.params, IdParamsStruct); - - const existingProduct = await prismaClient.product.findUnique({ - where: { id: Number(productId) }, - }); - if (!existingProduct) { - throw new NotFoundError('product', productId.toString()); - } - - const existingLike = await prismaClient.like.findFirst({ - where: { productId: Number(productId), userId: req.user.id }, - }); - if (existingLike) { - throw new BadRequestError('Already liked'); - } - - await prismaClient.like.create({ - data: { productId: Number(productId), userId: req.user.id }, - }); - return res.status(201).send(); + await favoritesService.createFavorite(productId, req.user.id); + res.status(201).send(); } -export async function deleteLike(req: Request, res: Response) { - if (!req.user) { - throw new UnauthorizedError('Unauthorized'); - } - +export async function deleteFavorite(req: Request, res: Response) { const { id: productId } = create(req.params, IdParamsStruct); - - const existingLike = await prismaClient.like.findFirst({ - where: { productId: Number(productId), userId: req.user.id }, - }); - if (!existingLike) { - throw new BadRequestError('Not liked'); - } - - await prismaClient.like.delete({ where: { id: existingLike.id } }); - return res.status(204).send(); + await favoritesService.deleteFavorite(productId, req.user.id); + res.status(204).send(); } diff --git a/src/controllers/usersController.js b/src/controllers/usersController.js deleted file mode 100644 index bf03449e..00000000 --- a/src/controllers/usersController.js +++ /dev/null @@ -1,92 +0,0 @@ -import bcrypt from 'bcrypt'; -import jwt from 'jsonwebtoken'; -import { prismaClient } from '../lib/prismaClient.js'; -import { BadRequestError } from '../lib/errors/BadRequestError.js'; - -export const signUp = async (req, res) => { - const { email, nickname, password } = req.body; - - if (!email || !nickname || !password) { - throw new BadRequestError('이메일, λ‹‰λ„€μž„, λΉ„λ°€λ²ˆν˜ΈλŠ” ν•„μˆ˜μž…λ‹ˆλ‹€.'); - } - - const existingUser = await prismaClient.user.findUnique({ where: { email } }); - if (existingUser) throw new BadRequestError('이미 μ‚¬μš© 쀑인 μ΄λ©”μΌμž…λ‹ˆλ‹€.'); - - const hashedPassword = await bcrypt.hash(password, 10); - const user = await prismaClient.user.create({ - data: { email, nickname, password: hashedPassword }, - select: { id: true, email: true, nickname: true, createdAt: true }, - }); - res.status(201).json(user); -}; - -export const signIn = async (req, res) => { - const { email, password } = req.body; - const user = await prismaClient.user.findUnique({ where: { email } }); - if (!user || !(await bcrypt.compare(password, user.password))) { - throw new BadRequestError('이메일 λ˜λŠ” λΉ„λ°€λ²ˆν˜Έκ°€ μΌμΉ˜ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.'); - } - - const accessToken = jwt.sign({ userId: user.id }, process.env.JWT_SECRET, { expiresIn: '2h' }); - const refreshToken = jwt.sign({ userId: user.id }, process.env.JWT_REFRESH_SECRET, { expiresIn: '7d' }); - - await prismaClient.user.update({ where: { id: user.id }, data: { refreshToken } }); - res.json({ accessToken, refreshToken, user: { id: user.id, email: user.email, nickname: user.nickname } }); -}; - -export const refresh = async (req, res) => { - const { refreshToken } = req.body; - if (!refreshToken) throw new BadRequestError('Refresh Token이 ν•„μš”ν•©λ‹ˆλ‹€.'); - - try { - const payload = jwt.verify(refreshToken, process.env.JWT_REFRESH_SECRET); - const user = await prismaClient.user.findUnique({ where: { id: payload.userId } }); - if (!user || user.refreshToken !== refreshToken) throw new Error(); - - const accessToken = jwt.sign({ userId: user.id }, process.env.JWT_SECRET, { expiresIn: '2h' }); - res.json({ accessToken }); - } catch { - res.status(401).json({ message: 'μœ νš¨ν•˜μ§€ μ•Šμ€ ν† ν°μž…λ‹ˆλ‹€.' }); - } -}; - -export const getMe = async (req, res) => { - const user = await prismaClient.user.findUnique({ - where: { id: req.user.id }, - select: { id: true, email: true, nickname: true, image: true, createdAt: true }, - }); - res.json(user); -}; - -export const updateMe = async (req, res) => { - const { nickname, image } = req.body; - const user = await prismaClient.user.update({ - where: { id: req.user.id }, - data: { nickname, image }, - select: { id: true, email: true, nickname: true, image: true }, - }); - res.json(user); -}; - -export const changePassword = async (req, res) => { - const { currentPassword, newPassword } = req.body; - const user = await prismaClient.user.findUnique({ where: { id: req.user.id } }); - if (!(await bcrypt.compare(currentPassword, user.password))) { - throw new BadRequestError('ν˜„μž¬ λΉ„λ°€λ²ˆν˜Έκ°€ μΌμΉ˜ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.'); - } - - await prismaClient.user.update({ - where: { id: req.user.id }, - data: { password: await bcrypt.hash(newPassword, 10) }, - }); - res.status(204).send(); -}; - -export const getMyProducts = async (req, res) => { - const products = await prismaClient.product.findMany({ - where: { userId: req.user.id }, - orderBy: { createdAt: 'desc' }, - }); - res.json(products); -}; \ No newline at end of file diff --git a/src/controllers/usersController.ts b/src/controllers/usersController.ts index 96f841cd..994fa0a6 100644 --- a/src/controllers/usersController.ts +++ b/src/controllers/usersController.ts @@ -1,158 +1,75 @@ -import type { Request, Response } from 'express'; +import { Request, Response } from 'express'; import { create } from 'superstruct'; -import bcrypt from 'bcrypt'; -import { prismaClient } from '../lib/prismaClient'; import { UpdateMeBodyStruct, UpdatePasswordBodyStruct, GetMyProductListParamsStruct, - GetMyLikeListParamsStruct, + GetMyFavoriteListParamsStruct, + GetMyNotificationsParamsStruct, } from '../structs/usersStructs'; -import NotFoundError from '../lib/errors/NotFoundError'; -import UnauthorizedError from '../lib/errors/UnauthorizedError'; +import * as usersService from '../services/usersService'; +import * as authService from '../services/authService'; +import * as notificationsService from '../services/notificationsService'; +import userResponseDTO from '../dto/userResponseDTO'; export async function getMe(req: Request, res: Response) { - if (!req.user) { - throw new UnauthorizedError('Unauthorized'); - } - - const user = await prismaClient.user.findUnique({ where: { id: req.user.id } }); - if (!user) { - throw new NotFoundError('user', req.user.id.toString()); - } - - const { password: _, ...userWithoutPassword } = user; - return res.send(userWithoutPassword); + const user = await usersService.getUser(req.user.id); + res.send(userResponseDTO(user)); } export async function updateMe(req: Request, res: Response) { - if (!req.user) { - throw new UnauthorizedError('Unauthorized'); - } - - const { nickname, image } = create(req.body, UpdateMeBodyStruct); - - const updatedUser = await prismaClient.user.update({ - where: { id: req.user.id }, - data: { - ...(nickname !== undefined && { nickname }), - ...(image !== undefined && { image }), - }, - }); - - const { password: _, ...userWithoutPassword } = updatedUser; - return res.status(200).send(userWithoutPassword); + const data = create(req.body, UpdateMeBodyStruct); + const updatedUser = await usersService.updateUser(req.user.id, data); + res.status(200).send(userResponseDTO(updatedUser)); } export async function updateMyPassword(req: Request, res: Response) { - if (!req.user) { - throw new UnauthorizedError('Unauthorized'); - } - const { password, newPassword } = create(req.body, UpdatePasswordBodyStruct); - - const user = await prismaClient.user.findUnique({ where: { id: req.user.id } }); - if (!user) { - throw new NotFoundError('user', req.user.id.toString()); - } - - const isPasswordValid = await bcrypt.compare(password, user.password); - if (!isPasswordValid) { - throw new UnauthorizedError('Invalid credentials'); - } - - const salt = await bcrypt.genSalt(10); - const hashedPassword = await bcrypt.hash(newPassword, salt); - - await prismaClient.user.update({ - where: { id: req.user.id }, - data: { password: hashedPassword }, - }); - - return res.status(200).send(); + await authService.updateMyPassword(req.user.id, password, newPassword); + res.status(200).send(); } export async function getMyProductList(req: Request, res: Response) { - if (!req.user) { - throw new UnauthorizedError('Unauthorized'); - } - const { page, pageSize, orderBy, keyword } = create(req.query, GetMyProductListParamsStruct); - - const where = { - userId: req.user.id, - ...(keyword - ? { - OR: [{ name: { contains: keyword } }, { description: { contains: keyword } }], - } - : {}), - }; - - const totalCount = await prismaClient.product.count({ where }); - - const products = await prismaClient.product.findMany({ - skip: (page - 1) * pageSize, - take: pageSize, - orderBy: orderBy === 'recent' ? { id: 'desc' } : { id: 'asc' }, - where, - include: { - likes: true, - }, + const { list, totalCount } = await usersService.getMyProductList(req.user.id, { + page, + pageSize, + orderBy, + keyword, }); - const productsWithLikes = products.map((product) => ({ - ...product, - likes: undefined, - likeCount: product.likes.length, - isLiked: product.likes.some((like) => like.userId === req.user!.id), - })); - - return res.send({ - list: productsWithLikes, + res.send({ + list, totalCount, }); } -// ν•¨μˆ˜λͺ…을 getMyLikeList둜 μˆ˜μ •ν–ˆμŠ΅λ‹ˆλ‹€. -export async function getMyLikeList(req: Request, res: Response) { - if (!req.user) { - throw new UnauthorizedError('Unauthorized'); - } - - const { page, pageSize, orderBy, keyword } = create(req.query, GetMyLikeListParamsStruct); - - const where = { - likes: { - some: { - userId: req.user.id, - }, - }, - ...(keyword - ? { OR: [{ name: { contains: keyword } }, { description: { contains: keyword } }] } - : {}), - }; - - const totalCount = await prismaClient.product.count({ where }); +export async function getMyFavoriteList(req: Request, res: Response) { + const { page, pageSize, orderBy, keyword } = create(req.query, GetMyFavoriteListParamsStruct); + const { list, totalCount } = await usersService.getMyFavoriteList(req.user.id, { + page, + pageSize, + orderBy, + keyword, + }); - const products = await prismaClient.product.findMany({ - skip: (page - 1) * pageSize, - take: pageSize, - orderBy: orderBy === 'recent' ? { id: 'desc' } : { id: 'asc' }, - where, - include: { - likes: true, - }, + res.send({ + list, + totalCount, }); +} - const productsWithLikes = products.map((product) => ({ - ...product, - likes: undefined, - likeCount: product.likes.length, - isLiked: true, - })); +export async function getMyNotifications(req: Request, res: Response) { + const { cursor, limit } = create(req.query, GetMyNotificationsParamsStruct); + const { list, totalCount, unreadCount, nextCursor } = await notificationsService.getMyNotifications(req.user.id, { + cursor, + limit, + }); - return res.send({ - list: productsWithLikes, + res.send({ + list, + nextCursor, + unreadCount, totalCount, }); } diff --git a/src/dto/userResponseDTO.ts b/src/dto/userResponseDTO.ts new file mode 100644 index 00000000..b5c6f8ad --- /dev/null +++ b/src/dto/userResponseDTO.ts @@ -0,0 +1,8 @@ +import User from '../types/User'; + +const userResponseDTO = (user: User) => { + const { password, ...userWithoutPassword } = user; + return userWithoutPassword; +}; + +export default userResponseDTO; diff --git a/src/exceptions/errors.js b/src/exceptions/errors.js deleted file mode 100644 index b41758eb..00000000 --- a/src/exceptions/errors.js +++ /dev/null @@ -1,29 +0,0 @@ -export class HttpError extends Error { - constructor(statusCode, message) { - super(message); - this.statusCode = statusCode; - this.name = this.constructor.name; - Error.captureStackTrace(this, this.constructor); - } -} - -// 400 Bad Request -export class BadRequestError extends HttpError { - constructor(message = "잘λͺ»λœ μš”μ²­μž…λ‹ˆλ‹€.") { - super(400, message); - } -} - -// 404 Not Found -export class NotFoundError extends HttpError { - constructor(message = "μš”μ²­ν•œ λ¦¬μ†ŒμŠ€λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.") { - super(404, message); - } -} - -// 500 Internal Server Error -export class InternalServerError extends HttpError { - constructor(message = "μ„œλ²„ λ‚΄λΆ€ 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.") { - super(500, message); - } -} diff --git a/src/lib/authMiddleware.js b/src/lib/authMiddleware.js deleted file mode 100644 index 7ac805ac..00000000 --- a/src/lib/authMiddleware.js +++ /dev/null @@ -1,18 +0,0 @@ -import jwt from 'jsonwebtoken'; -import { prismaClient } from './prismaClient.js'; - -export const authMiddleware = async (req, res, next) => { - const token = req.headers.authorization?.split(' ')[1]; - if (!token) return res.status(401).json({ message: '둜그인이 ν•„μš”ν•©λ‹ˆλ‹€.' }); - - try { - const decoded = jwt.verify(token, process.env.JWT_SECRET); - const user = await prismaClient.user.findUnique({ where: { id: decoded.userId } }); - if (!user) return res.status(404).json({ message: 'μœ μ €λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.' }); - - req.user = user; - next(); - } catch { - res.status(401).json({ message: 'μœ νš¨ν•˜μ§€ μ•Šμ€ ν† ν°μž…λ‹ˆλ‹€.' }); - } -}; \ No newline at end of file diff --git a/src/lib/constants.js b/src/lib/constants.js deleted file mode 100644 index aefa85fe..00000000 --- a/src/lib/constants.js +++ /dev/null @@ -1,7 +0,0 @@ -import dotenv from 'dotenv'; -dotenv.config(); - -export const DATABASE_URL = process.env.DATABASE_URL; -export const PORT = process.env.PORT || 3000; -export const PUBLIC_PATH = './public'; -export const STATIC_PATH = '/public'; diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 80fbc829..d2bfd0e9 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -3,10 +3,16 @@ dotenv.config(); export const ACCESS_TOKEN_COOKIE_NAME = 'access-token'; export const REFRESH_TOKEN_COOKIE_NAME = 'refresh-token'; -export const DATABASE_URL = process.env.DATABASE_URL; -export const JWT_ACCESS_TOKEN_SECRET = process.env.JWT_ACCESS_TOKEN_SECRET; -export const JWT_REFRESH_TOKEN_SECRET = process.env.JWT_REFRESH_TOKEN_SECRET; +export const DATABASE_URL = process.env.DATABASE_URL || ''; +export const JWT_ACCESS_TOKEN_SECRET = process.env.JWT_ACCESS_TOKEN_SECRET || ''; +export const JWT_REFRESH_TOKEN_SECRET = process.env.JWT_REFRESH_TOKEN_SECRET || ''; export const NODE_ENV = process.env.NODE_ENV || 'development'; export const PORT = process.env.PORT || 3000; export const PUBLIC_PATH = './public'; export const STATIC_PATH = '/public'; + +// AWS S3 +export const AWS_REGION = process.env.AWS_REGION || 'ap-northeast-2'; +export const AWS_ACCESS_KEY_ID = process.env.AWS_ACCESS_KEY_ID || ''; +export const AWS_SECRET_ACCESS_KEY = process.env.AWS_SECRET_ACCESS_KEY || ''; +export const AWS_S3_BUCKET_NAME = process.env.AWS_S3_BUCKET_NAME || ''; diff --git a/src/lib/errors/BadRequestError.js b/src/lib/errors/BadRequestError.js deleted file mode 100644 index 9fed4e9a..00000000 --- a/src/lib/errors/BadRequestError.js +++ /dev/null @@ -1,6 +0,0 @@ -export class BadRequestError extends Error { - constructor(message) { - super(message); - this.name = 'BadRequestError'; - } -} diff --git a/src/lib/errors/BadRequestError.ts b/src/lib/errors/BadRequestError.ts index 73c52d8e..4bafd09a 100644 --- a/src/lib/errors/BadRequestError.ts +++ b/src/lib/errors/BadRequestError.ts @@ -1,11 +1,7 @@ class BadRequestError extends Error { - name: string; - constructor(message: string) { super(message); this.name = 'BadRequestError'; - - Object.setPrototypeOf(this, BadRequestError.prototype); } } diff --git a/src/lib/errors/ForbiddenError.ts b/src/lib/errors/ForbiddenError.ts index 7e497772..6091711c 100644 --- a/src/lib/errors/ForbiddenError.ts +++ b/src/lib/errors/ForbiddenError.ts @@ -1,11 +1,7 @@ class ForbiddenError extends Error { - name: string; - constructor(message: string) { super(message); this.name = 'ForbiddenError'; - - Object.setPrototypeOf(this, ForbiddenError.prototype); } } diff --git a/src/lib/errors/NotFoundError.js b/src/lib/errors/NotFoundError.js deleted file mode 100644 index 1ebc84d2..00000000 --- a/src/lib/errors/NotFoundError.js +++ /dev/null @@ -1,8 +0,0 @@ -class NotFoundError extends Error { - constructor(modelName, id) { - super(`${modelName} with id ${id} not found`); - this.name = 'NotFoundError'; - } -} - -export default NotFoundError; diff --git a/src/lib/errors/NotFoundError.ts b/src/lib/errors/NotFoundError.ts index ba71a910..cf993d9a 100644 --- a/src/lib/errors/NotFoundError.ts +++ b/src/lib/errors/NotFoundError.ts @@ -1,13 +1,7 @@ -import { object } from "superstruct"; - class NotFoundError extends Error { - name: string; - - constructor(modelName: String, id: number | string) { + constructor(modelName: string, id: number) { super(`${modelName} with id ${id} not found`); this.name = 'NotFoundError'; - - Object.setPrototypeOf(this, NotFoundError.prototype); } } diff --git a/src/lib/errors/UnauthorizedError.ts b/src/lib/errors/UnauthorizedError.ts index 8a074232..980e8be4 100644 --- a/src/lib/errors/UnauthorizedError.ts +++ b/src/lib/errors/UnauthorizedError.ts @@ -1,11 +1,7 @@ class UnauthorizedError extends Error { - name: string; - constructor(message: string) { super(message); this.name = 'UnauthorizedError'; - - Object.setPrototypeOf(this, UnauthorizedError.prototype); } } diff --git a/src/lib/prismaClient.js b/src/lib/prismaClient.js deleted file mode 100644 index ff61894b..00000000 --- a/src/lib/prismaClient.js +++ /dev/null @@ -1,2 +0,0 @@ -import { PrismaClient } from '@prisma/client'; -export const prismaClient = new PrismaClient(); \ No newline at end of file diff --git a/src/lib/token.ts b/src/lib/token.ts index 3887e9d9..086aa919 100644 --- a/src/lib/token.ts +++ b/src/lib/token.ts @@ -1,15 +1,7 @@ -import jwt, { type JwtPayload } from 'jsonwebtoken'; +import jwt from 'jsonwebtoken'; import { JWT_ACCESS_TOKEN_SECRET, JWT_REFRESH_TOKEN_SECRET } from './constants'; -export interface UserPayload extends JwtPayload { - id: number; -} - export function generateTokens(userId: number) { - if (!JWT_ACCESS_TOKEN_SECRET || !JWT_REFRESH_TOKEN_SECRET) { - throw new Error('JWT ν™˜κ²½ λ³€μˆ˜κ°€ μ„€μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.'); - } - const accessToken = jwt.sign({ id: userId }, JWT_ACCESS_TOKEN_SECRET, { expiresIn: '1h', }); @@ -20,12 +12,17 @@ export function generateTokens(userId: number) { } export function verifyAccessToken(token: string) { - const decoded = jwt.verify(token, JWT_ACCESS_TOKEN_SECRET as string) as UserPayload; - + const decoded = jwt.verify(token, JWT_ACCESS_TOKEN_SECRET); + if (typeof decoded === 'string') { + throw new Error('Invalid token'); + } return { userId: decoded.id }; } export function verifyRefreshToken(token: string) { - const decoded = jwt.verify(token, JWT_REFRESH_TOKEN_SECRET as string) as UserPayload; + const decoded = jwt.verify(token, JWT_REFRESH_TOKEN_SECRET); + if (typeof decoded === 'string') { + throw new Error('Invalid token'); + } return { userId: decoded.id }; } diff --git a/src/lib/withAsync.js b/src/lib/withAsync.js deleted file mode 100644 index 08fea591..00000000 --- a/src/lib/withAsync.js +++ /dev/null @@ -1,9 +0,0 @@ -export function withAsync(handler) { - return async function (req, res, next) { - try { - await handler(req, res); - } catch (e) { - next(e); - } - }; -} diff --git a/src/lib/withAsync.ts b/src/lib/withAsync.ts index 79b5101e..624a25b7 100644 --- a/src/lib/withAsync.ts +++ b/src/lib/withAsync.ts @@ -1,4 +1,4 @@ -import type { Request, Response, NextFunction, RequestHandler } from 'express'; +import { Request, Response, NextFunction, RequestHandler } from 'express'; export function withAsync(handler: RequestHandler) { return async function (req: Request, res: Response, next: NextFunction) { diff --git a/src/main.js b/src/main.js deleted file mode 100644 index 330ae426..00000000 --- a/src/main.js +++ /dev/null @@ -1,30 +0,0 @@ -import "dotenv/config"; -import express from 'express'; -import cors from 'cors'; -import path from 'path'; -import { PORT, PUBLIC_PATH, STATIC_PATH } from './lib/constants.js'; -import articlesRouter from './routers/articlesRouter.js'; -import productsRouter from './routers/productsRouter.js'; -import commentsRouter from './routers/commentsRouter.js'; -import imagesRouter from './routers/imagesRouter.js'; -import usersRouter from "./routers/usersRouter.js"; -import { defaultNotFoundHandler, globalErrorHandler } from './controllers/errorController.js'; - -const app = express(); - -app.use(cors()); -app.use(express.json()); -app.use(STATIC_PATH, express.static(path.resolve(process.cwd(), PUBLIC_PATH))); - -app.use('/articles', articlesRouter); -app.use('/products', productsRouter); -app.use('/comments', commentsRouter); -app.use('/images', imagesRouter); -app.use('/users', usersRouter); - -app.use(defaultNotFoundHandler); -app.use(globalErrorHandler); - -app.listen(PORT, () => { - console.log(`Server started on port ${PORT}`); -}); diff --git a/src/main.ts b/src/main.ts index 2e05e361..faa5853c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,34 +1,11 @@ -import express from 'express'; -import type { Request, Response, NextFunction } from 'express'; -import cors from 'cors'; -import path from 'path'; -import cookieParser from 'cookie-parser'; -import { PORT, PUBLIC_PATH, STATIC_PATH } from './lib/constants'; -import articlesRouter from './routers/articlesRouter'; -import productsRouter from './routers/productsRouter'; -import commentsRouter from './routers/commentsRouter'; -import imagesRouter from './routers/imagesRouter'; -import authRouter from './routers/authRouter'; -import usersRouter from './routers/usersRouter'; -import { defaultNotFoundHandler, globalErrorHandler } from './controllers/errorController'; +import { createServer } from 'http'; +import { PORT } from './lib/constants'; +import app from './app'; +import socketService from './services/socketService'; -const app = express(); +const server = createServer(app); +socketService.initialize(server); -app.use(cors()); -app.use(express.json()); -app.use(cookieParser()); -app.use(STATIC_PATH, express.static(path.resolve(process.cwd(), PUBLIC_PATH))); - -app.use('/articles', articlesRouter); -app.use('/products', productsRouter); -app.use('/comments', commentsRouter); -app.use('/images', imagesRouter); -app.use('/auth', authRouter); -app.use('/users', usersRouter); - -app.use(defaultNotFoundHandler); -app.use(globalErrorHandler); - -app.listen(PORT, () => { +server.listen(PORT, () => { console.log(`Server started on port ${PORT}`); }); diff --git a/src/middlewares/authenticate.ts b/src/middlewares/authenticate.ts index 50acb82f..09d81725 100644 --- a/src/middlewares/authenticate.ts +++ b/src/middlewares/authenticate.ts @@ -1,39 +1,20 @@ -import type { Request, Response, NextFunction } from 'express'; -import { prismaClient } from '../lib/prismaClient'; -import { verifyAccessToken } from '../lib/token'; +import { Request, Response, NextFunction, RequestHandler } from 'express'; import { ACCESS_TOKEN_COOKIE_NAME } from '../lib/constants'; +import * as authService from '../services/authService'; -interface AuthenticateOptions { - optional?: boolean; -} - -function authenticate(options: AuthenticateOptions = { optional: false }) { +function authenticate(options = { optional: false }): RequestHandler { return async (req: Request, res: Response, next: NextFunction) => { const accessToken = req.cookies[ACCESS_TOKEN_COOKIE_NAME]; - if (!accessToken) { - if (options.optional) { - return next(); - } - return res.status(401).json({ message: 'Unauthorized' }); - } - try { - const { userId } = verifyAccessToken(accessToken); - - const user = await prismaClient.user.findUnique({ - where: { id: userId }, - }); - - if (!user) { - if (options.optional) return next(); - return res.status(401).json({ message: 'Unauthorized' }); - } + const user = await authService.authenticate(accessToken); req.user = user; } catch (error) { if (options.optional) { - return next(); + next(); + return; } - return res.status(401).json({ message: 'Unauthorized' }); + next(error); + return; } next(); }; diff --git a/src/middlewares/validator.js b/src/middlewares/validator.js deleted file mode 100644 index fe9a2afd..00000000 --- a/src/middlewares/validator.js +++ /dev/null @@ -1,283 +0,0 @@ -class ValidationError extends Error { - constructor(message) { - super(message); - this.name = "ValidationError"; - this.status = 400; - } -} - -// 헬퍼 ν•¨μˆ˜: ν•„μˆ˜ ν•„λ“œ λˆ„λ½ 검증 -const checkRequiredFields = (body, requiredFields) => { - for (const field of requiredFields) { - if (!(field in body) || body[field] === undefined || body[field] === null) { - throw new ValidationError(`ν•„μˆ˜ ν•„λ“œ '${field}'κ°€ λˆ„λ½λ˜μ—ˆμŠ΅λ‹ˆλ‹€.`); - } - } -}; - -// 헬퍼 ν•¨μˆ˜: 데이터 νƒ€μž… 검증 -const checkDataType = (body, field, expectedType) => { - if (field in body && typeof body[field] !== expectedType) { - if (expectedType === "array" && !Array.isArray(body[field])) { - throw new ValidationError( - `ν•„λ“œ '${field}'λŠ”(은) λ°°μ—΄ νƒ€μž…μ΄μ–΄μ•Ό ν•©λ‹ˆλ‹€. (ν˜„μž¬ νƒ€μž…: ${typeof body[field]})` - ); - } else if ( - expectedType !== "array" && - typeof body[field] !== expectedType - ) { - throw new ValidationError( - `ν•„λ“œ '${field}'λŠ”(은) ${expectedType} νƒ€μž…μ΄μ–΄μ•Ό ν•©λ‹ˆλ‹€. (ν˜„μž¬ νƒ€μž…: ${typeof body[field]})` - ); - } - } -}; - -/** - * Product 생성/μ—…λ°μ΄νŠΈ μš”μ²­ 본문을 κ²€μ¦ν•˜λŠ” 미듀웨어 - * @param {object} req - Express μš”μ²­ 객체 - * @param {object} res - Express 응닡 객체 - * @param {function} next - λ‹€μŒ 미듀웨어 ν•¨μˆ˜ - */ -export const validateProductInfo = (req, res, next) => { - try { - const { name, price, description, tags } = req.body; - // 1. ν•„μˆ˜ ν•„λ“œ λˆ„λ½ 검증 - checkRequiredFields(req.body, ["name", "price"]); - - // 2. 데이터 νƒ€μž… 검증 - checkDataType(req.body, "name", "string"); - checkDataType(req.body, "price", "number"); - if (description !== undefined) { - checkDataType(req.body, "description", "string"); - } - if (tags !== undefined) { - checkDataType(req.body, "tags", "object"); - if (Array.isArray(tags)) { - tags.forEach((tag, index) => { - if (typeof tag !== "string") { - throw new ValidationError( - `ν•„λ“œ 'tags'의 ${index}번째 μš”μ†ŒλŠ” λ¬Έμžμ—΄μ΄μ–΄μ•Ό ν•©λ‹ˆλ‹€.` - ); - } - }); - } else { - throw new ValidationError(`ν•„λ“œ 'tags'λŠ” λ°°μ—΄ νƒ€μž…μ΄μ–΄μ•Ό ν•©λ‹ˆλ‹€.`); - } - } - next(); - } catch (error) { - next(error); - } -}; - -/** - * Article 생성/μ—…λ°μ΄νŠΈ μš”μ²­ 본문을 κ²€μ¦ν•˜λŠ” 미듀웨어 - * @param {object} req - Express μš”μ²­ 객체 - * @param {object} res - Express 응닡 객체 - * @param {function} next - λ‹€μŒ 미듀웨어 ν•¨μˆ˜ - */ -export const validateArticleInfo = (req, res, next) => { - try { - // 1. ν•„μˆ˜ ν•„λ“œ λˆ„λ½ 검증 - checkRequiredFields(req.body, ["title", "content"]); - - // 2. 데이터 νƒ€μž… 검증 - checkDataType(req.body, "title", "string"); - checkDataType(req.body, "content", "string"); - - next(); - } catch (error) { - // 3. 검증 μ‹€νŒ¨ μ‹œ ValidationError 객체λ₯Ό next()둜 전달 - next(error); - } -}; - -// μƒμ„Έμ‘°νšŒ ν˜•μ‹ 검증 -export const validateBigIntId = (req, res, next) => { - const { id } = req.params; - - // 10μ§„μˆ˜ 숫자 λ¬Έμžμ—΄μΈμ§€ 확인 - const isNumeric = /^\d+$/.test(id); - - if (!isNumeric) { - const error = new ValidationError( - `ID '${id}'λŠ” μœ νš¨ν•œ 숫자 ν˜•μ‹μ΄μ–΄μ•Ό ν•©λ‹ˆλ‹€.` - ); - return next(error); - } - - next(); -}; - -// product PATCHλ₯Ό μœ„ν•œ 데이터 ν•„λ“œ 검증 -export const validateProductUpdateInfo = (req, res, next) => { - try { - const body = req.body || {}; - const { name, price, description, tags } = body; - - // 1. 데이터 νƒ€μž… 검증 (μ „λ‹¬λœ ν•„λ“œλ§Œ 검사) - checkDataType(body, "name", "string"); - checkDataType(body, "price", "number"); - if (description !== undefined) { - checkDataType(body, "description", "string"); - } - - // tags λ°°μ—΄ 및 λ‚΄λΆ€ μš”μ†Œ νƒ€μž… 검증 - if (tags !== undefined) { - checkDataType(body, "tags", "object"); - - if (Array.isArray(tags)) { - tags.forEach((tag, index) => { - if (typeof tag !== "string") { - throw new ValidationError( - `ν•„λ“œ 'tags'의 ${index}번째 μš”μ†ŒλŠ” λ¬Έμžμ—΄ νƒ€μž…μ΄μ–΄μ•Ό ν•©λ‹ˆλ‹€.` - ); - } - }); - } else { - throw new ValidationError(`ν•„λ“œ 'tags'λŠ” λ°°μ—΄ νƒ€μž…μ΄μ–΄μ•Ό ν•©λ‹ˆλ‹€.`); - } - } - - // 2. μˆ˜μ •ν•  ν•„λ“œκ°€ μ—†λŠ”μ§€ (빈 μš”μ²­μΈμ§€) 검증 - const validKeys = ["name", "price", "description", "tags"]; - const hasUpdateFields = Object.keys(body).some((key) => - validKeys.includes(key) - ); - - if (!hasUpdateFields) { - throw new ValidationError("μˆ˜μ •ν•  ν•„λ“œκ°€ μš”μ²­ 본문에 ν¬ν•¨λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€."); - } - - next(); - } catch (error) { - next(error); - } -}; - -// article PATCHλ₯Ό μœ„ν•œ 데이터 ν•„λ“œ 검증 -export const validateArticleUpdateInfo = (req, res, next) => { - try { - const body = req.body || {}; - const { title, content } = body; - - // 데이터 νƒ€μž… 검증: μ „λ‹¬λœ ν•„λ“œκ°€ string νƒ€μž…μΈμ§€ 확인 - checkDataType(body, "title", "string"); - checkDataType(body, "content", "string"); - - // μˆ˜μ •ν•  ν•„λ“œκ°€ μ—†λŠ”μ§€ (빈 μš”μ²­μΈμ§€) 검증 - const validKeys = ["title", "content"]; - // body 객체의 ν‚€λ₯Ό 기반으둜 μœ νš¨ν•œ μˆ˜μ • ν•„λ“œκ°€ μžˆλŠ”μ§€ 확인 - const hasUpdateFields = Object.keys(body).some((key) => - validKeys.includes(key) - ); - - if (!hasUpdateFields) { - throw new ValidationError("μˆ˜μ •ν•  ν•„λ“œκ°€ μš”μ²­ 본문에 ν¬ν•¨λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€."); - } - - next(); - } catch (error) { - next(error); - } -}; - -export { ValidationError }; - -/** - * μƒν’ˆ λŒ“κΈ€ 등둝/μˆ˜μ • μš”μ²­ 본문을 κ²€μ¦ν•˜λŠ” 미듀웨어 (content ν•„λ“œ 검증) - * @param {object} req - Express μš”μ²­ 객체 - * @param {object} res - Express 응닡 객체 - * @param {function} next - λ‹€μŒ 미듀웨어 ν•¨μˆ˜ - */ -export const validateProductCommentInfo = (req, res, next) => { - try { - const body = req.body || {}; - - // 1. ν•„μˆ˜ ν•„λ“œ λˆ„λ½ 검증 (content만 ν•„μˆ˜) - checkRequiredFields(body, ["content"]); - - // 2. 데이터 νƒ€μž… 검증 - checkDataType(body, "content", "string"); - - next(); - } catch (error) { - next(error); - } -}; - -/** - * κ²Œμ‹œκΈ€ λŒ“κΈ€ 등둝/μˆ˜μ • μš”μ²­ 본문을 κ²€μ¦ν•˜λŠ” 미듀웨어 (content ν•„λ“œ 검증) - * @param {object} req - Express μš”μ²­ 객체 - * @param {object} res - Express 응닡 객체 - * @param {function} next - λ‹€μŒ 미듀웨어 ν•¨μˆ˜ - */ -export const validateArticleCommentInfo = (req, res, next) => { - try { - const body = req.body || {}; - - // 1. ν•„μˆ˜ ν•„λ“œ λˆ„λ½ 검증 (content만 ν•„μˆ˜) - checkRequiredFields(body, ["content"]); - - // 2. 데이터 νƒ€μž… 검증 - checkDataType(body, "content", "string"); - - next(); - } catch (error) { - next(error); - } -}; - -export const validateCommentId = (req, res, next) => { - const { commentId } = req.params; - - // 10μ§„μˆ˜ 숫자 λ¬Έμžμ—΄μΈμ§€ 확인 - const isNumeric = /^\d+$/.test(commentId); - - if (!isNumeric) { - // μœ νš¨ν•˜μ§€ μ•Šμ€ ν˜•μ‹(예: 'ffffffff')일 경우 - const error = new ValidationError( - `λŒ“κΈ€ ID '${commentId}'λŠ” μœ νš¨ν•œ 숫자 ν˜•μ‹μ΄μ–΄μ•Ό ν•©λ‹ˆλ‹€.` - ); - error.status = 404; - return next(error); - } - - // BigInt둜 λ³€ν™˜ μ‹œ 였λ₯˜κ°€ λ‚  수 μžˆλŠ” 맀우 큰 숫자인 경우 404 처리 - try { - BigInt(commentId); - } catch (e) { - const error = new ValidationError( - `λŒ“κΈ€ ID '${commentId}'λŠ” μœ νš¨ν•˜μ§€ μ•Šκ±°λ‚˜ λ„ˆλ¬΄ 큰 κ°’μž…λ‹ˆλ‹€.` - ); - error.status = 404; - return next(error); - } - - next(); -}; - -export const validateGetComments = (req, res, next) => { - try { - const { limit, cursor } = req.query; - - if (limit !== undefined) { - const parsedLimit = parseInt(limit); - - if (isNaN(parsedLimit) || parsedLimit <= 0) { - throw new ValidationError("limit 값은 1 μ΄μƒμ˜ μ •μˆ˜μ—¬μ•Ό ν•©λ‹ˆλ‹€."); - } - } - - if (cursor !== undefined) { - if (typeof cursor !== "string") { - throw new ValidationError("cursor 값은 λ¬Έμžμ—΄μ΄μ–΄μ•Ό ν•©λ‹ˆλ‹€."); - } - } - - next(); - } catch (error) { - next(error); - } -}; diff --git a/src/models/article.js b/src/models/article.js deleted file mode 100644 index 6b2c9406..00000000 --- a/src/models/article.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = (sequelize, DataTypes) => { - const Article = sequelize.define( - "Article", - { - id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, - title: { type: DataTypes.STRING, allowNull: false }, - content: { type: DataTypes.TEXT, allowNull: false }, - }, - { timestamps: true } - ); - return Article; -}; diff --git a/src/models/comment.js b/src/models/comment.js deleted file mode 100644 index aeaa29c9..00000000 --- a/src/models/comment.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = (sequelize, DataTypes) => { - const Comment = sequelize.define( - "Comment", - { - id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, - content: { type: DataTypes.TEXT, allowNull: false }, - }, - { timestamps: true } - ); - return Comment; -}; diff --git a/src/models/index.js b/src/models/index.js deleted file mode 100644 index 7b7ace81..00000000 --- a/src/models/index.js +++ /dev/null @@ -1,6 +0,0 @@ -// Sequelize μ΄ˆκΈ°ν™” & λͺ¨λΈ μ—°κ²° -Product.hasMany(Comment, { foreignKey: "productId", onDelete: "CASCADE" }); -Comment.belongsTo(Product, { foreignKey: "productId" }); - -Article.hasMany(Comment, { foreignKey: "articleId", onDelete: "CASCADE" }); -Comment.belongsTo(Article, { foreignKey: "articleId" }); diff --git a/src/models/product.js b/src/models/product.js deleted file mode 100644 index 34bfdf2b..00000000 --- a/src/models/product.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = (sequelize, DataTypes) => { - const Product = sequelize.define( - "Product", - { - id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, - name: { type: DataTypes.STRING, allowNull: false }, - description: { type: DataTypes.TEXT }, - price: { type: DataTypes.INTEGER, allowNull: false }, - tags: { type: DataTypes.ARRAY(DataTypes.STRING), defaultValue: [] }, - }, - { timestamps: true } - ); - return Product; -}; diff --git a/src/repositories/articlesRepository.ts b/src/repositories/articlesRepository.ts new file mode 100644 index 00000000..3de0e3e7 --- /dev/null +++ b/src/repositories/articlesRepository.ts @@ -0,0 +1,94 @@ +import { Article } from '@prisma/client'; +import { prismaClient } from '../lib/prismaClient'; +import { PagePaginationParams } from '../types/pagination'; + +export async function createArticle(data: Omit) { + const createdArticle = await prismaClient.article.create({ + data, + }); + return createdArticle; +} + +export async function getArticle(id: number) { + const article = await prismaClient.article.findUnique({ where: { id } }); + return article; +} + +export async function getArticleWithLkes(id: number, { userId }: { userId?: number } = {}) { + const article = await prismaClient.article.findUnique({ + where: { id }, + include: { + likes: true, + }, + }); + + if (!article) { + return null; + } + + return { + ...article, + likes: undefined, + likeCount: article.likes.length, + isLiked: userId ? article.likes.some((like) => like.userId === userId) : undefined, + }; +} + +export async function getArticleListWithLikes( + { page, pageSize, orderBy, keyword }: PagePaginationParams, + { + userId, + }: { + userId?: number; + } = {}, +) { + const where = { + title: keyword ? { contains: keyword } : undefined, + }; + + const totalCount = await prismaClient.article.count({ where }); + const articles = await prismaClient.article.findMany({ + skip: (page - 1) * pageSize, + take: pageSize, + orderBy: orderBy === 'recent' ? { createdAt: 'desc' } : { id: 'asc' }, + where, + include: { + likes: true, + }, + }); + + const mappedArticles = articles.map((article) => ({ + ...article, + likes: undefined, + likeCount: article.likes.length, + isLiked: userId ? article.likes.some((like) => like.userId === userId) : undefined, + })); + + return { + list: mappedArticles, + totalCount, + }; +} + +export async function updateArticleWithLikes(id: number, data: Partial
) { + const updatedArticle = await prismaClient.article.update({ + where: { id }, + data, + include: { + likes: true, + }, + }); + return { + ...updatedArticle, + likeCount: updatedArticle.likes.length, + isLiked: data.userId + ? updatedArticle.likes.some((like) => like.userId === data.userId) + : undefined, + }; +} + +export async function deleteArticle(id: number) { + return prismaClient.article.delete({ + where: { id }, + }); +} diff --git a/src/repositories/commentsRepository.ts b/src/repositories/commentsRepository.ts new file mode 100644 index 00000000..d2a263b5 --- /dev/null +++ b/src/repositories/commentsRepository.ts @@ -0,0 +1,50 @@ +import { Comment } from '@prisma/client'; +import { prismaClient } from '../lib/prismaClient'; +import { CursorPaginationParams } from '../types/pagination'; + +export async function createComment(data: Omit) { + const createdComment = await prismaClient.comment.create({ + data, + }); + return createdComment; +} + +export async function getComment(id: number) { + const comment = await prismaClient.comment.findUnique({ + where: { id }, + }); + return comment; +} + +export async function getCommentList( + where: { articleId?: number; productId?: number }, + { cursor, limit }: CursorPaginationParams, +) { + const commentsWithCursor = await prismaClient.comment.findMany({ + cursor: cursor ? { id: cursor } : undefined, + take: limit + 1, + where, + orderBy: { createdAt: 'desc' }, + }); + const comments = commentsWithCursor.slice(0, limit); + const cursorComment = commentsWithCursor[commentsWithCursor.length - 1]; + const nextCursor = cursorComment ? cursorComment.id : null; + + return { + list: comments, + nextCursor, + }; +} + +export async function updateComment(id: number, data: Partial) { + return prismaClient.comment.update({ + where: { id }, + data, + }); +} + +export async function deleteComment(id: number) { + return prismaClient.comment.delete({ + where: { id }, + }); +} diff --git a/src/repositories/favoritesRepository.ts b/src/repositories/favoritesRepository.ts new file mode 100644 index 00000000..7ca91965 --- /dev/null +++ b/src/repositories/favoritesRepository.ts @@ -0,0 +1,29 @@ +import { Favorite } from '@prisma/client'; +import { prismaClient } from '../lib/prismaClient'; + +export async function createFavorite(data: Omit) { + const createdFavorite = await prismaClient.favorite.create({ + data, + }); + return createdFavorite; +} + +export async function getFavorite(productId: number, userId: number) { + const favorite = await prismaClient.favorite.findFirst({ + where: { productId, userId }, + }); + return favorite; +} + +export async function deleteFavorite(id: number) { + await prismaClient.favorite.delete({ + where: { id }, + }); +} + +export async function getFavoritesByProductId(productId: number) { + const favorites = await prismaClient.favorite.findMany({ + where: { productId }, + }); + return favorites; +} diff --git a/src/repositories/likesRepository.ts b/src/repositories/likesRepository.ts new file mode 100644 index 00000000..44a883a4 --- /dev/null +++ b/src/repositories/likesRepository.ts @@ -0,0 +1,22 @@ +import { Like } from '@prisma/client'; +import { prismaClient } from '../lib/prismaClient'; + +export async function createLike(data: Omit) { + const createdLike = await prismaClient.like.create({ + data, + }); + return createdLike; +} + +export async function getLike(articleId: number, userId: number) { + const like = await prismaClient.like.findFirst({ + where: { articleId, userId }, + }); + return like; +} + +export async function deleteLike(id: number) { + await prismaClient.like.delete({ + where: { id }, + }); +} diff --git a/src/repositories/notificationsRepository.ts b/src/repositories/notificationsRepository.ts new file mode 100644 index 00000000..a0e51c41 --- /dev/null +++ b/src/repositories/notificationsRepository.ts @@ -0,0 +1,60 @@ +import { prismaClient } from '../lib/prismaClient'; +import { Notification } from '../types/Notification'; +import { CursorPaginationParams } from '../types/pagination'; + +export async function getNotificationsByUserId(userId: number, params: CursorPaginationParams) { + const { cursor, limit } = params; + const where = { + userId, + }; + const notificationsWithCursor = await prismaClient.notification.findMany({ + cursor: cursor ? { id: cursor } : undefined, + take: limit + 1, + where, + orderBy: [{ createdAt: 'desc' }, { id: 'asc' }], + }); + const totalCount = await prismaClient.notification.count({ where }); + const unreadCount = await prismaClient.notification.count({ where: { ...where, read: false } }); + const notifications = notificationsWithCursor.slice(0, limit); + const cursorNotification = notificationsWithCursor[notificationsWithCursor.length - 1]; + const nextCursor = cursorNotification ? cursorNotification.id : null; + return { notifications, totalCount, unreadCount, nextCursor }; +} + +export async function createNotification( + data: Omit, +) { + const notification = await prismaClient.notification.create({ + data, + }); + return notification; +} + +export async function createNotifications( + data: Omit[], +) { + await prismaClient.notification.createMany({ + data, + }); +} + +export async function getNotificationById(id: number) { + const notification = await prismaClient.notification.findUnique({ + where: { id }, + }); + return notification; +} + +export async function updateNotificationById(id: number, data: Partial) { + await prismaClient.notification.update({ + where: { id }, + data, + }); +} + +export async function updateNotificationsByUserId(userId: number, data: Partial) { + await prismaClient.notification.updateMany({ + where: { userId }, + data, + }); +} diff --git a/src/repositories/productsRepository.ts b/src/repositories/productsRepository.ts new file mode 100644 index 00000000..315e820e --- /dev/null +++ b/src/repositories/productsRepository.ts @@ -0,0 +1,154 @@ +import { Product } from '@prisma/client'; +import { prismaClient } from '../lib/prismaClient'; +import { PagePaginationParams } from '../types/pagination'; + +export async function createProduct(data: Omit) { + return prismaClient.product.create({ + data, + }); +} + +export async function getProduct(id: number) { + const product = await prismaClient.product.findUnique({ + where: { id }, + }); + return product; +} + +export async function getProductWithFavorites(id: number, userId?: number) { + const product = await prismaClient.product.findUnique({ + where: { id }, + include: { favorites: true }, + }); + if (!product) { + return null; + } + + const mappedProduct = { + ...product, + favorites: undefined, + favoriteCount: product.favorites.length, + isFavorited: userId + ? product.favorites.some((favorite) => favorite.userId === userId) + : undefined, + }; + return mappedProduct; +} + +export async function getProductListWithFavorites( + { page, pageSize, orderBy, keyword }: PagePaginationParams, + { + userId, + }: { + userId?: number; + } = {}, +) { + const where = keyword + ? { + OR: [{ name: { contains: keyword } }, { description: { contains: keyword } }], + } + : {}; + + const totalCount = await prismaClient.product.count({ + where, + }); + + const products = await prismaClient.product.findMany({ + skip: (page - 1) * pageSize, + take: pageSize, + orderBy: orderBy === 'recent' ? { id: 'desc' } : { id: 'asc' }, + where, + include: { + favorites: true, + }, + }); + + const mappedProducts = products.map((product) => ({ + ...product, + favorites: undefined, + favoriteCount: product.favorites.length, + isFavorited: + userId !== undefined + ? product.favorites.some((favorite) => favorite.userId === userId) + : undefined, + })); + + return { + list: mappedProducts, + totalCount, + }; +} + +export async function getFavoriteProductListByOwnerId( + ownerId: number, + { page, pageSize, orderBy, keyword }: PagePaginationParams, +) { + const where = keyword + ? { + OR: [{ name: { contains: keyword } }, { description: { contains: keyword } }], + } + : {}; + const totalCount = await prismaClient.product.count({ + where: { + ...where, + favorites: { + some: { + userId: ownerId, + }, + }, + }, + }); + const products = await prismaClient.product.findMany({ + skip: (page - 1) * pageSize, + take: pageSize, + orderBy: orderBy === 'recent' ? { id: 'desc' } : { id: 'asc' }, + where: { + ...where, + favorites: { + some: { + userId: ownerId, + }, + }, + }, + include: { + favorites: true, + }, + }); + + const mappedProducts = products.map((product) => ({ + ...product, + favorites: undefined, + favoriteCount: product.favorites.length, + isFavorited: true, + })); + + return { + list: mappedProducts, + totalCount, + }; +} + +export async function updateProductWithFavorites(id: number, data: Partial) { + const product = await prismaClient.product.update({ + where: { id }, + data, + include: { + favorites: true, + }, + }); + const mappedProduct = { + ...product, + favorites: undefined, + favoriteCount: product.favorites.length, + isFavorited: data.userId + ? product.favorites.some((favorite) => favorite.userId === data.userId) + : undefined, + }; + return mappedProduct; +} + +export async function deleteProduct(id: number) { + return prismaClient.product.delete({ + where: { id }, + }); +} diff --git a/src/repositories/usersRepository.ts b/src/repositories/usersRepository.ts new file mode 100644 index 00000000..c8a1cfa4 --- /dev/null +++ b/src/repositories/usersRepository.ts @@ -0,0 +1,37 @@ +import { User } from '@prisma/client'; +import { prismaClient } from '../lib/prismaClient'; + +export async function createUser(data: Omit) { + const createdUser = await prismaClient.user.create({ + data, + }); + return createdUser; +} + +export async function getUser(id: number) { + const user = await prismaClient.user.findUnique({ + where: { id }, + }); + return user; +} + +export async function getUserByEmail(email: string) { + const user = await prismaClient.user.findUnique({ + where: { email }, + }); + return user; +} + +export async function updateUser(id: number, data: Partial) { + const updatedUser = await prismaClient.user.update({ + where: { id }, + data, + }); + return updatedUser; +} + +export async function deleteUser(id: number) { + await prismaClient.user.delete({ + where: { id }, + }); +} diff --git a/src/routers/articlesRouter.js b/src/routers/articlesRouter.js deleted file mode 100644 index 8896d192..00000000 --- a/src/routers/articlesRouter.js +++ /dev/null @@ -1,19 +0,0 @@ -import express from 'express'; -import { withAsync } from '../lib/withAsync.js'; -import * as ac from '../controllers/articlesController.js'; -import { authMiddleware } from '../lib/authMiddleware.js'; - -const router = express.Router(); - -router.get('/', withAsync(ac.getArticleList)); - -router.use(authMiddleware); - -router.get('/:id', withAsync(ac.getArticle)); -router.post('/', withAsync(ac.createArticle)); -router.post('/:id/like', withAsync(ac.toggleArticleLike)); -router.post('/:id/comments', withAsync(ac.createComment)); -router.patch('/:id', withAsync(ac.updateArticle)); -router.delete('/:id', withAsync(ac.deleteArticle)); - -export default router; \ No newline at end of file diff --git a/src/routers/commentsRouter.js b/src/routers/commentsRouter.js deleted file mode 100644 index 012d62e7..00000000 --- a/src/routers/commentsRouter.js +++ /dev/null @@ -1,11 +0,0 @@ -import express from 'express'; -import { withAsync } from '../lib/withAsync.js'; -import { updateComment, deleteComment } from '../controllers/commentsController.js'; -import { authMiddleware } from '../lib/authMiddleware.js'; - -const commentsRouter = express.Router(); - -commentsRouter.patch('/:id', authMiddleware, withAsync(updateComment)); -commentsRouter.delete('/:id', authMiddleware, withAsync(deleteComment)); - -export default commentsRouter; \ No newline at end of file diff --git a/src/routers/imagesRouter.js b/src/routers/imagesRouter.js deleted file mode 100644 index 163b87ce..00000000 --- a/src/routers/imagesRouter.js +++ /dev/null @@ -1,9 +0,0 @@ -import express from 'express'; -import { withAsync } from '../lib/withAsync.js'; -import { upload, uploadImage } from '../controllers/imagesController.js'; - -const imagesRouter = express.Router(); - -imagesRouter.post('/upload', upload.single('image'), withAsync(uploadImage)); - -export default imagesRouter; diff --git a/src/routers/likesRouter.js b/src/routers/likesRouter.js deleted file mode 100644 index 2bb100d3..00000000 --- a/src/routers/likesRouter.js +++ /dev/null @@ -1,12 +0,0 @@ -import express from 'express'; -import { authMiddleware } from '../lib/authMiddleware.js'; -import { withAsync } from '../lib/withAsync.js'; -import { toggleProductLike, getMyLikedProducts } from '../controllers/likesController.js'; - -const router = express.Router(); -router.use(authMiddleware); - -router.post('/products/:productId', withAsync(toggleProductLike)); -router.get('/my/products', withAsync(getMyLikedProducts)); - -export default router; \ No newline at end of file diff --git a/src/routers/notificationsRouter.ts b/src/routers/notificationsRouter.ts new file mode 100644 index 00000000..7a183ba7 --- /dev/null +++ b/src/routers/notificationsRouter.ts @@ -0,0 +1,10 @@ +import express from 'express'; +import { withAsync } from '../lib/withAsync'; +import authenticate from '../middlewares/authenticate'; +import { readNotification } from '../controllers/notificationsController'; + +const notificationsRouter = express.Router(); + +notificationsRouter.patch('/:id/read', authenticate(), withAsync(readNotification)); + +export default notificationsRouter; diff --git a/src/routers/productsRouter.js b/src/routers/productsRouter.js deleted file mode 100644 index 75123e85..00000000 --- a/src/routers/productsRouter.js +++ /dev/null @@ -1,19 +0,0 @@ -import express from 'express'; -import { withAsync } from '../lib/withAsync.js'; -import * as pc from '../controllers/productsController.js'; -import { authMiddleware } from '../lib/authMiddleware.js'; - -const router = express.Router(); - -router.get('/', withAsync(pc.getProductList)); -router.get('/:id', withAsync(pc.getProduct)); - -router.use(authMiddleware); -router.post('/', withAsync(pc.createProduct)); -router.post('/:id/like', withAsync(pc.toggleProductLike)); -router.post('/:id/comments', withAsync(pc.createComment)); -router.get('/:id/comments', withAsync(pc.getCommentList)); -router.patch('/:id', withAsync(pc.updateProduct)); -router.delete('/:id', withAsync(pc.deleteProduct)); - -export default router; \ No newline at end of file diff --git a/src/routers/productsRouter.ts b/src/routers/productsRouter.ts index 4d7d3727..bd16e662 100644 --- a/src/routers/productsRouter.ts +++ b/src/routers/productsRouter.ts @@ -8,8 +8,8 @@ import { getProductList, createComment, getCommentList, - createLike, - deleteLike, + createFavorite, + deleteFavorite, } from '../controllers/productsController'; import authenticate from '../middlewares/authenticate'; @@ -22,7 +22,7 @@ productsRouter.delete('/:id', authenticate(), withAsync(deleteProduct)); productsRouter.get('/', authenticate({ optional: true }), withAsync(getProductList)); productsRouter.post('/:id/comments', authenticate(), withAsync(createComment)); productsRouter.get('/:id/comments', withAsync(getCommentList)); -productsRouter.post('/:id/likes', authenticate(), withAsync(createLike)); -productsRouter.delete('/:id/likes', authenticate(), withAsync(deleteLike)); +productsRouter.post('/:id/favorites', authenticate(), withAsync(createFavorite)); +productsRouter.delete('/:id/favorites', authenticate(), withAsync(deleteFavorite)); export default productsRouter; diff --git a/src/routers/usersRouter.js b/src/routers/usersRouter.js deleted file mode 100644 index 8319c979..00000000 --- a/src/routers/usersRouter.js +++ /dev/null @@ -1,20 +0,0 @@ -import express from 'express'; -import * as uc from '../controllers/usersController.js'; -import { getMyLikedProducts } from '../controllers/likesController.js'; -import { withAsync } from '../lib/withAsync.js'; -import { authMiddleware } from '../lib/authMiddleware.js'; - -const router = express.Router(); - -router.post('/signup', withAsync(uc.signUp)); -router.post('/signin', withAsync(uc.signIn)); -router.post('/refresh', withAsync(uc.refresh)); - -router.use(authMiddleware); -router.get('/me', withAsync(uc.getMe)); -router.patch('/me', withAsync(uc.updateMe)); -router.patch('/me/password', withAsync(uc.changePassword)); -router.get('/me/products', withAsync(uc.getMyProducts)); -router.get('/me/liked-products', withAsync(getMyLikedProducts)); - -export default router; \ No newline at end of file diff --git a/src/routers/usersRouter.ts b/src/routers/usersRouter.ts index 43063012..48e79271 100644 --- a/src/routers/usersRouter.ts +++ b/src/routers/usersRouter.ts @@ -5,7 +5,8 @@ import { updateMe, updateMyPassword, getMyProductList, - getMyLikeList, + getMyFavoriteList, + getMyNotifications, } from '../controllers/usersController'; import authenticate from '../middlewares/authenticate'; @@ -15,6 +16,7 @@ usersRouter.get('/me', authenticate(), withAsync(getMe)); usersRouter.patch('/me', authenticate(), withAsync(updateMe)); usersRouter.patch('/me/password', authenticate(), withAsync(updateMyPassword)); usersRouter.get('/me/products', authenticate(), withAsync(getMyProductList)); -usersRouter.get('/me/likes', authenticate(), withAsync(getMyLikeList)); +usersRouter.get('/me/favorites', authenticate(), withAsync(getMyFavoriteList)); +usersRouter.get('/me/notifications', authenticate(), withAsync(getMyNotifications)); export default usersRouter; diff --git a/src/routes/article.js b/src/routes/article.js deleted file mode 100644 index 39a60d48..00000000 --- a/src/routes/article.js +++ /dev/null @@ -1,134 +0,0 @@ -import express from "express"; -import { prisma } from "../../prisma/prisma.js"; -import { - validateArticleInfo, - validateBigIntId, - validateArticleUpdateInfo, -} from "../middlewares/validator.js"; -import { getArticleList } from "../services/articleService.js"; -import articleCommentRouter from "./articleComment.js"; - -const router = express.Router(); - -class Article { - constructor(id, title, content, createdAt) { - this.id = id; - this.title = title; - this.content = content; - this.createdAt = createdAt; - } - - static fromEntity(entity) { - return new Article( - entity.id.toString(), - entity.title, - entity.content, - entity.created_at - ); - } -} - -// comment POST -router.post("/", validateArticleInfo, async (req, res, next) => { - try { - const { title, content } = req.body; - const newEntity = await prisma.article.create({ data: { title, content } }); - const article = Article.fromEntity(newEntity); - res.status(201).json(article); - } catch (e) { - console.error("κ²Œμ‹œκΈ€ 생성 쀑 였λ₯˜:", e); - next(e); - } -}); - -// comment GET -router.get("/", async (req, res, next) => { - try { - const limit = parseInt(req.query.limit) || 10; - const offset = parseInt(req.query.offset) || 0; - const keyword = req.query.keyword; - - const { articles, totalCount } = await getArticleList( - limit, - offset, - keyword - ); - - res.json({ articles, totalCount }); - } catch (e) { - console.error("κ²Œμ‹œκΈ€ λͺ©λ‘ 쑰회 쀑 였λ₯˜:", e); - next(e); - } -}); - -// comment GET μ‚΄μ„Έ -router.get("/:id", validateBigIntId, async (req, res, next) => { - try { - const articleId = req.params.id; - const entity = await prisma.article.findUnique({ - where: { id: BigInt(articleId) }, - }); - - if (!entity) { - return res - .status(404) - .json({ message: `ID ${articleId}λ₯Ό κ°€μ§„ κ²Œμ‹œκΈ€μ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.` }); - } - - const article = Article.fromEntity(entity); - res.json(article); - } catch (e) { - console.error("κ²Œμ‹œκΈ€ 상세 쑰회 쀑 였λ₯˜:", e); - next(e); - } -}); - -// comment PATCH -router.patch( - "/:id", - validateBigIntId, - validateArticleUpdateInfo, - async (req, res, next) => { - const articleId = req.params.id; - - try { - const { title, content } = req.body; - const updateData = {}; - if (title !== undefined) updateData.title = title; - if (content !== undefined) updateData.content = content; - - const updatedEntity = await prisma.article.update({ - where: { id: BigInt(articleId) }, - data: updateData, - }); - - const article = Article.fromEntity(updatedEntity); - res.json(article); - } catch (e) { - console.error("κ²Œμ‹œκΈ€ μˆ˜μ • 쀑 였λ₯˜ : ", e); - if (e.code === "P2025") { - return res.status(404).json({ - message: `ID ${articleId}λ₯Ό κ°€μ§„ κ²Œμ‹œκΈ€μ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.`, - }); - } - next(e); - } - } -); - -// comment DELETE -router.delete("/:id", async (req, res, next) => { - try { - const articleId = req.params.id; - await prisma.article.delete({ where: { id: BigInt(articleId) } }); - res.status(204).send(); // 204 No Content - } catch (e) { - console.error("κ²Œμ‹œκΈ€ μ‚­μ œ 쀑 였λ₯˜ : ", e); - next(e); - } -}); - -// Comment λΌμš°ν„° 마운트 (GET, POST, PATCH, DELETE) -router.use("/:id/comments", validateBigIntId, articleCommentRouter); - -export default router; diff --git a/src/routes/articleComment.js b/src/routes/articleComment.js deleted file mode 100644 index 81410fc9..00000000 --- a/src/routes/articleComment.js +++ /dev/null @@ -1,169 +0,0 @@ -import express from "express"; -import { prisma } from "../../prisma/prisma.js"; -import { ArticleComment } from "./comment.js"; -import { - validateArticleCommentInfo, - validateGetComments, - validateCommentId, -} from "../middlewares/validator.js"; -import { createArticleComment } from "../services/articleService.js"; -import { BadRequestError } from "../exceptions/errors.js"; - -const articleCommentRouter = express.Router({ mergeParams: true }); - -// comment GET (CUSOR) -articleCommentRouter.get("/", validateGetComments, async (req, res, next) => { - try { - const articleId = req.params.id; - const { cursor, limit = "10" } = req.query; - const take = parseInt(limit); - - if (isNaN(take) || take <= 0) { - throw new BadRequestError("μœ νš¨ν•˜μ§€ μ•Šμ€ limit κ°’μž…λ‹ˆλ‹€."); - } - const orderBy = [{ created_at: "desc" }, { id: "asc" }]; - const baseConditions = [{ article_id: BigInt(articleId) }]; - - let cursorWhere = []; - let nextCursor = null; - - if (cursor) { - const [cursorCreatedAtStr, cursorIdStr] = cursor.split("_"); - - if (cursorCreatedAtStr && cursorIdStr) { - const cursorCreatedAt = new Date(cursorCreatedAtStr); - const cursorId = BigInt(cursorIdStr); - - cursorWhere = [ - { - OR: [ - { - created_at: { lt: cursorCreatedAt }, - }, - { - AND: [ - { created_at: cursorCreatedAt }, - { id: { gt: cursorId } }, - ], - }, - ], - }, - ]; - } else { - throw new BadRequestError("잘λͺ»λœ μ»€μ„œ ν˜•μ‹μž…λ‹ˆλ‹€."); - } - } - - const whereConditions = baseConditions.concat(cursorWhere); - - const where = { AND: whereConditions }; - - const entities = await prisma.article_comment.findMany({ - where, - orderBy, - take: take + 1, - }); - - const hasNext = entities.length > take; - const items = hasNext ? entities.slice(0, take) : entities; - - if (hasNext) { - const lastItem = items[items.length - 1]; - const lastCreatedAt = lastItem.created_at.toISOString(); - const lastId = lastItem.id.toString(); - nextCursor = `${lastCreatedAt}_${lastId}`; - } else { - nextCursor = null; - } - - const articleComments = items.map(ArticleComment.fromEntity); - - res.json({ data: articleComments, nextCursor, hasNext }); - } catch (e) { - next(e); - } -}); - -// comment POST -articleCommentRouter.post( - "/", - validateArticleCommentInfo, - async (req, res, next) => { - const articleId = req.params.id; - const { content } = req.body; - - try { - const newEntity = await createArticleComment(articleId, content); - const articleComment = ArticleComment.fromEntity(newEntity); - res.status(201).json(articleComment); - } catch (e) { - console.error("κ²Œμ‹œκΈ€ λŒ“κΈ€ 등둝 쀑 였λ₯˜:", e); - next(e); - } - } -); - -// comment PATCH -articleCommentRouter.patch( - "/:commentId", - validateCommentId, - validateArticleCommentInfo, - async (req, res, next) => { - const articleId = req.params.id; - const commentId = req.params.commentId; - const { content } = req.body; - - try { - const updatedEntity = await prisma.article_comment.update({ - where: { id: BigInt(commentId), article_id: BigInt(articleId) }, - data: { content }, - }); - - const articleComment = ArticleComment.fromEntity(updatedEntity); - res.status(200).json(articleComment); - } catch (e) { - console.error(`λŒ“κΈ€ ID ${commentId} μˆ˜μ • 쀑 였λ₯˜:`, e); - - if (e.code === "P2025") { - return res.status(404).json({ - message: `κ²Œμ‹œκΈ€ ID ${articleId}μ—μ„œ λŒ“κΈ€ ID ${commentId}λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.`, - }); - } - - next(e); - } - } -); - -// comment DELETE -articleCommentRouter.delete( - "/:commentId", - validateCommentId, - async (req, res, next) => { - const articleId = req.params.id; - const commentId = req.params.commentId; - - try { - await prisma.article_comment.delete({ - where: { - id: BigInt(commentId), - article_id: BigInt(articleId), - }, - }); - - res.status(204).send(); - } catch (e) { - console.error(`λŒ“κΈ€ ID ${commentId} μ‚­μ œ 쀑 였λ₯˜:`, e); - - if (e.code === "P2025") { - return res.status(404).json({ - message: `κ²Œμ‹œκΈ€ ID ${articleId}μ—μ„œ λŒ“κΈ€ ID ${commentId}λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.`, - }); - } - - next(e); - } - } -); - -export default articleCommentRouter; diff --git a/src/routes/comment.js b/src/routes/comment.js deleted file mode 100644 index 4e5c4abd..00000000 --- a/src/routes/comment.js +++ /dev/null @@ -1,25 +0,0 @@ -export class ArticleComment { - constructor(id, content, created_at) { - this.id = id; - this.content = content; - this.created_at = created_at; - } - - static fromEntity(entity) { - const { id, content, created_at } = entity; - return new ArticleComment(id.toString(), content, created_at); - } -} - -export class ProductComment { - constructor(id, content, created_at) { - this.id = id; - this.content = content; - this.created_at = created_at; - } - - static fromEntity(entity) { - const { id, content, created_at } = entity; - return new ProductComment(id.toString(), content, created_at); - } -} diff --git a/src/routes/product.js b/src/routes/product.js deleted file mode 100644 index 3747880d..00000000 --- a/src/routes/product.js +++ /dev/null @@ -1,233 +0,0 @@ -import express from "express"; -import { prisma } from "../../prisma/prisma.js"; -import { - validateProductInfo, - validateBigIntId, - validateProductUpdateInfo, - validateProductCommentInfo, -} from "../middlewares/validator.js"; -import { - createProductComment, - getProductList, -} from "../services/productService.js"; -import { ProductComment } from "./comment.js"; -import productImageRouter from "./productImage.js"; - -const router = express.Router(); - -class Product { - constructor(id, name, description, price, tags, createdAt) { - this.id = id; - this.name = name; - this.description = description; - this.price = price; - this.tags = tags; - this.createdAt = createdAt; - } - - static fromEntity(entity) { - return new Product( - entity.id.toString(), - entity.name, - entity.description, - entity.price, - entity.tags, - entity.created_at - ); - } -} - -// POST -router.post("/", validateProductInfo, async (req, res, next) => { - try { - const { name, description, price, tags } = req.body; - - const newEntity = await prisma.product.create({ - data: { - name: name, - description: description, - price: price, - tags: tags, - }, - }); - - const product = Product.fromEntity(newEntity); - - res.status(201).json(product); - } catch (e) { - console.error("μƒν’ˆ 생성 쀑 였λ₯˜:", e); - next(e); - } -}); - -// GET -router.get("/", async (req, res, next) => { - try { - const limit = parseInt(req.query.limit) || 10; - const offset = parseInt(req.query.offset) || 0; - const keyword = req.query.keyword; - - const { products, totalCount } = await getProductList( - limit, - offset, - keyword - ); - - res.json({ - products: products, - totalCount: totalCount, - }); - } catch (e) { - console.error("μƒν’ˆ λͺ©λ‘ 쑰회 쀑 였λ₯˜:", e); - next(e); - } -}); - -// GET 상세 -router.get("/:id", validateBigIntId, async (req, res, next) => { - try { - const productId = req.params.id; - const entity = await prisma.product.findUnique({ - where: { id: BigInt(productId) }, - }); - - if (!entity) { - return res.status(404).json({ - message: `ID ${productId}λ₯Ό κ°€μ§„ μƒν’ˆμ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.`, - }); - } - - const product = Product.fromEntity(entity); - res.json(product); - } catch (e) { - console.error("μƒν’ˆ 상세 쑰회 쀑 였λ₯˜:", e); - next(e); - } -}); - -// PATCH -router.patch( - "/:id", - validateBigIntId, - validateProductUpdateInfo, - async (req, res, next) => { - const productId = req.params.id; - - try { - const { name, description, price, tags } = req.body; - - const updateData = {}; - if (name !== undefined) updateData.name = name; - if (description !== undefined) updateData.description = description; - if (price !== undefined) updateData.price = price; - if (tags !== undefined) updateData.tags = tags; - - const updatedEntity = await prisma.product.update({ - where: { id: BigInt(productId) }, - data: updateData, - }); - - const product = Product.fromEntity(updatedEntity); - res.json(product); - } catch (e) { - console.error("μƒν’ˆ μˆ˜μ • 쀑 였λ₯˜:", e); - - if (e.code === "P2025") { - return res.status(404).json({ - message: `ID ${productId}λ₯Ό κ°€μ§„ μƒν’ˆμ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.`, - }); - } - next(e); - } - } -); - -// DELETE -router.delete("/:id", async (req, res, next) => { - try { - const productId = req.params.id; - - await prisma.product.delete({ - where: { id: BigInt(productId) }, - }); - - res.status(204).send(); - } catch (e) { - console.error("μƒν’ˆ μ‚­μ œ 쀑 였λ₯˜:", e); - next(e); - } -}); - -// comment POST -router.post( - "/:id/comments", - validateBigIntId, - validateProductCommentInfo, - async (req, res, next) => { - const productId = req.params.id; - const { content } = req.body; - - try { - const newEntity = await createProductComment(productId, content); - - const productComment = ProductComment.fromEntity(newEntity); - res.status(201).json(productComment); - } catch (e) { - console.error("κ²Œμ‹œκΈ€ λŒ“κΈ€ 등둝 쀑 였λ₯˜:", e); - next(e); - } - } -); - -// comment PATCH -router.patch( - "/:id/comments/:commentId", - validateBigIntId, - validateProductCommentInfo, - async (req, res, next) => { - const productId = req.params.id; - const commentId = req.params.commentId; - const { content } = req.body; - - try { - // λŒ“κΈ€ ID와 λΆ€λͺ¨ IDλ₯Ό 쑰건으둜 μ—…λ°μ΄νŠΈ - const updatedEntity = await prisma.product_comment.update({ - where: { id: BigInt(commentId), product_id: BigInt(productId) }, - data: { content }, - }); - - const productComment = ProductComment.fromEntity(updatedEntity); - res.status(200).json(productComment); // 200 OK - } catch (e) { - console.error(`λŒ“κΈ€ ID ${commentId} μˆ˜μ • 쀑 였λ₯˜:`, e); - next(e); - } - } -); - -// comment DELETE -router.delete( - "/:id/comments/:commentId", - validateBigIntId, - async (req, res, next) => { - const productId = req.params.id; - const commentId = req.params.commentId; - - try { - await prisma.product_comment.delete({ - where: { - id: BigInt(commentId), - product_id: BigInt(productId), - }, - }); - res.status(204).send(); - } catch (e) { - console.error(`λŒ“κΈ€ ID ${commentId} μ‚­μ œ 쀑 였λ₯˜:`, e); - next(e); - } - } -); - -router.use("/:productId/image", productImageRouter); - -export default router; diff --git a/src/routes/productImage.js b/src/routes/productImage.js deleted file mode 100644 index 44a7e089..00000000 --- a/src/routes/productImage.js +++ /dev/null @@ -1,169 +0,0 @@ -import { Router } from "express"; -import { prisma } from "../../prisma/prisma.js"; -import multer from "multer"; -import _path from "path"; -import fs from "fs/promises"; -import { fileURLToPath } from "url"; -import { BadRequestError, NotFoundError } from "../exceptions/errors.js"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = _path.dirname(__filename); -const projectRoot = _path.join(__dirname, "..", ".."); - -const productImageRouter = Router({ mergeParams: true }); - -// Multer μ„€μ • -const upload = multer({ - storage: multer.diskStorage({ - // μ‚¬μš©μžλ³„ 폴더 생성 - destination: async function (req, file, cb) { - try { - const productId = req.params.productId; - - if (!productId) { - return cb(new Error("Product ID is missing in the URL path.")); - } - - const uploadDir = _path.join( - projectRoot, - "uploads", - "images", - "products", - productId - ); - - await fs.mkdir(uploadDir, { recursive: true }); - cb(null, uploadDir); - } catch (error) { - cb(error); - } - }, - filename: function (req, file, cb) { - const productId = req.params.productId; - const ext = _path.extname(file.originalname); - cb(null, `${productId}-${Date.now()}${ext}`); - }, - }), - limits: { - fileSize: 5 * 1024 * 1024, - }, - fileFilter: function (req, file, cb) { - const allowedTypes = /jpeg|jpg|png|gif|webp/; - const extname = allowedTypes.test( - _path.extname(file.originalname).toLowerCase() - ); - const mimetype = allowedTypes.test(file.mimetype); - - if (extname && mimetype) { - cb(null, true); - } else { - cb( - new BadRequestError( - "이미지 파일만 μ—…λ‘œλ“œ κ°€λŠ₯ν•©λ‹ˆλ‹€ (jpeg, jpg, png, gif, webp)" - ) - ); - } - }, -}); - -// 이미지 μ—…λ‘œλ“œ 및 등둝/ꡐ체 -productImageRouter - .route("/") - .post(upload.single("image"), async (req, res, next) => { - const productId = BigInt(req.params.productId); - - try { - if (!req.file) { - throw new BadRequestError("파일이 μ—…λ‘œλ“œλ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€"); - } - - const { filename: name, path: absolutePath, size } = req.file; - - const relativePath = absolutePath.substring(projectRoot.length + 1); - - const existingProduct = await prisma.product.findUnique({ - where: { id: productId }, - include: { image: true }, - }); - - if (!existingProduct) { - await fs.unlink(absolutePath).catch(() => {}); - throw new NotFoundError(`μ œν’ˆ ID ${productId}λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.`); - } - - if (existingProduct.image) { - const oldImagePath = _path.join( - projectRoot, - existingProduct.image.path - ); - await fs.unlink(oldImagePath).catch(console.error); - - await prisma.product_image.delete({ - where: { id: existingProduct.image.id }, - }); - } - - const newImageEntity = { - name, - path: relativePath, - size, - }; - - const updatedProduct = await prisma.product.update({ - where: { id: productId }, - data: { - image: { - create: newImageEntity, - }, - }, - include: { image: true }, - }); - - res.json({ - message: "μ œν’ˆ 이미지 μ—…λ‘œλ“œ 및 ꡐ체 성곡", - file: { - name, - path: relativePath, - size, - url: `/products/${productId}/image`, - }, - }); - } catch (err) { - if (req.file) { - await fs.unlink(req.file.path).catch(() => {}); - } - next(err); - } - }) - - // 이미지 쑰회 - .get(async (req, res, next) => { - const productId = BigInt(req.params.productId); - - try { - const product = await prisma.product.findUnique({ - where: { id: productId }, - include: { image: true }, - }); - - if (!product || !product.image) { - throw new NotFoundError( - `μ œν’ˆ ID ${productId}의 이미지λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€` - ); - } - - const absolutePath = _path.join(projectRoot, product.image.path); - - res.sendFile(absolutePath); - } catch (err) { - if (err.code === "ENOENT" || err instanceof NotFoundError) { - next( - new NotFoundError(`μ œν’ˆ ${productId}의 이미지λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.`) - ); - } else { - next(err); - } - } - }); - -export default productImageRouter; diff --git a/src/services/articleService.js b/src/services/articleService.js deleted file mode 100644 index 83d6709e..00000000 --- a/src/services/articleService.js +++ /dev/null @@ -1,64 +0,0 @@ -import { prisma } from "../../prisma/prisma.js"; - -// Article DTO -class Article { - constructor(id, title, content, createdAt) { - this.id = id; - this.title = title; - this.content = content; - this.createdAt = createdAt; - } - - static fromEntity(entity) { - return new Article( - entity.id.toString(), - entity.title, - entity.content, - entity.created_at - ); - } -} - -/** - * κ²Œμ‹œκΈ€ λͺ©λ‘ 및 전체 개수λ₯Ό μ‘°νšŒν•˜λŠ” μ„œλΉ„μŠ€ ν•¨μˆ˜ - * @param {number} limit - νŽ˜μ΄μ§€λ‹Ή 쑰회 개수 - * @param {number} offset - κ±΄λ„ˆλ›Έ 개수 - * @param {string} keyword - 검색 ν‚€μ›Œλ“œ (선택적) - * @returns {{articles: Article[], totalCount: number}} - */ -export async function getArticleList(limit, offset, keyword) { - const findOption = { - orderBy: { created_at: "desc" }, - take: limit, - skip: offset, - }; - - if (keyword) { - findOption.where = { - OR: [ - { title: { contains: keyword, mode: "insensitive" } }, - { content: { contains: keyword, mode: "insensitive" } }, - ], - }; - } - - // κ²Œμ‹œκΈ€ λͺ©λ‘κ³Ό 전체 개수λ₯Ό λ³‘λ ¬λ‘œ 쑰회 - const [entities, totalCount] = await prisma.$transaction([ - prisma.article.findMany(findOption), - prisma.article.count({ where: findOption.where }), - ]); - - const articles = entities.map(Article.fromEntity); - - return { articles, totalCount }; -} - -export async function createArticleComment(articleId, content) { - const newComment = await prisma.article_comment.create({ - data: { - article_id: BigInt(articleId), - content: content, - }, - }); - return newComment; -} diff --git a/src/services/articlesService.ts b/src/services/articlesService.ts new file mode 100644 index 00000000..6e963bb7 --- /dev/null +++ b/src/services/articlesService.ts @@ -0,0 +1,59 @@ +import * as articlesRepository from '../repositories/articlesRepository'; +import { PagePaginationParams, PagePaginationResult } from '../types/pagination'; +import ForbiddenError from '../lib/errors/ForbiddenError'; +import NotFoundError from '../lib/errors/NotFoundError'; +import Article from '../types/Article'; + +type CreateArticleData = Omit; +type UpdateArticleData = Partial & { userId: number }; + +export async function createArticle(data: CreateArticleData): Promise
{ + const createdArticle = await articlesRepository.createArticle(data); + return { + ...createdArticle, + likeCount: 0, + isLiked: false, + }; +} + +export async function getArticle(id: number): Promise
{ + const article = await articlesRepository.getArticleWithLkes(id); + if (!article) { + throw new NotFoundError('article', id); + } + return article; +} + +export async function getArticleList( + params: PagePaginationParams, +): Promise> { + const articles = await articlesRepository.getArticleListWithLikes(params); + return articles; +} + +export async function updateArticle(id: number, data: UpdateArticleData): Promise
{ + const existingArticle = await articlesRepository.getArticle(id); + if (!existingArticle) { + throw new NotFoundError('article', id); + } + + if (existingArticle.userId !== data.userId) { + throw new ForbiddenError('Should be the owner of the article'); + } + + const updatedArticle = await articlesRepository.updateArticleWithLikes(id, data); + return updatedArticle; +} + +export async function deleteArticle(id: number, userId: number): Promise { + const existingArticle = await articlesRepository.getArticle(id); + if (!existingArticle) { + throw new NotFoundError('article', id); + } + + if (existingArticle.userId !== userId) { + throw new ForbiddenError('Should be the owner of the article'); + } + + await articlesRepository.deleteArticle(id); +} diff --git a/src/services/authService.ts b/src/services/authService.ts new file mode 100644 index 00000000..4ab4944c --- /dev/null +++ b/src/services/authService.ts @@ -0,0 +1,102 @@ +import bcrypt from 'bcrypt'; +import * as usersRepository from '../repositories/usersRepository'; +import BadRequestError from '../lib/errors/BadRequestError'; +import NotFoundError from '../lib/errors/NotFoundError'; +import { generateTokens, verifyAccessToken, verifyRefreshToken } from '../lib/token'; +import UnauthorizedError from '../lib/errors/UnauthorizedError'; +import User from '../types/User'; + +type RegisterData = Omit; +type LoginData = Pick; + +async function verifyPassword(user: User, password: string) { + return await bcrypt.compare(password, user.password); +} + +async function hashPassword(password: string) { + const salt = await bcrypt.genSalt(10); + return await bcrypt.hash(password, salt); +} + +export async function register(data: RegisterData) { + const existingUser = await usersRepository.getUserByEmail(data.email); + if (existingUser) { + throw new BadRequestError('User already exists'); + } + + const hashedPassword = await hashPassword(data.password); + + const user = await usersRepository.createUser({ + email: data.email, + nickname: data.nickname, + password: hashedPassword, + image: data.image, + }); + + return user; +} + +export async function login(data: LoginData) { + const user = await usersRepository.getUserByEmail(data.email); + if (!user) { + throw new BadRequestError('Invalid credentials'); + } + + const isPasswordValid = await verifyPassword(user, data.password); + if (!isPasswordValid) { + throw new BadRequestError('Invalid credentials'); + } + + const { accessToken, refreshToken } = generateTokens(user.id); + return { + accessToken, + refreshToken, + }; +} + +export async function refreshToken(refreshToken?: string) { + if (!refreshToken) { + throw new BadRequestError('Invalid refresh token'); + } + + const { userId } = verifyRefreshToken(refreshToken); + + const user = await usersRepository.getUser(userId); + if (!user) { + throw new BadRequestError('Invalid refresh token'); + } + + const { accessToken, refreshToken: newRefreshToken } = generateTokens(userId); + return { + accessToken, + refreshToken: newRefreshToken, + }; +} + +export async function updateMyPassword(userId: User['id'], password: string, newPassword: string) { + const user = await usersRepository.getUser(userId); + if (!user) { + throw new NotFoundError('user', userId); + } + + const isPasswordValid = await verifyPassword(user, password); + if (!isPasswordValid) { + throw new BadRequestError('Invalid credentials'); + } + + const hashedPassword = await hashPassword(newPassword); + await usersRepository.updateUser(userId, { password: hashedPassword }); +} + +export async function authenticate(accessToken?: string) { + if (!accessToken) { + throw new UnauthorizedError('Unauthorized'); + } + + const { userId } = verifyAccessToken(accessToken); + const user = await usersRepository.getUser(userId); + if (!user) { + throw new UnauthorizedError('Unauthorized'); + } + return user; +} diff --git a/src/services/commentsService.ts b/src/services/commentsService.ts new file mode 100644 index 00000000..3eea37d8 --- /dev/null +++ b/src/services/commentsService.ts @@ -0,0 +1,122 @@ +import * as articlesRepository from '../repositories/articlesRepository'; +import * as commentsRepository from '../repositories/commentsRepository'; +import * as productsRepository from '../repositories/productsRepository'; +import * as notificationsService from './notificationsService'; +import { CursorPaginationParams, CursorPaginationResult } from '../types/pagination'; +import BadRequestError from '../lib/errors/BadRequestError'; +import ForbiddenError from '../lib/errors/ForbiddenError'; +import NotFoundError from '../lib/errors/NotFoundError'; +import Comment from '../types/Comment'; +import Article from '../types/Article'; +import { NotificationType } from '../types/Notification'; + +type CreateCommentData = Omit< + Comment, + 'id' | 'productId' | 'articleId' | 'createdAt' | 'updatedAt' +> & { + productId?: number; + articleId?: number; +}; + +export async function createComment(data: CreateCommentData): Promise { + if (!data.articleId && !data.productId) { + throw new BadRequestError('Either articleId or productId must be provided'); + } + + if (data.articleId) { + const article = await articlesRepository.getArticle(data.articleId); + if (!article) { + throw new NotFoundError('article', data.articleId); + } + } + + if (data.productId) { + const product = await productsRepository.getProduct(data.productId); + if (!product) { + throw new NotFoundError('product', data.productId); + } + } + + const comment = await commentsRepository.createComment({ + ...data, + articleId: data.articleId ?? null, + productId: data.productId ?? null, + }); + + /** New comment notification */ + if (data.articleId) { + const article = (await articlesRepository.getArticle(data.articleId)) as Article; + const commentWriterId = data.userId; + const articleWriterId = article.userId; + if (articleWriterId !== commentWriterId) { + await notificationsService.createNotification({ + userId: articleWriterId, + type: NotificationType.NEW_COMMENT, + payload: { + articleId: data.articleId, + }, + }); + } + } + return comment; +} + +export async function getComment(id: number): Promise { + const comment = await commentsRepository.getComment(id); + if (!comment) { + throw new NotFoundError('comment', id); + } + return comment; +} + +export async function getCommentListByArticleId( + articleId: number, + params: CursorPaginationParams, +): Promise> { + const article = await articlesRepository.getArticle(articleId); + if (!article) { + throw new NotFoundError('article', articleId); + } + + const result = commentsRepository.getCommentList({ articleId }, params); + return result; +} + +export async function getCommentListByProductId( + productId: number, + params: CursorPaginationParams, +): Promise> { + const product = await productsRepository.getProduct(productId); + if (!product) { + throw new NotFoundError('product', productId); + } + + const result = commentsRepository.getCommentList({ productId }, params); + return result; +} + +export async function updateComment(id: number, userId: number, content: string): Promise { + const comment = await commentsRepository.getComment(id); + if (!comment) { + throw new NotFoundError('comment', id); + } + + if (comment.userId !== userId) { + throw new ForbiddenError('Should be the owner of the comment'); + } + + return commentsRepository.updateComment(id, { content }); +} + +export async function deleteComment(id: number, userId: number): Promise { + const comment = await commentsRepository.getComment(id); + if (!comment) { + throw new NotFoundError('comment', id); + } + + if (comment.userId !== userId) { + throw new ForbiddenError('Should be the owner of the comment'); + } + + await commentsRepository.deleteComment(id); +} diff --git a/src/services/favoritesService.ts b/src/services/favoritesService.ts new file mode 100644 index 00000000..373e21e2 --- /dev/null +++ b/src/services/favoritesService.ts @@ -0,0 +1,32 @@ +import * as favoritesRepository from '../repositories/favoritesRepository'; +import * as productsRepository from '../repositories/productsRepository'; +import NotFoundError from '../lib/errors/NotFoundError'; +import BadRequestError from '../lib/errors/BadRequestError'; + +export async function createFavorite(productId: number, userId: number) { + const existingProduct = await productsRepository.getProduct(productId); + if (!existingProduct) { + throw new NotFoundError('product', productId); + } + + const existingFavorite = await favoritesRepository.getFavorite(productId, userId); + if (existingFavorite) { + throw new BadRequestError('Already favorited'); + } + + await favoritesRepository.createFavorite({ productId, userId }); +} + +export async function deleteFavorite(productId: number, userId: number) { + const existingProduct = await productsRepository.getProduct(productId); + if (!existingProduct) { + throw new NotFoundError('product', productId); + } + + const existingFavorite = await favoritesRepository.getFavorite(productId, userId); + if (!existingFavorite) { + throw new BadRequestError('Not favorited'); + } + + await favoritesRepository.deleteFavorite(existingFavorite.id); +} diff --git a/src/services/likesService.ts b/src/services/likesService.ts new file mode 100644 index 00000000..b15fdd70 --- /dev/null +++ b/src/services/likesService.ts @@ -0,0 +1,32 @@ +import * as likesRepository from '../repositories/likesRepository'; +import * as articlesRepository from '../repositories/articlesRepository'; +import NotFoundError from '../lib/errors/NotFoundError'; +import BadRequestError from '../lib/errors/BadRequestError'; + +export async function createLike(articleId: number, userId: number) { + const existingArticle = await articlesRepository.getArticle(articleId); + if (!existingArticle) { + throw new NotFoundError('article', articleId); + } + + const existingLike = await likesRepository.getLike(articleId, userId); + if (existingLike) { + throw new BadRequestError('Already liked'); + } + + await likesRepository.createLike({ articleId, userId }); +} + +export async function deleteLike(articleId: number, userId: number) { + const existingArticle = await articlesRepository.getArticle(articleId); + if (!existingArticle) { + throw new NotFoundError('article', articleId); + } + + const existingLike = await likesRepository.getLike(articleId, userId); + if (!existingLike) { + throw new BadRequestError('Not liked'); + } + + await likesRepository.deleteLike(existingLike.id); +} diff --git a/src/services/notificationsService.ts b/src/services/notificationsService.ts new file mode 100644 index 00000000..0fa38e3b --- /dev/null +++ b/src/services/notificationsService.ts @@ -0,0 +1,69 @@ +import UnauthorizedError from '../lib/errors/UnauthorizedError'; +import NotFoundError from '../lib/errors/NotFoundError'; +import ForbiddenError from '../lib/errors/ForbiddenError'; +import { CursorPaginationParams } from '../types/pagination'; +import { Notification } from '../types/Notification'; +import * as notificationsRepository from '../repositories/notificationsRepository'; +import * as usersRepository from '../repositories/usersRepository'; +import socketService from './socketService'; + +export async function createNotification( + data: Omit, +) { + const existingUser = await usersRepository.getUser(data.userId); + if (!existingUser) { + throw new NotFoundError('User', data.userId); + } + + const notification = await notificationsRepository.createNotification({ + ...data, + read: false, + }); + + socketService.sendNotification(notification as Notification); + + return notification; +} + +export async function createNotifications( + notifications: Omit[], +) { + await notificationsRepository.createNotifications( + notifications.map((notification) => ({ + ...notification, + read: false, + })), + ); + + notifications.forEach((notification) => { + socketService.sendNotification(notification as Notification); + }); +} + +export async function readNotificationById(id: number, userId?: number) { + if (!userId) { + throw new UnauthorizedError('Unauthorized'); + } + + const notification = await notificationsRepository.getNotificationById(id); + if (!notification) { + throw new NotFoundError('Notification', id); + } + + if (notification.userId !== userId) { + throw new ForbiddenError("Cannot read other user's notification"); + } + + await notificationsRepository.updateNotificationById(id, { read: true }); +} + +export async function getMyNotifications(userId: number, params: CursorPaginationParams) { + if (!userId) { + throw new UnauthorizedError('Unauthorized'); + } + + const { cursor, limit } = params; + const { notifications, totalCount, unreadCount, nextCursor } = + await notificationsRepository.getNotificationsByUserId(userId, { cursor, limit }); + return { list: notifications, totalCount, unreadCount, nextCursor }; +} diff --git a/src/services/productService.js b/src/services/productService.js deleted file mode 100644 index fbd9d2c8..00000000 --- a/src/services/productService.js +++ /dev/null @@ -1,69 +0,0 @@ -import { prisma } from "../../prisma/prisma.js"; - -// Product DTO μ •μ˜ -class Product { - constructor(id, name, description, price, tags, createdAt) { - this.id = id; - this.name = name; - this.description = description; - this.price = price; - this.tags = tags; - this.createdAt = createdAt; - } - - static fromEntity(entity) { - return new Product( - entity.id.toString(), - entity.name, - entity.description, - entity.price, - entity.tags, - entity.created_at - ); - } -} - -/** - * μƒν’ˆ λͺ©λ‘ 및 전체 개수λ₯Ό μ‘°νšŒν•˜λŠ” μ„œλΉ„μŠ€ ν•¨μˆ˜ - * @param {number} limit - νŽ˜μ΄μ§€λ‹Ή 쑰회 개수 - * @param {number} offset - κ±΄λ„ˆλ›Έ 개수 - * @param {string} keyword - 검색 ν‚€μ›Œλ“œ (선택적) - * @returns {{products: Product[], totalCount: number}} - */ -export async function getProductList(limit, offset, keyword) { - const findOption = { - orderBy: { created_at: "desc" }, // 3. μ΅œμ‹ μˆœ μ •λ ¬ 적용 - take: limit, // 2. limit 적용 - skip: offset, // 2. offset 적용 - }; - - if (keyword) { - findOption.where = { - OR: [ - { name: { contains: keyword, mode: "insensitive" } }, - { description: { contains: keyword, mode: "insensitive" } }, - ], - }; - } - - // μƒν’ˆ λͺ©λ‘κ³Ό 전체 개수λ₯Ό λ³‘λ ¬λ‘œ 쑰회 - const [entities, totalCount] = await prisma.$transaction([ - prisma.product.findMany(findOption), - // countλŠ” limit, offset, orderBy μ˜΅μ…˜μ„ μ œμ™Έν•˜κ³  where 쑰건만 μ μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€. - prisma.product.count({ where: findOption.where }), - ]); - - const products = entities.map(Product.fromEntity); - - return { products, totalCount }; -} - -export async function createProductComment(productId, content) { - const newComment = await prisma.product_comment.create({ - data: { - product_id: BigInt(productId), - content: content, - }, - }); - return newComment; -} diff --git a/src/services/productsService.ts b/src/services/productsService.ts new file mode 100644 index 00000000..bb7587c8 --- /dev/null +++ b/src/services/productsService.ts @@ -0,0 +1,80 @@ +import ForbiddenError from '../lib/errors/ForbiddenError'; +import NotFoundError from '../lib/errors/NotFoundError'; +import * as productsRepository from '../repositories/productsRepository'; +import * as favoritesRepository from '../repositories/favoritesRepository'; +import * as notificationsService from './notificationsService'; +import { PagePaginationParams, PagePaginationResult } from '../types/pagination'; +import Product from '../types/Product'; +import { NotificationType } from '../types/Notification'; + +type CreateProductData = Omit< + Product, + 'id' | 'createdAt' | 'updatedAt' | 'favoriteCount' | 'isFavorited' +>; +type UpdateProductData = Partial & { userId: number }; + +export async function createProduct(data: CreateProductData): Promise { + const createdProduct = await productsRepository.createProduct(data); + return { + ...createdProduct, + favoriteCount: 0, + isFavorited: false, + }; +} + +export async function getProduct(id: number): Promise { + const product = await productsRepository.getProductWithFavorites(id); + if (!product) { + throw new NotFoundError('product', id); + } + return product; +} + +export async function getProductList( + params: PagePaginationParams, + { userId }: { userId?: number } = {}, +): Promise> { + const products = await productsRepository.getProductListWithFavorites(params, { userId }); + return products; +} + +export async function updateProduct(id: number, data: UpdateProductData): Promise { + const existingProduct = await productsRepository.getProduct(id); + if (!existingProduct) { + throw new NotFoundError('product', id); + } + if (existingProduct.userId !== data.userId) { + throw new ForbiddenError('Should be the owner of the product'); + } + const updatedProduct = await productsRepository.updateProductWithFavorites(id, data); + + /** Price change notification */ + const previousPrice = existingProduct.price; + const updatedPrice = updatedProduct.price; + if (previousPrice !== updatedPrice) { + const favorites = await favoritesRepository.getFavoritesByProductId(id); + const likedUserIds = favorites.map((favorite) => favorite.userId); + const notifications = likedUserIds.map((userId) => ({ + userId, + type: NotificationType.PRICE_CHANGED, + payload: { + productId: id, + price: updatedPrice, + }, + })); + await notificationsService.createNotifications(notifications); + } + + return updatedProduct; +} + +export async function deleteProduct(id: number, userId: number): Promise { + const existingProduct = await productsRepository.getProduct(id); + if (!existingProduct) { + throw new NotFoundError('product', id); + } + if (existingProduct.userId !== userId) { + throw new ForbiddenError('Should be the owner of the product'); + } + await productsRepository.deleteProduct(id); +} diff --git a/src/services/socketService.ts b/src/services/socketService.ts new file mode 100644 index 00000000..a21b19e3 --- /dev/null +++ b/src/services/socketService.ts @@ -0,0 +1,39 @@ +import { ExtendedError, Server, Socket } from 'socket.io'; +import http from 'http'; +import * as authService from './authService'; +import { Notification } from '../types/Notification'; +import User from '../types/User'; + +class SocketService { + private io: Server; + + constructor() { + this.io = new Server(); + this.io.use(this.authenticate); + } + + private async authenticate(socket: Socket, next: (err?: ExtendedError) => void) { + let user: User; + try { + const accessToken = socket.handshake.auth.accessToken; + user = await authService.authenticate(accessToken); + } catch (error) { + console.log('error', error); + next(error as ExtendedError); + return; + } + socket.join(user.id.toString()); + next(); + } + + initialize(httpServer: http.Server) { + this.io.attach(httpServer); + } + + sendNotification(notification: Notification) { + const userId = notification.userId; + this.io.to(userId.toString()).emit('notification', notification); + } +} + +export default new SocketService(); diff --git a/src/services/usersService.ts b/src/services/usersService.ts new file mode 100644 index 00000000..4764a315 --- /dev/null +++ b/src/services/usersService.ts @@ -0,0 +1,38 @@ +import { Product } from '@prisma/client'; +import { PagePaginationParams, PagePaginationResult } from '../types/pagination'; +import * as usersRepository from '../repositories/usersRepository'; +import * as productsRepository from '../repositories/productsRepository'; +import NotFoundError from '../lib/errors/NotFoundError'; +import User from '../types/User'; + +type UpdateUserData = Partial>; + +export async function getUser(userId: number): Promise { + const user = await usersRepository.getUser(userId); + if (!user) { + throw new NotFoundError('user', userId); + } + + return user; +} + +export async function updateUser(userId: number, data: Partial): Promise { + const updatedUser = await usersRepository.updateUser(userId, data); + return updatedUser; +} + +export async function getMyProductList( + userId: number, + params: PagePaginationParams, +): Promise> { + const result = await productsRepository.getProductListWithFavorites(params, { userId }); + return result; +} + +export async function getMyFavoriteList( + userId: number, + params: PagePaginationParams, +): Promise> { + const result = await productsRepository.getFavoriteProductListByOwnerId(userId, params); + return result; +} diff --git a/src/structs/articlesStructs.js b/src/structs/articlesStructs.js deleted file mode 100644 index f77d7144..00000000 --- a/src/structs/articlesStructs.js +++ /dev/null @@ -1,12 +0,0 @@ -import { coerce, nonempty, optional, object, partial, string } from 'superstruct'; -import { PageParamsStruct } from './commonStructs.js'; - -export const GetArticleListParamsStruct = PageParamsStruct; - -export const CreateArticleBodyStruct = object({ - title: coerce(nonempty(string()), string(), (value) => value.trim()), - content: nonempty(string()), - image: optional(string()), -}); - -export const UpdateArticleBodyStruct = partial(CreateArticleBodyStruct); diff --git a/src/structs/authStructs.ts b/src/structs/authStructs.ts index b211e181..f8b6bcd6 100644 --- a/src/structs/authStructs.ts +++ b/src/structs/authStructs.ts @@ -1,9 +1,10 @@ -import { nonempty, object, string } from 'superstruct'; +import { nonempty, nullable, object, string } from 'superstruct'; export const RegisterBodyStruct = object({ email: nonempty(string()), nickname: nonempty(string()), password: nonempty(string()), + image: nullable(string()), }); export const LoginBodyStruct = object({ diff --git a/src/structs/commentsStruct.js b/src/structs/commentsStruct.js deleted file mode 100644 index 9f93a0ec..00000000 --- a/src/structs/commentsStruct.js +++ /dev/null @@ -1,10 +0,0 @@ -import { nonempty, object, partial, string } from 'superstruct'; -import { CursorParamsStruct } from './commonStructs.js'; - -export const CreateCommentBodyStruct = object({ - content: nonempty(string()), -}); - -export const GetCommentListParamsStruct = CursorParamsStruct; - -export const UpdateCommentBodyStruct = partial(CreateCommentBodyStruct); diff --git a/src/structs/commentsStruct.ts b/src/structs/commentsStruct.ts index dce57521..aff08b47 100644 --- a/src/structs/commentsStruct.ts +++ b/src/structs/commentsStruct.ts @@ -1,10 +1,12 @@ -import { nonempty, object, partial, string } from 'superstruct'; +import { nonempty, number, object, optional, string } from 'superstruct'; import { CursorParamsStruct } from './commonStructs'; export const CreateCommentBodyStruct = object({ content: nonempty(string()), + productId: optional(number()), + articleId: optional(number()), }); export const GetCommentListParamsStruct = CursorParamsStruct; -export const UpdateCommentBodyStruct = partial(CreateCommentBodyStruct); +export const UpdateCommentBodyStruct = CreateCommentBodyStruct; diff --git a/src/structs/commonStructs.js b/src/structs/commonStructs.js deleted file mode 100644 index 605bfa9e..00000000 --- a/src/structs/commonStructs.js +++ /dev/null @@ -1,22 +0,0 @@ -import { coerce, integer, object, string, defaulted, optional, enums, nonempty } from 'superstruct'; - -/** Convert string to integer then validate it */ -const integerString = coerce(integer(), string(), (value) => parseInt(value)); - -export const IdParamsStruct = object({ - id: integerString, -}); - -export const PageParamsStruct = object({ - page: defaulted(integerString, 1), - pageSize: defaulted(integerString, 10), - orderBy: optional(enums(['recent'])), - keyword: optional(nonempty(string())), -}); - -export const CursorParamsStruct = object({ - cursor: defaulted(integerString, 0), - limit: defaulted(integerString, 10), - orderBy: optional(enums(['recent'])), - keyword: optional(nonempty(string())), -}); diff --git a/src/structs/productsStruct.js b/src/structs/productsStruct.js deleted file mode 100644 index 69d416cf..00000000 --- a/src/structs/productsStruct.js +++ /dev/null @@ -1,14 +0,0 @@ -import { coerce, partial, object, string, min, nonempty, array, integer } from 'superstruct'; -import { PageParamsStruct } from './commonStructs.js'; - -export const CreateProductBodyStruct = object({ - name: coerce(nonempty(string()), string(), (value) => value.trim()), - description: nonempty(string()), - price: min(integer(), 0), - tags: array(nonempty(string())), - images: array(nonempty(string())), -}); - -export const GetProductListParamsStruct = PageParamsStruct; - -export const UpdateProductBodyStruct = partial(CreateProductBodyStruct); diff --git a/src/structs/usersStructs.js b/src/structs/usersStructs.js deleted file mode 100644 index 3b448a31..00000000 --- a/src/structs/usersStructs.js +++ /dev/null @@ -1,13 +0,0 @@ -import { nonempty, object, string, optional, size } from 'superstruct'; - -// λ‚΄ 정보 μˆ˜μ • (λ‹‰λ„€μž„, 이미지) -export const UpdateMeStruct = object({ - nickname: optional(nonempty(string())), - image: optional(string()), -}); - -// λΉ„λ°€λ²ˆν˜Έ λ³€κ²½ -export const ChangePasswordStruct = object({ - currentPassword: nonempty(string()), - newPassword: size(string(), 8, 100), // μ΅œμ†Œ 8자 이상 -}); \ No newline at end of file diff --git a/src/structs/usersStructs.ts b/src/structs/usersStructs.ts index dccd8b87..3ccbd04c 100644 --- a/src/structs/usersStructs.ts +++ b/src/structs/usersStructs.ts @@ -1,8 +1,9 @@ import { nullable, object, partial, string } from 'superstruct'; -import { PageParamsStruct } from './commonStructs'; +import { CursorParamsStruct, PageParamsStruct } from './commonStructs'; export const UpdateMeBodyStruct = partial( object({ + email: string(), nickname: string(), image: nullable(string()), }), @@ -15,4 +16,6 @@ export const UpdatePasswordBodyStruct = object({ export const GetMyProductListParamsStruct = PageParamsStruct; -export const GetMyLikeListParamsStruct = PageParamsStruct; +export const GetMyFavoriteListParamsStruct = PageParamsStruct; + +export const GetMyNotificationsParamsStruct = CursorParamsStruct; diff --git a/src/tests/articles.auth.test.ts b/src/tests/articles.auth.test.ts new file mode 100644 index 00000000..4f7c6158 --- /dev/null +++ b/src/tests/articles.auth.test.ts @@ -0,0 +1,241 @@ +import request from 'supertest'; +import app from '../app'; +import { prismaClient } from '../lib/prismaClient'; + +describe('Articles API (인증 ν•„μš”)', () => { + let ownerCookie: string; + let otherCookie: string; + let testArticleId: number; + + const ownerEmail = 'article-owner@example.com'; + const otherEmail = 'article-other@example.com'; + const password = 'Password1!'; + + beforeAll(async () => { + // μ†Œμœ μž νšŒμ›κ°€μž… & 둜그인 + await request(app).post('/auth/register').send({ + email: ownerEmail, + nickname: 'articleOwner', + password, + image: null, + }); + const ownerLogin = await request(app).post('/auth/login').send({ + email: ownerEmail, + password, + }); + ownerCookie = ownerLogin.headers['set-cookie'][0]; + + // λ‹€λ₯Έ μœ μ € νšŒμ›κ°€μž… & 둜그인 + await request(app).post('/auth/register').send({ + email: otherEmail, + nickname: 'articleOther', + password, + image: null, + }); + const otherLogin = await request(app).post('/auth/login').send({ + email: otherEmail, + password, + }); + otherCookie = otherLogin.headers['set-cookie'][0]; + }); + + afterAll(async () => { + const users = await prismaClient.user.findMany({ + where: { email: { in: [ownerEmail, otherEmail] } }, + select: { id: true }, + }); + const userIds = users.map((u) => u.id); + + await prismaClient.notification.deleteMany({ + where: { userId: { in: userIds } }, + }); + + await prismaClient.user.deleteMany({ + where: { id: { in: userIds } }, + }); + + await prismaClient.$disconnect(); + }); + + describe('POST /articles', () => { + it('인증된 μœ μ €κ°€ κ²Œμ‹œκΈ€μ„ μ •μƒμ μœΌλ‘œ μƒμ„±ν•œλ‹€', async () => { + const res = await request(app).post('/articles').set('Cookie', ownerCookie).send({ + title: 'μƒˆ κ²Œμ‹œκΈ€ 제λͺ©', + content: 'μƒˆ κ²Œμ‹œκΈ€ λ³Έλ¬Έ', + image: null, + }); + + expect(res.status).toBe(201); + expect(res.body).toMatchObject({ + title: 'μƒˆ κ²Œμ‹œκΈ€ 제λͺ©', + content: 'μƒˆ κ²Œμ‹œκΈ€ λ³Έλ¬Έ', + }); + expect(res.body).toHaveProperty('id'); + expect(res.body).toHaveProperty('likeCount', 0); + + testArticleId = res.body.id; // 이후 ν…ŒμŠ€νŠΈμ—μ„œ μ‚¬μš© + }); + + it('μΈμ¦λ˜μ§€ μ•Šμ€ μš”μ²­μ€ 401을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).post('/articles').send({ + title: '미인증 κ²Œμ‹œκΈ€', + content: 'λ³Έλ¬Έ', + image: null, + }); + + expect(res.status).toBe(401); + }); + + it('title ν•„λ“œ λˆ„λ½ μ‹œ 400을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app) + .post('/articles') + .set('Cookie', ownerCookie) + .send({ content: '본문만 있음', image: null }); + + expect(res.status).toBe(400); + }); + + it('content ν•„λ“œ λˆ„λ½ μ‹œ 400을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app) + .post('/articles') + .set('Cookie', ownerCookie) + .send({ title: '제λͺ©λ§Œ 있음', image: null }); + + expect(res.status).toBe(400); + }); + }); + + describe('PATCH /articles/:id', () => { + it('μ†Œμœ μžκ°€ κ²Œμ‹œκΈ€μ„ μ •μƒμ μœΌλ‘œ μˆ˜μ •ν•œλ‹€', async () => { + const res = await request(app) + .patch(`/articles/${testArticleId}`) + .set('Cookie', ownerCookie) + .send({ title: 'μˆ˜μ •λœ 제λͺ©', content: 'μˆ˜μ •λœ λ³Έλ¬Έ' }); + + expect(res.status).toBe(200); + expect(res.body).toMatchObject({ + title: 'μˆ˜μ •λœ 제λͺ©', + content: 'μˆ˜μ •λœ λ³Έλ¬Έ', + }); + }); + + it('μ†Œμœ μžκ°€ μ•„λ‹Œ μœ μ €κ°€ μˆ˜μ •ν•˜λ©΄ 403을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app) + .patch(`/articles/${testArticleId}`) + .set('Cookie', otherCookie) + .send({ title: 'νƒˆμ·¨ μˆ˜μ •' }); + + expect(res.status).toBe(403); + }); + + it('μΈμ¦λ˜μ§€ μ•Šμ€ μš”μ²­μ€ 401을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app) + .patch(`/articles/${testArticleId}`) + .send({ title: '미인증 μˆ˜μ •' }); + + expect(res.status).toBe(401); + }); + + it('μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” κ²Œμ‹œκΈ€ μˆ˜μ • μ‹œ 404λ₯Ό λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app) + .patch('/articles/9999999') + .set('Cookie', ownerCookie) + .send({ title: 'μ—†λŠ” κ²Œμ‹œκΈ€' }); + + expect(res.status).toBe(404); + }); + }); + + describe('POST /articles/:id/comments', () => { + it('인증된 μœ μ €κ°€ λŒ“κΈ€μ„ μ •μƒμ μœΌλ‘œ μž‘μ„±ν•œλ‹€', async () => { + const res = await request(app) + .post(`/articles/${testArticleId}/comments`) + .set('Cookie', otherCookie) + .send({ content: '쒋은 κΈ€μ΄λ„€μš”!', articleId: testArticleId }); + + expect(res.status).toBe(201); + expect(res.body).toHaveProperty('content', '쒋은 κΈ€μ΄λ„€μš”!'); + }); + + it('μΈμ¦λ˜μ§€ μ•Šμ€ μš”μ²­μ€ 401을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app) + .post(`/articles/${testArticleId}/comments`) + .send({ content: '미인증 λŒ“κΈ€' }); + + expect(res.status).toBe(401); + }); + + it('content ν•„λ“œ λˆ„λ½ μ‹œ 400을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app) + .post(`/articles/${testArticleId}/comments`) + .set('Cookie', ownerCookie) + .send({}); + + expect(res.status).toBe(400); + }); + }); + + describe('POST /articles/:id/likes (μ’‹μ•„μš”)', () => { + it('인증된 μœ μ €κ°€ κ²Œμ‹œκΈ€μ— μ’‹μ•„μš”λ₯Ό λˆ„λ₯Ό 수 μžˆλ‹€', async () => { + const res = await request(app) + .post(`/articles/${testArticleId}/likes`) + .set('Cookie', otherCookie); + + expect(res.status).toBe(201); + }); + + it('μΈμ¦λ˜μ§€ μ•Šμ€ μš”μ²­μ€ 401을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).post(`/articles/${testArticleId}/likes`); + + expect(res.status).toBe(401); + }); + }); + + describe('DELETE /articles/:id/likes (μ’‹μ•„μš” μ·¨μ†Œ)', () => { + it('μ’‹μ•„μš”ν•œ κ²Œμ‹œκΈ€μ˜ μ’‹μ•„μš”λ₯Ό μ·¨μ†Œν•  수 μžˆλ‹€', async () => { + const res = await request(app) + .delete(`/articles/${testArticleId}/likes`) + .set('Cookie', otherCookie); + + expect(res.status).toBe(204); + }); + + it('μΈμ¦λ˜μ§€ μ•Šμ€ μš”μ²­μ€ 401을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).delete(`/articles/${testArticleId}/likes`); + + expect(res.status).toBe(401); + }); + }); + + describe('DELETE /articles/:id', () => { + it('μ†Œμœ μžκ°€ μ•„λ‹Œ μœ μ €κ°€ μ‚­μ œν•˜λ©΄ 403을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app) + .delete(`/articles/${testArticleId}`) + .set('Cookie', otherCookie); + + expect(res.status).toBe(403); + }); + + it('μΈμ¦λ˜μ§€ μ•Šμ€ μš”μ²­μ€ 401을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).delete(`/articles/${testArticleId}`); + + expect(res.status).toBe(401); + }); + + it('μ†Œμœ μžκ°€ κ²Œμ‹œκΈ€μ„ μ •μƒμ μœΌλ‘œ μ‚­μ œν•œλ‹€', async () => { + const res = await request(app) + .delete(`/articles/${testArticleId}`) + .set('Cookie', ownerCookie); + + expect(res.status).toBe(204); + }); + + it('이미 μ‚­μ œλœ κ²Œμ‹œκΈ€ μ‚­μ œ μ‹œ 404λ₯Ό λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app) + .delete(`/articles/${testArticleId}`) + .set('Cookie', ownerCookie); + + expect(res.status).toBe(404); + }); + }); +}); diff --git a/src/tests/articles.public.test.ts b/src/tests/articles.public.test.ts new file mode 100644 index 00000000..1c74c77c --- /dev/null +++ b/src/tests/articles.public.test.ts @@ -0,0 +1,136 @@ +import request from 'supertest'; +import app from '../app'; +import { prismaClient } from '../lib/prismaClient'; + +describe('Articles API (인증 λΆˆν•„μš”)', () => { + let testUserId: number; + let testArticleId: number; + + beforeAll(async () => { + const user = await prismaClient.user.create({ + data: { + email: 'article-public-test@example.com', + nickname: 'articletester', + password: 'hashed-password', + }, + }); + testUserId = user.id; + + const article = await prismaClient.article.create({ + data: { + title: 'ν…ŒμŠ€νŠΈ κ²Œμ‹œκΈ€ 제λͺ©', + content: 'ν…ŒμŠ€νŠΈ κ²Œμ‹œκΈ€ λ³Έλ¬Έμž…λ‹ˆλ‹€.', + userId: testUserId, + }, + }); + testArticleId = article.id; + + await prismaClient.comment.create({ + data: { + content: 'ν…ŒμŠ€νŠΈ κ²Œμ‹œκΈ€ λŒ“κΈ€', + articleId: testArticleId, + userId: testUserId, + }, + }); + }); + + afterAll(async () => { + await prismaClient.comment.deleteMany({ where: { articleId: testArticleId } }); + await prismaClient.article.delete({ where: { id: testArticleId } }); + await prismaClient.user.delete({ where: { id: testUserId } }); + await prismaClient.$disconnect(); + }); + + describe('GET /articles', () => { + it('κ²Œμ‹œκΈ€ λͺ©λ‘μ„ μ •μƒμ μœΌλ‘œ λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).get('/articles'); + expect(res.status).toBe(200); + expect(res.body).toHaveProperty('list'); + expect(res.body).toHaveProperty('totalCount'); + expect(Array.isArray(res.body.list)).toBe(true); + }); + + it('page, pageSize 쿼리 νŒŒλΌλ―Έν„°κ°€ μ μš©λœλ‹€', async () => { + const res = await request(app).get('/articles?page=1&pageSize=1'); + expect(res.status).toBe(200); + expect(res.body.list.length).toBeLessThanOrEqual(1); + }); + + it('keyword 검색이 λ™μž‘ν•œλ‹€', async () => { + const res = await request(app).get('/articles?keyword=ν…ŒμŠ€νŠΈ κ²Œμ‹œκΈ€'); + expect(res.status).toBe(200); + expect(res.body.list.length).toBeGreaterThanOrEqual(1); + expect(res.body.list[0].title).toContain('ν…ŒμŠ€νŠΈ κ²Œμ‹œκΈ€'); + }); + + it('μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” keywordλŠ” 빈 λͺ©λ‘μ„ λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).get('/articles?keyword=μ ˆλŒ€μ—†λŠ”κ²Œμ‹œκΈ€xyz123'); + expect(res.status).toBe(200); + expect(res.body.list).toHaveLength(0); + }); + + it('각 κ²Œμ‹œκΈ€μ— likeCount ν•„λ“œκ°€ ν¬ν•¨λœλ‹€', async () => { + const res = await request(app).get('/articles'); + expect(res.status).toBe(200); + res.body.list.forEach((article: any) => { + expect(article).toHaveProperty('likeCount'); + }); + }); + + it('orderBy=recent 정렬이 λ™μž‘ν•œλ‹€', async () => { + const res = await request(app).get('/articles?orderBy=recent'); + expect(res.status).toBe(200); + expect(res.body).toHaveProperty('list'); + }); + }); + + describe('GET /articles/:id', () => { + it('μ‘΄μž¬ν•˜λŠ” κ²Œμ‹œκΈ€μ„ μ •μƒμ μœΌλ‘œ λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).get(`/articles/${testArticleId}`); + expect(res.status).toBe(200); + expect(res.body).toMatchObject({ + id: testArticleId, + title: 'ν…ŒμŠ€νŠΈ κ²Œμ‹œκΈ€ 제λͺ©', + content: 'ν…ŒμŠ€νŠΈ κ²Œμ‹œκΈ€ λ³Έλ¬Έμž…λ‹ˆλ‹€.', + }); + }); + + it('κ²Œμ‹œκΈ€μ— likeCount ν•„λ“œκ°€ ν¬ν•¨λœλ‹€', async () => { + const res = await request(app).get(`/articles/${testArticleId}`); + expect(res.status).toBe(200); + expect(res.body).toHaveProperty('likeCount'); + expect(res.body.likeCount).toBe(0); + }); + + it('μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” κ²Œμ‹œκΈ€ IDλŠ” 404λ₯Ό λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).get('/articles/9999999'); + expect(res.status).toBe(404); + }); + + it('μœ νš¨ν•˜μ§€ μ•Šμ€ ID ν˜•μ‹μ€ 400을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).get('/articles/not-a-number'); + expect(res.status).toBe(400); + }); + }); + + describe('GET /articles/:id/comments', () => { + it('κ²Œμ‹œκΈ€μ˜ λŒ“κΈ€ λͺ©λ‘μ„ μ •μƒμ μœΌλ‘œ λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).get(`/articles/${testArticleId}/comments`); + expect(res.status).toBe(200); + expect(res.body).toHaveProperty('list'); + expect(Array.isArray(res.body.list)).toBe(true); + expect(res.body.list.length).toBeGreaterThanOrEqual(1); + }); + + it('λŒ“κΈ€μ— content ν•„λ“œκ°€ ν¬ν•¨λœλ‹€', async () => { + const res = await request(app).get(`/articles/${testArticleId}/comments`); + expect(res.status).toBe(200); + expect(res.body.list[0]).toHaveProperty('content', 'ν…ŒμŠ€νŠΈ κ²Œμ‹œκΈ€ λŒ“κΈ€'); + }); + + it('μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” κ²Œμ‹œκΈ€μ˜ λŒ“κΈ€ λͺ©λ‘μ€ 빈 배열을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).get('/articles/9999999/comments'); + expect(res.status).toBe(404); + }); + }); +}); diff --git a/src/tests/auth.test.ts b/src/tests/auth.test.ts new file mode 100644 index 00000000..8650def6 --- /dev/null +++ b/src/tests/auth.test.ts @@ -0,0 +1,154 @@ +import request from 'supertest'; +import app from '../app'; +import { prismaClient } from '../lib/prismaClient'; + +describe('Auth API (νšŒμ›κ°€μž… / 둜그인)', () => { + const createdEmails: string[] = []; + + afterAll(async () => { + await prismaClient.user.deleteMany({ + where: { email: { in: createdEmails } }, + }); + await prismaClient.$disconnect(); + }); + + describe('POST /auth/register', () => { + it('μ˜¬λ°”λ₯Έ μ •λ³΄λ‘œ νšŒμ›κ°€μž…ν•˜λ©΄ 201κ³Ό μœ μ € 정보λ₯Ό λ°˜ν™˜ν•œλ‹€', async () => { + const email = 'register-success@example.com'; + createdEmails.push(email); + + const res = await request(app).post('/auth/register').send({ + email, + nickname: 'newuser', + password: 'Password1!', + image: null, + }); + + expect(res.status).toBe(201); + expect(res.body).toHaveProperty('id'); + expect(res.body).toHaveProperty('email', email); + expect(res.body).toHaveProperty('nickname', 'newuser'); + // λΉ„λ°€λ²ˆν˜ΈλŠ” 응닡에 ν¬ν•¨λ˜μ§€ μ•Šμ•„μ•Ό 함 + expect(res.body).not.toHaveProperty('password'); + }); + + it('이미 μ‘΄μž¬ν•˜λŠ” μ΄λ©”μΌλ‘œ κ°€μž…ν•˜λ©΄ 400을 λ°˜ν™˜ν•œλ‹€', async () => { + const email = 'register-duplicate@example.com'; + createdEmails.push(email); + + await request(app).post('/auth/register').send({ + email, + nickname: 'user1', + password: 'Password1!', + }); + + const res = await request(app).post('/auth/register').send({ + email, + nickname: 'user2', + password: 'Password1!', + }); + + expect(res.status).toBe(400); + }); + + it('email ν•„λ“œ λˆ„λ½ μ‹œ 400을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).post('/auth/register').send({ + nickname: 'noEmail', + password: 'Password1!', + }); + + expect(res.status).toBe(400); + }); + + it('nickname ν•„λ“œ λˆ„λ½ μ‹œ 400을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).post('/auth/register').send({ + email: 'no-nickname@example.com', + password: 'Password1!', + }); + + expect(res.status).toBe(400); + }); + + it('password ν•„λ“œ λˆ„λ½ μ‹œ 400을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).post('/auth/register').send({ + email: 'no-password@example.com', + nickname: 'noPass', + }); + + expect(res.status).toBe(400); + }); + }); + + describe('POST /auth/login', () => { + const loginEmail = 'login-test@example.com'; + const loginPassword = 'Password1!'; + + beforeAll(async () => { + createdEmails.push(loginEmail); + await request(app).post('/auth/register').send({ + email: loginEmail, + nickname: 'loginuser', + password: loginPassword, + image: null, + }); + }); + + it('μ˜¬λ°”λ₯Έ 이메일/λΉ„λ°€λ²ˆν˜Έλ‘œ λ‘œκ·ΈμΈν•˜λ©΄ 200을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).post('/auth/login').send({ + email: loginEmail, + password: loginPassword, + }); + + expect(res.status).toBe(200); + }); + + it('둜그인 성곡 μ‹œ access-token μΏ ν‚€κ°€ μ„€μ •λœλ‹€', async () => { + const res = await request(app).post('/auth/login').send({ + email: loginEmail, + password: loginPassword, + }); + + expect(res.status).toBe(200); + const cookies = res.headers['set-cookie']; + expect(cookies).toBeDefined(); + const hasAccessToken = (cookies as unknown as string[]).some((cookie: string) => + cookie.startsWith('access-token='), + ); + expect(hasAccessToken).toBe(true); + }); + + it('μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” μ΄λ©”μΌλ‘œ λ‘œκ·ΈμΈν•˜λ©΄ 400을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).post('/auth/login').send({ + email: 'notexist@example.com', + password: loginPassword, + }); + + expect(res.status).toBe(400); + }); + + it('잘λͺ»λœ λΉ„λ°€λ²ˆν˜Έλ‘œ λ‘œκ·ΈμΈν•˜λ©΄ 400을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).post('/auth/login').send({ + email: loginEmail, + password: 'WrongPassword!', + }); + + expect(res.status).toBe(400); + }); + + it('email ν•„λ“œ λˆ„λ½ μ‹œ 400을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).post('/auth/login').send({ + password: loginPassword, + }); + + expect(res.status).toBe(400); + }); + + it('password ν•„λ“œ λˆ„λ½ μ‹œ 400을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).post('/auth/login').send({ + email: loginEmail, + }); + + expect(res.status).toBe(400); + }); + }); +}); diff --git a/src/tests/products.auth.test.ts b/src/tests/products.auth.test.ts new file mode 100644 index 00000000..5c066b88 --- /dev/null +++ b/src/tests/products.auth.test.ts @@ -0,0 +1,241 @@ +import request from 'supertest'; +import app from '../app'; +import { prismaClient } from '../lib/prismaClient'; + +describe('Products API (인증 ν•„μš”)', () => { + let ownerCookie: string; + let otherCookie: string; + let testProductId: number; + + const ownerEmail = 'product-owner@example.com'; + const otherEmail = 'product-other@example.com'; + const password = 'Password1!'; + + beforeAll(async () => { + // μ†Œμœ μž νšŒμ›κ°€μž… & 둜그인 + await request(app).post('/auth/register').send({ + email: ownerEmail, + nickname: 'owner', + password, + image: null, + }); + const ownerLogin = await request(app).post('/auth/login').send({ + email: ownerEmail, + password, + }); + ownerCookie = ownerLogin.headers['set-cookie'][0]; + + // λ‹€λ₯Έ μœ μ € νšŒμ›κ°€μž… & 둜그인 + await request(app).post('/auth/register').send({ + email: otherEmail, + nickname: 'other', + password, + image: null, + }); + const otherLogin = await request(app).post('/auth/login').send({ + email: otherEmail, + password, + }); + otherCookie = otherLogin.headers['set-cookie'][0]; + }); + + afterAll(async () => { + await prismaClient.user.deleteMany({ + where: { email: { in: [ownerEmail, otherEmail] } }, + }); + await prismaClient.$disconnect(); + }); + + describe('POST /products', () => { + it('인증된 μœ μ €κ°€ μƒν’ˆμ„ μ •μƒμ μœΌλ‘œ μƒμ„±ν•œλ‹€', async () => { + const res = await request(app) + .post('/products') + .set('Cookie', ownerCookie) + .send({ + name: 'μƒˆ μƒν’ˆ', + description: 'μƒˆ μƒν’ˆ μ„€λͺ…', + price: 20000, + tags: ['νƒœκ·ΈA'], + images: [], + }); + + expect(res.status).toBe(201); + expect(res.body).toMatchObject({ + name: 'μƒˆ μƒν’ˆ', + description: 'μƒˆ μƒν’ˆ μ„€λͺ…', + price: 20000, + }); + expect(res.body).toHaveProperty('id'); + + testProductId = res.body.id; // 이후 ν…ŒμŠ€νŠΈμ—μ„œ μ‚¬μš© + }); + + it('μΈμ¦λ˜μ§€ μ•Šμ€ μš”μ²­μ€ 401을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).post('/products').send({ + name: '미인증 μƒν’ˆ', + description: 'μ„€λͺ…', + price: 1000, + tags: [], + images: [], + }); + + expect(res.status).toBe(401); + }); + + it('name ν•„λ“œ λˆ„λ½ μ‹œ 400을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).post('/products').set('Cookie', ownerCookie).send({ + description: 'μ„€λͺ…', + price: 1000, + tags: [], + images: [], + }); + + expect(res.status).toBe(400); + }); + + it('price ν•„λ“œ λˆ„λ½ μ‹œ 400을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).post('/products').set('Cookie', ownerCookie).send({ + name: 'μƒν’ˆλͺ…', + description: 'μ„€λͺ…', + tags: [], + images: [], + }); + + expect(res.status).toBe(400); + }); + }); + + describe('PATCH /products/:id', () => { + it('μ†Œμœ μžκ°€ μƒν’ˆμ„ μ •μƒμ μœΌλ‘œ μˆ˜μ •ν•œλ‹€', async () => { + const res = await request(app) + .patch(`/products/${testProductId}`) + .set('Cookie', ownerCookie) + .send({ name: 'μˆ˜μ •λœ μƒν’ˆλͺ…', price: 25000 }); + + expect(res.status).toBe(200); + expect(res.body).toMatchObject({ + name: 'μˆ˜μ •λœ μƒν’ˆλͺ…', + price: 25000, + }); + }); + + it('μ†Œμœ μžκ°€ μ•„λ‹Œ μœ μ €κ°€ μˆ˜μ •ν•˜λ©΄ 403을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app) + .patch(`/products/${testProductId}`) + .set('Cookie', otherCookie) + .send({ name: 'νƒˆμ·¨ μˆ˜μ •' }); + + expect(res.status).toBe(403); + }); + + it('μΈμ¦λ˜μ§€ μ•Šμ€ μš”μ²­μ€ 401을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app) + .patch(`/products/${testProductId}`) + .send({ name: '미인증 μˆ˜μ •' }); + + expect(res.status).toBe(401); + }); + + it('μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” μƒν’ˆ μˆ˜μ • μ‹œ 404λ₯Ό λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app) + .patch('/products/9999999') + .set('Cookie', ownerCookie) + .send({ name: 'μ—†λŠ” μƒν’ˆ' }); + + expect(res.status).toBe(404); + }); + }); + + describe('POST /products/:id/comments', () => { + it('인증된 μœ μ €κ°€ λŒ“κΈ€μ„ μ •μƒμ μœΌλ‘œ μž‘μ„±ν•œλ‹€', async () => { + const res = await request(app) + .post(`/products/${testProductId}/comments`) + .set('Cookie', otherCookie) + .send({ content: '쒋은 μƒν’ˆμ΄λ„€μš”!', productId: testProductId }); + + expect(res.status).toBe(201); + expect(res.body).toHaveProperty('content', '쒋은 μƒν’ˆμ΄λ„€μš”!'); + }); + + it('μΈμ¦λ˜μ§€ μ•Šμ€ μš”μ²­μ€ 401을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app) + .post(`/products/${testProductId}/comments`) + .send({ content: '미인증 λŒ“κΈ€' }); + + expect(res.status).toBe(401); + }); + + it('content ν•„λ“œ λˆ„λ½ μ‹œ 400을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app) + .post(`/products/${testProductId}/comments`) + .set('Cookie', ownerCookie) + .send({}); + + expect(res.status).toBe(400); + }); + }); + + describe('POST /products/:id/favorites (μ°œν•˜κΈ°)', () => { + it('인증된 μœ μ €κ°€ μƒν’ˆμ„ μ°œν•  수 μžˆλ‹€', async () => { + const res = await request(app) + .post(`/products/${testProductId}/favorites`) + .set('Cookie', otherCookie); + + expect(res.status).toBe(201); + }); + + it('μΈμ¦λ˜μ§€ μ•Šμ€ μš”μ²­μ€ 401을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).post(`/products/${testProductId}/favorites`); + + expect(res.status).toBe(401); + }); + }); + + describe('DELETE /products/:id/favorites (찜 μ·¨μ†Œ)', () => { + it('μ°œν•œ μƒν’ˆμ„ 찜 μ·¨μ†Œν•  수 μžˆλ‹€', async () => { + const res = await request(app) + .delete(`/products/${testProductId}/favorites`) + .set('Cookie', otherCookie); + + expect(res.status).toBe(204); + }); + + it('μΈμ¦λ˜μ§€ μ•Šμ€ μš”μ²­μ€ 401을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).delete(`/products/${testProductId}/favorites`); + + expect(res.status).toBe(401); + }); + }); + + describe('DELETE /products/:id', () => { + it('μ†Œμœ μžκ°€ μ•„λ‹Œ μœ μ €κ°€ μ‚­μ œν•˜λ©΄ 403을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app) + .delete(`/products/${testProductId}`) + .set('Cookie', otherCookie); + + expect(res.status).toBe(403); + }); + + it('μΈμ¦λ˜μ§€ μ•Šμ€ μš”μ²­μ€ 401을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).delete(`/products/${testProductId}`); + + expect(res.status).toBe(401); + }); + + it('μ†Œμœ μžκ°€ μƒν’ˆμ„ μ •μƒμ μœΌλ‘œ μ‚­μ œν•œλ‹€', async () => { + const res = await request(app) + .delete(`/products/${testProductId}`) + .set('Cookie', ownerCookie); + + expect(res.status).toBe(204); + }); + + it('이미 μ‚­μ œλœ μƒν’ˆ μ‚­μ œ μ‹œ 404λ₯Ό λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app) + .delete(`/products/${testProductId}`) + .set('Cookie', ownerCookie); + + expect(res.status).toBe(404); + }); + }); +}); diff --git a/src/tests/products.public.test.ts b/src/tests/products.public.test.ts new file mode 100644 index 00000000..f0c71941 --- /dev/null +++ b/src/tests/products.public.test.ts @@ -0,0 +1,146 @@ +import request from 'supertest'; +import app from '../app'; +import { prismaClient } from '../lib/prismaClient'; + +describe('Products API (인증 λΆˆν•„μš”)', () => { + let testUserId: number; + let testProductId: number; + + beforeAll(async () => { + const user = await prismaClient.user.create({ + data: { + email: 'product-public-test@example.com', + nickname: 'tester', + password: 'hashed-password', + }, + }); + testUserId = user.id; + + const product = await prismaClient.product.create({ + data: { + name: 'ν…ŒμŠ€νŠΈ μƒν’ˆ', + description: 'ν…ŒμŠ€νŠΈ μƒν’ˆ μ„€λͺ…', + price: 10000, + tags: ['νƒœκ·Έ1', 'νƒœκ·Έ2'], + images: [], + userId: testUserId, + }, + }); + testProductId = product.id; + + await prismaClient.comment.create({ + data: { + content: 'ν…ŒμŠ€νŠΈ λŒ“κΈ€μž…λ‹ˆλ‹€.', + productId: testProductId, + userId: testUserId, + }, + }); + }); + + afterAll(async () => { + await prismaClient.comment.deleteMany({ where: { productId: testProductId } }); + await prismaClient.product.delete({ where: { id: testProductId } }); + await prismaClient.user.delete({ where: { id: testUserId } }); + await prismaClient.$disconnect(); + }); + + describe('GET /products', () => { + it('μƒν’ˆ λͺ©λ‘μ„ μ •μƒμ μœΌλ‘œ λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).get('/products'); + expect(res.status).toBe(200); + expect(res.body).toHaveProperty('list'); + expect(res.body).toHaveProperty('totalCount'); + expect(Array.isArray(res.body.list)).toBe(true); + }); + + it('page, pageSize 쿼리 νŒŒλΌλ―Έν„°κ°€ μ μš©λœλ‹€', async () => { + const res = await request(app).get('/products?page=1&pageSize=1'); + expect(res.status).toBe(200); + expect(res.body.list.length).toBeLessThanOrEqual(1); + }); + + it('keyword 검색이 λ™μž‘ν•œλ‹€', async () => { + const res = await request(app).get('/products?keyword=ν…ŒμŠ€νŠΈ μƒν’ˆ'); + expect(res.status).toBe(200); + expect(res.body.list.length).toBeGreaterThanOrEqual(1); + expect(res.body.list[0].name).toContain('ν…ŒμŠ€νŠΈ μƒν’ˆ'); + }); + + it('μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” keywordλŠ” 빈 λͺ©λ‘μ„ λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).get('/products?keyword=μ ˆλŒ€μ—†λŠ”μƒν’ˆλͺ…xyz123'); + expect(res.status).toBe(200); + expect(res.body.list).toHaveLength(0); + }); + + it('각 μƒν’ˆμ— favoriteCount ν•„λ“œκ°€ ν¬ν•¨λœλ‹€', async () => { + const res = await request(app).get('/products'); + expect(res.status).toBe(200); + res.body.list.forEach((product: any) => { + expect(product).toHaveProperty('favoriteCount'); + }); + }); + + it('orderBy=recent 정렬이 λ™μž‘ν•œλ‹€', async () => { + const res = await request(app).get('/products?orderBy=recent'); + expect(res.status).toBe(200); + expect(res.body).toHaveProperty('list'); + }); + }); + + describe('GET /products/:id', () => { + it('μ‘΄μž¬ν•˜λŠ” μƒν’ˆμ„ μ •μƒμ μœΌλ‘œ λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).get(`/products/${testProductId}`); + expect(res.status).toBe(200); + expect(res.body).toMatchObject({ + id: testProductId, + name: 'ν…ŒμŠ€νŠΈ μƒν’ˆ', + description: 'ν…ŒμŠ€νŠΈ μƒν’ˆ μ„€λͺ…', + price: 10000, + }); + }); + + it('μƒν’ˆμ— favoriteCount ν•„λ“œκ°€ ν¬ν•¨λœλ‹€', async () => { + const res = await request(app).get(`/products/${testProductId}`); + expect(res.status).toBe(200); + expect(res.body).toHaveProperty('favoriteCount'); + expect(res.body.favoriteCount).toBe(0); + }); + + it('λΉ„λ‘œκ·ΈμΈ μƒνƒœμ—μ„œλŠ” isFavoritedκ°€ undefined이닀', async () => { + const res = await request(app).get(`/products/${testProductId}`); + expect(res.status).toBe(200); + expect(res.body.isFavorited).toBeUndefined(); + }); + + it('μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” μƒν’ˆ IDλŠ” 404λ₯Ό λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).get('/products/9999999'); + expect(res.status).toBe(404); + }); + + it('μœ νš¨ν•˜μ§€ μ•Šμ€ ID ν˜•μ‹μ€ 400을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).get('/products/not-a-number'); + expect(res.status).toBe(400); + }); + }); + + describe('GET /products/:id/comments', () => { + it('μƒν’ˆμ˜ λŒ“κΈ€ λͺ©λ‘μ„ μ •μƒμ μœΌλ‘œ λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).get(`/products/${testProductId}/comments`); + expect(res.status).toBe(200); + expect(res.body).toHaveProperty('list'); + expect(Array.isArray(res.body.list)).toBe(true); + expect(res.body.list.length).toBeGreaterThanOrEqual(1); + }); + + it('λŒ“κΈ€μ— content ν•„λ“œκ°€ ν¬ν•¨λœλ‹€', async () => { + const res = await request(app).get(`/products/${testProductId}/comments`); + expect(res.status).toBe(200); + expect(res.body.list[0]).toHaveProperty('content', 'ν…ŒμŠ€νŠΈ λŒ“κΈ€μž…λ‹ˆλ‹€.'); + }); + + it('μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” μƒν’ˆμ˜ λŒ“κΈ€ λͺ©λ‘μ€ 빈 배열을 λ°˜ν™˜ν•œλ‹€', async () => { + const res = await request(app).get('/products/9999999/comments'); + expect(res.status).toBe(404); + }); + }); +}); diff --git a/src/tests/productsService.unit.test.ts b/src/tests/productsService.unit.test.ts new file mode 100644 index 00000000..e2c2d641 --- /dev/null +++ b/src/tests/productsService.unit.test.ts @@ -0,0 +1,234 @@ +jest.mock('../repositories/productsRepository'); +jest.mock('../repositories/favoritesRepository'); +jest.mock('../services/notificationsService'); + +import * as productsService from '../services/productsService'; +import * as productsRepository from '../repositories/productsRepository'; +import * as favoritesRepository from '../repositories/favoritesRepository'; +import * as notificationsService from '../services/notificationsService'; +import NotFoundError from '../lib/errors/NotFoundError'; +import ForbiddenError from '../lib/errors/ForbiddenError'; +import { NotificationType } from '../types/Notification'; + +// Mock νƒ€μž… 단좕어 +const mockProductsRepo = productsRepository as jest.Mocked; +const mockFavoritesRepo = favoritesRepository as jest.Mocked; +const mockNotificationsService = notificationsService as jest.Mocked; + +// 곡톡 ν”½μŠ€μ²˜ +const baseProduct = { + id: 1, + name: 'ν…ŒμŠ€νŠΈ μƒν’ˆ', + description: 'ν…ŒμŠ€νŠΈ μ„€λͺ…', + price: 10000, + tags: ['tag1'], + images: [] as string[], + userId: 1, + createdAt: new Date(), + updatedAt: new Date(), +}; + +const productWithFavorites = { + ...baseProduct, + favorites: undefined, + favoriteCount: 2, + isFavorited: false, +}; + +beforeEach(() => { + jest.clearAllMocks(); // 각 ν…ŒμŠ€νŠΈ 전에 Mock 호좜 기둝 μ΄ˆκΈ°ν™” +}); + +// ── createProduct ──────────────────────────────────── +describe('productsService.createProduct()', () => { + it('repositoryλ₯Ό ν˜ΈμΆœν•˜κ³  favoriteCount:0, isFavorited:falseλ₯Ό λΆ™μ—¬ λ°˜ν™˜ν•œλ‹€', async () => { + mockProductsRepo.createProduct.mockResolvedValue(baseProduct); + + const result = await productsService.createProduct({ + name: 'μƒˆ μƒν’ˆ', + description: 'μ„€λͺ…', + price: 5000, + tags: [], + images: [], + userId: 1, + }); + + expect(mockProductsRepo.createProduct).toHaveBeenCalledTimes(1); + expect(result.favoriteCount).toBe(0); + expect(result.isFavorited).toBe(false); + }); +}); + +// ── getProduct ─────────────────────────────────────── +describe('productsService.getProduct()', () => { + it('μ‘΄μž¬ν•˜λŠ” μƒν’ˆμ„ λ°˜ν™˜ν•œλ‹€', async () => { + mockProductsRepo.getProductWithFavorites.mockResolvedValue(productWithFavorites); + + const result = await productsService.getProduct(1); + + expect(mockProductsRepo.getProductWithFavorites).toHaveBeenCalledWith(1); + expect(result).toEqual(productWithFavorites); + }); + + it('μƒν’ˆμ΄ μ—†μœΌλ©΄ NotFoundErrorλ₯Ό λ˜μ§„λ‹€', async () => { + mockProductsRepo.getProductWithFavorites.mockResolvedValue(null); + + await expect(productsService.getProduct(999)).rejects.toThrow(NotFoundError); + }); +}); + +// ── updateProduct ──────────────────────────────────── +describe('productsService.updateProduct()', () => { + it('μ†Œμœ μžκ°€ μƒν’ˆμ„ μ •μƒμ μœΌλ‘œ μˆ˜μ •ν•œλ‹€', async () => { + mockProductsRepo.getProduct.mockResolvedValue(baseProduct); + mockProductsRepo.updateProductWithFavorites.mockResolvedValue({ + ...productWithFavorites, + name: 'μˆ˜μ •λœ μƒν’ˆ', + price: 15000, + }); + mockFavoritesRepo.getFavoritesByProductId.mockResolvedValue([]); + + const result = await productsService.updateProduct(1, { + name: 'μˆ˜μ •λœ μƒν’ˆ', + price: 15000, + userId: 1, + }); + + expect(result.name).toBe('μˆ˜μ •λœ μƒν’ˆ'); + expect(result.price).toBe(15000); + expect(mockProductsRepo.updateProductWithFavorites).toHaveBeenCalledTimes(1); + }); + + it('μ†Œμœ μžκ°€ μ•„λ‹Œ μœ μ €κ°€ μˆ˜μ •ν•˜λ©΄ ForbiddenErrorλ₯Ό λ˜μ§„λ‹€', async () => { + mockProductsRepo.getProduct.mockResolvedValue(baseProduct); // userId: 1 + + await expect( + productsService.updateProduct(1, { + name: 'νƒˆμ·¨ μˆ˜μ •', + userId: 99, // λ‹€λ₯Έ μœ μ € + }), + ).rejects.toThrow(ForbiddenError); + + // κΆŒν•œ μ—†μœΌλ©΄ updateκ°€ μ ˆλŒ€ ν˜ΈμΆœλ˜μ§€ μ•Šμ•„μ•Ό 함 + expect(mockProductsRepo.updateProductWithFavorites).not.toHaveBeenCalled(); + }); + + it('μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” μƒν’ˆ μˆ˜μ • μ‹œ NotFoundErrorλ₯Ό λ˜μ§„λ‹€', async () => { + mockProductsRepo.getProduct.mockResolvedValue(null); + + await expect( + productsService.updateProduct(999, { name: 'μ—†λŠ” μƒν’ˆ', userId: 1 }), + ).rejects.toThrow(NotFoundError); + }); + + // ── 핡심: 가격 λ³€κ²½ μ•Œλ¦Ό 둜직 ────────────────────── + describe('가격 λ³€κ²½ μ•Œλ¦Ό', () => { + it('가격이 λ³€κ²½λ˜λ©΄ μ°œν•œ μœ μ €λ“€μ—κ²Œ μ•Œλ¦Όμ„ μƒμ„±ν•œλ‹€', async () => { + const favorites = [ + { id: 1, productId: 1, userId: 10, createdAt: new Date(), updatedAt: new Date() }, + { id: 2, productId: 1, userId: 20, createdAt: new Date(), updatedAt: new Date() }, + ]; + + mockProductsRepo.getProduct.mockResolvedValue(baseProduct); // price: 10000 + mockProductsRepo.updateProductWithFavorites.mockResolvedValue({ + ...productWithFavorites, + price: 8000, // 가격 λ³€κ²½ + }); + mockFavoritesRepo.getFavoritesByProductId.mockResolvedValue(favorites); + mockNotificationsService.createNotifications.mockResolvedValue(undefined); + + const spy = jest.spyOn(notificationsService, 'createNotifications'); + + await productsService.updateProduct(1, { price: 8000, userId: 1 }); + + // μ°œν•œ μœ μ € 2λͺ…μ—κ²Œ μ•Œλ¦Ό μƒμ„±λλŠ”μ§€ 검증 + expect(spy).toHaveBeenCalledTimes(1); + const calledWith = spy.mock.calls[0][0]; + expect(calledWith).toHaveLength(2); + expect(calledWith[0]).toMatchObject({ + userId: 10, + type: NotificationType.PRICE_CHANGED, + payload: { productId: 1, price: 8000 }, + }); + }); + + it('가격이 λ³€κ²½λ˜μ§€ μ•ŠμœΌλ©΄ μ•Œλ¦Όμ„ μƒμ„±ν•˜μ§€ μ•ŠλŠ”λ‹€', async () => { + mockProductsRepo.getProduct.mockResolvedValue(baseProduct); // price: 10000 + mockProductsRepo.updateProductWithFavorites.mockResolvedValue({ + ...productWithFavorites, + name: 'μ΄λ¦„λ§Œ λ³€κ²½', + price: 10000, // 가격 동일 + }); + mockFavoritesRepo.getFavoritesByProductId.mockResolvedValue([]); + + const spy = jest.spyOn(notificationsService, 'createNotifications'); + + await productsService.updateProduct(1, { name: 'μ΄λ¦„λ§Œ λ³€κ²½', userId: 1 }); + + expect(spy).not.toHaveBeenCalled(); + }); + + it('μ°œν•œ μœ μ €κ°€ μ—†μœΌλ©΄ μ•Œλ¦Ό 배열이 λΉ„μ–΄μžˆλ‹€', async () => { + mockProductsRepo.getProduct.mockResolvedValue(baseProduct); // price: 10000 + mockProductsRepo.updateProductWithFavorites.mockResolvedValue({ + ...productWithFavorites, + price: 5000, // 가격 λ³€κ²½ + }); + mockFavoritesRepo.getFavoritesByProductId.mockResolvedValue([]); // 찜 μ—†μŒ + + const spy = jest.spyOn(notificationsService, 'createNotifications'); + + await productsService.updateProduct(1, { price: 5000, userId: 1 }); + + const calledWith = spy.mock.calls[0]?.[0] ?? []; + expect(calledWith).toHaveLength(0); + }); + }); +}); + +// ── deleteProduct ──────────────────────────────────── +describe('productsService.deleteProduct()', () => { + it('μ†Œμœ μžκ°€ μƒν’ˆμ„ μ •μƒμ μœΌλ‘œ μ‚­μ œν•œλ‹€', async () => { + mockProductsRepo.getProduct.mockResolvedValue(baseProduct); + mockProductsRepo.deleteProduct.mockResolvedValue(baseProduct); + + await productsService.deleteProduct(1, 1); + + expect(mockProductsRepo.deleteProduct).toHaveBeenCalledWith(1); + }); + + it('μ†Œμœ μžκ°€ μ•„λ‹Œ μœ μ €κ°€ μ‚­μ œν•˜λ©΄ ForbiddenErrorλ₯Ό λ˜μ§„λ‹€', async () => { + mockProductsRepo.getProduct.mockResolvedValue(baseProduct); // userId: 1 + + await expect(productsService.deleteProduct(1, 99)).rejects.toThrow(ForbiddenError); + + expect(mockProductsRepo.deleteProduct).not.toHaveBeenCalled(); + }); + + it('μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” μƒν’ˆ μ‚­μ œ μ‹œ NotFoundErrorλ₯Ό λ˜μ§„λ‹€', async () => { + mockProductsRepo.getProduct.mockResolvedValue(null); + + await expect(productsService.deleteProduct(999, 1)).rejects.toThrow(NotFoundError); + }); +}); + +// ── getProductList ─────────────────────────────────── +describe('productsService.getProductList()', () => { + it('repositoryμ—μ„œ 받은 λͺ©λ‘μ„ κ·ΈλŒ€λ‘œ λ°˜ν™˜ν•œλ‹€', async () => { + const mockResult = { + list: [productWithFavorites], + totalCount: 1, + }; + mockProductsRepo.getProductListWithFavorites.mockResolvedValue(mockResult); + + const result = await productsService.getProductList({ + page: 1, + pageSize: 10, + orderBy: 'recent', + }); + + expect(mockProductsRepo.getProductListWithFavorites).toHaveBeenCalledTimes(1); + expect(result.list).toHaveLength(1); + expect(result.totalCount).toBe(1); + }); +}); diff --git a/src/tests/setup.ts b/src/tests/setup.ts new file mode 100644 index 00000000..9df9fe23 --- /dev/null +++ b/src/tests/setup.ts @@ -0,0 +1,3 @@ +process.env.NODE_ENV = 'test'; +process.env.JWT_ACCESS_TOKEN_SECRET = 'test-access-secret'; +process.env.JWT_REFRESH_TOKEN_SECRET = 'test-refresh-secret'; diff --git a/src/types/Article.ts b/src/types/Article.ts new file mode 100644 index 00000000..815abfcd --- /dev/null +++ b/src/types/Article.ts @@ -0,0 +1,13 @@ +interface Article { + id: number; + title: string; + content: string; + image: string | null; + userId: number; + createdAt: Date; + updatedAt: Date; + likeCount: number; + isLiked?: boolean; +} + +export default Article; diff --git a/src/types/Comment.ts b/src/types/Comment.ts new file mode 100644 index 00000000..d8d65d34 --- /dev/null +++ b/src/types/Comment.ts @@ -0,0 +1,11 @@ +interface Comment { + id: number; + content: string; + userId: number; + articleId: number | null; + productId: number | null; + createdAt: Date; + updatedAt: Date; +} + +export default Comment; diff --git a/src/types/Notification.ts b/src/types/Notification.ts new file mode 100644 index 00000000..50f93d45 --- /dev/null +++ b/src/types/Notification.ts @@ -0,0 +1,29 @@ +export enum NotificationType { + PRICE_CHANGED = 'PRICE_CHANGED', + NEW_COMMENT = 'NEW_COMMENT', +} + +interface BaseNotification { + id: number; + userId: number; + read: boolean; + createdAt: Date; + updatedAt: Date; +} + +interface PriceChangedNotification extends BaseNotification { + type: NotificationType.PRICE_CHANGED; + payload: { + productId: number; + price: number; + }; +} + +interface NewCommentNotification extends BaseNotification { + type: NotificationType.NEW_COMMENT; + payload: { + articleId: number; + }; +} + +export type Notification = PriceChangedNotification | NewCommentNotification; diff --git a/src/types/Product.ts b/src/types/Product.ts new file mode 100644 index 00000000..52c8aa64 --- /dev/null +++ b/src/types/Product.ts @@ -0,0 +1,15 @@ +interface Product { + id: number; + name: string; + description: string; + price: number; + tags: string[]; + images: string[]; + userId: number; + createdAt: Date; + updatedAt: Date; + favoriteCount: number; + isFavorited?: boolean; +} + +export default Product; diff --git a/src/types/User.ts b/src/types/User.ts new file mode 100644 index 00000000..99ebe3a8 --- /dev/null +++ b/src/types/User.ts @@ -0,0 +1,11 @@ +interface User { + id: number; + email: string; + password: string; + nickname: string; + image: string | null; + createdAt: Date; + updatedAt: Date; +} + +export default User; diff --git a/src/types/express.d.ts b/src/types/express.d.ts index ec0b8ca6..1fc9b1ac 100644 --- a/src/types/express.d.ts +++ b/src/types/express.d.ts @@ -1,13 +1,9 @@ -import * as express from 'express'; +import Express from 'express'; declare global { namespace Express { interface Request { - user?: { - id: number; - email: string; - nickname: string; - }; + user: User; } } } diff --git a/src/types/pagination.ts b/src/types/pagination.ts new file mode 100644 index 00000000..05e4b283 --- /dev/null +++ b/src/types/pagination.ts @@ -0,0 +1,21 @@ +export interface PagePaginationParams { + page: number; + pageSize: number; + orderBy?: 'recent' | 'oldest'; + keyword?: string; +} + +export interface PagePaginationResult { + list: T[]; + totalCount: number; +} + +export interface CursorPaginationParams { + cursor: number; + limit: number; +} + +export interface CursorPaginationResult { + list: T[]; + nextCursor: number | null; +} diff --git a/src/utils/cursorUtils.js b/src/utils/cursorUtils.js deleted file mode 100644 index c4e34ecb..00000000 --- a/src/utils/cursorUtils.js +++ /dev/null @@ -1,79 +0,0 @@ -import { BadRequestError } from "../exceptions/errors.js"; - -// 1. μ»€μ„œ 토큰 νŒŒμ‹± ν•¨μˆ˜ -export function parseContinuationToken(cursor) { - if (!cursor) return null; - - try { - // Base64 λ””μ½”λ”© 및 JSON νŒŒμ‹± - const jsonString = Buffer.from(cursor, "base64").toString("utf8"); - const parsed = JSON.parse(jsonString); // ν•„μˆ˜ ν•„λ“œ μœ νš¨μ„± 검사: data와 sortκ°€ μžˆλŠ”μ§€ 확인 - - if (!parsed.data || !parsed.sort) { - throw new Error("Invalid token format"); - } - return parsed; - } catch (e) { - throw new BadRequestError("μœ νš¨ν•˜μ§€ μ•Šμ€ μ»€μ„œ 토큰 ν˜•μ‹μž…λ‹ˆλ‹€."); - } -} - -// 2. μ»€μ„œ 토큰 생성 ν•¨μˆ˜ -export function createContinuationToken(data, sort) { - const payload = JSON.stringify({ data, sort }); - return Buffer.from(payload).toString("base64"); -} - -// 3. μ •λ ¬ 배열을 λ‹¨μˆœν™”λœ ν˜•μ‹μœΌλ‘œ λ³€ν™˜ -export function orderByToSort(orderBy) { - return orderBy.map((item) => { - const key = Object.keys(item)[0]; - return `${key}_${item[key]}`; - }); -} - -// 4. μ»€μ„œ 기반 WHERE 쑰건 생성 (핡심 둜직 κ°œμ„ ) -export function buildCursorWhere(lastItemData, sortKeys) { - // sortKeys: ["created_at_desc", "id_asc"] κΈ°μ€€ - if (sortKeys.length < 2) { - throw new Error( - "μ»€μ„œ νŽ˜μ΄μ§•μ€ μ΅œμ†Œ 2개의 μ •λ ¬ ν‚€(μ£Όμš” ν‚€, 보쑰 ν‚€)κ°€ ν•„μš”ν•©λ‹ˆλ‹€." - ); - } - - const [mainSortKey, secondarySortKey] = sortKeys; - - const mainKey = mainSortKey.split("_")[0]; - const secondaryKey = secondarySortKey.split("_")[0]; - - // 1. μ£Όμš” ν‚€ κ°’ (created_at) λ³€ν™˜ - let lastMainValue = lastItemData[mainKey]; - if (mainKey.includes("created_at") && typeof lastMainValue === "string") { - lastMainValue = new Date(lastMainValue); // λ¬Έμžμ—΄μ„ Date 객체둜 λ³€ν™˜ - } - - // 2. 보쑰 ν‚€ κ°’ (id) λ³€ν™˜ - let lastSecondaryValue = lastItemData[secondaryKey]; - if (secondaryKey === "id" && typeof lastSecondaryValue !== "bigint") { - // BigInt(λ¬Έμžμ—΄) λ˜λŠ” BigInt(숫자)둜 λ³€ν™˜ - lastSecondaryValue = BigInt(lastSecondaryValue); - } - const mainOrder = mainSortKey.split("_")[1]; // desc - const secondaryOrder = secondarySortKey.split("_")[1]; // asc - // 1. μ£Όμš” ν‚€(created_at)κ°€ 이전 값보닀 더 'μ •λ ¬ μˆœμ„œμ— 맞게' μ •λ ¬λ˜λŠ” 쑰건 - const mainOp = mainOrder === "desc" ? "lt" : "gt"; - const mainCondition = { - [mainKey]: { [mainOp]: lastMainValue }, - }; - - // 2. 보쑰 ν‚€(id) 쑰건: μ£Όμš” ν‚€ 값이 같을 경우 보쑰 ν‚€κ°€ λ‹€μŒ λ ˆμ½”λ“œλ₯Ό κ°€λ¦¬μΌœμ•Ό 함 - const secondaryOp = secondaryOrder === "asc" ? "gt" : "lt"; - - const secondaryCondition = { - // μ£Όμš” ν‚€λŠ” 이전 κ°’κ³Ό κ°™μ•„μ•Ό 함 - [mainKey]: lastMainValue, // 보쑰 ν‚€λŠ” μˆœμ„œμ— 맞게 컀야 함 (idλŠ” 보톡 ascμ΄λ―€λ‘œ gt) - [secondaryKey]: { [secondaryOp]: lastSecondaryValue }, - }; // 두 쑰건을 OR둜 λ¬Άμ–΄μ„œ λ°˜ν™˜ν•©λ‹ˆλ‹€. - // { (created_at < 이전값) OR (created_at = 이전값 AND id > 이전값) } - return [{ OR: [mainCondition, secondaryCondition] }]; -} diff --git a/tests/test.http b/tests/test.http index d15a9a7e..92786d26 100644 --- a/tests/test.http +++ b/tests/test.http @@ -24,7 +24,7 @@ Content-Type: application/json } ### Article μ‚­μ œν•˜κΈ° -DELETE http://localhost:3000/articles/2 +DELETE http://localhost:3000/articles/1 ### Article μ’‹μ•„μš” ν…ŒμŠ€νŠΈ POST http://localhost:3000/articles/1/likes @@ -43,7 +43,7 @@ Content-Type: application/json } ### Article의 Comment κ°€μ Έμ˜€κΈ° ν…ŒμŠ€νŠΈ -GET http://localhost:3000/articles/1/comments?limit=200 +GET http://localhost:3000/articles/1/comments?limit=4 ### Comment μ—…λ°μ΄νŠΈ ν…ŒμŠ€νŠΈ PATCH http://localhost:3000/comments/1 @@ -75,22 +75,18 @@ GET http://localhost:3000/products GET http://localhost:3000/products/1 ### Product μ—…λ°μ΄νŠΈν•˜κΈ° ν…ŒμŠ€νŠΈ -PATCH http://localhost:3000/products/2 +PATCH http://localhost:3000/products/1 Content-Type: application/json { - "name": "μ—…λ°μ΄νŠΈλœ ν…ŒμŠ€νŠΈ Product", - "description": "이것은 μ—…λ°μ΄νŠΈλœ ν…ŒμŠ€νŠΈ Product μ„€λͺ…μž…λ‹ˆλ‹€.", - "price": 150, - "tags": ["μ—…λ°μ΄νŠΈ", "Product"], - "images": ["μ—…λ°μ΄νŠΈλœ_image1.png"] + "price": 110 } ### Product μ‚­μ œν•˜κΈ° ν…ŒμŠ€νŠΈ DELETE http://localhost:3000/products/2 ### Product μ’‹μ•„μš” ν…ŒμŠ€νŠΈ -POST http://localhost:3000/products/102/favorites +POST http://localhost:3000/products/1/favorites ### Product μ’‹μ•„μš” μ·¨μ†Œ ν…ŒμŠ€νŠΈ DELETE http://localhost:3000/products/1/favorites @@ -139,9 +135,9 @@ POST http://localhost:3000/auth/register Content-Type: application/json { - - "email": "testuser@example.com", - "nickname": "testuser", + "image": "https://example.com/image.jpg", + "email": "testuser2@example.com", + "nickname": "testuser2", "password": "testpassword" } @@ -186,3 +182,8 @@ GET http://localhost:3000/users/me/products?page=1&pageSize=5 ### λ‚΄ μ’‹μ•„μš” λͺ©λ‘ κ°€μ Έμ˜€κΈ° ν…ŒμŠ€νŠΈ GET http://localhost:3000/users/me/favorites?page=1&pageSize=5 +### λ‚΄ μ•Œλ¦Ό μ‘°νšŒν•˜κΈ° +GET http://localhost:3000/users/me/notifications?limit=5&cursor=2 + +### λ‚΄ μ•Œλ¦Ό 읽기 +PATCH http://localhost:3000/notifications/1/read diff --git a/tests/websocket-test-scenario.http b/tests/websocket-test-scenario.http new file mode 100644 index 00000000..e69de29b diff --git a/tsconfig.json b/tsconfig.json index 256929aa..55fb7ccc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,45 +1,117 @@ { "compilerOptions": { - /* κΈ°λ³Έ 경둜 μ„€μ • */ - "rootDir": "./src", - "outDir": "./dist", - - /* ν™˜κ²½ μ„€μ • */ - "target": "ESNext", - "module": "ESNext", - "moduleResolution": "Bundler", // μ΅œμ‹  λ²ˆλ“€λŸ¬ μŠ€νƒ€μΌ μœ μ§€ - "lib": ["ESNext"], - "types": ["node"], - - /* λͺ¨λ“ˆ 및 μƒν˜Έμš΄μš©μ„± */ - "verbatimModuleSyntax": true, - "isolatedModules": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - - /* μ—„κ²©ν•œ νƒ€μž… 검사 */ - "strict": true, - "noUncheckedIndexedAccess": true, - "exactOptionalPropertyTypes": true, - "skipLibCheck": true, - - /* 기타 μ„€μ • */ - "sourceMap": true, - "declaration": true, - "declarationMap": true, - "allowJs": true, - "checkJs": false, - "moduleDetection": "force", - "jsx": "react-jsx" - }, - - /* ts-node μ‚¬μš© μ‹œ ν™•μž₯자 없이 import κ°€λŠ₯ν•˜κ²Œ ν•˜λŠ” μ„€μ • */ - "ts-node": { - "esm": true, - "experimentalSpecifierResolution": "node", - "transpileOnly": true - }, + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "libReplacement": true, /* Enable lib replacement. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "commonjs" /* Specify what module code is generated. */, + "rootDir": "./src" /* Specify the root folder within your source files. */, + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + "typeRoots": [ + "./src/types", + "./node_modules/@types" + ] /* Specify multiple folders that act like './node_modules/@types'. */, + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "rewriteRelativeImportExtensions": true, /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "noUncheckedSideEffectImports": true, /* Check side effect imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ - "include": ["src/**/*"], - "exclude": ["node_modules"] + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./build" /* Specify an output folder for all emitted files. */, + // "removeComments": true, /* Disable emitting comments. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ + // "erasableSyntaxOnly": true, /* Do not allow runtime constructs that are not part of ECMAScript. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + }, + "exclude": ["node_modules", "jest.config.ts"] }