From fdcf4da4ede641b74267ea4bcbe3e240805dd07e Mon Sep 17 00:00:00 2001 From: Isaac Hunter Date: Sat, 5 Oct 2024 14:40:35 -0400 Subject: [PATCH 01/10] reafactor project to nestjs, setup base project structure --- .eslintrc.js | 55 +- .gitignore | 1 + .prettierrc | 6 +- README.md | 153 +- docs/Project-Structure.md | 24 + jest.config.ts | 219 - nest-cli.json | 8 + package-lock.json | 8524 +++++++---------- package.json | 138 +- packages/config/constants.ts | 13 - packages/config/index.ts | 1 - packages/config/package.json | 12 - packages/lib/index.ts | 9 - packages/lib/kafka.ts | 198 - packages/lib/logger.ts | 34 - packages/lib/package.json | 14 - server/Dockerfile | 29 - server/config/constants.ts | 26 - server/config/database.ts | 17 - server/config/index.ts | 3 - server/config/jest.setup.ts | 27 - server/config/server.ts | 29 - server/controllers/groupController.ts | 96 - server/controllers/index.ts | 2 - server/controllers/userController.ts | 36 - server/docs/swagger.ts | 82 - server/docs/swagger_output.json | 2066 ---- server/events/consumers.ts | 8 - server/events/index.ts | 5 - server/events/producers.ts | 3 - server/index.ts | 32 - server/lib/index.ts | 1 - server/lib/spotify.ts | 116 - server/middleware/authMiddleware.ts | 91 - server/middleware/docsMiddleware.ts | 24 - server/middleware/errorHandler.ts | 25 - server/middleware/index.ts | 2 - server/models/groupModel.ts | 87 - server/models/index.ts | 3 - server/models/spotifyAuthModel.ts | 76 - server/models/tests/userModel.test.ts | 16 - server/models/userModel.ts | 95 - server/routes/groupRoutes.ts | 21 - server/routes/index.ts | 32 - server/routes/router.ts | 19 - server/routes/spotifyRoutes.ts | 12 - server/routes/userRoutes.ts | 26 - server/services/authService.ts | 95 - server/services/groupService.ts | 66 - server/services/index.ts | 3 - server/services/spotifyService.ts | 117 - server/services/tests/groupService.test.ts | 86 - server/types/country.d.ts | 256 - server/types/index.d.ts | 12 - server/types/spotify.d.ts | 108 - server/utils/apis/index.ts | 3 - server/utils/apis/viewsets.ts | 94 - server/utils/apis/wrappers.ts | 36 - server/utils/exceptions/generalExceptions.ts | 27 - server/utils/exceptions/index.ts | 1 - server/utils/generator.ts | 11 - server/utils/index.ts | 3 - server/utils/responses/codes.ts | 21 - server/utils/responses/getResJson.ts | 5 - server/utils/responses/index.ts | 3 - server/utils/responses/responses.test.ts | 376 - server/utils/responses/responses.ts | 313 - server/views/baseViews.ts | 56 - server/views/groupViews.ts | 194 - server/views/spotifyAuthViews.ts | 61 - server/views/tests/baseViews.test.ts | 26 - server/views/tests/userViews.test.ts | 187 - server/views/userViews.ts | 208 - src/app.controller.spec.ts | 22 + src/app.controller.ts | 12 + src/app.module.ts | 12 + src/app.service.ts | 8 + src/main.ts | 8 + .../spotify/schemas/spotify-auth.schema.ts | 0 src/spotify/spotify.controller.ts | 4 + src/spotify/spotify.module.ts | 9 + src/spotify/spotify.service.ts | 4 + src/spotify/tests/spotify.controller.spec.ts | 18 + src/spotify/tests/spotify.service.spec.ts | 18 + .../tests/track-queue.service.spec.ts | 18 + .../track-queue}/tests/trackQueue.test.ts | 3 +- src/track-queue/track-queue.module.ts | 7 + .../track-queue/track-queue.service.ts | 7 +- test/app.e2e-spec.ts | 24 + test/jest-e2e.json | 9 + tsconfig.build.json | 4 + tsconfig.json | 156 +- websocket/Dockerfile | 29 - websocket/config/constants.ts | 14 - websocket/config/index.ts | 10 - websocket/config/router.ts | 12 - websocket/config/server.ts | 28 - websocket/controllers/controller.ts | 13 - websocket/controllers/index.ts | 13 - websocket/events/consumers.ts | 14 - websocket/events/index.ts | 6 - websocket/events/producers.ts | 7 - websocket/events/socketHandlers.ts | 10 - websocket/index.ts | 29 - websocket/lib/index.ts | 8 - websocket/lib/socket-io.ts | 22 - websocket/middleware/authMiddleware.ts | 16 - websocket/middleware/index.ts | 4 - websocket/types/index.ts | 23 - .../utils/exceptions/generalExceptions.ts | 6 - websocket/utils/exceptions/index.ts | 1 - websocket/utils/index.ts | 2 - websocket/utils/utils.ts | 1 - 113 files changed, 3908 insertions(+), 11587 deletions(-) create mode 100644 docs/Project-Structure.md delete mode 100644 jest.config.ts create mode 100644 nest-cli.json delete mode 100644 packages/config/constants.ts delete mode 100644 packages/config/index.ts delete mode 100644 packages/config/package.json delete mode 100644 packages/lib/index.ts delete mode 100644 packages/lib/kafka.ts delete mode 100644 packages/lib/logger.ts delete mode 100644 packages/lib/package.json delete mode 100644 server/Dockerfile delete mode 100644 server/config/constants.ts delete mode 100644 server/config/database.ts delete mode 100644 server/config/index.ts delete mode 100644 server/config/jest.setup.ts delete mode 100644 server/config/server.ts delete mode 100644 server/controllers/groupController.ts delete mode 100644 server/controllers/index.ts delete mode 100644 server/controllers/userController.ts delete mode 100644 server/docs/swagger.ts delete mode 100644 server/docs/swagger_output.json delete mode 100644 server/events/consumers.ts delete mode 100644 server/events/index.ts delete mode 100644 server/events/producers.ts delete mode 100644 server/index.ts delete mode 100644 server/lib/index.ts delete mode 100644 server/lib/spotify.ts delete mode 100644 server/middleware/authMiddleware.ts delete mode 100644 server/middleware/docsMiddleware.ts delete mode 100644 server/middleware/errorHandler.ts delete mode 100644 server/middleware/index.ts delete mode 100644 server/models/groupModel.ts delete mode 100644 server/models/index.ts delete mode 100644 server/models/spotifyAuthModel.ts delete mode 100644 server/models/tests/userModel.test.ts delete mode 100644 server/models/userModel.ts delete mode 100644 server/routes/groupRoutes.ts delete mode 100644 server/routes/index.ts delete mode 100644 server/routes/router.ts delete mode 100644 server/routes/spotifyRoutes.ts delete mode 100644 server/routes/userRoutes.ts delete mode 100644 server/services/authService.ts delete mode 100644 server/services/groupService.ts delete mode 100644 server/services/index.ts delete mode 100644 server/services/spotifyService.ts delete mode 100644 server/services/tests/groupService.test.ts delete mode 100644 server/types/country.d.ts delete mode 100644 server/types/index.d.ts delete mode 100644 server/types/spotify.d.ts delete mode 100644 server/utils/apis/index.ts delete mode 100644 server/utils/apis/viewsets.ts delete mode 100644 server/utils/apis/wrappers.ts delete mode 100644 server/utils/exceptions/generalExceptions.ts delete mode 100644 server/utils/exceptions/index.ts delete mode 100644 server/utils/generator.ts delete mode 100644 server/utils/index.ts delete mode 100644 server/utils/responses/codes.ts delete mode 100644 server/utils/responses/getResJson.ts delete mode 100644 server/utils/responses/index.ts delete mode 100644 server/utils/responses/responses.test.ts delete mode 100644 server/utils/responses/responses.ts delete mode 100644 server/views/baseViews.ts delete mode 100644 server/views/groupViews.ts delete mode 100644 server/views/spotifyAuthViews.ts delete mode 100644 server/views/tests/baseViews.test.ts delete mode 100644 server/views/tests/userViews.test.ts delete mode 100644 server/views/userViews.ts create mode 100644 src/app.controller.spec.ts create mode 100644 src/app.controller.ts create mode 100644 src/app.module.ts create mode 100644 src/app.service.ts create mode 100644 src/main.ts rename server/models/utils/testGroup.ts => src/spotify/schemas/spotify-auth.schema.ts (100%) create mode 100644 src/spotify/spotify.controller.ts create mode 100644 src/spotify/spotify.module.ts create mode 100644 src/spotify/spotify.service.ts create mode 100644 src/spotify/tests/spotify.controller.spec.ts create mode 100644 src/spotify/tests/spotify.service.spec.ts create mode 100644 src/track-queue/tests/track-queue.service.spec.ts rename {server/services => src/track-queue}/tests/trackQueue.test.ts (96%) create mode 100644 src/track-queue/track-queue.module.ts rename server/services/trackQueue.ts => src/track-queue/track-queue.service.ts (94%) create mode 100644 test/app.e2e-spec.ts create mode 100644 test/jest-e2e.json create mode 100644 tsconfig.build.json delete mode 100644 websocket/Dockerfile delete mode 100644 websocket/config/constants.ts delete mode 100644 websocket/config/index.ts delete mode 100644 websocket/config/router.ts delete mode 100644 websocket/config/server.ts delete mode 100644 websocket/controllers/controller.ts delete mode 100644 websocket/controllers/index.ts delete mode 100644 websocket/events/consumers.ts delete mode 100644 websocket/events/index.ts delete mode 100644 websocket/events/producers.ts delete mode 100644 websocket/events/socketHandlers.ts delete mode 100644 websocket/index.ts delete mode 100644 websocket/lib/index.ts delete mode 100644 websocket/lib/socket-io.ts delete mode 100644 websocket/middleware/authMiddleware.ts delete mode 100644 websocket/middleware/index.ts delete mode 100644 websocket/types/index.ts delete mode 100644 websocket/utils/exceptions/generalExceptions.ts delete mode 100644 websocket/utils/exceptions/index.ts delete mode 100644 websocket/utils/index.ts delete mode 100644 websocket/utils/utils.ts diff --git a/.eslintrc.js b/.eslintrc.js index af5c277..259de13 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,44 +1,25 @@ module.exports = { - root: true, parser: '@typescript-eslint/parser', - env: { - browser: true, - es2021: true + parserOptions: { + project: 'tsconfig.json', + tsconfigRootDir: __dirname, + sourceType: 'module', }, - extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], - overrides: [ - { - env: { - node: true - }, - files: ['.eslintrc.{js,cjs}'], - parserOptions: { - sourceType: 'script' - } - } + plugins: ['@typescript-eslint/eslint-plugin'], + extends: [ + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', ], - parserOptions: { - ecmaVersion: 'latest', - sourceType: 'module' + root: true, + env: { + node: true, + jest: true, }, - plugins: ['@typescript-eslint', 'prefer-arrow-functions', 'prettier'], + ignorePatterns: ['.eslintrc.js'], rules: { - '@typescript-eslint/consistent-type-imports': 'warn', - '@typescript-eslint/no-unused-vars': 'off', - '@typescript-eslint/no-redeclare': 'off', - '@typescript-eslint/space-before-function-paren': 'off', + '@typescript-eslint/interface-name-prefix': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/no-explicit-any': 'off', - 'prefer-const': 'warn', - 'prettier/prettier': 'warn', - 'prefer-arrow-functions/prefer-arrow-functions': [ - 'warn', - { - allowNamedFunctions: false, - classPropertiesAllowed: false, - disallowPrototype: false, - returnStyle: 'unchanged', - singleReturnOnly: false - } - ] - } -} + }, +}; diff --git a/.gitignore b/.gitignore index 656d91d..c86f3aa 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ utils-old/ coverage/ _depricated/ _deprecated/ +_deprecated_*/ ### Terraform ### # Local .terraform directories diff --git a/.prettierrc b/.prettierrc index 1b4c854..dcb7279 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,6 +1,4 @@ { - "semi": false, - "trailingComma": "none", "singleQuote": true, - "printWidth": 100 -} + "trailingComma": "all" +} \ No newline at end of file diff --git a/README.md b/README.md index d2c7801..c997880 100644 --- a/README.md +++ b/README.md @@ -1,118 +1,85 @@ -# OSC Jukebox Server - -[![Unit Testing](https://github.com/ufosc/Jukebox-Server/actions/workflows/test-api.yml/badge.svg)](https://github.com/ufosc/Jukebox-Server/actions/workflows/test-api.yml) -[![Code Linting](https://github.com/ufosc/Jukebox-Server/actions/workflows/code-linting.yml/badge.svg)](https://github.com/ufosc/Jukebox-Server/actions/workflows/code-linting.yml) - -Welcome to the Jukebox Server! To get the server running, you only need Node.js installed on your computer. If you want to contribute to the DevOps portion, you will also need docker and docker-compose installed. - -## Table of Contents - -- [Table of Contents](#table-of-contents) -- [Description](#description) -- [Project Install One-Liner](#project-install-one-liner) -- [Getting started](#getting-started) -- [Technology Stack (with documentation link)](#technology-stack-with-documentation-link) -- [Workflow](#workflow) -- [Testing](#testing) +

+ Nest Logo +

+ +[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 +[circleci-url]: https://circleci.com/gh/nestjs/nest + +

A progressive Node.js framework for building efficient and scalable server-side applications.

+

+NPM Version +Package License +NPM Downloads +CircleCI +Coverage +Discord +Backers on Open Collective +Sponsors on Open Collective + Donate us + Support us + Follow us on Twitter +

+ ## Description -The Jukebox Server is a Node.js-based server that connects with Spotify's API, allowing users to manage and potentially play music and function like a Jukebox. Required software includes Docker, Docker Compose, and Git. -This project has two Github pages this is designated for the Backend Development. If you are interested in the Frontend Development please link here. - -## Project Install One-Liner - -Copy and paste the following command into your terminal to clone the repository and get the server up and running. +[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. -This assumes you have **Docker**, **Docker Compose**, and **Git** installed. +## Project setup -```sh -git clone git@github.com:ufosc/Jukebox-Server.git && cd Jukebox-Server && cp sample.env .env && docker-compose up --build +```bash +$ npm install ``` -## Getting started +## Compile and run the project -Follow these steps to download the project locally and get it running with nodemon. - -1. Clone the repository: - -```sh -git clone https://github.com/ufosc/Jukebox-Server.git -cd Jukebox-Server -``` - -2. Set up the environment: - -```sh -cp sample.env .env -``` +```bash +# development +$ npm run start -3. Build and run the Docker containers: +# watch mode +$ npm run start:dev -```sh -docker-compose build -docker-compose up +# production mode +$ npm run start:prod ``` -We use Docker Compose to manage the server and its dependencies, including databases and other containers. While you can run the server using `npm run dev`, Docker Compose provides more reliability. +## Run tests -Once the server is running, visit to authenticate with Spotify. +```bash +# unit tests +$ npm run test -## Technology Stack (with documentation link) +# e2e tests +$ npm run test:e2e -| Use | Tech | -| ---------------------- | --------------------------------------------------------------------------------------- | -| Language | [TypeScript](https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.html) | -| Backend Runtime | [Node.js](https://nodejs.dev/en/learn/) | -| Backend Framework | [Express.js](https://expressjs.com/en/4x/api.html#express) | -| SQL Database | [Postgres](https://node-postgres.com/) | -| Unit Tests | [Jest](https://jestjs.io/docs/getting-started) | -| Auto Documentation | [Swagger](https://swagger.io/docs/specification/about/) | -| Infrastructure as Code | [Terraform](https://developer.hashicorp.com/terraform/docs) | -| Hosting | [AWS](https://docs.aws.amazon.com/) | -| Containerization | [Docker](https://docs.docker.com/get-started/) | - -## Workflow - -1. Start by reviewing the [issues list](https://github.com/ufosc/Jukebox-Server/issues) and pick a task or propose a new feature. - -2. Clone the main branch onto your local system: - -```sh -git clone git@github.com:ufosc/Jukebox-Server.git && cd Jukebox-Server && cp sample.env .env && docker-compose up --build -``` - -3. Create a feature branch: - -```sh -git checkout -b feature/[insert name here] +# test coverage +$ npm run test:cov ``` -_Ensure your branch focuses on a specific, fully working feature e.g. documentation, implementing new authentication logic. [Read more about feature branch workflow here](https://craftquest.io/guides/git/git-workflows/feature-branch-workflow)._ - -Before submitting a pull request, write at least three unit tests. If possible, follow the Test-Driven Development (TDD) paradigm, which involves writing tests before coding the feature itself. [Learn more about TDD here](https://www.browserstack.com/guide/what-is-test-driven-development). - -4. Push your feature branch and submit a pull request (PR). Your PR will be reviewed and tested by a maintainer before merging. +## Resources -## Testing +Check out a few resources that may come in handy when working with NestJS: -We use Jest for unit testing. **At least 3 unit tests** must accompany any new feature. +- Visit the [NestJS Documentation](https://docs.nestjs.com) to learn more about the framework. +- For questions and support, please visit our [Discord channel](https://discord.gg/G7Qnnhy). +- To dive deeper and get more hands-on experience, check out our official video [courses](https://courses.nestjs.com/). +- Visualize your application graph and interact with the NestJS application in real-time using [NestJS Devtools](https://devtools.nestjs.com). +- Need help with your project (part-time to full-time)? Check out our official [enterprise support](https://enterprise.nestjs.com). +- To stay in the loop and get updates, follow us on [X](https://x.com/nestframework) and [LinkedIn](https://linkedin.com/company/nestjs). +- Looking for a job, or have a job to offer? Check out our official [Jobs board](https://jobs.nestjs.com). -Example of Jest Formatting: +## Support -``` -const converter = require('../app/converter'); +Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). -// Example test -test('Jukebox Unit Test', () => { - expect(converter.convertPlaylist('playlist-id')).toBe('expected-output'); -}); -``` +## Stay in touch -To run the tests, use the following command. This will execute Jest, which will look for test files inside the `/test` directory: +- Author - [Kamil Myśliwiec](https://twitter.com/kammysliwiec) +- Website - [https://nestjs.com](https://nestjs.com/) +- Twitter - [@nestframework](https://twitter.com/nestframework) -```sh -docker-compose run --rm api sh -c "npm test" -``` +## License -When writing new tests, write them inside this `/test` directory. +Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE). diff --git a/docs/Project-Structure.md b/docs/Project-Structure.md new file mode 100644 index 0000000..905b220 --- /dev/null +++ b/docs/Project-Structure.md @@ -0,0 +1,24 @@ +# Project Structure + +```txt +jukebox-server/ +|-- proxy/ +|-- deploy/ +|-- src + |-- [module]/ + | |-- [module].module.ts <-- Module root + | |-- [module].controller.ts <-- Api routes defined, no business logic + | |-- [module].service.ts <-- Business logic + | |-- [module].gateway.ts <-- Websocket input/output router, no business logic + | |-- tests/ + | | |-- [module].[type].spec.ts + | |-- dto/ + | | |-- [model].dto.ts <-- Api input/output object structures + | |-- schemas/ + | | |-- [model].schema.ts <-- Mongoose schemas + |-- spotify/ + | |-- * + |-- track-queue/ + | |-- * + +``` diff --git a/jest.config.ts b/jest.config.ts deleted file mode 100644 index cc3892d..0000000 --- a/jest.config.ts +++ /dev/null @@ -1,219 +0,0 @@ -/** - * For a detailed explanation regarding each configuration property, visit: - * https://jestjs.io/docs/configuration - */ -// import type {Config} from 'jest'; -// import type { JestConfigWithTsJest } from "ts-jest"; -// const { pathsToModuleNameMapper } = require("ts-jest/utils"); - -const SRC_PATH = '/server' - -const config = { - preset: 'ts-jest', - // All imported modules in your tests should be mocked automatically - // automock: false, - - // Stop running tests after `n` failures - // bail: 0, - - // The directory where Jest should store its cached dependency information - // cacheDirectory: "/private/var/folders/nz/8lnj6q2d61n9_rxng8hgfj300000gn/T/jest_dx", - - // Automatically clear mock calls, instances, contexts and results before every test - clearMocks: true, - - // Indicates whether the coverage information should be collected while executing the test - collectCoverage: true, - - // An array of glob patterns indicating a set of files for which coverage information should be collected - collectCoverageFrom: [ - './**/*.ts', - // 'server/controllers/**', - // 'server/models/**', - // 'server/middleware/**' - ], - - // The directory where Jest should output its coverage files - // coverageDirectory: "coverage", - - // An array of regexp pattern strings used to skip coverage collection - coveragePathIgnorePatterns: ['/node_modules/', '/build/', 'docs/', 'index.ts', 'config/', 'lib/', 'types/', '_deprecated/'], - - // Indicates which provider should be used to instrument code for coverage - coverageProvider: 'v8', - - // A list of reporter names that Jest uses when writing coverage reports - // coverageReporters: [ - // "json", - // "text", - // "lcov", - // "clover" - // ], - - // An object that configures minimum threshold enforcement for coverage results - // coverageThreshold: undefined, - - // A path to a custom dependency extractor - // dependencyExtractor: undefined, - - // Make calling deprecated APIs throw helpful error messages - // errorOnDeprecated: false, - - // The default configuration for fake timers - // fakeTimers: { - // "enableGlobally": false - // }, - - // Force coverage collection from ignored files using an array of glob patterns - // forceCoverageMatch: [], - - // A path to a module which exports an async function that is triggered once before all test suites - // globalSetup: undefined, - - // A path to a module which exports an async function that is triggered once after all test suites - // globalTeardown: undefined, - - // A set of global variables that need to be available in all test environments - // globals: {}, - - // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. - // maxWorkers: "50%", - - // An array of directory names to be searched recursively up from the requiring module's location - moduleDirectories: [ - 'node_modules', - 'server' - // "./" - ], - - // An array of file extensions your modules use - // moduleFileExtensions: [ - // "js", - // "mjs", - // "cjs", - // "jsx", - // "ts", - // "tsx", - // "json", - // "node" - // ], - - // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module - // moduleNameMapper: { - // "src/(.*)": ["/src/$1", "node_modules/"], - // // "(.*)": ["/node_modules/$1"] - // }, - - // this enables us to use tsconfig-paths with jest - modulePaths: ['.'], - // moduleNameMapper: compilerOptions.paths, - // moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths), - - // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader - // modulePathIgnorePatterns: [], - - // Activates notifications for test results - // notify: false, - - // An enum that specifies notification mode. Requires { notify: true } - // notifyMode: "failure-change", - - // A preset that is used as a base for Jest's configuration - // preset: undefined, - - // Run tests from one or more projects - // projects: undefined, - - // Use this configuration option to add custom reporters to Jest - // reporters: undefined, - - // Automatically reset mock state before every test - // resetMocks: false, - - // Reset the module registry before running each individual test - resetModules: true, - - // A path to a custom resolver - // resolver: undefined, - - // Automatically restore mock state and implementation before every test - // restoreMocks: false, - - // The root directory that Jest should scan for tests and modules within - rootDir: './', - - // A list of paths to directories that Jest should use to search for files in - roots: [ - './server', - SRC_PATH - // "./src/*" - ], - - // Allows you to use a custom runner instead of Jest's default test runner - // runner: "jest-runner", - - // The paths to modules that run some code to configure or set up the testing environment before each test - // setupFiles: [], - - // A list of paths to modules that run some code to configure or set up the testing framework before each test - setupFilesAfterEnv: ['./server/config/jest.setup.ts'] - - // The number of seconds after which a test is considered as slow and reported as such in the results. - // slowTestThreshold: 5, - - // A list of paths to snapshot serializer modules Jest should use for snapshot testing - // snapshotSerializers: [], - - // The test environment that will be used for testing - // testEnvironment: "jest-environment-node", - - // Options that will be passed to the testEnvironment - // testEnvironmentOptions: {}, - - // Adds a location field to test results - // testLocationInResults: false, - - // The glob patterns Jest uses to detect test files - // testMatch: [ - // "**/__tests__/**/*.[jt]s?(x)", - // "**/?(*.)+(spec|test).[tj]s?(x)" - // ], - - // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped - // testPathIgnorePatterns: [ - // "/node_modules/" - // ], - - // The regexp pattern or array of patterns that Jest uses to detect test files - // testRegex: [], - - // This option allows the use of a custom results processor - // testResultsProcessor: undefined, - - // This option allows use of a custom test runner - // testRunner: "jest-circus/runner", - - // A map from regular expressions to paths to transformers - // transform: undefined, - - // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation - // transformIgnorePatterns: [ - // "/node_modules/", - // "\\.pnp\\.[^\\/]+$" - // ], - - // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them - // unmockedModulePathPatterns: undefined, - - // Indicates whether each individual test should be reported during the run - // verbose: undefined, - - // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode - // watchPathIgnorePatterns: [], - - // Whether to use watchman for file crawling - // watchman: true, -} - -// export default config; -module.exports = config diff --git a/nest-cli.json b/nest-cli.json new file mode 100644 index 0000000..f9aa683 --- /dev/null +++ b/nest-cli.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/nest-cli", + "collection": "@nestjs/schematics", + "sourceRoot": "src", + "compilerOptions": { + "deleteOutDir": true + } +} diff --git a/package-lock.json b/package-lock.json index 72439b8..e8813e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,75 +1,47 @@ { - "name": "spotify_app", - "version": "1.0.0", + "name": "jukebox-server", + "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "spotify_app", - "version": "1.0.0", - "license": "ISC", - "workspaces": [ - "packages/a", - "packages/lib", - "packages/config" - ], - "dependencies": { - "@jukebox/config": "^1.0.0", - "@jukebox/lib": "^1.0.0", + "name": "jukebox-server", + "version": "0.0.1", + "license": "UNLICENSED", + "dependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/mongoose": "^10.0.10", + "@nestjs/platform-express": "^10.0.0", + "@nestjs/platform-socket.io": "^10.4.4", + "@nestjs/websockets": "^10.4.4", "@spotify/web-api-ts-sdk": "^1.2.0", - "axios": "^1.6.7", - "bcrypt": "^5.1.1", - "body-parser": "^1.20.2", - "cookie-parser": "^1.4.6", - "cors": "^2.8.5", - "dotenv": "^16.0.3", - "express": "^4.18.2", - "jsonwebtoken": "^9.0.2", - "kafkajs": "^2.2.4", - "module-alias": "^2.2.3", - "mongoose": "^7.5.2", - "morgan": "^1.10.0", - "multer": "^1.4.5-lts.1", - "socket.io": "^4.7.5", - "url": "^0.11.3", - "winston": "^3.10.0" + "mongoose": "^8.7.0", + "reflect-metadata": "^0.2.0", + "rxjs": "^7.8.1" }, "devDependencies": { - "@types/bcrypt": "^5.0.2", - "@types/cookie-parser": "^1.4.4", - "@types/cors": "^2.8.16", + "@nestjs/cli": "^10.0.0", + "@nestjs/schematics": "^10.0.0", + "@nestjs/testing": "^10.0.0", "@types/express": "^4.17.17", - "@types/jest": "^29.5.12", - "@types/jsonwebtoken": "^9.0.5", - "@types/module-alias": "^2.0.4", - "@types/morgan": "^1.9.9", - "@types/multer": "^1.4.12", - "@types/request": "^2.48.10", - "@types/swagger-ui-express": "^4.1.4", - "@typescript-eslint/eslint-plugin": "^6.19.1", - "@typescript-eslint/parser": "^6.19.1", - "esbuild": "^0.20.0", - "eslint": "^8.56.0", - "eslint-config-prettier": "^9.1.0", - "eslint-config-standard-with-typescript": "^43.0.1", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-n": "^16.6.2", - "eslint-plugin-prefer-arrow-functions": "^3.2.4", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-promise": "^6.1.1", - "jest": "^29.7.0", - "node-mocks-http": "^1.13.0", - "nodemon": "^3.1.4", - "swagger-autogen": "^2.23.1", - "swagger-jsdoc": "^6.2.8", - "swagger-ui-express": "^5.0.0", - "ts-jest": "^29.1.1", + "@types/jest": "^29.5.2", + "@types/node": "^20.3.1", + "@types/supertest": "^6.0.0", + "@typescript-eslint/eslint-plugin": "^8.0.0", + "@typescript-eslint/parser": "^8.0.0", + "eslint": "^8.42.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.0", + "jest": "^29.5.0", + "prettier": "^3.0.0", + "source-map-support": "^0.5.21", + "supertest": "^7.0.0", + "ts-jest": "^29.1.0", + "ts-loader": "^9.4.3", "ts-node": "^10.9.1", - "ts-node-dev": "^2.0.0", - "tsc-alias": "^1.8.8", "tsconfig-paths": "^4.2.0", - "tsx": "^4.7.0", - "typescript": "^5.5.4" + "typescript": "^5.1.3" } }, "node_modules/@ampproject/remapping": { @@ -86,62 +58,154 @@ "node": ">=6.0.0" } }, - "node_modules/@apidevtools/json-schema-ref-parser": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", - "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==", + "node_modules/@angular-devkit/core": { + "version": "17.3.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.8.tgz", + "integrity": "sha512-Q8q0voCGudbdCgJ7lXdnyaxKHbNQBARH68zPQV72WT8NWy+Gw/tys870i6L58NWbBaCJEUcIj/kb6KoakSRu+Q==", "dev": true, "license": "MIT", "dependencies": { - "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.6", - "call-me-maybe": "^1.0.1", - "js-yaml": "^4.1.0" + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.1", + "picomatch": "4.0.1", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } } }, - "node_modules/@apidevtools/openapi-schemas": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", - "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", + "node_modules/@angular-devkit/schematics": { + "version": "17.3.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.8.tgz", + "integrity": "sha512-QRVEYpIfgkprNHc916JlPuNbLzOgrm9DZalHasnLUz4P6g7pR21olb8YCyM2OTJjombNhya9ZpckcADU5Qyvlg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "17.3.8", + "jsonc-parser": "3.2.1", + "magic-string": "0.30.8", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/schematics-cli": { + "version": "17.3.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-17.3.8.tgz", + "integrity": "sha512-TjmiwWJarX7oqvNiRAroQ5/LeKUatxBOCNEuKXO/PV8e7pn/Hr/BqfFm+UcYrQoFdZplmtNAfqmbqgVziKvCpA==", "dev": true, "license": "MIT", + "dependencies": { + "@angular-devkit/core": "17.3.8", + "@angular-devkit/schematics": "17.3.8", + "ansi-colors": "4.1.3", + "inquirer": "9.2.15", + "symbol-observable": "4.0.0", + "yargs-parser": "21.1.1" + }, + "bin": { + "schematics": "bin/schematics.js" + }, "engines": { - "node": ">=10" + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" } }, - "node_modules/@apidevtools/swagger-methods": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", - "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==", + "node_modules/@angular-devkit/schematics-cli/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@angular-devkit/schematics-cli/node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 12" + } }, - "node_modules/@apidevtools/swagger-parser": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz", - "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==", + "node_modules/@angular-devkit/schematics-cli/node_modules/inquirer": { + "version": "9.2.15", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.15.tgz", + "integrity": "sha512-vI2w4zl/mDluHt9YEQ/543VTCwPKWiHzKtm9dM2V0NdFcqEexDAjUHzO1oA60HRNaVifGXXM1tRRNluLVHa0Kg==", "dev": true, "license": "MIT", "dependencies": { - "@apidevtools/json-schema-ref-parser": "^9.0.6", - "@apidevtools/openapi-schemas": "^2.0.4", - "@apidevtools/swagger-methods": "^3.0.2", - "@jsdevtools/ono": "^7.1.3", - "call-me-maybe": "^1.0.1", - "z-schema": "^5.0.1" + "@ljharb/through": "^2.3.12", + "ansi-escapes": "^4.3.2", + "chalk": "^5.3.0", + "cli-cursor": "^3.1.0", + "cli-width": "^4.1.0", + "external-editor": "^3.1.0", + "figures": "^3.2.0", + "lodash": "^4.17.21", + "mute-stream": "1.0.0", + "ora": "^5.4.1", + "run-async": "^3.0.0", + "rxjs": "^7.8.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0" }, - "peerDependencies": { - "openapi-types": ">=7" + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular-devkit/schematics-cli/node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@angular-devkit/schematics-cli/node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" } }, "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", + "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.7", + "@babel/highlight": "^7.25.7", "picocolors": "^1.0.0" }, "engines": { @@ -149,9 +213,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", - "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.7.tgz", + "integrity": "sha512-9ickoLz+hcXCeh7jrcin+/SLWm+GkxE2kTvoYyp38p4WkdFXfQJxDFGWp/YHjiKLPx06z2A7W8XKuqbReXDzsw==", "dev": true, "license": "MIT", "engines": { @@ -159,22 +223,22 @@ } }, "node_modules/@babel/core": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", - "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.7.tgz", + "integrity": "sha512-yJ474Zv3cwiSOO9nXJuqzvwEeM+chDuQ8GJirw+pZ91sCGCyOZ3dJkVE09fTV0VEVzXyLWhh3G/AolYTPX7Mow==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-module-transforms": "^7.25.2", - "@babel/helpers": "^7.25.0", - "@babel/parser": "^7.25.0", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.2", - "@babel/types": "^7.25.2", + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helpers": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/template": "^7.25.7", + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -200,31 +264,31 @@ } }, "node_modules/@babel/generator": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", - "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz", + "integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.6", + "@babel/types": "^7.25.7", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", - "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz", + "integrity": "sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.2", - "@babel/helper-validator-option": "^7.24.8", - "browserslist": "^4.23.1", + "@babel/compat-data": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -243,30 +307,30 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz", + "integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", - "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz", + "integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.2" + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-simple-access": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -276,9 +340,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz", + "integrity": "sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==", "dev": true, "license": "MIT", "engines": { @@ -286,23 +350,23 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz", + "integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", + "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", "dev": true, "license": "MIT", "engines": { @@ -310,9 +374,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", "dev": true, "license": "MIT", "engines": { @@ -320,9 +384,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz", + "integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==", "dev": true, "license": "MIT", "engines": { @@ -330,27 +394,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", - "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", + "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6" + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", + "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", + "@babel/helper-validator-identifier": "^7.25.7", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" @@ -438,13 +502,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", - "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.7.tgz", + "integrity": "sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.6" + "@babel/types": "^7.25.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -509,13 +573,13 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz", - "integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.7.tgz", + "integrity": "sha512-AqVo+dguCgmpi/3mYBdu9lkngOBlQ2w2vnNpa6gfiCxQZLzV4ZbhsXitJ2Yblkoe1VQwtHSaNmIaGll/26YWRw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -551,13 +615,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", - "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.7.tgz", + "integrity": "sha512-ruZOnKO+ajVL/MVx+PwNBPOkrnXTXoWMtte1MBpegfCArhqOe3Bj52avVj1huLLxNKYKXYaSxZ2F+woK1ekXfw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -677,13 +741,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz", - "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.7.tgz", + "integrity": "sha512-rR+5FDjpCHqqZN2bzZm18bVYGaejGq5ZkpVCJLXor/+zlSrSoc4KWcHI0URVWjl/68Dyr1uwZUz/1njycEAv9g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -693,32 +757,32 @@ } }, "node_modules/@babel/template": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", - "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", + "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.25.0", - "@babel/types": "^7.25.0" + "@babel/code-frame": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", - "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.7.tgz", + "integrity": "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.6", - "@babel/parser": "^7.25.6", - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6", + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -737,14 +801,14 @@ } }, "node_modules/@babel/types": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", - "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.7.tgz", + "integrity": "sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", + "@babel/helper-string-parser": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -759,10 +823,12 @@ "license": "MIT" }, "node_modules/@colors/colors": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", - "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, "license": "MIT", + "optional": true, "engines": { "node": ">=0.1.90" } @@ -791,526 +857,584 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@dabh/diagnostics": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", - "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, "license": "MIT", "dependencies": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0" + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", - "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", - "cpu": [ - "ppc64" - ], + "node_modules/@eslint-community/regexpp": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "aix" - ], "engines": { - "node": ">=12" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", - "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", - "cpu": [ - "arm" - ], + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, "engines": { - "node": ">=12" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", - "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", - "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", - "cpu": [ - "x64" - ], + "node_modules/@eslint/eslintrc/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==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=12" + "node": "*" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", - "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": ">=12" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", - "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", - "cpu": [ - "x64" - ], + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, "engines": { - "node": ">=12" + "node": ">=10.10.0" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", - "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", - "cpu": [ - "arm64" - ], + "node_modules/@humanwhocodes/config-array/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==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=12" + "node": "*" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", - "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", - "cpu": [ - "x64" - ], + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "license": "Apache-2.0", "engines": { - "node": ">=12" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", - "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", - "cpu": [ - "arm" - ], + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "BSD-3-Clause" + }, + "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/@esbuild/linux-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", - "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", - "cpu": [ - "arm64" - ], + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", - "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", - "cpu": [ - "ia32" - ], + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", - "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", - "cpu": [ - "loong64" - ], + "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", - "optional": true, - "os": [ - "linux" - ], + "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/@esbuild/linux-mips64el": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", - "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", - "cpu": [ - "mips64el" - ], + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "ansi-regex": "^6.0.1" + }, "engines": { "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", - "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", - "cpu": [ - "ppc64" - ], + "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", - "optional": true, - "os": [ - "linux" - ], + "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/@esbuild/linux-riscv64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", - "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", - "cpu": [ - "riscv64" - ], + "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": "MIT", - "optional": true, - "os": [ - "linux" - ], + "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": ">=12" + "node": ">=8" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", - "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", - "cpu": [ - "s390x" - ], + "node_modules/@istanbuljs/load-nyc-config/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", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "dependencies": { + "sprintf-js": "~1.0.2" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", - "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", - "cpu": [ - "x64" - ], + "node_modules/@istanbuljs/load-nyc-config/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", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", - "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", - "cpu": [ - "x64" - ], + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", - "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", - "cpu": [ - "arm64" - ], + "node_modules/@istanbuljs/load-nyc-config/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", - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "p-locate": "^4.1.0" + }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", - "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", - "cpu": [ - "x64" - ], + "node_modules/@istanbuljs/load-nyc-config/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", - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "p-try": "^2.0.0" + }, "engines": { - "node": ">=12" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", - "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", - "cpu": [ - "x64" - ], + "node_modules/@istanbuljs/load-nyc-config/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", - "optional": true, - "os": [ - "sunos" - ], + "dependencies": { + "p-limit": "^2.2.0" + }, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", - "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", - "cpu": [ - "arm64" - ], + "node_modules/@istanbuljs/load-nyc-config/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", - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", - "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", - "cpu": [ - "ia32" - ], + "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", - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", - "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", - "cpu": [ - "x64" - ], + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, "license": "MIT", "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@eslint/eslintrc/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==", + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": "*" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" }, "engines": { - "node": ">=10.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "node_modules/@jest/reporters/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==", @@ -1321,553 +1445,564 @@ "concat-map": "0.0.1" } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@jest/reporters/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", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "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": "*" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true, - "license": "BSD-3-Clause" - }, - "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==", + "node_modules/@jest/reporters/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "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" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/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==", + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/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==", + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/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==", + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/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==", + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/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==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, "engines": { - "node": ">=8" + "node": ">=6.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/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/@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==", + "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, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=6.0.0" } }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.0.0" } }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "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, - "license": "MIT", - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "license": "MIT" }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "license": "MIT", "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "node_modules/@ljharb/through": { + "version": "2.3.13", + "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.13.tgz", + "integrity": "sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==", "dev": true, "license": "MIT", "dependencies": { - "jest-get-type": "^29.6.3" + "call-bind": "^1.0.7" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" } }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "dev": true, + "node_modules/@lukeed/csprng": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", + "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "dev": true, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", + "integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==", "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "sparse-bitfield": "^3.0.3" } }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" + "node_modules/@nestjs/cli": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.4.5.tgz", + "integrity": "sha512-FP7Rh13u8aJbHe+zZ7hM0CC4785g9Pw4lz4r2TTgRtf0zTxSWMkJaPEwyjX8SK9oWK2GsYxl+fKpwVZNbmnj9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "17.3.8", + "@angular-devkit/schematics": "17.3.8", + "@angular-devkit/schematics-cli": "17.3.8", + "@nestjs/schematics": "^10.0.1", + "chalk": "4.1.2", + "chokidar": "3.6.0", + "cli-table3": "0.6.5", + "commander": "4.1.1", + "fork-ts-checker-webpack-plugin": "9.0.2", + "glob": "10.4.2", + "inquirer": "8.2.6", + "node-emoji": "1.11.0", + "ora": "5.4.1", + "tree-kill": "1.2.2", + "tsconfig-paths": "4.2.0", + "tsconfig-paths-webpack-plugin": "4.1.0", + "typescript": "5.3.3", + "webpack": "5.94.0", + "webpack-node-externals": "3.0.0" + }, + "bin": { + "nest": "bin/nest.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 16.14" }, "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "@swc/cli": "^0.1.62 || ^0.3.0 || ^0.4.0", + "@swc/core": "^1.3.62" }, "peerDependenciesMeta": { - "node-notifier": { + "@swc/cli": { + "optional": true + }, + "@swc/core": { "optional": true } } }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/@nestjs/cli/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "@sinclair/typebox": "^0.27.8" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8.0.0" } }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "node_modules/@nestjs/cli/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, + "license": "BSD-2-Clause", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=4.0" } }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "node_modules/@nestjs/cli/node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.17" } }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" + "node_modules/@nestjs/cli/node_modules/webpack": { + "version": "5.94.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", + "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.7.1", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.1", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } } }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, + "node_modules/@nestjs/common": { + "version": "10.4.4", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.4.tgz", + "integrity": "sha512-0j2/zqRw9nvHV1GKTktER8B/hIC/Z8CYFjN/ZqUuvwayCH+jZZBhCR2oRyuvLTXdnlSmtCAg2xvQ0ULqQvzqhA==", "license": "MIT", "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" + "iterare": "1.2.1", + "tslib": "2.7.0", + "uid": "2.0.2" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } } }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, + "node_modules/@nestjs/core": { + "version": "10.4.4", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.4.tgz", + "integrity": "sha512-y9tjmAzU6LTh1cC/lWrRsCcOd80khSR0qAHAqwY2svbW+AhsR/XCzgpZrAAKJrm/dDfjLCZKyxJSayeirGcW5Q==", + "hasInstallScript": true, "license": "MIT", "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "@nuxtjs/opencollective": "0.3.2", + "fast-safe-stringify": "2.1.1", + "iterare": "1.2.1", + "path-to-regexp": "3.3.0", + "tslib": "2.7.0", + "uid": "2.0.2" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/microservices": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "@nestjs/websockets": "^10.0.0", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + }, + "@nestjs/websockets": { + "optional": true + } } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, + "node_modules/@nestjs/mongoose": { + "version": "10.0.10", + "resolved": "https://registry.npmjs.org/@nestjs/mongoose/-/mongoose-10.0.10.tgz", + "integrity": "sha512-3Ff60ock8nwlAJC823TG91Qy+Qc6av+ddIb6n6wlFsTK0akDF/aTcagX8cF8uI8mWxCWjEwEsgv99vo6p0yJ+w==", "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0", + "mongoose": "^6.0.2 || ^7.0.0 || ^8.0.0", + "rxjs": "^7.0.0" } }, - "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, + "node_modules/@nestjs/platform-express": { + "version": "10.4.4", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.4.tgz", + "integrity": "sha512-y52q1MxhbHaT3vAgWd08RgiYon0lJgtTa8U6g6gV0KI0IygwZhDQFJVxnrRDUdxQGIP5CKHmfQu3sk9gTNFoEA==", "license": "MIT", - "engines": { - "node": ">=6.0.0" + "dependencies": { + "body-parser": "1.20.3", + "cors": "2.8.5", + "express": "4.21.0", + "multer": "1.4.4-lts.1", + "tslib": "2.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, + "node_modules/@nestjs/platform-socket.io": { + "version": "10.4.4", + "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-10.4.4.tgz", + "integrity": "sha512-5GEYUA3sNbX2jOBP6FmrIK/zv9VCdvpdr4Sef1OKvt1U0qsV1YgmWPWDPumZM77n5DI0VHSJPyo7yjZaEKWOiQ==", "license": "MIT", - "engines": { - "node": ">=6.0.0" + "dependencies": { + "socket.io": "4.7.5", + "tslib": "2.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/websockets": "^10.0.0", + "rxjs": "^7.1.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, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "node_modules/@nestjs/schematics": { + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-10.1.4.tgz", + "integrity": "sha512-QpY8ez9cTvXXPr3/KBrtSgXQHMSV6BkOUYy2c2TTe6cBqriEdGnCYqGl8cnfrQl3632q3lveQPaZ/c127dHsEw==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@angular-devkit/core": "17.3.8", + "@angular-devkit/schematics": "17.3.8", + "comment-json": "4.2.3", + "jsonc-parser": "3.3.1", + "pluralize": "8.0.0" + }, + "peerDependencies": { + "typescript": ">=4.8.2" } }, - "node_modules/@jsdevtools/ono": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", - "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "node_modules/@nestjs/schematics/node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", "dev": true, "license": "MIT" }, - "node_modules/@jukebox/config": { - "resolved": "packages/config", - "link": true - }, - "node_modules/@jukebox/lib": { - "resolved": "packages/lib", - "link": true - }, - "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==", - "license": "BSD-3-Clause", + "node_modules/@nestjs/testing": { + "version": "10.4.4", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.4.tgz", + "integrity": "sha512-qRGFj51A5RM7JqA8pcyEwSLA3Y0dle/PAZ8oxP0suimoCusRY3Tk7wYqutZdCNj1ATb678SDaUZDHk2pwSv9/g==", + "dev": true, + "license": "MIT", "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" + "tslib": "2.7.0" }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/microservices": "^10.0.0", + "@nestjs/platform-express": "^10.0.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + } } }, - "node_modules/@mongodb-js/saslprep": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", - "integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==", + "node_modules/@nestjs/websockets": { + "version": "10.4.4", + "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-10.4.4.tgz", + "integrity": "sha512-ZHnak04i/iKBS0csjJa7K6D6xdsB0Yz6duJuCR7xGLItchFK+Ne21m9rEF8ffvW74U7UAYkQHBgD5242LBBYiQ==", "license": "MIT", - "optional": true, "dependencies": { - "sparse-bitfield": "^3.0.3" + "iterare": "1.2.1", + "object-hash": "3.0.0", + "tslib": "2.7.0" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/platform-socket.io": "^10.0.0", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "@nestjs/platform-socket.io": { + "optional": true + } } }, "node_modules/@nodelib/fs.scandir": { @@ -1908,6 +2043,35 @@ "node": ">= 8" } }, + "node_modules/@nuxtjs/opencollective": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", + "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "consola": "^2.15.0", + "node-fetch": "^2.6.1" + }, + "bin": { + "opencollective": "bin/opencollective.js" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "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.1.1", "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", @@ -1921,13 +2085,6 @@ "url": "https://opencollective.com/unts" } }, - "node_modules/@rtsao/scc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", - "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", - "dev": true, - "license": "MIT" - }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -2040,16 +2197,6 @@ "@babel/types": "^7.20.7" } }, - "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, - "license": "MIT", - "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", @@ -2061,13 +2208,6 @@ "@types/node": "*" } }, - "node_modules/@types/caseless": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz", - "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/connect": { "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", @@ -2084,15 +2224,12 @@ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", "license": "MIT" }, - "node_modules/@types/cookie-parser": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.7.tgz", - "integrity": "sha512-Fvuyi354Z+uayxzIGCwYTayFKocfV7TuDYZClCdIP9ckhvAu/ixDtCB6qx2TT0FKjPLf1f3P/J1rgf6lPs64mw==", + "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", - "dependencies": { - "@types/express": "*" - } + "license": "MIT" }, "node_modules/@types/cors": { "version": "2.8.17", @@ -2103,6 +2240,13 @@ "@types/node": "*" } }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/express": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", @@ -2117,9 +2261,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.19.5", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", - "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", "dev": true, "license": "MIT", "dependencies": { @@ -2174,9 +2318,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.12", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", - "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "version": "29.5.13", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.13.tgz", + "integrity": "sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg==", "dev": true, "license": "MIT", "dependencies": { @@ -2191,23 +2335,13 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "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/jsonwebtoken": { - "version": "9.0.6", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz", - "integrity": "sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", @@ -2215,46 +2349,19 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/module-alias": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/module-alias/-/module-alias-2.0.4.tgz", - "integrity": "sha512-5+G/QXO/DvHZw60FjvbDzO4JmlD/nG5m2/vVGt25VN1eeP3w2bCoks1Wa7VuptMPM1TxJdx6RjO70N9Fw0nZPA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/morgan": { - "version": "1.9.9", - "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.9.tgz", - "integrity": "sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@types/express": "*" - } - }, "node_modules/@types/node": { - "version": "22.5.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", - "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "version": "20.16.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", + "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", "license": "MIT", "dependencies": { "undici-types": "~6.19.2" } }, "node_modules/@types/qs": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "version": "6.9.16", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz", + "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==", "dev": true, "license": "MIT" }, @@ -2265,26 +2372,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/request": { - "version": "2.48.12", - "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.12.tgz", - "integrity": "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/caseless": "*", - "@types/node": "*", - "@types/tough-cookie": "*", - "form-data": "^2.5.0" - } - }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/send": { "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", @@ -2315,43 +2402,29 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/strip-json-comments": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", - "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/swagger-ui-express": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.6.tgz", - "integrity": "sha512-UVSiGYXa5IzdJJG3hrc86e8KdZWLYxyEsVoUI4iPXc7CO4VZ3AfNP8d/8+hrDRIqz+HAaSMtZSqAsF3Nq2X/Dg==", + "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/express": "*", - "@types/serve-static": "*" + "@types/cookiejar": "^2.1.5", + "@types/methods": "^1.1.4", + "@types/node": "*", + "form-data": "^4.0.0" } }, - "node_modules/@types/tough-cookie": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "node_modules/@types/supertest": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.2.tgz", + "integrity": "sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==", "dev": true, - "license": "MIT" - }, - "node_modules/@types/triple-beam": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", - "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", - "license": "MIT" + "license": "MIT", + "dependencies": { + "@types/methods": "^1.1.4", + "@types/superagent": "^8.1.0" + } }, "node_modules/@types/webidl-conversions": { "version": "7.0.3", @@ -2360,12 +2433,11 @@ "license": "MIT" }, "node_modules/@types/whatwg-url": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", - "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", "license": "MIT", "dependencies": { - "@types/node": "*", "@types/webidl-conversions": "*" } }, @@ -2387,34 +2459,32 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", - "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz", + "integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/type-utils": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/type-utils": "8.8.0", + "@typescript-eslint/utils": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "graphemer": "^1.4.0", - "ignore": "^5.2.4", + "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -2423,27 +2493,27 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", - "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz", + "integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "debug": "^4.3.4" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -2452,17 +2522,17 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz", + "integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2470,27 +2540,24 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", - "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz", + "integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/utils": "8.8.0", "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, "peerDependenciesMeta": { "typescript": { "optional": true @@ -2498,13 +2565,13 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz", + "integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==", "dev": true, "license": "MIT", "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2512,23 +2579,23 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz", + "integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "debug": "^4.3.4", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2541,43 +2608,40 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz", + "integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "semver": "^7.5.4" + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.57.0 || ^9.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz", + "integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "8.8.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2591,11 +2655,180 @@ "dev": true, "license": "ISC" }, - "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==", - "license": "ISC" + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "license": "Apache-2.0" }, "node_modules/accepts": { "version": "1.3.8", @@ -2623,6 +2856,16 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^8" + } + }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -2634,9 +2877,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", - "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", "dev": true, "license": "MIT", "dependencies": { @@ -2646,28 +2889,16 @@ "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==", - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", "uri-js": "^4.2.2" }, "funding": { @@ -2675,6 +2906,34 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -2708,6 +2967,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -2717,7 +2977,6 @@ "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" @@ -2743,46 +3002,25 @@ "node": ">= 8" } }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "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==", "license": "MIT" }, - "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==", - "license": "ISC" - }, - "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.", - "license": "ISC", - "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==", - "license": "MIT", - "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", @@ -2797,255 +3035,100 @@ "dev": true, "license": "Python-2.0" }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "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==", "license": "MIT" }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "node_modules/array-timsort": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", + "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "license": "MIT" }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "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", - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "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": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@babel/core": "^7.8.0" } }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "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==", - "license": "MIT" - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/axios/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/babel-plugin-istanbul/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": { @@ -3116,6 +3199,28 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "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==", + "dev": true, + "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": { @@ -3127,38 +3232,6 @@ "node": "^4.5.0 || >= 5.9" } }, - "node_modules/basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/basic-auth/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==", - "license": "MIT" - }, - "node_modules/bcrypt": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", - "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", - "hasInstallScript": true, - "license": "MIT", - "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", @@ -3172,10 +3245,37 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "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==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "license": "MIT", "dependencies": { "bytes": "3.1.2", @@ -3186,7 +3286,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -3235,9 +3335,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", + "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", "dev": true, "funding": [ { @@ -3255,8 +3355,8 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", + "caniuse-lite": "^1.0.30001663", + "electron-to-chromium": "^1.5.28", "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, @@ -3291,19 +3391,38 @@ } }, "node_modules/bson": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/bson/-/bson-5.5.1.tgz", - "integrity": "sha512-ix0EwukN2EpC0SRWIj/7B5+A6uQMQy6KMREI9qQqvgpkV2frH63T0UDVd1SYedL6dNCmDBYB3QtXi4ISk9YT+g==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.8.0.tgz", + "integrity": "sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ==", "license": "Apache-2.0", "engines": { - "node": ">=14.20.1" + "node": ">=16.20.1" } }, - "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==", - "license": "BSD-3-Clause" + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "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": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } }, "node_modules/buffer-from": { "version": "1.1.2", @@ -3311,29 +3430,6 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "license": "MIT" }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/builtins": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.1.0.tgz", - "integrity": "sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.0.0" - } - }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -3373,13 +3469,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/call-me-maybe": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", - "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", - "dev": true, - "license": "MIT" - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -3401,9 +3490,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001658", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001658.tgz", - "integrity": "sha512-N2YVqWbJELVdrnsW5p+apoQyYt51aBMSsBZki1XZEfeBCexcM/sf4xiAHcXQBkuOwJBXtWF7aW1sYX6tKebPHw==", + "version": "1.0.30001667", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001667.tgz", + "integrity": "sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==", "dev": true, "funding": [ { @@ -3425,7 +3514,6 @@ "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", @@ -3448,6 +3536,13 @@ "node": ">=10" } }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true, + "license": "MIT" + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -3473,26 +3568,14 @@ "fsevents": "~2.3.2" } }, - "node_modules/chokidar/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==", + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "license": "ISC", + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=6.0" } }, "node_modules/ci-info": { @@ -3512,122 +3595,148 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.0.tgz", - "integrity": "sha512-N1NGmowPlGBLsOZLPvm48StN04V4YvQRL0i6b7ctrVY3epjP/ct7hFLOItz6pDIvRjwpfPxi52a2UWV2ziir8g==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", "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==", + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "restore-cursor": "^3.1.0" }, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, "license": "MIT", "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", "dev": true, - "license": "MIT" - }, - "node_modules/color": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", - "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", "license": "MIT", "dependencies": { - "color-convert": "^1.9.3", - "color-string": "^1.6.0" + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" } }, - "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==", + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", "dev": true, - "license": "MIT", + "license": "ISC", + "engines": { + "node": ">= 10" + } + }, + "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": { - "color-name": "~1.1.4" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=12" } }, - "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==", - "license": "MIT" - }, - "node_modules/color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "node_modules/cliui/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": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" + "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/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==", - "license": "ISC", - "bin": { - "color-support": "bin.js" + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" } }, - "node_modules/color/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "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", - "dependencies": { - "color-name": "1.1.3" + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" } }, - "node_modules/color/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true, "license": "MIT" }, - "node_modules/colorspace": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", - "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "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==", "license": "MIT", "dependencies": { - "color": "^3.1.3", - "text-hex": "1.0.x" + "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==", + "license": "MIT" + }, "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" @@ -3637,19 +3746,47 @@ } }, "node_modules/commander": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", - "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/comment-json": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.3.tgz", + "integrity": "sha512-SsxdiOf064DWoZLH799Ata6u7iV658A11PlWtZATDlXPpKGJnbJZ5Z24ybixAi+LUUqJ/GKowAejtC5GFUG7Tw==", "dev": true, "license": "MIT", + "dependencies": { + "array-timsort": "^1.0.3", + "core-util-is": "^1.0.3", + "esprima": "^4.0.1", + "has-own-prop": "^2.0.0", + "repeat-string": "^1.6.1" + }, "engines": { "node": ">= 6" } }, + "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==", + "dev": true, "license": "MIT" }, "node_modules/concat-stream": { @@ -3667,11 +3804,11 @@ "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==", - "license": "ISC" + "node_modules/consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", + "license": "MIT" }, "node_modules/content-disposition": { "version": "0.5.4", @@ -3702,33 +3839,27 @@ "license": "MIT" }, "node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "license": "MIT", "engines": { "node": ">= 0.6" } }, - "node_modules/cookie-parser": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", - "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", - "license": "MIT", - "dependencies": { - "cookie": "0.4.1", - "cookie-signature": "1.0.6" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "license": "MIT" }, + "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", @@ -3748,6 +3879,33 @@ "node": ">= 0.10" } }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -3792,60 +3950,6 @@ "node": ">= 8" } }, - "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/debug": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", @@ -3895,6 +3999,19 @@ "node": ">=0.10.0" } }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -3912,39 +4029,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "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==", - "license": "MIT" - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -3964,15 +4058,6 @@ "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==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -3983,6 +4068,17 @@ "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", @@ -4003,19 +4099,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -4029,36 +4112,12 @@ "node": ">=6.0.0" } }, - "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/dynamic-dedupe": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", - "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==", + "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", - "dependencies": { - "xtend": "^4.0.0" - } - }, - "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==", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - } + "license": "MIT" }, "node_modules/ee-first": { "version": "1.1.1", @@ -4083,9 +4142,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.18", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.18.tgz", - "integrity": "sha512-1OfuVACu+zKlmjsNdcJuVQuVE61sZOLbNM4JAQ1Rvh6EOj0/EUKhMJjRH73InPlXSh8HIJk1cVZ8pyOV/FMdUQ==", + "version": "1.5.32", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.32.tgz", + "integrity": "sha512-M+7ph0VGBQqqpTT2YrabjNKSQ2fEl9PVx6AK3N558gDH9NO8O6XN9SXXFWRo9u9PbEg/bWq+tjXQr+eXmxubCw==", "dev": true, "license": "ISC" }, @@ -4106,18 +4165,13 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/enabled": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", - "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", + "dev": true, "license": "MIT" }, "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==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -4153,75 +4207,37 @@ "node": ">=10.0.0" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" + "engines": { + "node": ">= 0.6" } }, - "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dev": true, "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10.13.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" } }, "node_modules/es-define-property": { @@ -4245,100 +4261,12 @@ "node": ">= 0.4" } }, - "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.0" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/esbuild": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", - "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.20.2", - "@esbuild/android-arm": "0.20.2", - "@esbuild/android-arm64": "0.20.2", - "@esbuild/android-x64": "0.20.2", - "@esbuild/darwin-arm64": "0.20.2", - "@esbuild/darwin-x64": "0.20.2", - "@esbuild/freebsd-arm64": "0.20.2", - "@esbuild/freebsd-x64": "0.20.2", - "@esbuild/linux-arm": "0.20.2", - "@esbuild/linux-arm64": "0.20.2", - "@esbuild/linux-ia32": "0.20.2", - "@esbuild/linux-loong64": "0.20.2", - "@esbuild/linux-mips64el": "0.20.2", - "@esbuild/linux-ppc64": "0.20.2", - "@esbuild/linux-riscv64": "0.20.2", - "@esbuild/linux-s390x": "0.20.2", - "@esbuild/linux-x64": "0.20.2", - "@esbuild/netbsd-x64": "0.20.2", - "@esbuild/openbsd-x64": "0.20.2", - "@esbuild/sunos-x64": "0.20.2", - "@esbuild/win32-arm64": "0.20.2", - "@esbuild/win32-ia32": "0.20.2", - "@esbuild/win32-x64": "0.20.2" - } + "license": "MIT" }, "node_modules/escalade": { "version": "3.2.0", @@ -4370,17 +4298,18 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -4425,22 +4354,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-compat-utils": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz", - "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.4" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "eslint": ">=6.0.0" - } - }, "node_modules/eslint-config-prettier": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", @@ -4454,162 +4367,85 @@ "eslint": ">=7.0.0" } }, - "node_modules/eslint-config-standard": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", - "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", + "node_modules/eslint-plugin-prettier": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", "dev": true, - "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": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.9.1" + }, "engines": { - "node": ">=12.0.0" + "node": "^14.18.0 || >=16.0.0" }, - "peerDependencies": { - "eslint": "^8.0.1", - "eslint-plugin-import": "^2.25.2", - "eslint-plugin-n": "^15.0.0 || ^16.0.0 ", - "eslint-plugin-promise": "^6.0.0" - } - }, - "node_modules/eslint-config-standard-with-typescript": { - "version": "43.0.1", - "resolved": "https://registry.npmjs.org/eslint-config-standard-with-typescript/-/eslint-config-standard-with-typescript-43.0.1.tgz", - "integrity": "sha512-WfZ986+qzIzX6dcr4yGUyVb/l9N3Z8wPXCc5z/70fljs3UbWhhV+WxrfgsqMToRzuuyX9MqZ974pq2UPhDTOcA==", - "deprecated": "Please use eslint-config-love, instead.", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/parser": "^6.4.0", - "eslint-config-standard": "17.1.0" + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^6.4.0", - "eslint": "^8.0.1", - "eslint-plugin-import": "^2.25.2", - "eslint-plugin-n": "^15.0.0 || ^16.0.0 ", - "eslint-plugin-promise": "^6.0.0", - "typescript": "*" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.11.0.tgz", - "integrity": "sha512-gbBE5Hitek/oG6MUVj6sFuzEjA/ClzNflVrLovHi/JgLdC7fiN5gLAY1WIPW1a0V5I999MnsrvVrCOGmmVqDBQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" }, "peerDependenciesMeta": { - "eslint": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { "optional": true } } }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "ms": "^2.1.1" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-plugin-es-x": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.8.0.tgz", - "integrity": "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==", + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "funding": [ - "https://github.com/sponsors/ota-meshi", - "https://opencollective.com/eslint" - ], - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.1.2", - "@eslint-community/regexpp": "^4.11.0", - "eslint-compat-utils": "^0.5.1" - }, + "license": "Apache-2.0", "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "peerDependencies": { - "eslint": ">=8" + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-plugin-import": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.30.0.tgz", - "integrity": "sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw==", + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", "dependencies": { - "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.8", - "array.prototype.findlastindex": "^1.2.5", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.9.0", - "hasown": "^2.0.2", - "is-core-module": "^2.15.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "object.groupby": "^1.0.3", - "object.values": "^1.2.0", - "semver": "^6.3.1", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "node_modules/eslint/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==", @@ -4620,43 +4456,27 @@ "concat-map": "0.0.1" } }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "license": "Apache-2.0", + "license": "ISC", "dependencies": { - "esutils": "^2.0.2" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=0.10.0" + "node": ">=10.13.0" } }, - "node_modules/eslint-plugin-import/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } + "license": "MIT" }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { + "node_modules/eslint/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", @@ -4669,222 +4489,22 @@ "node": "*" } }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-import/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/eslint-plugin-n": { - "version": "16.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.6.2.tgz", - "integrity": "sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "builtins": "^5.0.1", - "eslint-plugin-es-x": "^7.5.0", - "get-tsconfig": "^4.7.0", - "globals": "^13.24.0", - "ignore": "^5.2.4", - "is-builtin-module": "^3.2.1", - "is-core-module": "^2.12.1", - "minimatch": "^3.1.2", - "resolve": "^1.22.2", - "semver": "^7.5.3" - }, - "engines": { - "node": ">=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-n/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==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-n/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-prefer-arrow-functions": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prefer-arrow-functions/-/eslint-plugin-prefer-arrow-functions-3.4.1.tgz", - "integrity": "sha512-c8NP0E8xpkRqDq2eDSRr+wA4jwkwOEVNnZx4YY3O0V9M7OhtKdQIj5zmzIXwu+ueURmbwYrnz65sEoLLoIVZpg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "eslint": ">=8.0.0" - } - }, - "node_modules/eslint-plugin-prettier": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", - "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", - "dev": true, - "license": "MIT", - "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.9.1" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": "*", - "prettier": ">=3.0.0" - }, - "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-promise": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.6.0.tgz", - "integrity": "sha512-57Zzfw8G6+Gq7axm2Pdo3gW/Rx3h9Yywgn61uE/3elTCOePEHVrn2i5CdfBwA1BLK0Q0WqctICIUSqXZW/VprQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/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==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/esprima": { @@ -4956,6 +4576,16 @@ "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==", + "dev": true, + "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", @@ -4980,6 +4610,13 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/execa/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==", + "dev": true, + "license": "ISC" + }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -5007,37 +4644,37 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "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", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -5048,15 +4685,6 @@ "node": ">= 0.10.0" } }, - "node_modules/express/node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/express/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -5072,6 +4700,27 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/express/node_modules/path-to-regexp": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "license": "MIT" + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "license": "MIT", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -5103,19 +4752,6 @@ "node": ">=8.6.0" } }, - "node_modules/fast-glob/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, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "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", @@ -5130,6 +4766,12 @@ "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==", + "license": "MIT" + }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -5150,11 +4792,31 @@ "bser": "2.1.1" } }, - "node_modules/fecha": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", - "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", - "license": "MIT" + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } }, "node_modules/file-entry-cache": { "version": "6.0.1", @@ -5206,13 +4868,13 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "license": "MIT", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -5277,55 +4939,104 @@ "dev": true, "license": "ISC" }, - "node_modules/fn.name": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", - "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", - "license": "MIT" - }, - "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", + "integrity": "sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cosmiconfig": "^8.2.0", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">=12.13.0", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" } }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "node_modules/fork-ts-checker-webpack-plugin/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==", "dev": true, "license": "MIT", "dependencies": { - "is-callable": "^1.1.3" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, "node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", + "combined-stream": "^1.0.8", "mime-types": "^2.1.12" }, "engines": { - "node": ">= 0.12" + "node": ">= 6" + } + }, + "node_modules/formidable": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.1.tgz", + "integrity": "sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "dezalgo": "^1.0.4", + "hexoid": "^1.0.0", + "once": "^1.4.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" } }, "node_modules/forwarded": { @@ -5346,40 +5057,33 @@ "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==", - "license": "ISC", - "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==", - "license": "ISC", + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/fs-minipass/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" + "node_modules/fs-monkey": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", + "dev": true, + "license": "Unlicense" }, "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==", + "dev": true, "license": "ISC" }, "node_modules/fsevents": { @@ -5406,56 +5110,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "license": "MIT", - "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.", - "license": "ISC", - "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", @@ -5518,92 +5172,49 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.0.tgz", - "integrity": "sha512-Pgba6TExTZ0FJAn1qkJAjIeKoDJ3CsI2ChuLohJnZl/tTU8MVrq3b+2t5UOPfRa4RMsorClBjJALkJUMjG1PAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, "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", + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", + "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", + "dev": true, "license": "ISC", "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" + "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" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "license": "ISC", "dependencies": { - "is-glob": "^4.0.3" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob/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==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node": ">= 6" } }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/globals": { "version": "13.24.0", @@ -5621,44 +5232,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -5685,20 +5258,19 @@ "dev": true, "license": "MIT" }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-own-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", + "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==", "dev": true, "license": "MIT", "engines": { @@ -5741,28 +5313,6 @@ "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==", - "license": "ISC" - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -5775,6 +5325,16 @@ "node": ">= 0.4" } }, + "node_modules/hexoid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", + "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -5798,19 +5358,6 @@ "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==", - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -5833,26 +5380,40 @@ "node": ">=0.10.0" } }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "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==", + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "dev": true, - "license": "ISC" - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "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": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "license": "MIT", @@ -5902,6 +5463,7 @@ "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.", + "dev": true, "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -5914,32 +5476,31 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, - "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "node_modules/inquirer": { + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", - "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^6.0.1" }, "engines": { - "node": ">= 12" + "node": ">=12.0.0" } }, "node_modules/ipaddr.js": { @@ -5951,23 +5512,6 @@ "node": ">= 0.10" } }, - "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -5975,19 +5519,6 @@ "dev": true, "license": "MIT" }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -6001,52 +5532,6 @@ "node": ">=8" } }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "dev": true, - "license": "MIT", - "dependencies": { - "builtin-modules": "^3.3.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-core-module": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", @@ -6063,38 +5548,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -6109,6 +5562,7 @@ "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==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -6137,17 +5591,14 @@ "node": ">=0.10.0" } }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, "node_modules/is-number": { @@ -6160,22 +5611,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", @@ -6186,43 +5621,11 @@ "node": ">=8" } }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "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" @@ -6231,65 +5634,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, "license": "MIT", - "dependencies": { - "which-typed-array": "^1.1.14" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/isarray": { @@ -6347,22 +5702,6 @@ "node": ">=10" } }, - "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-source-maps": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", @@ -6378,6 +5717,16 @@ "node": ">=10" } }, + "node_modules/istanbul-lib-source-maps/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/istanbul-reports": { "version": "3.1.7", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", @@ -6392,6 +5741,31 @@ "node": ">=8" } }, + "node_modules/iterare": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", + "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==", + "license": "ISC", + "engines": { + "node": ">=6" + } + }, + "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/jake": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", @@ -6589,12 +5963,58 @@ } } }, - "node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "license": "MIT", + "node_modules/jest-config/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-config/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", + "dev": true, + "license": "ISC", + "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/jest-config/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.6.3", @@ -6851,6 +6271,27 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-runner/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/jest-runner/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/jest-runtime": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", @@ -6885,6 +6326,52 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-runtime/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-runtime/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", + "dev": true, + "license": "ISC", + "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/jest-runtime/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/jest-snapshot": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", @@ -6935,6 +6422,19 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-util/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/jest-validate": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", @@ -7038,23 +6538,17 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "license": "MIT" - }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-buffer": { @@ -7072,9 +6566,9 @@ "license": "MIT" }, "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, "license": "MIT" }, @@ -7098,62 +6592,30 @@ "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==", - "license": "MIT", - "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/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "license": "MIT", - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } + "node_modules/jsonc-parser": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", + "dev": true, + "license": "MIT" }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, "license": "MIT", "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/kafkajs": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/kafkajs/-/kafkajs-2.2.4.tgz", - "integrity": "sha512-j/YeapB1vfPT2iOIUn/vxdyKEuhuY2PxMBvf5JWux6iSaukAccrMtXEY/Lb7OvavDhOWME589bpLrEdnVHjfjA==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, "node_modules/kareem": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", - "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", + "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", "license": "Apache-2.0", "engines": { "node": ">=12.0.0" @@ -7179,12 +6641,6 @@ "node": ">=6" } }, - "node_modules/kuler": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", - "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", - "license": "MIT" - }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -7216,6 +6672,16 @@ "dev": true, "license": "MIT" }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.11.5" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -7232,56 +6698,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "dev": true, - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true, "license": "MIT" }, - "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==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -7296,34 +6719,21 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.mergewith": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", - "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "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==", - "license": "MIT" - }, - "node_modules/logform": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.1.tgz", - "integrity": "sha512-CdaO738xRapbKIMVn2m4F6KTj4j7ooJ8POVnebSgKo3KBz5axNXRAL7ZdRjIV6NOr2Uf4vjtRkxrFETOioCqSA==", "license": "MIT", "dependencies": { - "@colors/colors": "1.6.0", - "@types/triple-beam": "^1.3.2", - "fecha": "^4.2.0", - "ms": "^2.1.1", - "safe-stable-stringify": "^2.3.1", - "triple-beam": "^1.3.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { - "node": ">= 12.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lru-cache": { @@ -7336,30 +6746,35 @@ "yallist": "^3.0.2" } }, + "node_modules/magic-string": { + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, "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==", + "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": "^6.0.0" + "semver": "^7.5.3" }, "engines": { - "node": ">=8" + "node": ">=10" }, "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==", - "license": "ISC", - "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", @@ -7386,18 +6801,33 @@ "node": ">= 0.6" } }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "license": "Unlicense", + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/memory-pager": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "license": "MIT", - "optional": true + "license": "MIT" }, "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==", - "license": "MIT" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -7439,6 +6869,19 @@ "node": ">=8.6" } }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -7483,9 +6926,9 @@ } }, "node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "license": "ISC", "dependencies": { @@ -7508,45 +6951,15 @@ } }, "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, "license": "ISC", "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "license": "MIT", - "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==", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -7559,34 +6972,27 @@ "mkdirp": "bin/cmd.js" } }, - "node_modules/module-alias": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.2.3.tgz", - "integrity": "sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q==", - "license": "MIT" - }, "node_modules/mongodb": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.9.2.tgz", - "integrity": "sha512-H60HecKO4Bc+7dhOv4sJlgvenK4fQNqqUIlXxZYQNbfEWSALGAwGoyJd/0Qwk4TttFXUOHJ2ZJQe/52ScaUwtQ==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.9.0.tgz", + "integrity": "sha512-UMopBVx1LmEUbW/QE0Hw18u583PEDVQmUmVzzBRH0o/xtE9DBRA5ZYLOjpLIa03i8FXjzvQECJcqoMvCXftTUA==", "license": "Apache-2.0", "dependencies": { - "bson": "^5.5.0", - "mongodb-connection-string-url": "^2.6.0", - "socks": "^2.7.1" + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.7.0", + "mongodb-connection-string-url": "^3.0.0" }, "engines": { - "node": ">=14.20.1" - }, - "optionalDependencies": { - "@mongodb-js/saslprep": "^1.1.0" + "node": ">=16.20.1" }, "peerDependencies": { "@aws-sdk/credential-providers": "^3.188.0", - "@mongodb-js/zstd": "^1.0.0", - "kerberos": "^1.0.0 || ^2.0.0", - "mongodb-client-encryption": ">=2.3.0 <3", - "snappy": "^7.2.2" + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" }, "peerDependenciesMeta": { "@aws-sdk/credential-providers": { @@ -7595,6 +7001,9 @@ "@mongodb-js/zstd": { "optional": true }, + "gcp-metadata": { + "optional": true + }, "kerberos": { "optional": true }, @@ -7603,82 +7012,76 @@ }, "snappy": { "optional": true + }, + "socks": { + "optional": true } } }, "node_modules/mongodb-connection-string-url": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", - "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz", + "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==", "license": "Apache-2.0", "dependencies": { - "@types/whatwg-url": "^8.2.1", - "whatwg-url": "^11.0.0" + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" } }, - "node_modules/mongoose": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.8.1.tgz", - "integrity": "sha512-c3MY8P1mGUGO+0H8rqxMNmAmhP0xb2EPNItfr7tHAHkh52uB0owH4Gu6q1GTUYj8yoHEDG5MN2V1aBBR6aJPuA==", + "node_modules/mongodb-connection-string-url/node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", "license": "MIT", "dependencies": { - "bson": "^5.5.0", - "kareem": "2.5.1", - "mongodb": "5.9.2", - "mpath": "0.9.0", - "mquery": "5.0.0", - "ms": "2.1.3", - "sift": "16.0.1" + "punycode": "^2.3.0" }, "engines": { - "node": ">=14.20.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mongoose" + "node": ">=14" } }, - "node_modules/morgan": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", - "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", - "license": "MIT", - "dependencies": { - "basic-auth": "~2.0.1", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-finished": "~2.3.0", - "on-headers": "~1.0.2" - }, + "node_modules/mongodb-connection-string-url/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", "engines": { - "node": ">= 0.8.0" + "node": ">=12" } }, - "node_modules/morgan/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/mongodb-connection-string-url/node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", "license": "MIT", "dependencies": { - "ms": "2.0.0" + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" } }, - "node_modules/morgan/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/morgan/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "node_modules/mongoose": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.7.0.tgz", + "integrity": "sha512-rUCSF1mMYQXjXYdqEQLLlMD3xbcj2j1/hRn+9VnVj7ipzru/UoUZxlj/hWmteKMAh4EFnDZ+BIrmma9l/0Hi1g==", "license": "MIT", "dependencies": { - "ee-first": "1.1.1" + "bson": "^6.7.0", + "kareem": "2.6.3", + "mongodb": "6.9.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "17.1.3" }, "engines": { - "node": ">= 0.8" + "node": ">=16.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" } }, "node_modules/mpath": { @@ -7709,9 +7112,9 @@ "license": "MIT" }, "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==", + "version": "1.4.4-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz", + "integrity": "sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==", "license": "MIT", "dependencies": { "append-field": "^1.0.0", @@ -7726,19 +7129,12 @@ "node": ">= 6.0.0" } }, - "node_modules/mylas": { - "version": "2.1.13", - "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", - "integrity": "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==", + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/raouldeheer" - } + "license": "ISC" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -7756,12 +7152,30 @@ "node": ">= 0.6" } }, - "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/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-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "dev": true, "license": "MIT" }, + "node_modules/node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -7782,28 +7196,6 @@ } } }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, - "node_modules/node-fetch/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==", - "license": "BSD-2-Clause" - }, - "node_modules/node-fetch/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==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -7811,40 +7203,6 @@ "dev": true, "license": "MIT" }, - "node_modules/node-mocks-http": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/node-mocks-http/-/node-mocks-http-1.15.1.tgz", - "integrity": "sha512-X/GpUpNNiPDYUeUD183W8V4OW6OHYWI29w/QDyb+c/GzOfVEAlo6HjbW9++eXT2aV2lGg+uS+XqTD2q0pNREQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "^4.17.21", - "@types/node": "*", - "accepts": "^1.3.7", - "content-disposition": "^0.5.3", - "depd": "^1.1.0", - "fresh": "^0.5.2", - "merge-descriptors": "^1.0.1", - "methods": "^1.1.2", - "mime": "^1.3.4", - "parseurl": "^1.3.3", - "range-parser": "^1.2.0", - "type-is": "^1.6.18" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/node-mocks-http/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/node-releases": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", @@ -7852,97 +7210,6 @@ "dev": true, "license": "MIT" }, - "node_modules/nodemon": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.4.tgz", - "integrity": "sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==", - "dev": true, - "license": "MIT", - "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/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/nodemon/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, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/nodemon/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/nodemon/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, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "license": "ISC", - "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", @@ -7966,19 +7233,6 @@ "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.", - "license": "ISC", - "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", @@ -7988,6 +7242,15 @@ "node": ">=0.10.0" } }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", @@ -8000,166 +7263,94 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, + "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==", "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, "engines": { - "node": ">= 0.4" + "node": ">= 0.8" } }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "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==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "wrappy": "1" } }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "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": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" + "mimic-fn": "^2.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { - "node": ">= 0.4" + "node": ">= 0.8.0" } }, - "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "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==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "license": "MIT", - "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==", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/one-time": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", - "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", - "license": "MIT", - "dependencies": { - "fn.name": "1.x.x" - } - }, - "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" + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/openapi-types": { - "version": "12.1.3", - "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", - "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true, "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, "engines": { - "node": ">= 0.8.0" + "node": ">=0.10.0" } }, "node_modules/p-limit": { @@ -8204,6 +7395,13 @@ "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/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -8259,6 +7457,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -8281,10 +7480,34 @@ "dev": true, "license": "MIT" }, + "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==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", + "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==", "license": "MIT" }, "node_modules/path-type": { @@ -8305,13 +7528,13 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.1.tgz", + "integrity": "sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==", "dev": true, "license": "MIT", "engines": { - "node": ">=8.6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" @@ -8396,27 +7619,14 @@ "node": ">=8" } }, - "node_modules/plimit-lit": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", - "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "queue-lit": "^1.5.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=4" } }, "node_modules/prelude-ls": { @@ -8435,7 +7645,6 @@ "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -8520,19 +7729,6 @@ "node": ">= 0.10" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" - }, - "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, - "license": "MIT" - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -8560,12 +7756,12 @@ "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==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -8574,16 +7770,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/queue-lit": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", - "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -8605,6 +7791,16 @@ ], "license": "MIT" }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -8670,23 +7866,33 @@ "node": ">=8.10.0" } }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.6", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" - }, "engines": { - "node": ">= 0.4" + "node": ">=8.6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "license": "Apache-2.0" + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10" } }, "node_modules/require-directory": { @@ -8699,6 +7905,16 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -8750,16 +7966,6 @@ "node": ">=4" } }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, "node_modules/resolve.exports": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", @@ -8770,6 +7976,27 @@ "node": ">=10" } }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/restore-cursor/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==", + "dev": true, + "license": "ISC" + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -8786,6 +8013,7 @@ "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", + "dev": true, "license": "ISC", "dependencies": { "glob": "^7.1.3" @@ -8797,6 +8025,62 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/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", + "dev": true, + "license": "ISC", + "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/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -8821,32 +8105,15 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", - "dev": true, - "license": "MIT", + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "license": "Apache-2.0", "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "tslib": "^2.1.0" } }, - "node_modules/safe-array-concat/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "license": "MIT" - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -8867,43 +8134,70 @@ ], "license": "MIT" }, - "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-regex": "^1.1.4" + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" }, "engines": { - "node": ">= 0.4" + "node": ">= 10.13.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/safe-stable-stringify": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", - "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "node_modules/schema-utils/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "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/schema-utils/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/schema-utils/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, "license": "MIT" }, "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -8913,9 +8207,9 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "license": "MIT", "dependencies": { "debug": "2.6.9", @@ -8951,27 +8245,40 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/send/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==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, "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==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.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==", - "license": "ISC" - }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -8989,22 +8296,6 @@ "node": ">= 0.4" } }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -9053,43 +8344,22 @@ } }, "node_modules/sift": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", - "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==", + "version": "17.1.3", + "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", + "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==", "license": "MIT" }, "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==", - "license": "ISC" - }, - "node_modules/simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, - "node_modules/simple-swizzle/node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "license": "MIT" - }, - "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==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, + "license": "ISC", "engines": { - "node": ">=10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/sisteransi": { @@ -9109,16 +8379,6 @@ "node": ">=8" } }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, "node_modules/socket.io": { "version": "4.7.5", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", @@ -9160,34 +8420,20 @@ "node": ">=10.0.0" } }, - "node_modules/socks": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", - "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", - "license": "MIT", - "dependencies": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, "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==", + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true, "license": "BSD-3-Clause", "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, "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==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "license": "MIT", "dependencies": { @@ -9195,31 +8441,32 @@ "source-map": "^0.6.0" } }, + "node_modules/source-map-support/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/sparse-bitfield": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", "license": "MIT", - "optional": true, "dependencies": { "memory-pager": "^1.0.2" } }, "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "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-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -9293,6 +8540,7 @@ "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", @@ -9303,62 +8551,41 @@ "node": ">=8" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "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": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/strip-ansi": { + "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" @@ -9371,1210 +8598,600 @@ "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/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/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/swagger-autogen": { - "version": "2.23.7", - "resolved": "https://registry.npmjs.org/swagger-autogen/-/swagger-autogen-2.23.7.tgz", - "integrity": "sha512-vr7uRmuV0DCxWc0wokLJAwX3GwQFJ0jwN+AWk0hKxre2EZwusnkGSGdVFd82u7fQLgwSTnbWkxUL7HXuz5LTZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^7.4.1", - "deepmerge": "^4.2.2", - "glob": "^7.1.7", - "json5": "^2.2.3" - } - }, - "node_modules/swagger-autogen/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/swagger-jsdoc": { - "version": "6.2.8", - "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz", - "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "commander": "6.2.0", - "doctrine": "3.0.0", - "glob": "7.1.6", - "lodash.mergewith": "^4.6.2", - "swagger-parser": "^10.0.3", - "yaml": "2.0.0-1" - }, - "bin": { - "swagger-jsdoc": "bin/swagger-jsdoc.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/swagger-jsdoc/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==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/swagger-jsdoc/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/swagger-jsdoc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/swagger-parser": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz", - "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@apidevtools/swagger-parser": "10.0.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/swagger-ui-dist": { - "version": "5.17.14", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.14.tgz", - "integrity": "sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/swagger-ui-express": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.1.tgz", - "integrity": "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==", - "dev": true, - "license": "MIT", - "dependencies": { - "swagger-ui-dist": ">=5.0.0" - }, - "engines": { - "node": ">= v0.10.32" - }, - "peerDependencies": { - "express": ">=4.0.0 || >=5.0.0-beta" - } - }, - "node_modules/synckit": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", - "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "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==", - "license": "ISC", - "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==", - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, - "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/test-exclude/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==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/text-hex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", - "license": "MIT" - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "license": "MIT" - }, - "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-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "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, - "license": "MIT", - "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==", - "license": "MIT", - "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, - "license": "ISC", - "bin": { - "nodetouch": "bin/nodetouch.js" - } - }, - "node_modules/tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "license": "MIT", - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "license": "MIT", - "bin": { - "tree-kill": "cli.js" - } - }, - "node_modules/triple-beam": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", - "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", - "license": "MIT", - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/ts-jest": { - "version": "29.2.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", - "integrity": "sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "bs-logger": "^0.2.6", - "ejs": "^3.1.10", - "fast-json-stable-stringify": "^2.1.0", - "jest-util": "^29.0.0", - "json5": "^2.2.3", - "lodash.memoize": "^4.1.2", - "make-error": "^1.3.6", - "semver": "^7.6.3", - "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", - "@jest/types": "^29.0.0", - "babel-jest": "^29.0.0", - "jest": "^29.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 - } - } - }, - "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, - "license": "MIT", - "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/ts-node-dev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz", - "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": "^3.5.1", - "dynamic-dedupe": "^0.3.0", - "minimist": "^1.2.6", - "mkdirp": "^1.0.4", - "resolve": "^1.0.0", - "rimraf": "^2.6.1", - "source-map-support": "^0.5.12", - "tree-kill": "^1.2.2", - "ts-node": "^10.4.0", - "tsconfig": "^7.0.0" - }, - "bin": { - "ts-node-dev": "lib/bin.js", - "tsnd": "lib/bin.js" - }, - "engines": { - "node": ">=0.8.0" - }, - "peerDependencies": { - "node-notifier": "*", - "typescript": "*" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/ts-node-dev/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ts-node-dev/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/tsc-alias": { - "version": "1.8.10", - "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.10.tgz", - "integrity": "sha512-Ibv4KAWfFkFdKJxnWfVtdOmB0Zi1RJVxcbPGiCDsFpCQSsmpWyuzHG3rQyI5YkobWwxFPEyQfu1hdo4qLG2zPw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": "^3.5.3", - "commander": "^9.0.0", - "globby": "^11.0.4", - "mylas": "^2.1.9", - "normalize-path": "^3.0.0", - "plimit-lit": "^1.2.6" - }, - "bin": { - "tsc-alias": "dist/bin/index.js" - } - }, - "node_modules/tsc-alias/node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || >=14" - } - }, - "node_modules/tsconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", - "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/strip-bom": "^3.0.0", - "@types/strip-json-comments": "0.0.30", - "strip-bom": "^3.0.0", - "strip-json-comments": "^2.0.0" - } - }, - "node_modules/tsconfig-paths": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, + "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "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": ">=4" + "node": ">=6" } }, - "node_modules/tsconfig/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "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": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tsconfig/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "node_modules/superagent": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-9.0.2.tgz", + "integrity": "sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w==", "dev": true, "license": "MIT", + "dependencies": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^3.5.1", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=14.18.0" } }, - "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", - "dev": true, - "license": "0BSD" - }, - "node_modules/tsx": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.0.tgz", - "integrity": "sha512-bV30kM7bsLZKZIOCHeMNVMJ32/LuJzLVajkQI/qf92J2Qr08ueLQvW00PUZGiuLPP760UINwupgUj8qrSCPUKg==", + "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", - "dependencies": { - "esbuild": "~0.23.0", - "get-tsconfig": "^4.7.5" - }, "bin": { - "tsx": "dist/cli.mjs" + "mime": "cli.js" }, "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" + "node": ">=4.0.0" } }, - "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", - "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", - "cpu": [ - "ppc64" - ], + "node_modules/supertest": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.0.0.tgz", + "integrity": "sha512-qlsr7fIC0lSddmA3tzojvzubYxvlGtzumcdHgPwbFWMISQwL22MhM2Y3LNt+6w9Yyx7559VW5ab70dgphm8qQA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "aix" - ], + "dependencies": { + "methods": "^1.1.2", + "superagent": "^9.0.1" + }, "engines": { - "node": ">=18" + "node": ">=14.18.0" } }, - "node_modules/tsx/node_modules/@esbuild/android-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", - "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", - "cpu": [ - "arm" - ], - "dev": true, + "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==", "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/tsx/node_modules/@esbuild/android-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", - "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", - "cpu": [ - "arm64" - ], + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=18" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tsx/node_modules/@esbuild/android-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", - "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", - "cpu": [ - "x64" - ], + "node_modules/symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=18" + "node": ">=0.10" } }, - "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", - "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", - "cpu": [ - "arm64" - ], + "node_modules/synckit": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", + "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=18" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" } }, - "node_modules/tsx/node_modules/@esbuild/darwin-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", - "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", - "cpu": [ - "x64" - ], + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": ">=18" + "node": ">=6" } }, - "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", - "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", - "cpu": [ - "arm64" - ], + "node_modules/terser": { + "version": "5.34.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.34.1.tgz", + "integrity": "sha512-FsJZ7iZLd/BXkz+4xrRTGJ26o/6VTjQytUk8b8OxkwcD2I+79VPJlz7qss1+zE7h8GNIScFqXcDyJ/KqBYZFVA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, "engines": { - "node": ">=18" + "node": ">=10" } }, - "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", - "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", - "cpu": [ - "x64" - ], + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, "engines": { - "node": ">=18" + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } } }, - "node_modules/tsx/node_modules/@esbuild/linux-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", - "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", - "cpu": [ - "arm" - ], + "node_modules/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, "engines": { - "node": ">=18" + "node": ">= 10.13.0" } }, - "node_modules/tsx/node_modules/@esbuild/linux-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", - "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", - "cpu": [ - "arm64" - ], + "node_modules/terser-webpack-plugin/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", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=18" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/tsx/node_modules/@esbuild/linux-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", - "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", - "cpu": [ - "ia32" - ], + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "MIT" + }, + "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": ">=18" + "node": ">=8" } }, - "node_modules/tsx/node_modules/@esbuild/linux-loong64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", - "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", - "cpu": [ - "loong64" - ], + "node_modules/test-exclude/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==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", - "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", - "cpu": [ - "mips64el" - ], + "node_modules/test-exclude/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", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "ISC", + "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": ">=18" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", - "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", - "cpu": [ - "ppc64" - ], + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=18" + "node": "*" } }, - "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", - "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", - "cpu": [ - "riscv64" - ], + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "os-tmpdir": "~1.0.2" + }, "engines": { - "node": ">=18" + "node": ">=0.6.0" } }, - "node_modules/tsx/node_modules/@esbuild/linux-s390x": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", - "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", - "cpu": [ - "s390x" - ], + "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": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } + "license": "BSD-3-Clause" }, - "node_modules/tsx/node_modules/@esbuild/linux-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", - "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", - "cpu": [ - "x64" - ], + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=4" } }, - "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", - "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", - "cpu": [ - "x64" - ], + "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, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "is-number": "^7.0.0" + }, "engines": { - "node": ">=18" + "node": ">=8.0" } }, - "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", - "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", - "cpu": [ - "x64" - ], - "dev": true, + "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==", "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], "engines": { - "node": ">=18" + "node": ">=0.6" } }, - "node_modules/tsx/node_modules/@esbuild/sunos-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", - "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", - "cpu": [ - "x64" - ], + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" + "bin": { + "tree-kill": "cli.js" } }, - "node_modules/tsx/node_modules/@esbuild/win32-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", - "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", - "cpu": [ - "arm64" - ], + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=18" + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" } }, - "node_modules/tsx/node_modules/@esbuild/win32-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", - "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", - "cpu": [ - "ia32" - ], + "node_modules/ts-jest": { + "version": "29.2.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", + "integrity": "sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "bs-logger": "^0.2.6", + "ejs": "^3.1.10", + "fast-json-stable-stringify": "^2.1.0", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.6.3", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" + }, "engines": { - "node": ">=18" + "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", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.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 + } } }, - "node_modules/tsx/node_modules/@esbuild/win32-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", - "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", - "cpu": [ - "x64" - ], + "node_modules/ts-loader": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", + "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + }, "engines": { - "node": ">=18" + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" } }, - "node_modules/tsx/node_modules/esbuild": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", - "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", + "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, - "hasInstallScript": true, "license": "MIT", + "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": { - "esbuild": "bin/esbuild" + "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" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.1", - "@esbuild/android-arm": "0.23.1", - "@esbuild/android-arm64": "0.23.1", - "@esbuild/android-x64": "0.23.1", - "@esbuild/darwin-arm64": "0.23.1", - "@esbuild/darwin-x64": "0.23.1", - "@esbuild/freebsd-arm64": "0.23.1", - "@esbuild/freebsd-x64": "0.23.1", - "@esbuild/linux-arm": "0.23.1", - "@esbuild/linux-arm64": "0.23.1", - "@esbuild/linux-ia32": "0.23.1", - "@esbuild/linux-loong64": "0.23.1", - "@esbuild/linux-mips64el": "0.23.1", - "@esbuild/linux-ppc64": "0.23.1", - "@esbuild/linux-riscv64": "0.23.1", - "@esbuild/linux-s390x": "0.23.1", - "@esbuild/linux-x64": "0.23.1", - "@esbuild/netbsd-x64": "0.23.1", - "@esbuild/openbsd-arm64": "0.23.1", - "@esbuild/openbsd-x64": "0.23.1", - "@esbuild/sunos-x64": "0.23.1", - "@esbuild/win32-arm64": "0.23.1", - "@esbuild/win32-ia32": "0.23.1", - "@esbuild/win32-x64": "0.23.1" + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", "dev": true, "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1" + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=6" } }, - "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==", + "node_modules/tsconfig-paths-webpack-plugin": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.1.0.tgz", + "integrity": "sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA==", "dev": true, "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.7.0", + "tsconfig-paths": "^4.1.2" + }, "engines": { - "node": ">=4" + "node": ">=10.13.0" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "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==", "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, "engines": { - "node": ">= 0.6" + "node": ">=4" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" + "prelude-ls": "^1.2.1" }, "engines": { - "node": ">= 0.4" + "node": ">= 0.8.0" } }, - "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "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", - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" } }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", - "dev": true, + "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==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" + "media-typer": "0.3.0", + "mime-types": "~2.1.24" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.6" } }, "node_modules/typedarray": { @@ -10584,9 +9201,9 @@ "license": "MIT" }, "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -10597,35 +9214,34 @@ "node": ">=14.17" } }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, + "node_modules/uid": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", + "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "@lukeed/csprng": "^1.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=8" } }, - "node_modules/undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "dev": true, - "license": "MIT" - }, "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "license": "MIT" }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -10636,9 +9252,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "dev": true, "funding": [ { @@ -10656,8 +9272,8 @@ ], "license": "MIT", "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -10676,40 +9292,6 @@ "punycode": "^2.1.0" } }, - "node_modules/url": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", - "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", - "license": "MIT", - "dependencies": { - "punycode": "^1.4.1", - "qs": "^6.12.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/url/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "license": "MIT" - }, - "node_modules/url/node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -10747,16 +9329,6 @@ "node": ">=10.12.0" } }, - "node_modules/validator": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", - "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -10776,152 +9348,154 @@ "makeerror": "1.0.12" } }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "node_modules/watchpack": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "dev": true, "license": "MIT", "dependencies": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" }, "engines": { - "node": ">=12" + "node": ">=10.13.0" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" + "defaults": "^1.0.3" } }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "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==", + "license": "BSD-2-Clause" + }, + "node_modules/webpack": { + "version": "5.95.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz", + "integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.7.1", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.1", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } } }, - "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "node_modules/webpack-node-externals": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz", + "integrity": "sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==", "dev": true, "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.2" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=6" } }, - "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==", - "license": "ISC", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" } }, - "node_modules/winston": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.14.2.tgz", - "integrity": "sha512-CO8cdpBB2yqzEf8v895L+GNKYJiEq8eKlHU38af3snQBQ+sdAIUepjMSguOIJC7ICbzm0ZI+Af2If4vIJrtmOg==", - "license": "MIT", + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, "dependencies": { - "@colors/colors": "^1.6.0", - "@dabh/diagnostics": "^2.0.2", - "async": "^3.2.3", - "is-stream": "^2.0.0", - "logform": "^2.6.0", - "one-time": "^1.0.0", - "readable-stream": "^3.4.0", - "safe-stable-stringify": "^2.3.1", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.7.0" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" }, "engines": { - "node": ">= 12.0.0" + "node": ">=8.0.0" } }, - "node_modules/winston-transport": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.1.tgz", - "integrity": "sha512-wQCXXVgfv/wUPOfb2x0ruxzwkcZfxcktz6JIMUaPLmcNhO4bZTwA/WtDWK74xV3F2dKu8YadrFv0qhwYjVEwhA==", - "license": "MIT", - "dependencies": { - "logform": "^2.6.1", - "readable-stream": "^3.6.2", - "triple-beam": "^1.3.0" - }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, "engines": { - "node": ">= 12.0.0" + "node": ">=4.0" } }, - "node_modules/winston-transport/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==", + "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==", "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" } }, - "node_modules/winston/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", + "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": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" }, "engines": { - "node": ">= 6" + "node": ">= 8" } }, "node_modules/word-wrap": { @@ -10935,6 +9509,22 @@ } }, "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", @@ -10956,6 +9546,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, "license": "ISC" }, "node_modules/write-file-atomic": { @@ -10972,6 +9563,13 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/write-file-atomic/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==", + "dev": true, + "license": "ISC" + }, "node_modules/ws": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", @@ -11019,16 +9617,6 @@ "dev": true, "license": "ISC" }, - "node_modules/yaml": { - "version": "2.0.0-1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz", - "integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 6" - } - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -11080,52 +9668,6 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/z-schema": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", - "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash.get": "^4.4.2", - "lodash.isequal": "^4.5.0", - "validator": "^13.7.0" - }, - "bin": { - "z-schema": "bin/z-schema" - }, - "engines": { - "node": ">=8.0.0" - }, - "optionalDependencies": { - "commander": "^9.4.1" - } - }, - "node_modules/z-schema/node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": "^12.20.0 || >=14" - } - }, - "packages/config": { - "name": "@jukebox/config", - "version": "1.0.0", - "license": "ISC", - "devDependencies": {} - }, - "packages/lib": { - "name": "@jukebox/lib", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "@jukebox/config": "^1.0.0" - } } } } diff --git a/package.json b/package.json index 1b6ad8b..de1621b 100644 --- a/package.json +++ b/package.json @@ -1,88 +1,74 @@ { - "name": "spotify_app", - "version": "1.0.0", - "description": "App that connects to spotify API to do enable OSC members access to music", - "main": "dist/server/index.js", - "scripts": { - "test": "NODE_ENV=test&& npm run build && jest --testTimeout=5000 --detectOpenHandles --forceExit", - "test:watch": "npm run build && jest --watch --testTimeout=5000 --detectOpenHandles --forceExit --verbose", - "test:verbose": "npm run build && jest --testTimeout=5000 --detectOpenHandles --forceExit --verbose", - "start": "NODE_PATH=server node ./dist/server/index.js", - "dev": "npm run dev:server", - "dev:server": "ts-node-dev --respawn --pretty --transpile-only --ignore-watch swagger_output.json -r tsconfig-paths/register --exit-child server/index.ts", - "dev:websocket": "ts-node-dev --respawn --pretty --transpile-only --ignore-watch swagger_output.json -r tsconfig-paths/register --exit-child websocket/index.ts", - "build": "rimraf ./dist && tsc && tsc-alias", - "lint": "npx eslint server/**/*.ts", - "lint:fix": "npm run lint -- --fix" - }, + "name": "jukebox-server", + "version": "0.0.1", + "description": "", "author": "", - "license": "ISC", - "_moduleAliases": { - "src": "./dist/src", - "server": "./dist/server", - "websocket": "./dist/websocket" + "private": true, + "license": "UNLICENSED", + "scripts": { + "build": "nest build", + "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", + "start": "nest start", + "start:dev": "nest start --watch", + "start:debug": "nest start --debug --watch", + "start:prod": "node dist/main", + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", + "test": "jest", + "test:watch": "jest --watch", + "test:cov": "jest --coverage", + "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", + "test:e2e": "jest --config ./test/jest-e2e.json" }, "dependencies": { - "@jukebox/config": "^1.0.0", - "@jukebox/lib": "^1.0.0", + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/mongoose": "^10.0.10", + "@nestjs/platform-express": "^10.0.0", + "@nestjs/platform-socket.io": "^10.4.4", + "@nestjs/websockets": "^10.4.4", "@spotify/web-api-ts-sdk": "^1.2.0", - "axios": "^1.6.7", - "bcrypt": "^5.1.1", - "body-parser": "^1.20.2", - "cookie-parser": "^1.4.6", - "cors": "^2.8.5", - "dotenv": "^16.0.3", - "express": "^4.18.2", - "jsonwebtoken": "^9.0.2", - "kafkajs": "^2.2.4", - "module-alias": "^2.2.3", - "mongoose": "^7.5.2", - "morgan": "^1.10.0", - "multer": "^1.4.5-lts.1", - "socket.io": "^4.7.5", - "url": "^0.11.3", - "winston": "^3.10.0" + "mongoose": "^8.7.0", + "reflect-metadata": "^0.2.0", + "rxjs": "^7.8.1" }, "devDependencies": { - "@types/bcrypt": "^5.0.2", - "@types/cookie-parser": "^1.4.4", - "@types/cors": "^2.8.16", + "@nestjs/cli": "^10.0.0", + "@nestjs/schematics": "^10.0.0", + "@nestjs/testing": "^10.0.0", "@types/express": "^4.17.17", - "@types/jest": "^29.5.12", - "@types/jsonwebtoken": "^9.0.5", - "@types/module-alias": "^2.0.4", - "@types/morgan": "^1.9.9", - "@types/multer": "^1.4.12", - "@types/request": "^2.48.10", - "@types/swagger-ui-express": "^4.1.4", - "@typescript-eslint/eslint-plugin": "^6.19.1", - "@typescript-eslint/parser": "^6.19.1", - "esbuild": "^0.20.0", - "eslint": "^8.56.0", - "eslint-config-prettier": "^9.1.0", - "eslint-config-standard-with-typescript": "^43.0.1", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-n": "^16.6.2", - "eslint-plugin-prefer-arrow-functions": "^3.2.4", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-promise": "^6.1.1", - "jest": "^29.7.0", - "node-mocks-http": "^1.13.0", - "nodemon": "^3.1.4", - "swagger-autogen": "^2.23.1", - "swagger-jsdoc": "^6.2.8", - "swagger-ui-express": "^5.0.0", - "ts-jest": "^29.1.1", + "@types/jest": "^29.5.2", + "@types/node": "^20.3.1", + "@types/supertest": "^6.0.0", + "@typescript-eslint/eslint-plugin": "^8.0.0", + "@typescript-eslint/parser": "^8.0.0", + "eslint": "^8.42.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.0", + "jest": "^29.5.0", + "prettier": "^3.0.0", + "source-map-support": "^0.5.21", + "supertest": "^7.0.0", + "ts-jest": "^29.1.0", + "ts-loader": "^9.4.3", "ts-node": "^10.9.1", - "ts-node-dev": "^2.0.0", - "tsc-alias": "^1.8.8", "tsconfig-paths": "^4.2.0", - "tsx": "^4.7.0", - "typescript": "^5.5.4" + "typescript": "^5.1.3" }, - "workspaces": [ - "packages/a", - "packages/lib", - "packages/config" - ] + "jest": { + "moduleFileExtensions": [ + "js", + "json", + "ts" + ], + "rootDir": "src", + "testRegex": ".*\\.spec\\.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + }, + "collectCoverageFrom": [ + "**/*.(t|j)s" + ], + "coverageDirectory": "../coverage", + "testEnvironment": "node" + } } diff --git a/packages/config/constants.ts b/packages/config/constants.ts deleted file mode 100644 index 7f342e8..0000000 --- a/packages/config/constants.ts +++ /dev/null @@ -1,13 +0,0 @@ -import 'dotenv/config' - -type nodenv = 'development' | 'production' | 'test' | 'network' - -export const NODE_ENV: nodenv = (process.env.NODE_ENV as nodenv) || 'development' - -export const LOG_LEVEL = process.env.LOG_LEVEL || 'warn' -export const LOG_NS = process.env.LOG_NS || 'server' - -export const KAFKA_BROKERS = process.env.KAFKA_BROKERS?.split(',') ?? ['kafka:9092'] -export const KAFKA_GROUP_ID = process.env.KAFKA_GROUP_ID ?? 'jbx-server' -export const KAFKA_CONNECT_TIMEOUT_MS = +(process.env.KAFKA_CONNECT_TIMEOUT_MS ?? 60000) -export const KAFKA_REQ_TIMEOUT_MS = +(process.env.KAFKA_REQ_TIMEOUT_MS ?? KAFKA_CONNECT_TIMEOUT_MS) \ No newline at end of file diff --git a/packages/config/index.ts b/packages/config/index.ts deleted file mode 100644 index f87cf01..0000000 --- a/packages/config/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './constants' diff --git a/packages/config/package.json b/packages/config/package.json deleted file mode 100644 index e74ce69..0000000 --- a/packages/config/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "@jukebox/config", - "version": "1.0.0", - "main": "index.ts", - "devDependencies": {}, - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "ISC", - "description": "" -} diff --git a/packages/lib/index.ts b/packages/lib/index.ts deleted file mode 100644 index 5efbd46..0000000 --- a/packages/lib/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * @module lib - * @description External library managers. - * - * Use this directory to create proxy classes and functions for libraries like Axios, - * Kafka, etc. This will aid in keeping the codebase safe against deprecation. - */ -export * from './kafka' -export * from './logger' diff --git a/packages/lib/kafka.ts b/packages/lib/kafka.ts deleted file mode 100644 index 3276bc8..0000000 --- a/packages/lib/kafka.ts +++ /dev/null @@ -1,198 +0,0 @@ -/** - * Kafka Configuration with KafkaJS - * - * Resources: - * https://kafka.js.org/docs/introduction - */ - -import { Kafka, Partitioners, logLevel, type Message } from 'kafkajs' -import { KAFKA_BROKERS, KAFKA_CONNECT_TIMEOUT_MS, KAFKA_GROUP_ID, KAFKA_REQ_TIMEOUT_MS, NODE_ENV } from '@jukebox/config' -import { logger } from './logger' - -const toWinstonLogLevel = (level: logLevel) => { - switch (level) { - case logLevel.ERROR: - return 'warn' - case logLevel.WARN: - return 'info' - case logLevel.INFO: - case logLevel.NOTHING: - case logLevel.DEBUG: - return 'debug' - default: - return 'debug' - } -} - -const WinstonLogCreator = () => { - return (entry: { - namespace: string - level: logLevel - label: string - log: { message: string } - }) => { - const { log, level } = entry - const { message, ...extra } = log - - logger.log({ - level: toWinstonLogLevel(level), - message, - service: 'kafka', - extra - }) - } -} - -const getKafkaInstance = () => { - if (NODE_ENV === 'network' || NODE_ENV === 'production') { - return new Kafka({ - clientId: KAFKA_GROUP_ID, - brokers: KAFKA_BROKERS, - logLevel: logLevel.INFO, - logCreator: WinstonLogCreator, - connectionTimeout: KAFKA_CONNECT_TIMEOUT_MS, - requestTimeout: KAFKA_REQ_TIMEOUT_MS, - - retry: { - retries: 5, - restartOnFailure: async () => true, - maxRetryTime: KAFKA_REQ_TIMEOUT_MS - } - }) - } else { - return {} as Kafka - } -} - -export const kafka = getKafkaInstance() - -/** - * Create a producer for a Kafka topic. - * @param topic - The topic to produce to. - * @param action - The action to send to the consumer. - * - * @returns wrapper function - * @param key - Used to determine partition, resource level id - * @param data - The data to send to Kafka - * - */ -export const createProducer = - (topic: string, action?: string) => - async (key: string, data: T | T[]) => { - if (NODE_ENV === 'network' || NODE_ENV === 'production') { - const producer = kafka.producer({ - createPartitioner: Partitioners.DefaultPartitioner, - allowAutoTopicCreation: true - }) - await producer.connect() - let messages: Message[] - - if (Array.isArray(data)) { - messages = data.map((item) => ({ key, value: JSON.stringify({ action, data: item }) })) - } else { - messages = [{ key, value: JSON.stringify({ action, data }) }] - } - - await producer - .send({ - topic, - messages - }) - .then(() => { - logger.debug(`Produced message for ${topic}.`) - }) - .catch((error) => { - logger.error('Error sending producer message:', error) - }) - await producer.disconnect() - } - } - -/** - * Create a consumer for a Kafka topic. - * - * @param topic - The topic to consume from. - * @param action - The action to listen for. - * @param callback - The callback to run when the action is received. - * @param options - Optional configuration parameters - */ -export const createConsumer = async ( - topic: string, - callback: (data: any, action?: string) => Promise | void, - options?: { fromBeginning?: boolean; manualCommit?: boolean } -) => { - if (NODE_ENV === 'network' || NODE_ENV === 'production') { - const consumer = kafka.consumer({ - groupId: `${KAFKA_GROUP_ID}-${topic}`, - sessionTimeout: 10000, - heartbeatInterval: 1000, - allowAutoTopicCreation: true, - retry: { - retries: 5, - restartOnFailure: async () => true, - maxRetryTime: 20000 - } - }) - await consumer.connect() - await consumer - .subscribe({ - topic, - fromBeginning: options?.fromBeginning || false - }) - .then(() => { - logger.info(`Consumer created for ${topic}.`) - }) - if (!options?.manualCommit) { - await consumer.run({ - eachMessage: async ({ message }) => { - try { - const payload = JSON.parse(message.value?.toString() || '') - const { action, data } = payload - logger.debug(`Consumed message for ${topic}.`) - - await callback(data, action) - } catch (error) { - logger.error('Error handling data from event queue:', error) - } - } - }) - } else { - await consumer.run({ - eachBatchAutoResolve: false, - eachBatch: async ({ - batch, - resolveOffset, - heartbeat, - isRunning, - isStale, - commitOffsetsIfNecessary - }) => { - if (!isRunning() || isStale()) return - logger.debug( - `Consumed batch for ${topic} with ${batch.messages.length} ${ - (batch.messages.length === 1 && 'message') || 'messages' - }.` - ) - // pause() - - await Promise.all( - batch.messages.map(async (message) => { - if (!isRunning() || isStale()) return - - const payload = JSON.parse(message.value?.toString() || '') - const { action, data } = payload - - await callback(data, action) - resolveOffset(message.offset) - - await heartbeat() - }) - ).then(() => { - logger.debug(`Finished batch for ${topic}.`) - commitOffsetsIfNecessary() - }) - } - }) - } - } -} diff --git a/packages/lib/logger.ts b/packages/lib/logger.ts deleted file mode 100644 index fd419df..0000000 --- a/packages/lib/logger.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { addColors, createLogger, format, transports } from 'winston' -import { LOG_LEVEL, LOG_NS } from '@jukebox/config' - -const consoleTransport = new transports.Console({ - format: format.combine( - format.colorize({ all: true }), - format.timestamp({ format: 'YYYY-MM-DD hh:mm:ss.SSS' }), - format.printf((info) => { - return `[${info.level}] [${info.service || LOG_NS}] ${info.message}` - }) - ), - level: LOG_LEVEL -}) - -addColors({ - error: 'red', - warn: 'yellow', - info: 'green', - http: 'cyan', - debug: 'grey' -}) - -export const logger = createLogger({ - level: LOG_LEVEL, - format: format.json(), - transports: [consoleTransport], - levels: { - error: 0, - warn: 1, - info: 2, - http: 3, - debug: 4 - } -}) diff --git a/packages/lib/package.json b/packages/lib/package.json deleted file mode 100644 index 5b07727..0000000 --- a/packages/lib/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "@jukebox/lib", - "version": "1.0.0", - "main": "index.ts", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "ISC", - "description": "", - "dependencies": { - "@jukebox/config": "^1.0.0" - } -} diff --git a/server/Dockerfile b/server/Dockerfile deleted file mode 100644 index 182f011..0000000 --- a/server/Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -# Server Image -################################################ -FROM node:20-bookworm - -WORKDIR /app - -COPY ./package.json /app/package.json -COPY ./package-lock.json /app/package-lock.json -COPY ./packages /app/packages - -ARG NODE_ENV=development - -USER root - -RUN npm install -g npm && \ - npm install -g typescript && \ - npm install -g rimraf && \ - npm install - -COPY ./tsconfig.json /app/tsconfig.json -COPY ./jest.config.ts /app/jest.config.ts -COPY ./server/ /app/server - -RUN npm run build - -EXPOSE 8000 -VOLUME ["/app/server"] - -CMD ["npm", "start"] diff --git a/server/config/constants.ts b/server/config/constants.ts deleted file mode 100644 index 66eaba2..0000000 --- a/server/config/constants.ts +++ /dev/null @@ -1,26 +0,0 @@ -import 'dotenv/config' - -type nodenv = 'development' | 'production' | 'test' | 'network' - -// export const NODE_ENV: nodenv = (process.env.NODE_ENV as nodenv) || 'development' -export const HOST: string = process.env.HOST || 'localhost' -export const PORT = process.env.PORT || 3000 -export const MONGO_URI = process.env.MONGO_URI || 'mongodb://localhost:27017/mongo-jukebox' -export const BASE_URL = process.env.BASE_URL || `http://${HOST}:${PORT}` - -export const JWT_SECRET_KEY: string = process.env.JWT_SECRET_KEY || 'secret' -export const JWT_ISSUER = process.env.JWT_ISSUER || 'jukebox' -export const JWT_ALGORITHM = 'HS256' -export const AUTH_TOKEN_COOKIE_NAME = 'dev-auth-token' -// export const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || '1h' - -export const SPOTIFY_CLIENT_ID = process.env.SPOTIFY_CLIENT_ID || 'changeme' -export const SPOTIFY_CLIENT_SECRET = process.env.SPOTIFY_CLIENT_SECRET || 'changeme' -export const SPOTIFY_REDIRECT_PATH = '/api/spotify/login-callback/' -export const SPOTIFY_REDIRECT_URI = BASE_URL + SPOTIFY_REDIRECT_PATH - -// export const LOG_LEVEL = process.env.LOG_LEVEL || 'warn' -// export const LOG_NS = process.env.LOG_NS || 'server' - -// export const KAFKA_BROKERS = process.env.KAFKA_BROKERS?.split(',') ?? ['kafka:9092'] -// export const KAFKA_GROUP_ID = process.env.KAFKA_GROUP_ID ?? 'jbx-server' diff --git a/server/config/database.ts b/server/config/database.ts deleted file mode 100644 index 7f65eb4..0000000 --- a/server/config/database.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { logger } from '@jukebox/lib' -import mongoose from 'mongoose' -import { MONGO_URI } from './constants' - -export const setupDatabase = async (): Promise => { - await mongoose - .connect(MONGO_URI, { - autoIndex: true, - socketTimeoutMS: 5000 - }) - .then(() => { - logger.info('Connected to MongoDB successfully') - }) - .catch((err: any) => { - logger.error('Error connecting to MongoDB: ', err) - }) -} diff --git a/server/config/index.ts b/server/config/index.ts deleted file mode 100644 index d586e18..0000000 --- a/server/config/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './constants' -export { setupDatabase } from './database' -// export { server } from './server' diff --git a/server/config/jest.setup.ts b/server/config/jest.setup.ts deleted file mode 100644 index 2de065c..0000000 --- a/server/config/jest.setup.ts +++ /dev/null @@ -1,27 +0,0 @@ -import mongoose from 'mongoose' -import 'dotenv/config' - -// const MONGO_URI = `mongodb://${process.env.MONGO_USER}:${process.env.MONGO_PASSWORD}@${process.env.MONGO_HOST}:${process.env.MONGO_PORT}/${process.env.MONGO_DB}`; -const MONGO_URI = process.env.MONGO_URI - -const connect = async () => { - await mongoose.connect(MONGO_URI || '') -} - -const closeDatabase = async () => { - await mongoose.connection.dropDatabase() - await mongoose.connection.close() -} - -const clearDatabase = async () => { - // await mongoose.connection.dropDatabase(); - const collections = mongoose.connection.collections - for (const key in collections) { - const collection = collections[key] - await collection.deleteMany({}) - } -} - -beforeEach(async () => await connect()) -afterEach(async () => await clearDatabase()) -afterAll(async () => await closeDatabase()) diff --git a/server/config/server.ts b/server/config/server.ts deleted file mode 100644 index 442560d..0000000 --- a/server/config/server.ts +++ /dev/null @@ -1,29 +0,0 @@ -import express from 'express' -import morgan from 'morgan' -import multer from 'multer' - -import { logger } from '@jukebox/lib' -import cookieParser from 'cookie-parser' -import { errorHandler } from 'server/middleware' -import { router } from 'server/routes' - -const server = express() - -const urlencodedParser = express.urlencoded({ extended: false }) -const jsonParser = express.json() - -server.use(urlencodedParser) -server.use(jsonParser) -server.use(multer().any()) -server.use(cookieParser()) - -server.use( - morgan(':remote-addr :method :url :status :res[content-length] - :response-time ms', { - stream: { write: (message) => logger.http(message, { service: 'express' }) } - }) -) - -server.use(router) -server.use(errorHandler) - -export { server } diff --git a/server/controllers/groupController.ts b/server/controllers/groupController.ts deleted file mode 100644 index ee9baf6..0000000 --- a/server/controllers/groupController.ts +++ /dev/null @@ -1,96 +0,0 @@ -import type { Model } from 'mongoose' -import { Group, SpotifyAuth, type User } from 'server/models' -import { SpotifyService } from 'server/services' -import { NotFoundError } from 'server/utils' - -const getOrError = async >(id: string, model: T): Promise> => { - const query = await model.findById(id) - if (!query) { - throw new NotFoundError(`${model.name} with id ${id} not found.`) - } - - return query -} - -export const assignSpotifyToGroup = async ( - user: User, - groupId: string, - spotifyEmail: string -): Promise => { - const auth = await SpotifyAuth.findOne({ userId: user._id.toString(), spotifyEmail }) - - if (!auth) - throw new Error(`User ${user.email} is not connected to spotify account ${spotifyEmail}.`) - - const group = await getOrError(groupId, Group) - - await group.updateOne({ spotifyAuthId: auth._id }, { new: true }) - return group -} - -export const getGroupSpotifyAuth = async (groupId: string) => { - const group = await getOrError(groupId, Group) - const auth = await getOrError(group.spotifyAuthId?.toString() ?? '', SpotifyAuth) - - if (auth.isExpired()) { - const spotify = await SpotifyService.connect(auth.spotifyEmail) - const updatedAccessToken = await spotify.getAccessToken() - auth.accessToken = updatedAccessToken - auth.save() - } - - return auth -} - -export const getGroupSpotify = async (groupId: string) => { - const auth = await getGroupSpotifyAuth(groupId) - // const group = await getOrError(groupId, Group) - - // const auth = await SpotifyAuth.findById(group.spotifyAuthId) - // if (!auth) throw new Error(`No linked Spotify accounts for group ${group.name}.`) - - return SpotifyService.connect(auth.spotifyEmail) -} - -export const getGroupTrack = async (groupId: string) => { - const spotify = await getGroupSpotify(groupId) - return await spotify.sdk.player.getCurrentlyPlayingTrack() -} - -export const getGroupDevices = async (groupId: string) => { - const spotify = await getGroupSpotify(groupId) - return await spotify.sdk.player.getAvailableDevices() -} - -export const setGroupDefaultDevice = async (groupId: string, deviceId: string) => { - const group = await getOrError(groupId, Group) - group.defaultDeviceId = deviceId - await group.save() - - return group -} - -export const setGroupPlayerState = async ( - groupId: string, - state: 'play' | 'pause' | 'next' | 'previous' -) => { - const spotify = await getGroupSpotify(groupId) - const group = await getOrError(groupId, Group) - - switch (state) { - case 'play': - await spotify.sdk.player.startResumePlayback(group.defaultDeviceId ?? '') - break - case 'pause': - await spotify.sdk.player.pausePlayback(group.defaultDeviceId ?? '') - break - case 'next': - await spotify.sdk.player.skipToNext(group.defaultDeviceId ?? '') - break - case 'previous': - await spotify.sdk.player.skipToPrevious(group.defaultDeviceId ?? '') - break - default: - throw new Error(`Cannot set player state to ${state}.`) - } -} diff --git a/server/controllers/index.ts b/server/controllers/index.ts deleted file mode 100644 index a785c73..0000000 --- a/server/controllers/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './groupController' -export * from './userController' diff --git a/server/controllers/userController.ts b/server/controllers/userController.ts deleted file mode 100644 index 28c4b91..0000000 --- a/server/controllers/userController.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { SpotifyAuth, User } from 'server/models' -import { AuthService } from 'server/services' -import { NotFoundError } from 'server/utils' - -// TODO: Implement user from middleware - -export const registerUser = async (email: string, password: string): Promise => { - return await AuthService.registerUser({ email, password }) -} - -export const getUserToken = async (email: string, password: string): Promise => { - const user: User = await AuthService.authorizeUser(email, password) - return await AuthService.generateToken(user) -} - -export const requestPasswordReset = async (email: string): Promise => { - const user: User | null = await User.findOne({ email: email }) - console.log('reset password for: ', user) - - // TODO: Send email to user with reset link - return false -} - -export const resetPassword = async (email: string, newPassword: string): Promise => { - const user: User | null = await User.findOne({ email: email }) - - if (!user) throw new NotFoundError('User not found.') - - const updatedUser: User = await AuthService.changePassword(user, newPassword) - return true -} - -export const getUserSpotifyEmails = async (user: User): Promise => { - const auths = await SpotifyAuth.find({ userId: user._id }) - return auths.map((auth) => auth.spotifyEmail) -} diff --git a/server/docs/swagger.ts b/server/docs/swagger.ts deleted file mode 100644 index 1d92a73..0000000 --- a/server/docs/swagger.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { BASE_URL } from 'server/config' -import type { IGroup, IGroupFields, IUser } from 'server/models' -import { ResponseCodes, formatJsonResponse } from 'server/utils' -import swaggerAutogen from 'swagger-autogen' - -const outputFile = './docs/swagger_output.json' -const endpointsFiles = ['server/routes/router.ts'] - -swaggerAutogen({ openapi: '3.0.0' }) - -const doc = { - info: { - version: '1.0.0', - title: 'Jukebox API', - description: 'Documentation automatically generated by the swagger-autogen module.' - }, - host: BASE_URL.replace(/(http|https):\/\//, ''), - basePath: '/', - schemes: ['http', 'https'], - consumes: ['application/json'], - produces: ['application/json'], - tags: [ - { - name: 'General', - description: 'General endpoints' - }, - { - name: 'User', - description: 'User management' - }, - { - name: 'Spotify', - description: 'Communicate with Spotify' - } - ], - components: {}, - securityDefinitions: { - Bearer: { - type: 'apiKey', - name: 'Authorization', - in: 'header', - description: 'The token for authentication into system.' - } - }, - definitions: { - IGroupFields: { name: '', ownerId: '' } as IGroupFields, - IGroup: { id: '', name: '', ownerId: '' } as IGroup, - IUser: new (class implements IUser { - id: string = 'some-id' - email: string = 'user@example.com' - firstName?: string | undefined - lastName?: string | undefined - image?: string | undefined - })(), - IUserDetails: { - id: 'abc123', - firstName: 'John', - email: 'john@example.com', - lastName: 'Doe', - groups: [{ id: '456def', name: 'Example Group', ownerId: 'abc123' }], - image: - 'https://static.vecteezy.com/system/resources/thumbnails/001/840/618/small_2x/picture-profile-icon-male-icon-human-or-people-sign-and-symbol-free-vector.jpg' - } as IUser & { groups: IGroup[] } - } -} -const generateResponseDocs = () => { - const codes = ResponseCodes - - for (const codeStr of Object.keys(codes)) { - const code = parseInt(codeStr) - if (code > 299) { - doc.definitions[`Error${code}`] = formatJsonResponse(code, 'Example message') - } else { - doc.definitions[`Success${code}`] = formatJsonResponse(code, 'Example message') - } - } -} - -export const initializeSwagger = async () => { - generateResponseDocs() - return await swaggerAutogen()(outputFile, endpointsFiles, doc) -} diff --git a/server/docs/swagger_output.json b/server/docs/swagger_output.json deleted file mode 100644 index bfbddf6..0000000 --- a/server/docs/swagger_output.json +++ /dev/null @@ -1,2066 +0,0 @@ -{ - "swagger": "2.0", - "info": { - "version": "1.0.0", - "title": "Jukebox API", - "description": "Documentation automatically generated by the swagger-autogen module." - }, - "host": "localhost:8080", - "basePath": "/", - "tags": [ - { - "name": "General", - "description": "General endpoints" - }, - { - "name": "User", - "description": "User management" - }, - { - "name": "Spotify", - "description": "Communicate with Spotify" - } - ], - "schemes": [ - "http", - "https" - ], - "securityDefinitions": { - "Bearer": { - "type": "apiKey", - "name": "Authorization", - "in": "header", - "description": "The token for authentication into system." - } - }, - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "paths": { - "/": { - "get": { - "tags": [ - "General" - ], - "summary": "Health Check", - "description": "Root route to check if the system is online.", - "responses": { - "default": { - "description": "" - } - } - } - }, - "/api": { - "get": { - "tags": [ - "General" - ], - "summary": "API Help and Navigation", - "description": "Main links to use for navigating api.", - "responses": { - "200": { - "schema": { - "type": "object", - "properties": { - "spotifyLogin": { - "type": "string", - "example": "http://localhost:8000/api/spotify/login/" - }, - "documenation": { - "type": "string", - "example": "http://localhost:8000/api/docs/" - } - }, - "xml": { - "name": "main" - } - }, - "description": "Monitor updated" - } - } - } - }, - "/api/ping": { - "get": { - "tags": [ - "General" - ], - "summary": "Test out flow of events from client to server.", - "description": "Triggers a Kafka event that every server as a consumer for, forcing them all to respond for sanity checks.", - "responses": { - "default": { - "description": "" - } - } - } - }, - "/api/spotify/login": { - "get": { - "tags": [ - "Spotify" - ], - "description": "", - "parameters": [ - { - "name": "redirectUri", - "in": "query", - "type": "string" - }, - { - "name": "groupId", - "in": "query", - "type": "string" - } - ], - "responses": { - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - } - }, - "/api/spotify/login-callback": { - "get": { - "tags": [ - "Spotify" - ], - "description": "", - "parameters": [ - { - "name": "code", - "in": "query", - "type": "string" - }, - { - "name": "state", - "in": "query", - "type": "string" - } - ], - "responses": { - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - } - } - }, - "/api/spotify/": { - "delete": { - "tags": [ - "Spotify" - ], - "description": "", - "parameters": [ - { - "name": "body", - "in": "body", - "schema": { - "type": "object", - "properties": { - "spotifyEmail": { - "example": "any" - } - } - } - } - ], - "responses": { - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - } - }, - "/api/user/register": { - "post": { - "tags": [ - "User" - ], - "summary": "Register new user", - "description": "Create a new user account", - "parameters": [ - { - "name": "body", - "in": "body", - "schema": { - "type": "object", - "properties": { - "email": { - "example": "any" - }, - "password": { - "example": "any" - } - } - } - } - ], - "responses": { - "200": { - "description": "Return created user", - "schema": { - "$ref": "#/definitions/IUser" - } - }, - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - } - } - }, - "/api/user/token": { - "post": { - "tags": [ - "User" - ], - "summary": "Get token for logging in a user", - "description": "", - "parameters": [ - { - "name": "body", - "in": "body", - "schema": { - "type": "object", - "properties": { - "email": { - "example": "any" - }, - "password": { - "example": "any" - } - } - } - } - ], - "responses": { - "200": { - "schema": { - "type": "object", - "properties": { - "token": { - "type": "string", - "example": "example-token" - } - }, - "xml": { - "name": "main" - } - }, - "description": "OK" - }, - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - } - } - }, - "/api/user/request-password-reset": { - "post": { - "tags": [ - "User" - ], - "summary": "Request a password reset for authenticated user (TODO)", - "description": "", - "parameters": [ - { - "name": "body", - "in": "body", - "schema": { - "type": "object", - "properties": { - "schema": { - "example": "any" - }, - "description": { - "example": "any" - } - } - } - } - ], - "responses": { - "200": { - "schema": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 200 - }, - "type": { - "type": "string", - "example": "Ok" - } - }, - "xml": { - "name": "main" - } - }, - "description": "OK" - }, - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - } - }, - "/api/user/reset-password": { - "post": { - "tags": [ - "User" - ], - "summary": "Allow user to reset password from reset request (TODO)", - "description": "", - "parameters": [ - { - "name": "body", - "in": "body", - "schema": { - "type": "object", - "properties": { - "schema": { - "example": "any" - }, - "description": { - "example": "any" - } - } - } - } - ], - "responses": { - "200": { - "schema": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 200 - }, - "type": { - "type": "string", - "example": "Ok" - } - }, - "xml": { - "name": "main" - } - }, - "description": "OK" - }, - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - } - }, - "/api/user/me": { - "get": { - "tags": [ - "User" - ], - "summary": "Get info about the authenticated user", - "description": "", - "responses": { - "200": { - "schema": { - "$ref": "#/definitions/IUserDetails" - }, - "description": "OK" - }, - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - }, - "put": { - "description": "", - "parameters": [ - { - "name": "body", - "in": "body", - "schema": { - "type": "object", - "properties": { - "firstName": { - "example": "any" - }, - "lastName": { - "example": "any" - }, - "image": { - "example": "any" - } - } - } - } - ], - "responses": { - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - } - }, - "/api/user/me/spotify-accounts": { - "get": { - "tags": [ - "User" - ], - "summary": "Get connected spotify accounts for user", - "description": "", - "responses": { - "200": { - "schema": { - "type": "object", - "properties": {}, - "xml": { - "name": "main" - } - }, - "description": "OK" - }, - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - } - }, - "/api/user/users": { - "post": { - "tags": [ - "User" - ], - "summary": "Create a new user", - "description": "", - "responses": { - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - }, - "get": { - "tags": [ - "User" - ], - "summary": "Get a list of all users", - "description": "", - "responses": { - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - } - }, - "/api/user/users/{id}": { - "get": { - "tags": [ - "User" - ], - "summary": "Get a single user by id", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": "string" - } - ], - "responses": { - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - }, - "put": { - "tags": [ - "User" - ], - "summary": "Update all fields on a user", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": "string" - } - ], - "responses": { - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - }, - "patch": { - "tags": [ - "User" - ], - "summary": "Update some fields on a user", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": "string" - } - ], - "responses": { - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - }, - "delete": { - "tags": [ - "User" - ], - "summary": "Delete a user by id", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": "string" - } - ], - "responses": { - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - } - }, - "/api/group/{id}/spotify/current-track": { - "get": { - "tags": [ - "Group" - ], - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": "string" - } - ], - "responses": { - "200": { - "schema": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "66e9f064f4b6247a0c26291e" - }, - "ownerId": { - "type": "string", - "example": "66e8a2e7f4b6247a0c262910" - }, - "name": { - "type": "string", - "example": "group" - }, - "spotifyAuthId": { - "type": "string", - "example": "66e9fbbcb14c1ccc11b3d8fd" - } - }, - "xml": { - "name": "main" - } - }, - "description": "Success" - }, - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - } - }, - "/api/group/{id}/spotify/state": { - "post": { - "tags": [ - "Group" - ], - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": "string" - }, - { - "name": "body", - "in": "body", - "schema": { - "type": "object", - "properties": { - "state": { - "example": "any" - } - } - } - } - ], - "responses": { - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - } - }, - "/api/group/{id}/spotify/devices": { - "get": { - "tags": [ - "Group" - ], - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": "string" - } - ], - "responses": { - "200": { - "schema": { - "type": "object", - "properties": { - "devices": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "ff25d0139c6039819da122cacbdb275fe83e5286" - }, - "is_active": { - "type": "boolean", - "example": false - }, - "is_private_session": { - "type": "boolean", - "example": false - }, - "is_restricted": { - "type": "boolean", - "example": false - }, - "name": { - "type": "string", - "example": "Nabeel’s MacBook Air" - }, - "supports_volume": { - "type": "boolean", - "example": true - }, - "type": { - "type": "string", - "example": "Computer" - }, - "volume_percent": { - "type": "number", - "example": 81 - } - } - } - } - }, - "xml": { - "name": "main" - } - }, - "description": "Success" - }, - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - } - }, - "/api/group/{id}/spotify/default-device": { - "post": { - "tags": [ - "Group" - ], - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": "string" - }, - { - "name": "body", - "in": "body", - "schema": { - "type": "object", - "properties": { - "deviceId": { - "example": "any" - } - } - } - } - ], - "responses": { - "200": { - "schema": { - "type": "object", - "properties": { - "spotifyLogin": { - "type": "string", - "example": "http://localhost:8000/api/spotify/login/" - }, - "documenation": { - "type": "string", - "example": "http://localhost:8000/api/docs/" - } - }, - "xml": { - "name": "main" - } - }, - "description": "Monitor updated" - }, - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - } - }, - "/api/group/{id}/spotify/auth": { - "get": { - "tags": [ - "Group" - ], - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": "string" - } - ], - "responses": { - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - }, - "post": { - "tags": [ - "Group" - ], - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": "string" - }, - { - "name": "body", - "in": "body", - "schema": { - "type": "object", - "properties": { - "spotifyEmail": { - "example": "any" - } - } - } - } - ], - "responses": { - "200": { - "schema": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "66e9f064f4b6247a0c26291e" - }, - "ownerId": { - "type": "string", - "example": "66e8a2e7f4b6247a0c262910" - }, - "name": { - "type": "string", - "example": "group" - }, - "spotifyAuthId": { - "type": "string", - "example": "66e9fbbcb14c1ccc11b3d8fd" - } - }, - "xml": { - "name": "main" - } - }, - "description": "Monitor updated" - }, - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - } - }, - "/api/group/groups": { - "post": { - "tags": [ - "Group" - ], - "description": "", - "parameters": [ - { - "name": "body", - "in": "body", - "description": "Group Object", - "required": true, - "schema": { - "$ref": "#/definitions/IGroupFields" - } - } - ], - "responses": { - "200": { - "schema": { - "$ref": "#/definitions/IGroup" - }, - "description": "OK" - }, - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - }, - "get": { - "tags": [ - "Group" - ], - "description": "", - "responses": { - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - } - } - }, - "/api/group/groups/{id}": { - "get": { - "tags": [ - "Group" - ], - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": "string" - } - ], - "responses": { - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - }, - "put": { - "tags": [ - "Group" - ], - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": "string" - } - ], - "responses": { - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - }, - "patch": { - "tags": [ - "Group" - ], - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": "string" - } - ], - "responses": { - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - }, - "delete": { - "tags": [ - "Group" - ], - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": "string" - } - ], - "responses": { - "400": { - "schema": { - "$ref": "#/definitions/Error400" - }, - "description": "Bad request" - }, - "404": { - "schema": { - "$ref": "#/definitions/Error404" - }, - "description": "Not found" - }, - "500": { - "schema": { - "$ref": "#/definitions/Error500" - }, - "description": "Internal Server Error" - }, - "501": { - "schema": { - "$ref": "#/definitions/Error501" - }, - "description": "Not implemented" - } - }, - "security": [ - { - "Bearer": [] - } - ] - } - } - }, - "definitions": { - "IGroupFields": { - "type": "object", - "properties": { - "name": { - "type": "string", - "example": "" - }, - "ownerId": { - "type": "string", - "example": "" - } - } - }, - "IGroup": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "" - }, - "name": { - "type": "string", - "example": "" - }, - "ownerId": { - "type": "string", - "example": "" - } - } - }, - "IUser": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "some-id" - }, - "email": { - "type": "string", - "example": "user@example.com" - } - } - }, - "IUserDetails": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "abc123" - }, - "firstName": { - "type": "string", - "example": "John" - }, - "email": { - "type": "string", - "example": "john@example.com" - }, - "lastName": { - "type": "string", - "example": "Doe" - }, - "groups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "456def" - }, - "name": { - "type": "string", - "example": "Example Group" - }, - "ownerId": { - "type": "string", - "example": "abc123" - } - } - } - }, - "image": { - "type": "string", - "example": "https://static.vecteezy.com/system/resources/thumbnails/001/840/618/small_2x/picture-profile-icon-male-icon-human-or-people-sign-and-symbol-free-vector.jpg" - } - } - }, - "Success200": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 200 - }, - "type": { - "type": "string", - "example": "Ok" - }, - "message": { - "type": "string", - "example": "Example message" - } - } - }, - "Success201": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 201 - }, - "type": { - "type": "string", - "example": "Created" - }, - "message": { - "type": "string", - "example": "Example message" - } - } - }, - "Success204": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 204 - }, - "type": { - "type": "string", - "example": "No Content" - }, - "message": { - "type": "string", - "example": "Example message" - } - } - }, - "Error301": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 301 - }, - "type": { - "type": "string", - "example": "Moved Perminantly" - }, - "message": { - "type": "string", - "example": "Example message" - } - } - }, - "Error302": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 302 - }, - "type": { - "type": "string", - "example": "Found" - }, - "message": { - "type": "string", - "example": "Example message" - } - } - }, - "Error303": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 303 - }, - "type": { - "type": "string", - "example": "See Other" - }, - "message": { - "type": "string", - "example": "Example message" - } - } - }, - "Error400": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 400 - }, - "type": { - "type": "string", - "example": "Bad Request" - }, - "message": { - "type": "string", - "example": "Example message" - } - } - }, - "Error401": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 401 - }, - "type": { - "type": "string", - "example": "Unauthorized" - }, - "message": { - "type": "string", - "example": "Example message" - } - } - }, - "Error403": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 403 - }, - "type": { - "type": "string", - "example": "Forbidden" - }, - "message": { - "type": "string", - "example": "Example message" - } - } - }, - "Error404": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 404 - }, - "type": { - "type": "string", - "example": "Not Found" - }, - "message": { - "type": "string", - "example": "Example message" - } - } - }, - "Error405": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 405 - }, - "type": { - "type": "string", - "example": "Method Not Allowed" - }, - "message": { - "type": "string", - "example": "Example message" - } - } - }, - "Error409": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 409 - }, - "type": { - "type": "string", - "example": "Conflict" - }, - "message": { - "type": "string", - "example": "Example message" - } - } - }, - "Error410": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 410 - }, - "type": { - "type": "string", - "example": "Gone" - }, - "message": { - "type": "string", - "example": "Example message" - } - } - }, - "Error500": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 500 - }, - "type": { - "type": "string", - "example": "Internal Server Error" - }, - "message": { - "type": "string", - "example": "Example message" - } - } - }, - "Error501": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 501 - }, - "type": { - "type": "string", - "example": "Not Implemented" - }, - "message": { - "type": "string", - "example": "Example message" - } - } - }, - "Error502": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 502 - }, - "type": { - "type": "string", - "example": "Bad Gateway" - }, - "message": { - "type": "string", - "example": "Example message" - } - } - }, - "Error503": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 503 - }, - "type": { - "type": "string", - "example": "Service Unavailable" - }, - "message": { - "type": "string", - "example": "Example message" - } - } - }, - "Error504": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 504 - }, - "type": { - "type": "string", - "example": "Gateway Timeout" - }, - "message": { - "type": "string", - "example": "Example message" - } - } - }, - "Error511": { - "type": "object", - "properties": { - "status": { - "type": "number", - "example": 511 - }, - "type": { - "type": "string", - "example": "Network Authentication Required" - }, - "message": { - "type": "string", - "example": "Example message" - } - } - } - } -} \ No newline at end of file diff --git a/server/events/consumers.ts b/server/events/consumers.ts deleted file mode 100644 index d85c564..0000000 --- a/server/events/consumers.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { createConsumer, logger } from '@jukebox/lib' - -export const registerConsumers = async () => { - createConsumer('ping-pong', (data) => { - const logData = data ?? 'No data received.' - logger.info(`Pong: ${logData}`) - }) -} diff --git a/server/events/index.ts b/server/events/index.ts deleted file mode 100644 index d3282ae..0000000 --- a/server/events/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -/** - * Producers and consumers for Kafka. - * Instantiated in src/config/kafka.ts - */ -export * from './consumers' diff --git a/server/events/producers.ts b/server/events/producers.ts deleted file mode 100644 index fd61361..0000000 --- a/server/events/producers.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { createProducer } from '@jukebox/lib' - -export const producePing = createProducer('ping-pong') diff --git a/server/index.ts b/server/index.ts deleted file mode 100644 index 4019434..0000000 --- a/server/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -/** - * @fileoverview Entry point of the application. - */ -// import 'module-alias/register' -// if (process.env.NODE_ENV === 'production') { -// require('module-alias/register') -// } - -import 'dotenv/config' -import swaggerUi from 'swagger-ui-express' - -import { NODE_ENV } from '@jukebox/config' -import { logger } from '@jukebox/lib' -import { HOST, PORT, setupDatabase } from './config' -import { server } from './config/server' // Direct import, otherwise it breaks on tests -import { initializeSwagger } from './docs/swagger' -import { registerConsumers } from './events' - -setupDatabase() - -if (NODE_ENV === 'production' || NODE_ENV === 'network') { - registerConsumers() -} - -initializeSwagger().then(async () => { - const swaggerDocument = await import('server/docs/swagger_output.json') - server.use('/api/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument, { explorer: true })) -}) - -server.listen(PORT, () => { - logger.info(`Server running at http://${HOST}:${PORT}.`) -}) diff --git a/server/lib/index.ts b/server/lib/index.ts deleted file mode 100644 index 6c6a464..0000000 --- a/server/lib/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './spotify' \ No newline at end of file diff --git a/server/lib/spotify.ts b/server/lib/spotify.ts deleted file mode 100644 index 9e13a50..0000000 --- a/server/lib/spotify.ts +++ /dev/null @@ -1,116 +0,0 @@ -/** - * Resources - * - Repo: https://github.com/spotify/spotify-web-api-ts-sdk/tree/main - * - Authentication: https://developer.spotify.com/documentation/web-api/tutorials/code-flow - * - Scopes: https://developer.spotify.com/documentation/web-api/concepts/scopes - */ -import { SpotifyApi } from '@spotify/web-api-ts-sdk' -import axios from 'axios' -import { stringify } from 'querystring' -import { SPOTIFY_CLIENT_ID, SPOTIFY_CLIENT_SECRET, SPOTIFY_REDIRECT_URI } from 'server/config' - -const SPOTIFY_SCOPES = [ - 'user-read-private', - 'user-read-email', - 'playlist-modify-public', - 'playlist-modify-private', - 'user-read-playback-state', - 'user-modify-playback-state', - 'user-read-currently-playing', - 'app-remote-control', - 'streaming' -] - -export type SpotifySdk = SpotifyApi - -export interface SpotifyTokens { - accessToken: string - refreshToken: string - expiresIn: number - tokenType: string -} - -type SpotifyAuthReqBody = - | { - grant_type: 'authorization_code' - code: string - redirect_uri: string - } - | { - grant_type: 'refresh_token' - refresh_token: string - } - -export const getSpotifySdk = (tokens: SpotifyTokens): SpotifySdk => { - return SpotifyApi.withAccessToken(SPOTIFY_CLIENT_ID, { - access_token: tokens.accessToken, - refresh_token: tokens.refreshToken, - expires_in: tokens.expiresIn, - token_type: tokens.tokenType - }) -} - -export const getSpotifyRedirectUri = (state: { userId: string; finalRedirect?: string }) => { - const stateString = JSON.stringify(state) - - const url = - 'https://accounts.spotify.com/authorize?' + - stringify({ - response_type: 'code', - client_id: SPOTIFY_CLIENT_ID, - scope: SPOTIFY_SCOPES.join(', '), - redirect_uri: SPOTIFY_REDIRECT_URI, - state: stateString - }) - - return url -} - -export const authenticateSpotify = async (params: { - type: 'authorization_code' | 'refresh_token' - payload: string -}): Promise => { - const body: SpotifyAuthReqBody = - params.type === 'authorization_code' - ? { - grant_type: params.type, - code: params.payload, - redirect_uri: SPOTIFY_REDIRECT_URI - } - : { - grant_type: params.type, - refresh_token: params.payload - } - const spotifyAuthBuffer: Buffer = Buffer.from(SPOTIFY_CLIENT_ID + ':' + SPOTIFY_CLIENT_SECRET) - - const spotifyRes = await axios - .post('https://accounts.spotify.com/api/token', body, { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - Authorization: 'Basic ' + spotifyAuthBuffer.toString('base64') - } - }) - .catch((error: any) => { - console.log('Error authorizing with spotify:', error) - throw new Error(error?.response?.data?.error_description || error) - }) - - if (spotifyRes.status > 299 || !spotifyRes.data) - throw new Error('Error authenticating with spotify.') - - const { - access_token: accessToken, - refresh_token: refreshToken, - expires_in: expiresIn, - token_type: tokenType - } = spotifyRes.data - - return { accessToken, refreshToken, expiresIn, tokenType } -} - -export const getSpotifyEmail = async (tokens: SpotifyTokens) => { - const sdk = getSpotifySdk(tokens) - const userProfile = await sdk.currentUser.profile() - - return userProfile.email -} diff --git a/server/middleware/authMiddleware.ts b/server/middleware/authMiddleware.ts deleted file mode 100644 index d700355..0000000 --- a/server/middleware/authMiddleware.ts +++ /dev/null @@ -1,91 +0,0 @@ -/** - * @fileoverview Authentication middleware. - */ -import type { Jwt } from 'jsonwebtoken' -import jwt from 'jsonwebtoken' - -import type { NextFunction, Request, Response } from 'express' -import { JWT_ALGORITHM, JWT_ISSUER, JWT_SECRET_KEY } from 'server/config' -import { User } from 'server/models' -import { httpUnauthorized } from '../utils' - -export interface AuthLocals { - user: User -} - -export type AuthResponse = Response & { - locals: AuthLocals -} - -export const isAuthenticated = async (req: Request, res: Response, next: NextFunction) => { - /** - @swagger - #swagger.security = [{ - "Bearer": [] - }] - */ - - let token: string = req.headers['authorization'] || '' - let jwtPayload: Jwt - - // if (NODE_ENV === 'development') { - // token = String(req.cookies[AUTH_TOKEN_COOKIE_NAME]) - // } - - try { - jwtPayload = jwt.verify(token.split(' ')[1], JWT_SECRET_KEY, { - complete: true, - issuer: JWT_ISSUER, - algorithms: [JWT_ALGORITHM], - clockTolerance: 0, - ignoreExpiration: false, - ignoreNotBefore: false - }) - - const { userId } = jwtPayload.payload as any - const user: User | null = await User.findById(userId) - if (!user) return httpUnauthorized(res) - - res.locals = { ...res.locals, user } as AuthLocals - } catch (error) { - return httpUnauthorized(res) - } - - return next() -} - -export const hasSpotifyToken = async (_: Request, res: Response, next: NextFunction) => { - // if (NODE_ENV === 'development') return next() - - // const spotifyToken: string = (req.headers['x-spotify-access-token'] as string) ?? '' - const { userId } = res.locals - const user: User | null = await User.findById(userId) - // if (!user) return httpUnauthorized(res, 'User not logged in.') - - // try { - // const spotifyToken = user.spotifyAccessToken - // if (!spotifyToken) return httpUnauthorized(res, 'Spotify token required.') - - // const isExpired = user.spotifyTokenExpiration - // ? user.spotifyTokenExpiration.getTime() < Date.now() - // : true - - // if (isExpired) { - // const currentRefreshToken = user.spotifyRefreshToken || '' - // const { accessToken, expiresAt, refreshToken } = - // await SpotifyService.refreshUserToken(currentRefreshToken) - // await user.updateOne({ - // spotifyAccessToken: accessToken, - // spotifyRefreshToken: refreshToken, - // spotifyTokenExpiration: expiresAt - // }) - // res.locals = { ...res.locals, spotifyAccessToken: accessToken } - // } else { - // res.locals = { ...res.locals, spotifyAccessToken: spotifyToken } - // } - // } catch (error: any) { - // return httpBadRequest(res, 'Unable to verify spotify token.') - // } - - return next() -} diff --git a/server/middleware/docsMiddleware.ts b/server/middleware/docsMiddleware.ts deleted file mode 100644 index e332039..0000000 --- a/server/middleware/docsMiddleware.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { NextFunction, Request, Response } from 'express' - -export const docsMiddleware = (req: Request, res: Response, next: NextFunction) => { - /** - @swagger - #swagger.responses[400] = { - schema: {$ref: "#/definitions/Error400"}, - description: "Bad request" - } - #swagger.responses[404] = { - schema: {$ref: "#/definitions/Error404"}, - description: "Not found" - } - #swagger.responses[500] = { - schema: {$ref: "#/definitions/Error500"}, - description: "Internal Server Error" - } - #swagger.responses[501] = { - schema: {$ref: "#/definitions/Error501"}, - description: "Not implemented" - } - */ - next() -} diff --git a/server/middleware/errorHandler.ts b/server/middleware/errorHandler.ts deleted file mode 100644 index 3bba307..0000000 --- a/server/middleware/errorHandler.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { logger } from '@jukebox/lib' -import type { NextFunction, Request, Response } from 'express' -import { - httpBadRequest, - httpNotFound, - httpNotImplemented, - httpUnauthorized, - NotFoundError, - NotImplementedError, - UnauthorizedError -} from 'server/utils' - -export const errorHandler = (error: Error, req: Request, res: Response, next: NextFunction) => { - logger.error(error.stack || 'Unknown API Error.') - - if (error instanceof NotFoundError) { - return next(httpNotFound(res, error)) - } else if (error instanceof NotImplementedError) { - return next(httpNotImplemented(res, error)) - } else if (error instanceof UnauthorizedError) { - return next(httpUnauthorized(res, error)) - } else { - return next(httpBadRequest(res, error)) - } -} diff --git a/server/middleware/index.ts b/server/middleware/index.ts deleted file mode 100644 index 4743286..0000000 --- a/server/middleware/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './authMiddleware' -export * from './errorHandler' diff --git a/server/models/groupModel.ts b/server/models/groupModel.ts deleted file mode 100644 index 2c7f1dd..0000000 --- a/server/models/groupModel.ts +++ /dev/null @@ -1,87 +0,0 @@ -import mongoose, { Types, type Model } from 'mongoose' - -export interface IGroupFields { - name: string - ownerId: string - spotifyAuthId?: string - defaultDeviceId?: string -} - -export interface IGroup extends IGroupFields { - id: string -} - -export interface GroupFields extends Omit { - ownerId: typeof Types.ObjectId - spotifyAuthId?: typeof Types.ObjectId -} -export interface GroupMethods extends IModelMethods {} -type GroupModel = Model - -const GroupSchema = new mongoose.Schema( - { - ownerId: { - type: Types.ObjectId, - required: true - }, - name: { - type: String, - required: true, - unique: true - }, - spotifyAuthId: { - type: Types.ObjectId, - ref: 'SpotifyAuth', - unique: true, - dropDups: true, - sparse: true - }, - defaultDeviceId: { - type: String - } - }, - { - timestamps: true - } -) - -GroupSchema.methods.serialize = function () { - return { - id: this.id, - ownerId: this.ownerId.toString(), - name: this.name, - spotifyAuthId: this.spotifyAuthId?.toString() - } -} - -const membershipSchema = new mongoose.Schema( - { - groupId: { - type: Types.ObjectId, - required: true, - ref: 'Group' - }, - userId: { - type: Types.ObjectId, - required: true, - ref: 'User' - }, - role: { - type: String, - enum: ['admin', 'owner', 'member'], - default: 'member' - }, - points: { - type: Number, - default: 0 - } - }, - { - timestamps: true - } -) - -export const Group = mongoose.model('Group', GroupSchema) -export type Group = InstanceType -export const Membership = mongoose.model('Membership', membershipSchema) -export type Membership = InstanceType diff --git a/server/models/index.ts b/server/models/index.ts deleted file mode 100644 index 04a8380..0000000 --- a/server/models/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './groupModel' -export * from './spotifyAuthModel' -export * from './userModel' diff --git a/server/models/spotifyAuthModel.ts b/server/models/spotifyAuthModel.ts deleted file mode 100644 index 3ab69fa..0000000 --- a/server/models/spotifyAuthModel.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { Schema, Types, model, type Model } from 'mongoose' - -export interface ISpotifyAuth { - id: string - accessToken: string - refreshToken: string - userId: string - spotifyEmail: string - expiresIn: number - tokenType: string - expiresAt: Date -} - -export interface ISpotifyAuthFields extends Omit { - userId: typeof Types.ObjectId -} - -export interface ISpotifyAuthMethods extends IModelMethods { - isExpired: () => boolean -} - -export type ISpotifyAuthModel = Model - -export const SpotifyAuthSchema = new Schema< - ISpotifyAuthFields, - ISpotifyAuthModel, - ISpotifyAuthMethods ->({ - accessToken: { - type: String - }, - refreshToken: { - type: String - }, - userId: { - type: Types.ObjectId, - required: true, - ref: 'User' - }, - spotifyEmail: { - type: String, - required: true, - unique: true - }, - expiresIn: { - type: Number - }, - expiresAt: { - type: Date - }, - tokenType: { - type: String - } -}) - -SpotifyAuthSchema.methods.isExpired = function () { - const expiresAt: Date = this.expiresAt - - return expiresAt.getTime() <= Date.now() -} - -SpotifyAuthSchema.methods.serialize = function () { - return { - id: this.id, - accessToken: this.accessToken, - refreshToken: this.refreshToken, - userId: this.userId, - spotifyEmail: this.spotifyEmail, - expiresIn: this.expiresIn, - tokenType: this.tokenType, - expiresAt: this.expiresAt - } -} - -export const SpotifyAuth = model('SpotifyAuth', SpotifyAuthSchema) -export type SpotifyAuth = InstanceType diff --git a/server/models/tests/userModel.test.ts b/server/models/tests/userModel.test.ts deleted file mode 100644 index b73d3af..0000000 --- a/server/models/tests/userModel.test.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @fileoverview User model tests. - */ - -import { User } from '../userModel' - -describe('User Model', () => { - test('model can be created', async () => { - const userFields = { email: 'john doe', password: 'unhashed-password' } - const user = await User.create(userFields) - - expect(user).not.toBeNull() - expect(user.email).toEqual(userFields.email) - expect(user.password).toEqual(userFields.password) // Hashing is done by another service, model doesn't know/care - }) -}) diff --git a/server/models/userModel.ts b/server/models/userModel.ts deleted file mode 100644 index 6a227de..0000000 --- a/server/models/userModel.ts +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @fileoverview User model - */ -import mongoose, { Schema, type Model } from 'mongoose' - -export interface IUserFields { - email: string - firstName?: string - lastName?: string - image?: string -} - -export interface IUser extends IUserFields { - id: string -} - -export interface UserFields extends Omit { - // export interface IUserFields extends IModelFields { - password: string -} -export interface UserMethods extends IModelMethods {} - -export type UserModel = Model - -export const UserSchema = new Schema({ - // username: { - // type: String, - // required: true, - // unique: true, - // index: true, - // dropDups: true - // }, - email: { - // TODO: Validate - type: String, - unique: true, - required: true, - index: true, - dropDups: true - }, - password: { - // TODO: Validate - type: String, - required: true - }, - firstName: { - type: String, - required: false - }, - lastName: { - type: String, - required: false - }, - image: { - type: String, - required: false - } -}) - -UserSchema.methods.serialize = function () { - return { - id: this._id.toString(), - email: this.email, - firstName: this.firstName, - lastName: this.lastName, - image: this.image - } -} - -export const cleanUser = (data: any): Partial => { - let payload: Partial = {} - - // TODO: Create cleanModel utility - if ('id' in data) { - payload = { ...payload, id: data.id } - } - if ('email' in data) { - payload = { ...payload, email: data.email } - } - if ('firstName' in data) { - payload = { ...payload, firstName: data.firstName } - } - if ('lastName' in data) { - payload = { ...payload, lastName: data.lastName } - } - if ('image' in data) { - payload = { ...payload, image: data.image } - } - - return payload -} - -export const User = mongoose.model('User', UserSchema) - -export type User = InstanceType diff --git a/server/routes/groupRoutes.ts b/server/routes/groupRoutes.ts deleted file mode 100644 index 61f0c39..0000000 --- a/server/routes/groupRoutes.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Router } from 'express' -import { isAuthenticated } from '../middleware/authMiddleware' -import * as views from '../views/groupViews' - -const router = Router() - -router.get('/:id/spotify/current-track', isAuthenticated, views.getGroupCurrentTrackView) -router.post('/:id/spotify/state', isAuthenticated, views.setGroupPlayerStateView) -router.get('/:id/spotify/devices', isAuthenticated, views.getGroupDevicesView) -router.post('/:id/spotify/default-device', isAuthenticated, views.setGroupDefaultDeviceView) -router.get('/:id/spotify/auth', isAuthenticated, views.getGroupSpotifyAuthView) -router.post('/:id/spotify/auth', isAuthenticated, views.assignSpotifyAccountView) - -router.post('/groups', isAuthenticated, views.groupCreateView) -router.get('/groups', views.groupListView) -router.get('/groups/:id', isAuthenticated, views.groupGetView) -router.put('/groups/:id', isAuthenticated, views.groupUpdateView) -router.patch('/groups/:id', isAuthenticated, views.groupPartialUpdateView) -router.delete('/groups/:id', isAuthenticated, views.groupDeleteView) - -export const groupRoutes = router diff --git a/server/routes/index.ts b/server/routes/index.ts deleted file mode 100644 index 1b6163c..0000000 --- a/server/routes/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -// /** -// * CRUD Structure: -// * /api/{RESOURCE}/{OBJECTS} -// * -// * Actions: -// * /api/{RESOURCE}/{ACTION} -// */ - -// import { Router } from 'express' -// import * as BaseController from '../controllers/baseController' -// import { groupRoutes } from './groupRoutes' -// import { spotifyRouter } from './spotifyRoutes' -// import { userRouter } from './userRoutes' - -// const router = Router() -// router.get('/api', BaseController.healthCheck) -// router.use('/api/spotify', spotifyRouter) -// router.use('/api/user', userRouter) -// router.use('/api/group', groupRoutes) - -// export { router } -/** - * @module router - * @description Network ingress/egress router - * - * The routers are responsible for defining which - * endpoints are available, and directing requests from - * those endpoints to the appropriate views. They can - * only reference views and middleware. - */ - -export { router } from './router' diff --git a/server/routes/router.ts b/server/routes/router.ts deleted file mode 100644 index e029428..0000000 --- a/server/routes/router.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Router } from 'express' -import { docsMiddleware } from '../middleware/docsMiddleware' -import * as baseViews from '../views/baseViews' -import { groupRoutes } from './groupRoutes' -import { spotifyRouter } from './spotifyRoutes' -import { userRouter } from './userRoutes' - -const router = Router() - -router.get('/', baseViews.healthcheck) -router.get('/api', baseViews.apiHelp) -router.get('/api/ping', baseViews.pingPongView) - -router.use(docsMiddleware) -router.use('/api/spotify', spotifyRouter) -router.use('/api/user', userRouter) -router.use('/api/group', groupRoutes) - -export { router } diff --git a/server/routes/spotifyRoutes.ts b/server/routes/spotifyRoutes.ts deleted file mode 100644 index 5c82042..0000000 --- a/server/routes/spotifyRoutes.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Router } from 'express' -import * as views from '../views/spotifyAuthViews' -import { isAuthenticated } from './../middleware/authMiddleware' - -const router = Router() - -/**== Spotify Authentication - /api/spotify/ ==**/ -router.get('/login', isAuthenticated, views.spotifyLoginView) -router.get('/login-callback', views.spotifyLoginCallbackView) -router.delete('/', isAuthenticated, views.removeSpotifyConnection) - -export const spotifyRouter = router diff --git a/server/routes/userRoutes.ts b/server/routes/userRoutes.ts deleted file mode 100644 index ad863ec..0000000 --- a/server/routes/userRoutes.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Router } from 'express' -import { isAuthenticated } from '../middleware/authMiddleware' -import * as views from '../views/userViews' - -const router = Router() - -/**== User Authentication ==**/ -router.post('/register', views.registerUserView) -router.post('/token', views.loginUserView) -router.post('/request-password-reset', isAuthenticated, views.requestPasswordResetView) -router.post('/reset-password', isAuthenticated, views.resetPasswordView) - -router.get('/me', isAuthenticated, views.currentUserView) -router.put('/me', isAuthenticated, views.updateCurrentUserView) -router.get('/me/spotify-accounts', isAuthenticated, views.connectedSpotifyAccounts) - -/**== User Management ==**/ -// router.use('/users', isAuthenticated, UserViewset.registerRouter()) -router.post('/users', isAuthenticated, views.userCreateView) -router.get('/users', isAuthenticated, views.userListView) -router.get('/users/:id', isAuthenticated, views.userGetView) -router.put('/users/:id', isAuthenticated, views.userUpdateView) -router.patch('/users/:id', isAuthenticated, views.userPartialUpdateView) -router.delete('/users/:id', isAuthenticated, views.userDeleteView) - -export const userRouter = router diff --git a/server/services/authService.ts b/server/services/authService.ts deleted file mode 100644 index 2ac6122..0000000 --- a/server/services/authService.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { compare, genSalt, hash } from 'bcrypt' -import type { Algorithm } from 'jsonwebtoken' -import { sign } from 'jsonwebtoken' -import { JWT_ALGORITHM, JWT_ISSUER, JWT_SECRET_KEY } from 'server/config' -import { User } from 'server/models' - -export class AuthService { - private static jwtSecret: string = JWT_SECRET_KEY - private static jwtIssuer: string = JWT_ISSUER - private static jwtAlgorithm: Algorithm | undefined = JWT_ALGORITHM || 'HS256' - private static jwtExpiresIn: string = '48h' - private static jwtNotBefore: string | number = 0 - - /** - * Hash a password using bycrypt. - * - * @param password The password to hash. - * @return The hashed password. - */ - private static hashPassword = async (password: string): Promise => { - if (!password || password === '') throw new Error('No password provided') - - const salt = await genSalt(10) - const hashedPassword = await hash(password, salt) - - return hashedPassword - } - - private static generateNewPassword = (length: number = 8): string => { - const str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 'abcdefghijklmnopqrstuvwxyz0123456789@#$' - let password = '' - - for (let i = 1; i <= length; i++) { - const char = Math.floor(Math.random() * str.length + 1) - - password += str.charAt(char) - } - - return password - } - - public static registerUser = async (details: { - email: string - password: string - }): Promise => { - const { email, password } = details - const existingUser: User | null = await User.findOne({ email: email }) - - if (existingUser) throw new Error('email already exists!') - - const hashedPassword = await this.hashPassword(password) - const user: User = await User.create({ email, password: hashedPassword }) - - return user - } - - public static inviteUser = async (email: string): Promise => { - const user: User = await User.create({ email, password: this.generateNewPassword() }) - // TODO: Send invite email, prompt user to change password - - return user - } - - public static authorizeUser = async (email: string, password: string): Promise => { - if (!email || !password) throw new Error('Missing email or password') - - const user: User | null = await User.findOne({ email }) - if (!user) throw new Error('User not found') - - const validPassword = await compare(password, user.password!) - - if (!validPassword) throw new Error('Invalid password') - - return user - } - - public static generateToken = async (user: User): Promise => { - const token = sign({ userId: user._id }, this.jwtSecret, { - expiresIn: this.jwtExpiresIn, - issuer: this.jwtIssuer, - algorithm: this.jwtAlgorithm, - notBefore: this.jwtNotBefore - }) - - return token - } - - // FIXME: Changing password should require validation - public static changePassword = async (user: User, newPassword: string): Promise => { - const hashedPassword = await this.hashPassword(newPassword) - const updatedUser: User = await user.updateOne({ password: hashedPassword }) - - return updatedUser - } -} diff --git a/server/services/groupService.ts b/server/services/groupService.ts deleted file mode 100644 index 8388e78..0000000 --- a/server/services/groupService.ts +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @fileoverview Group Service - * - * @description The group service is not responsible for all CRUD operations - * on the group model. Instead, it is responsible for the operations that effect - * other models and services, including memberships and users. - */ -import { Group, Membership, User } from 'server/models' - -export class GroupService { - static async createGroup(owner: User, name: string, options?: any): Promise { - try { - const group = await Group.create({ ...options, ownerId: owner._id, name }) - - await Membership.create({ - groupId: group._id, - userId: owner._id, - role: 'owner' - }) - - return group - } catch (error: any) { - throw new Error(error?.message) - } - } - static async registerGroupMember( - group: Group, - user: User, - options?: { role: string } - ): Promise { - try { - const membership = await Membership.create({ - groupId: group._id, - userId: user._id - }) - if (options?.role) { - membership.role = options.role as Membership['role'] - await membership.save() - } - - return membership - } catch (error: any) { - throw new Error(error?.message) - } - } - // TODO: Remove group member - - static async deleteGroup(group: Group) { - await Membership.deleteMany({ groupId: group._id }) - await group.deleteOne() - - return group - } - static async getGroupMembers(group: Group) { - const memberships = await Membership.find({ groupId: group._id }) - const members: User[] = await Promise.all( - memberships.map(async (m) => await User.findById(m.userId)) - ).then((result) => result.filter((user) => user !== null) as User[]) - - return members - } - - static async getGroupMemberships(group: Group) { - return await Membership.find({ groupId: group._id }) - } -} diff --git a/server/services/index.ts b/server/services/index.ts deleted file mode 100644 index e379775..0000000 --- a/server/services/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { AuthService } from './authService' -export { GroupService } from './groupService' -export { SpotifyService } from './spotifyService' diff --git a/server/services/spotifyService.ts b/server/services/spotifyService.ts deleted file mode 100644 index 8912f62..0000000 --- a/server/services/spotifyService.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { - authenticateSpotify, - getSpotifyEmail, - getSpotifySdk, - type SpotifySdk, - type SpotifyTokens -} from 'server/lib' -import { SpotifyAuth } from 'server/models' - -export class SpotifyService { - private auth: SpotifyAuth - public sdk: SpotifySdk - - private constructor(auth: SpotifyAuth) { - this.auth = auth - this.sdk = getSpotifySdk(auth) - } - - public static async connect(spotifyEmail: string): Promise { - const spotifyAuth = await SpotifyAuth.findOne({ spotifyEmail }) - - if (!spotifyAuth) - throw new Error(`Unable to find connected spotify account with email ${spotifyEmail}.`) - - if (spotifyAuth.expiresAt.getTime() > Date.now()) { - return new SpotifyService(spotifyAuth) - } - - const tokens = await authenticateSpotify({ - type: 'refresh_token', - payload: spotifyAuth.refreshToken - }) - - const updatedAuth = await this.udpateOrCreateAuth( - spotifyAuth.userId.toString(), - spotifyAuth.spotifyEmail, - tokens - ) - - return new SpotifyService(updatedAuth) - } - - public static async authenticateUser(userId: string, code: string): Promise { - const tokens = await authenticateSpotify({ type: 'authorization_code', payload: code }) - const userEmail = await getSpotifyEmail(tokens) - - const spotifyAuth = await this.udpateOrCreateAuth(userId, userEmail, tokens) - return new SpotifyService(spotifyAuth) - } - - private static async udpateOrCreateAuth( - userId: string, - spotifyEmail: string, - tokens: SpotifyTokens - ): Promise { - const query = await SpotifyAuth.findOne({ userId, spotifyEmail }) - - if (!query) { - return await SpotifyAuth.create({ - userId, - spotifyEmail, - expiresAt: new Date(Date.now() + tokens.expiresIn * 1000), - ...tokens - }) - } else { - // const updated = await query.updateOne({ ...tokens }, { new: true }) - query.accessToken = tokens.accessToken - query.expiresIn = tokens.expiresIn - query.expiresAt = new Date(Date.now() + tokens.expiresIn * 1000) - return query - } - } - - public async getProfile() { - return await this.sdk.currentUser.profile() - } - - public async getAccessToken() { - const tokens = await this.sdk.getAccessToken() - return tokens?.access_token ?? '' - } - - // public async getActiveDevice(failSilently: true): Promise - // public async getActiveDevice(failSilently?: false): Promise - // public async getActiveDevice(failSilently = false) { - // const devices = await this.sdk.player.getAvailableDevices() - // const activeDevice = devices.devices.reduce((currentDevice, device) => { - // if (device.is_active || !currentDevice) return device - - // return currentDevice - // }) - - // if (!failSilently && !activeDevice) { - // throw new Error('No active devices to play tracks.') - // } - - // return activeDevice - // } - - // public async playTrack() { - // const activeDevice = await this.getActiveDevice() - // await this.sdk.player.startResumePlayback(activeDevice.id!) - // } - - // public async pauseTrack() { - // const activeDevice = await this.getActiveDevice() - // await this.sdk.player.pausePlayback(activeDevice.id!) - // } - // public async nextTrack() { - // const activeDevice = await this.getActiveDevice() - // await this.sdk.player.skipToNext(activeDevice.id!) - // } - // public async previousTrack() { - // const activeDevice = await this.getActiveDevice() - // await this.sdk.player.skipToPrevious(activeDevice.id!) - // } -} diff --git a/server/services/tests/groupService.test.ts b/server/services/tests/groupService.test.ts deleted file mode 100644 index 6cb15df..0000000 --- a/server/services/tests/groupService.test.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { Group, Membership, type User } from 'server/models' -import { AuthService } from '../authService' -import { GroupService } from '../groupService' - -const createGroup = async (owner: User): Promise => { - return await GroupService.createGroup(owner, 'Example Group') -} - -describe('Group service, Group initialization', () => { - it('should create group', async () => { - const owner = await AuthService.registerUser({ email: 'owner@example.com', password: 'abc123' }) - const groupName = 'Example Group' - - const group = await GroupService.createGroup(owner, groupName) - - expect(String(group.ownerId)).toEqual(String(owner._id)) - expect(group.name).toEqual(groupName) - - const members = await Membership.find({ groupId: group._id }) - expect(members).toHaveLength(1) - expect(String(members[0].userId)).toEqual(String(owner._id)) - }) -}) - -describe('Group service, Group management', () => { - let owner: User - let group: Group - - beforeEach(async () => { - owner = await AuthService.registerUser({ email: 'owner@example.com', password: 'abc123' }) - group = await createGroup(owner) - }) - - it('should create group member', async () => { - const user = await AuthService.registerUser({ - email: 'john.doe@example.com', - password: 'abc123' - }) - - const membership = await GroupService.registerGroupMember(group, user) - - expect(String(membership.groupId)).toEqual(String(group._id)) - expect(String(membership.userId)).toEqual(String(user._id)) - expect(membership.role).toEqual('member') - expect(membership.points).toEqual(0) - }) - it('should create group member with role', async () => { - const role = 'admin' - const user = await AuthService.registerUser({ - email: 'john.doe@example.com', - password: 'abc123' - }) - - const membership = await GroupService.registerGroupMember(group, user, { role }) - - expect(String(membership.groupId)).toEqual(String(group._id)) - expect(String(membership.userId)).toEqual(String(user._id)) - expect(membership.role).toEqual(role) - expect(membership.points).toEqual(0) - }) - - it('should delete group', async () => { - const pre = await Group.find({}) - expect(pre).toHaveLength(1) - - await GroupService.deleteGroup(group) - - const post = await Group.find({}) - expect(post).toHaveLength(0) - - const members = await Membership.find({ groupId: group._id }) - expect(members).toHaveLength(0) - }) - it('should get group members', async () => { - for (let i = 0; i < 5; i++) { - const user = await AuthService.registerUser({ - email: `user${i}@example.com`, - password: 'abc123' - }) - await GroupService.registerGroupMember(group, user) - } - - const members = await GroupService.getGroupMembers(group) - expect(members).toHaveLength(6) // 5 members + owner - }) -}) diff --git a/server/types/country.d.ts b/server/types/country.d.ts deleted file mode 100644 index 19da09c..0000000 --- a/server/types/country.d.ts +++ /dev/null @@ -1,256 +0,0 @@ -// /** -// * Created by kyranjamie -// * Reference: https://gist.github.com/kyranjamie/646386d5edc174e8b549111572897f81 -// */ - -// declare enum Country { -// Afghanistan = 'AF', -// AlandIslands = 'AX', -// Albania = 'AL', -// Algeria = 'DZ', -// AmericanSamoa = 'AS', -// Andorra = 'AD', -// Angola = 'AO', -// Anguilla = 'AI', -// Antarctica = 'AQ', -// AntiguaAndBarbuda = 'AG', -// Argentina = 'AR', -// Armenia = 'AM', -// Aruba = 'AW', -// Australia = 'AU', -// Austria = 'AT', -// Azerbaijan = 'AZ', -// Bahamas = 'BS', -// Bahrain = 'BH', -// Bangladesh = 'BD', -// Barbados = 'BB', -// Belarus = 'BY', -// Belgium = 'BE', -// Belize = 'BZ', -// Benin = 'BJ', -// Bermuda = 'BM', -// Bhutan = 'BT', -// Bolivia = 'BO', -// BonaireSintEustatiusSaba = 'BQ', -// BosniaAndHerzegovina = 'BA', -// Botswana = 'BW', -// BouvetIsland = 'BV', -// Brazil = 'BR', -// BritishIndianOceanTerritory = 'IO', -// BruneiDarussalam = 'BN', -// Bulgaria = 'BG', -// BurkinaFaso = 'BF', -// Burundi = 'BI', -// Cambodia = 'KH', -// Cameroon = 'CM', -// Canada = 'CA', -// CapeVerde = 'CV', -// CaymanIslands = 'KY', -// CentralAfricanRepublic = 'CF', -// Chad = 'TD', -// Chile = 'CL', -// China = 'CN', -// ChristmasIsland = 'CX', -// CocosKeelingIslands = 'CC', -// Colombia = 'CO', -// Comoros = 'KM', -// Congo = 'CG', -// CongoDemocraticRepublic = 'CD', -// CookIslands = 'CK', -// CostaRica = 'CR', -// CoteDIvoire = 'CI', -// Croatia = 'HR', -// Cuba = 'CU', -// Curaçao = 'CW', -// Cyprus = 'CY', -// CzechRepublic = 'CZ', -// Denmark = 'DK', -// Djibouti = 'DJ', -// Dominica = 'DM', -// DominicanRepublic = 'DO', -// Ecuador = 'EC', -// Egypt = 'EG', -// ElSalvador = 'SV', -// EquatorialGuinea = 'GQ', -// Eritrea = 'ER', -// Estonia = 'EE', -// Ethiopia = 'ET', -// FalklandIslands = 'FK', -// FaroeIslands = 'FO', -// Fiji = 'FJ', -// Finland = 'FI', -// France = 'FR', -// FrenchGuiana = 'GF', -// FrenchPolynesia = 'PF', -// FrenchSouthernTerritories = 'TF', -// Gabon = 'GA', -// Gambia = 'GM', -// Georgia = 'GE', -// Germany = 'DE', -// Ghana = 'GH', -// Gibraltar = 'GI', -// Greece = 'GR', -// Greenland = 'GL', -// Grenada = 'GD', -// Guadeloupe = 'GP', -// Guam = 'GU', -// Guatemala = 'GT', -// Guernsey = 'GG', -// Guinea = 'GN', -// GuineaBissau = 'GW', -// Guyana = 'GY', -// Haiti = 'HT', -// HeardIslandMcdonaldIslands = 'HM', -// HolySeeVaticanCityState = 'VA', -// Honduras = 'HN', -// HongKong = 'HK', -// Hungary = 'HU', -// Iceland = 'IS', -// India = 'IN', -// Indonesia = 'ID', -// Iran = 'IR', -// Iraq = 'IQ', -// Ireland = 'IE', -// IsleOfMan = 'IM', -// Israel = 'IL', -// Italy = 'IT', -// Jamaica = 'JM', -// Japan = 'JP', -// Jersey = 'JE', -// Jordan = 'JO', -// Kazakhstan = 'KZ', -// Kenya = 'KE', -// Kiribati = 'KI', -// Korea = 'KR', -// KoreaDemocraticPeoplesRepublic = 'KP', -// Kuwait = 'KW', -// Kyrgyzstan = 'KG', -// LaoPeoplesDemocraticRepublic = 'LA', -// Latvia = 'LV', -// Lebanon = 'LB', -// Lesotho = 'LS', -// Liberia = 'LR', -// LibyanArabJamahiriya = 'LY', -// Liechtenstein = 'LI', -// Lithuania = 'LT', -// Luxembourg = 'LU', -// Macao = 'MO', -// Macedonia = 'MK', -// Madagascar = 'MG', -// Malawi = 'MW', -// Malaysia = 'MY', -// Maldives = 'MV', -// Mali = 'ML', -// Malta = 'MT', -// MarshallIslands = 'MH', -// Martinique = 'MQ', -// Mauritania = 'MR', -// Mauritius = 'MU', -// Mayotte = 'YT', -// Mexico = 'MX', -// Micronesia = 'FM', -// Moldova = 'MD', -// Monaco = 'MC', -// Mongolia = 'MN', -// Montenegro = 'ME', -// Montserrat = 'MS', -// Morocco = 'MA', -// Mozambique = 'MZ', -// Myanmar = 'MM', -// Namibia = 'NA', -// Nauru = 'NR', -// Nepal = 'NP', -// Netherlands = 'NL', -// NewCaledonia = 'NC', -// NewZealand = 'NZ', -// Nicaragua = 'NI', -// Niger = 'NE', -// Nigeria = 'NG', -// Niue = 'NU', -// NorfolkIsland = 'NF', -// NorthernMarianaIslands = 'MP', -// Norway = 'NO', -// Oman = 'OM', -// Pakistan = 'PK', -// Palau = 'PW', -// PalestinianTerritory = 'PS', -// Panama = 'PA', -// PapuaNewGuinea = 'PG', -// Paraguay = 'PY', -// Peru = 'PE', -// Philippines = 'PH', -// Pitcairn = 'PN', -// Poland = 'PL', -// Portugal = 'PT', -// PuertoRico = 'PR', -// Qatar = 'QA', -// Reunion = 'RE', -// Romania = 'RO', -// RussianFederation = 'RU', -// Rwanda = 'RW', -// SaintBarthelemy = 'BL', -// SaintHelena = 'SH', -// SaintKittsAndNevis = 'KN', -// SaintLucia = 'LC', -// SaintMartin = 'MF', -// SaintPierreAndMiquelon = 'PM', -// SaintVincentAndGrenadines = 'VC', -// Samoa = 'WS', -// SanMarino = 'SM', -// SaoTomeAndPrincipe = 'ST', -// SaudiArabia = 'SA', -// Senegal = 'SN', -// Serbia = 'RS', -// Seychelles = 'SC', -// SierraLeone = 'SL', -// Singapore = 'SG', -// SintMaarten = 'SX', -// Slovakia = 'SK', -// Slovenia = 'SI', -// SolomonIslands = 'SB', -// Somalia = 'SO', -// SouthAfrica = 'ZA', -// SouthGeorgiaAndSandwichIsl = 'GS', -// SouthSudan = 'SS', -// Spain = 'ES', -// SriLanka = 'LK', -// Sudan = 'SD', -// Suriname = 'SR', -// SvalbardAndJanMayen = 'SJ', -// Swaziland = 'SZ', -// Sweden = 'SE', -// Switzerland = 'CH', -// SyrianArabRepublic = 'SY', -// Taiwan = 'TW', -// Tajikistan = 'TJ', -// Tanzania = 'TZ', -// Thailand = 'TH', -// TimorLeste = 'TL', -// Togo = 'TG', -// Tokelau = 'TK', -// Tonga = 'TO', -// TrinidadAndTobago = 'TT', -// Tunisia = 'TN', -// Turkey = 'TR', -// Turkmenistan = 'TM', -// TurksAndCaicosIslands = 'TC', -// Tuvalu = 'TV', -// Uganda = 'UG', -// Ukraine = 'UA', -// UnitedArabEmirates = 'AE', -// UnitedKingdom = 'GB', -// UnitedStates = 'US', -// UnitedStatesOutlyingIslands = 'UM', -// Uruguay = 'UY', -// Uzbekistan = 'UZ', -// Vanuatu = 'VU', -// Venezuela = 'VE', -// Vietnam = 'VN', -// VirginIslandsBritish = 'VG', -// VirginIslandsUS = 'VI', -// WallisAndFutuna = 'WF', -// WesternSahara = 'EH', -// Yemen = 'YE', -// Zambia = 'ZM', -// Zimbabwe = 'ZW' -// } diff --git a/server/types/index.d.ts b/server/types/index.d.ts deleted file mode 100644 index 8263a4e..0000000 --- a/server/types/index.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -type Serializable = Record - -declare interface IModelMethods { - serialize: () => T - // static clean: (data: any) => T -} - -// declare type IModelFields = Omit - -// declare interface IModelFields extends Omit { - -// } diff --git a/server/types/spotify.d.ts b/server/types/spotify.d.ts deleted file mode 100644 index 6ca4221..0000000 --- a/server/types/spotify.d.ts +++ /dev/null @@ -1,108 +0,0 @@ -// // declare interface SpotifyToken { -// // accessToken: string -// // refreshTOken: string -// // expirationDate: Date -// // } - -// declare type SpotifyImage = { -// url: string -// height?: number -// width?: number -// } - -// declare type Album = { -// album_type: 'album' | 'single' | 'compilation' -// total_tracks: number -// available_markets: Country[] -// external_urls: { -// spotify: string -// } -// href: string -// id: string -// images: SpotifyImage[] -// name: string -// release_date: string -// release_date_precision: 'year' | 'month' | 'day' -// restrictions: { -// reason: 'market' | 'product' | 'explicit' -// } -// type: 'album' -// uri: string -// artists: SimplifiedArtist[] -// } - -// declare type SimplifiedArtist = { -// external_urls: { -// spotify: string -// } -// href: string -// id: string -// name: string -// type: 'artist' -// uri: string -// } - -// declare type Artist = { -// external_urls: { -// spotify: string -// } -// followers: { -// total: number -// } -// genres: string[] -// href: string -// id: string -// images: SpotifyImage[] -// name: string -// popularity: number -// type: 'artist' -// uri: string -// } - -// declare type Track = { -// album: Album -// artists: Artist[] -// available_markets: Country[] -// disc_number: number -// duration_ms: number -// explicit: boolean -// external_ids: { -// iserver: string -// ean: string -// upc: string -// } -// external_urls: { -// spotify: string -// } -// href: string -// id: string -// is_playable: boolean -// restrictions: { -// reason: 'market' | 'product' | 'explicit' -// } -// name: string -// popularity: number -// preview_url?: string -// track_number: number -// type: 'track' -// uri: string -// is_local: boolean -// } - -// interface SpotifyUserProfile { -// country: string -// display_name: string -// email: string -// explicit_content: { -// filter_enabled: boolean -// filter_locked: boolean -// } -// external_urls: { spotify: string } -// followers: { href: string; total: number } -// href: string -// id: string -// images: SpotifyImage[] -// product: string -// type: string -// uri: string -// } diff --git a/server/utils/apis/index.ts b/server/utils/apis/index.ts deleted file mode 100644 index 95454bf..0000000 --- a/server/utils/apis/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './viewsets' -export * from './wrappers' - diff --git a/server/utils/apis/viewsets.ts b/server/utils/apis/viewsets.ts deleted file mode 100644 index 578f8aa..0000000 --- a/server/utils/apis/viewsets.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { type NextFunction, type Request, type Response, Router } from 'express' -import type { Model } from 'mongoose' -import { NotFoundError } from '../exceptions' -import { httpCreated } from '../responses' -import { apiRequest } from './wrappers' - -export type ApiArgs = [req: Request, res: Response, next: NextFunction] - -export class Viewset< - T extends Model = Model, - S extends Serializable = any -> { - private model: T - private clean: (data: any) => S - - constructor(model: T, clean: (data: any) => S = (data) => data) { - this.model = model - this.clean = clean - } - - private apiWrapper = apiRequest - - protected async handleCreate(req: Request, res: Response, next: NextFunction) { - const { body } = req - const data = this.clean(body) - const obj = await this.model.create(data) - - return obj.serialize() - } - protected async handleList(req: Request, res: Response, next: NextFunction) { - const query = await this.model.find({}) - return query.map((obj: InstanceType) => obj.serialize()) - } - protected async handleGet(req: Request, res: Response, next: NextFunction) { - const { id } = req.params - const result = await this.model.findById(id) - - if (!result) throw new NotFoundError(`${this.model.name} with id ${id} not found.`) - - return result.serialize() - } - protected async handleUpdate(req: Request, res: Response, next: NextFunction) { - const { body, params } = req - const data = this.clean(body) - - const obj = await this.model.findOneAndUpdate({ _id: params.id }, data, { new: true }) - if (!obj) throw new NotFoundError(`${this.model.name} with id ${params.id} not found.`) - - return obj.serialize() - } - protected async handlePartialUpdate(req: Request, res: Response, next: NextFunction) { - const { body, params } = req - const data = this.clean(body) - - const obj = await this.model.findOneAndUpdate({ _id: params.id }, data, { new: true }) - if (!obj) throw new NotFoundError(`${this.model.name} with id ${params.id} not found.`) - - return obj.serialize() - } - protected async handleDelete(req: Request, res: Response, next: NextFunction) { - const { id } = req.params - const result: InstanceType>> | null = - await this.model.findById(id) - - if (!result) throw new NotFoundError(`${this.model.name} with id ${id} not found.`) - - await result.deleteOne() - - return result.serialize() - } - - /** - * #swagger.tags = ['Group'] - */ - public create = this.apiWrapper(this.handleCreate.bind(this), { onSuccess: httpCreated }) - public list = this.apiWrapper(this.handleList.bind(this)) - public get = this.apiWrapper(this.handleGet.bind(this)) - public update = this.apiWrapper(this.handleUpdate.bind(this)) - public partialUpdate = this.apiWrapper(this.handlePartialUpdate.bind(this)) - public delete = this.apiWrapper(this.handleDelete.bind(this)) - - registerRouter(path = '/'): Router { - const router = Router() - - router.post(path, this.create) - router.get(path, this.list) - router.get(`${path}:id`, this.get) - router.post(`${path}:id`, this.update) - router.patch(`${path}:id`, this.partialUpdate) - router.delete(`${path}:id`, this.delete) - - return router - } -} diff --git a/server/utils/apis/wrappers.ts b/server/utils/apis/wrappers.ts deleted file mode 100644 index 43dfda4..0000000 --- a/server/utils/apis/wrappers.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { type NextFunction, type Request, type Response } from 'express' -import type { AuthResponse } from 'server/middleware' -import { errorResponse, httpOk } from '../responses' - -const wrapper = ( - cb: (req: Request, res: T, next: NextFunction) => Promise | any | void, - config: { - onSuccess?: ( - res: Response, - data?: any, - showStatus?: boolean - ) => Response> | void - showStatus?: boolean - } = {} -) => { - const { onSuccess, showStatus } = config - - /** - @swagger - #swagger.summary = 'Get single monitor' - */ - return async (req: Request, res: T, next: NextFunction) => { - try { - const data = await cb(req, res, next) - - if (!res.headersSent) { - return onSuccess ? onSuccess(res, data, showStatus) : httpOk(res, data, showStatus) - } - } catch (e) { - return errorResponse(e, res, next) - } - } -} - -export const apiRequest = wrapper -export const apiAuthRequest = wrapper diff --git a/server/utils/exceptions/generalExceptions.ts b/server/utils/exceptions/generalExceptions.ts deleted file mode 100644 index bee4107..0000000 --- a/server/utils/exceptions/generalExceptions.ts +++ /dev/null @@ -1,27 +0,0 @@ -export class NotImplementedError extends Error { - constructor(methodName: string) { - super(`Method ${methodName} is not implemented.`) - this.name = 'NotImplementedError' - } -} - -export class NotFoundError extends Error { - constructor(message?: string) { - super(message ?? 'Resource not found.') - this.name = 'NotFoundError' - } -} - -export class ValidationError extends Error { - constructor(message?: string) { - super(message ?? 'Validation Error.') - this.name = 'ValidationError' - } -} - -export class UnauthorizedError extends Error { - constructor(message?: string) { - super(message ?? 'Unauthorized Error.') - this.name = 'UnauthorizedError' - } -} diff --git a/server/utils/exceptions/index.ts b/server/utils/exceptions/index.ts deleted file mode 100644 index 9eb88d9..0000000 --- a/server/utils/exceptions/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './generalExceptions' diff --git a/server/utils/generator.ts b/server/utils/generator.ts deleted file mode 100644 index d2c7e0e..0000000 --- a/server/utils/generator.ts +++ /dev/null @@ -1,11 +0,0 @@ -const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' - -export const generateRandomString = (length: number) => { - let result = '' - const charactersLength = characters.length - for (let i = 0; i < length; i++) { - result += characters.charAt(Math.floor(Math.random() * charactersLength)) - } - - return result -} diff --git a/server/utils/index.ts b/server/utils/index.ts deleted file mode 100644 index 5a486e6..0000000 --- a/server/utils/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './apis' -export * from './exceptions' -export * from './responses' diff --git a/server/utils/responses/codes.ts b/server/utils/responses/codes.ts deleted file mode 100644 index c2382bf..0000000 --- a/server/utils/responses/codes.ts +++ /dev/null @@ -1,21 +0,0 @@ -export const ResponseCodes: { [code: number]: string } = { - 200: 'Ok', - 201: 'Created', - 204: 'No Content', - 301: 'Moved Perminantly', - 302: 'Found', - 303: 'See Other', - 400: 'Bad Request', - 401: 'Unauthorized', - 403: 'Forbidden', - 404: 'Not Found', - 405: 'Method Not Allowed', - 409: 'Conflict', - 410: 'Gone', - 500: 'Internal Server Error', - 501: 'Not Implemented', - 502: 'Bad Gateway', - 503: 'Service Unavailable', - 504: 'Gateway Timeout', - 511: 'Network Authentication Required' -} diff --git a/server/utils/responses/getResJson.ts b/server/utils/responses/getResJson.ts deleted file mode 100644 index 462a1b6..0000000 --- a/server/utils/responses/getResJson.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { Response } from 'express' - -export const getMockResJson = (res: Response) => { - return (res as any)._getJSONData() -} diff --git a/server/utils/responses/index.ts b/server/utils/responses/index.ts deleted file mode 100644 index 63fc139..0000000 --- a/server/utils/responses/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './codes' -export * from './getResJson' -export * from './responses' diff --git a/server/utils/responses/responses.test.ts b/server/utils/responses/responses.test.ts deleted file mode 100644 index 21d409a..0000000 --- a/server/utils/responses/responses.test.ts +++ /dev/null @@ -1,376 +0,0 @@ -import { ResponseCodes } from './codes' -import * as Responses from './responses' - -describe('Response Boilerplate Tests', () => { - const getResJson = (res: any) => res.json.mock.calls[0][0] - // const res = { - // status: jest.fn().mockReturnThis(), - // json: jest.fn() - // } - - it('should return a 200 status code', () => { - const res1 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpOk(res1 as any, 'Test message', true) - expect(res1.status).toHaveBeenCalledWith(200) - - const resJson = getResJson(res1) - expect(resJson.status).toBe(200) - expect(resJson.type).toBe(ResponseCodes[200]) - expect(resJson.message).toBe('Test message') - - const res2 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpOk(res2 as any, 'Test message', false) - expect(res2.status).toHaveBeenCalledWith(200) - - const resJson2 = getResJson(res2) - expect(resJson2).toBe('Test message') - }) - it('should return a 201 status code', () => { - const res1 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpCreated(res1 as any, 'Test message', true) - expect(res1.status).toHaveBeenCalledWith(201) - - const resJson = getResJson(res1) - expect(resJson.status).toBe(201) - expect(resJson.type).toBe(ResponseCodes[201]) - expect(resJson.message).toBe('Test message') - - const res2 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpCreated(res2 as any, 'Test message', false) - expect(res2.status).toHaveBeenCalledWith(201) - - const resJson2 = getResJson(res2) - expect(resJson2).toBe('Test message') - }) - - it('should return a 204 status code', () => { - const res: any = { - status: jest.fn().mockReturnThis(), - send: jest.fn() - } - Responses.httpNoContent(res as any) - expect(res.status).toHaveBeenCalledWith(204) - expect(res.send).toHaveBeenCalled() - expect(res.json).toBeUndefined() - }) - - it('should return a 400 status code', () => { - const res1 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpBadRequest(res1 as any, 'Test message', true) - expect(res1.status).toHaveBeenCalledWith(400) - - const resJson = getResJson(res1) - expect(resJson.status).toBe(400) - expect(resJson.type).toBe(ResponseCodes[400]) - expect(resJson.message).toBe('Test message') - - const res2 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpBadRequest(res2 as any, 'Test message', false) - expect(res2.status).toHaveBeenCalledWith(400) - - const resJson2 = getResJson(res2) - expect(resJson2).toBe('Test message') - }) - it('should return a 401 status code', () => { - const res1 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpUnauthorized(res1 as any, 'Test message', true) - expect(res1.status).toHaveBeenCalledWith(401) - - const resJson = getResJson(res1) - expect(resJson.status).toBe(401) - expect(resJson.type).toBe(ResponseCodes[401]) - expect(resJson.message).toBe('Test message') - - const res2 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpUnauthorized(res2 as any, 'Test message', false) - expect(res2.status).toHaveBeenCalledWith(401) - - const resJson2 = getResJson(res2) - expect(resJson2).toBe('Test message') - }) - it('should return a 403 status code', () => { - const res1 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpForbidden(res1 as any, 'Test message', true) - expect(res1.status).toHaveBeenCalledWith(403) - - const resJson = getResJson(res1) - expect(resJson.status).toBe(403) - expect(resJson.type).toBe(ResponseCodes[403]) - expect(resJson.message).toBe('Test message') - - const res2 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpForbidden(res2 as any, 'Test message', false) - expect(res2.status).toHaveBeenCalledWith(403) - - const resJson2 = getResJson(res2) - expect(resJson2).toBe('Test message') - }) - it('should return a 404 status code', () => { - const res1 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpNotFound(res1 as any, 'Test message', true) - expect(res1.status).toHaveBeenCalledWith(404) - - const resJson = getResJson(res1) - expect(resJson.status).toBe(404) - expect(resJson.type).toBe(ResponseCodes[404]) - expect(resJson.message).toBe('Test message') - - const res2 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpNotFound(res2 as any, 'Test message', false) - expect(res2.status).toHaveBeenCalledWith(404) - - const resJson2 = getResJson(res2) - expect(resJson2).toBe('Test message') - }) - - it('should return a 405 status code', () => { - const res1 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpMethodNotAllowed(res1 as any, 'Test message', true) - expect(res1.status).toHaveBeenCalledWith(405) - - const resJson = getResJson(res1) - expect(resJson.status).toBe(405) - expect(resJson.type).toBe(ResponseCodes[405]) - expect(resJson.message).toBe('Test message') - - const res2 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpMethodNotAllowed(res2 as any, 'Test message', false) - expect(res2.status).toHaveBeenCalledWith(405) - - const resJson2 = getResJson(res2) - expect(resJson2).toBe('Test message') - }) - - it('should return a 409 status code', () => { - const res1 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpConflict(res1 as any, 'Test message', true) - expect(res1.status).toHaveBeenCalledWith(409) - - const resJson = getResJson(res1) - expect(resJson.status).toBe(409) - expect(resJson.type).toBe(ResponseCodes[409]) - expect(resJson.message).toBe('Test message') - - const res2 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpConflict(res2 as any, 'Test message', false) - expect(res2.status).toHaveBeenCalledWith(409) - - const resJson2 = getResJson(res2) - expect(resJson2).toBe('Test message') - }) - - it('should return a 410 status code', () => { - const res1 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpGone(res1 as any, 'Test message', true) - expect(res1.status).toHaveBeenCalledWith(410) - - const resJson = getResJson(res1) - expect(resJson.status).toBe(410) - expect(resJson.type).toBe(ResponseCodes[410]) - expect(resJson.message).toBe('Test message') - - const res2 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpGone(res2 as any, 'Test message', false) - expect(res2.status).toHaveBeenCalledWith(410) - - const resJson2 = getResJson(res2) - expect(resJson2).toBe('Test message') - }) - - it('should return a 500 status code', () => { - const res1 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpInternalServerError(res1 as any, 'Test message', true) - expect(res1.status).toHaveBeenCalledWith(500) - - const resJson = getResJson(res1) - expect(resJson.status).toBe(500) - expect(resJson.type).toBe(ResponseCodes[500]) - expect(resJson.message).toBe('Test message') - - const res2 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpInternalServerError(res2 as any, 'Test message', false) - expect(res2.status).toHaveBeenCalledWith(500) - - const resJson2 = getResJson(res2) - expect(resJson2).toBe('Test message') - }) - it('should return a 501 status code', () => { - const res1 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpNotImplemented(res1 as any, 'Test message', true) - expect(res1.status).toHaveBeenCalledWith(501) - - const resJson = getResJson(res1) - expect(resJson.status).toBe(501) - expect(resJson.type).toBe(ResponseCodes[501]) - expect(resJson.message).toBe('Test message') - - const res2 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpNotImplemented(res2 as any, 'Test message', false) - expect(res2.status).toHaveBeenCalledWith(501) - - const resJson2 = getResJson(res2) - expect(resJson2).toBe('Test message') - }) - - it('should return a 502 status code', () => { - const res1 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpBadGateway(res1 as any, 'Test message', true) - expect(res1.status).toHaveBeenCalledWith(502) - - const resJson = getResJson(res1) - expect(resJson.status).toBe(502) - expect(resJson.type).toBe(ResponseCodes[502]) - expect(resJson.message).toBe('Test message') - - const res2 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpBadGateway(res2 as any, 'Test message', false) - expect(res2.status).toHaveBeenCalledWith(502) - - const resJson2 = getResJson(res2) - expect(resJson2).toBe('Test message') - }) - - it('should return a 503 status code', () => { - const res1 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpServiceUnavailable(res1 as any, 'Test message', true) - expect(res1.status).toHaveBeenCalledWith(503) - - const resJson = getResJson(res1) - expect(resJson.status).toBe(503) - expect(resJson.type).toBe(ResponseCodes[503]) - expect(resJson.message).toBe('Test message') - - const res2 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpServiceUnavailable(res2 as any, 'Test message', false) - expect(res2.status).toHaveBeenCalledWith(503) - - const resJson2 = getResJson(res2) - expect(resJson2).toBe('Test message') - }) - - it('should return a 504 status code', () => { - const res1 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpGatewayTimeout(res1 as any, 'Test message', true) - expect(res1.status).toHaveBeenCalledWith(504) - - const resJson = getResJson(res1) - expect(resJson.status).toBe(504) - expect(resJson.type).toBe(ResponseCodes[504]) - expect(resJson.message).toBe('Test message') - - const res2 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpGatewayTimeout(res2 as any, 'Test message', false) - expect(res2.status).toHaveBeenCalledWith(504) - - const resJson2 = getResJson(res2) - expect(resJson2).toBe('Test message') - }) - - it('should return a 511 status code', () => { - const res1 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpNetworkAuthenticationRequired(res1 as any, 'Test message', true) - expect(res1.status).toHaveBeenCalledWith(511) - - const resJson = getResJson(res1) - expect(resJson.status).toBe(511) - expect(resJson.type).toBe(ResponseCodes[511]) - expect(resJson.message).toBe('Test message') - - const res2 = { - status: jest.fn().mockReturnThis(), - json: jest.fn() - } - Responses.httpNetworkAuthenticationRequired(res2 as any, 'Test message', false) - expect(res2.status).toHaveBeenCalledWith(511) - - const resJson2 = getResJson(res2) - expect(resJson2).toBe('Test message') - }) -}) diff --git a/server/utils/responses/responses.ts b/server/utils/responses/responses.ts deleted file mode 100644 index 64a044f..0000000 --- a/server/utils/responses/responses.ts +++ /dev/null @@ -1,313 +0,0 @@ -/** - * @fileoverview General routes for the API. - * - * Additional resources: - * - https://developer.mozilla.org/en-US/docs/Web/HTTP/Status - * - https://enterprisecraftsmanship.com/posts/rest-api-response-codes-400-vs-500/ - */ - -import { type NextFunction, type Response } from 'express' -import { ResponseCodes } from './codes' - -export interface ResponsePayload { - status: number - type: string - message?: string -} - -const formatResponse = (status: number, message?: any): ResponsePayload => { - // message = String(message) || '' - const defaultMessage = ResponseCodes[status] || 'Unknown error' - message = String(message) || null - - const payload: ResponsePayload = { - status, - type: defaultMessage - } - - if (message && message !== 'undefined') { - payload.message = message - } - - return payload -} -export const formatJsonResponse = formatResponse - -/** - * Send an error from a view to the error handling middleware. - * If unhandled in middleware, will cause a 500. - */ -export const errorResponse = (error: any, res: Response, next: NextFunction) => { - res.status(500) - return next(error) -} - -/** - * #swagger.responses[200] = { - schema: {$ref: "#/definitions/Success200"}, - } - * @response 200 - OK - * The request succeeded. - */ -export const httpOk = (res: Response, data?: any, showStatus?: boolean): any => { - const payload: ResponsePayload = formatResponse(200, data) - - if (showStatus) { - return res.status(200).json(payload) - } else { - return res.status(200).json(data || payload) - } -} - -/** - * @response 201 - Created - * The request has been fulfilled, resulting in the creation of a new resource. - */ -export const httpCreated = (res: Response, data?: any, showStatus?: boolean): any => { - const payload: ResponsePayload = formatResponse(201, data) - - if (showStatus) { - return res.status(201).json(payload) - } else { - return res.status(201).json(data || payload) - } -} - -/** - * @response 204 - No Content - * The server successfully processed the request and is not returning any content. - */ -export const httpNoContent = (res: Response): any => { - res.status(204).send() -} - -/** - * @returns Response 301 - Moved Perminantly - * @description The URL of the requested resource has been changed permanently. - */ -export const httpMovedPermanently = ( - res: Response, - uri: string, - headers?: { [field: string]: string } -) => { - return res.status(301).set(headers).redirect(uri) -} - -/** - * @returns Response 302 - Found - * @description The URL of the requested resource has been changed temporarily. Further changes - * in the URL might be made in the future. This is used as a temporary redirect. - */ -export const httpFound = (res: Response, uri: string, headers?: { [field: string]: string }) => { - return res.status(302).set(headers).redirect(uri) -} - -/** - * @returns Response 303 - See Other - * @description The response to the request can be found under another URL using a GET method. - */ -export const httpSeeOther = (res: Response, uri: string, headers?: { [field: string]: string }) => { - return res.status(303).set(headers).redirect(uri) -} - -/** - * @response 400 - Bad Request - * The server cannot or will not process the request due to an apparent client error. - * Unlike 500 errors which the user can’t do anything about, 400 errors are their fault. - */ -export const httpBadRequest = (res: Response, message?: any, showStatus: boolean = true): any => { - const payload: ResponsePayload = formatResponse(400, message) - if (showStatus) { - return res.status(400).json(payload) - } else { - return res.status(400).json(message || payload) - } -} - -/** - * @response 401 - Unauthorized - * The request has not been applied because it lacks valid authentication credentials for the target resource. - */ -export const httpUnauthorized = (res: Response, message?: any, showStatus: boolean = true): any => { - const payload: ResponsePayload = formatResponse(401, message) - if (showStatus) { - return res.status(401).json(payload) - } else { - return res.status(401).json(message || payload) - } -} - -/** - * @response 403 - Forbidden - * The server understood the request but refuses to authorize it. - * Unlike 401 Unauthorized, the client's identity is known to the server. - */ -export const httpForbidden = (res: Response, message?: any, showStatus: boolean = true): any => { - const payload: ResponsePayload = formatResponse(403, message) - if (showStatus) { - return res.status(403).json(payload) - } else { - return res.status(403).json(message || payload) - } -} - -/** - * @response 404 - Not Found - * The requested resource could not be found but may be available in the future. - * Subsequent requests by the client are permissible. - */ -export const httpNotFound = (res: Response, message?: any, showStatus: boolean = true): any => { - const payload: ResponsePayload = formatResponse(404, message) - if (showStatus) { - return res.status(404).json(payload) - } else { - return res.status(404).json(message || payload) - } -} - -/** - * @response 405 - Method Not Allowed - * The request method is known by the server but is not supported by the target resource. - */ -export const httpMethodNotAllowed = ( - res: Response, - message?: any, - showStatus: boolean = true -): any => { - const payload: ResponsePayload = formatResponse(405, message) - if (showStatus) { - return res.status(405).json(payload) - } else { - return res.status(405).json(message || payload) - } -} - -/** - * @response 409 - Conflict - * This response is sent when a request conflicts with the current state of the server. - */ -export const httpConflict = (res: Response, message?: any, showStatus: boolean = true): any => { - const payload: ResponsePayload = formatResponse(409, message) - if (showStatus) { - return res.status(409).json(payload) - } else { - return res.status(409).json(message || payload) - } -} - -/** - * @response 410 - Gone - * This response is sent when the requested content has been permanently deleted from server, - * clients are expected to remove their caches and links to the resource. The HTTP specification - * intends this status code to be used for "limited-time, promotional services". - */ -export const httpGone = (res: Response, message?: any, showStatus: boolean = true): any => { - const payload: ResponsePayload = formatResponse(410, message) - if (showStatus) { - return res.status(410).json(payload) - } else { - return res.status(410).json(message || payload) - } -} - -/** - * @response 500 - Internal Server Error - * The server has encountered a situation it does not know how to handle. - * Never return 500 errors intentionally. The only way your service should - * respond with a 500 code is by processing an unhandled exception. - */ -export const httpInternalServerError = ( - res: Response, - message?: any, - showStatus: boolean = true -): any => { - const payload: ResponsePayload = formatResponse(500, message) - if (showStatus) { - return res.status(500).json(payload) - } else { - return res.status(500).json(message || payload) - } -} - -/** - * @response 501 - Not Implemented - * The server either does not recognize the request method, or it lacks the ability to fulfil the request. - * The only methods that servers are required to support (and therefore that must - * not return this code) are GET and HEAD. - */ -export const httpNotImplemented = ( - res: Response, - message?: any, - showStatus: boolean = true -): any => { - const payload: ResponsePayload = formatResponse(501, message) - if (showStatus) { - return res.status(501).json(payload) - } else { - return res.status(501).json(message || payload) - } -} - -/** - * @response 502 - Bad Gateway - * The server was acting as a gateway or proxy and received an invalid response from the upstream server. - */ -export const httpBadGateway = (res: Response, message?: any, showStatus: boolean = true): any => { - const payload: ResponsePayload = formatResponse(502, message) - if (showStatus) { - return res.status(502).json(payload) - } else { - return res.status(502).json(message || payload) - } -} - -/** - * @response 503 - Service Unavailable - * The server cannot handle the request (because it is overloaded or down for maintenance). - */ -export const httpServiceUnavailable = ( - res: Response, - message?: any, - showStatus: boolean = true -): any => { - const payload: ResponsePayload = formatResponse(503, message) - if (showStatus) { - return res.status(503).json(payload) - } else { - return res.status(503).json(message || payload) - } -} - -/** - * @response 504 - Gateway Timeout - * This error response is given when the server is acting as a gateway and cannot get a response in time. - */ -export const httpGatewayTimeout = ( - res: Response, - message?: any, - showStatus: boolean = true -): any => { - const payload: ResponsePayload = formatResponse(504, message) - if (showStatus) { - return res.status(504).json(payload) - } else { - return res.status(504).json(message || payload) - } -} - -/** - * @response 511 - Network Authentication Required - * The client needs to authenticate to gain network access. - */ -export const httpNetworkAuthenticationRequired = ( - res: Response, - message?: any, - showStatus: boolean = true -): any => { - const payload: ResponsePayload = formatResponse(511, message) - if (showStatus) { - return res.status(511).json(payload) - } else { - return res.status(511).json(message || payload) - } -} diff --git a/server/views/baseViews.ts b/server/views/baseViews.ts deleted file mode 100644 index 0813a3a..0000000 --- a/server/views/baseViews.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { producePing } from 'server/events/producers' -import { apiRequest } from 'server/utils' - -/** - * REST Api Views - * - * Views handle requests and responses from the router, and - * will call any necessary controller. Views cannot directly access - * services, validators, models, or other views. - */ -export const healthcheck = apiRequest( - (req, res) => { - /** - @swagger Health Check - #swagger.summary = 'Health Check' - #swagger.tags = ['General'] - #swagger.description = 'Root route to check if the system is online.' - */ - return 'All systems operational.' - }, - { showStatus: true } -) - -export const apiHelp = apiRequest((req, res) => { - /** - @swagger API Help - #swagger.summary = 'API Help and Navigation' - #swagger.tags = ['General'] - #swagger.description = 'Main links to use for navigating api.' - #swagger.responses[200] = { - schema: { - "spotifyLogin": "http://localhost:8000/api/spotify/login/", - "documenation": "http://localhost:8000/api/docs/" - }, - description: "Monitor updated" - } - */ - const baseUrl = req.protocol + '://' + req.get('host') - - return { - spotifyLogin: `${baseUrl}/api/spotify/login/`, - documenation: `${baseUrl}/api/docs/` - } -}) - -export const pingPongView = apiRequest((req, res) => { - /** - @swagger - #swagger.tags = ['General'] - #swagger.summary = 'Test out flow of events from client to server.' - #swagger.description = 'Triggers a Kafka event that every server as a consumer for, - forcing them all to respond for sanity checks.' - */ - const data = 'Ping from api.' - producePing(new Date().toLocaleTimeString(), data) -}) diff --git a/server/views/groupViews.ts b/server/views/groupViews.ts deleted file mode 100644 index e1e3815..0000000 --- a/server/views/groupViews.ts +++ /dev/null @@ -1,194 +0,0 @@ -import type { Devices, PlaybackState } from '@spotify/web-api-ts-sdk' -import { - assignSpotifyToGroup, - getGroupDevices, - getGroupSpotifyAuth, - getGroupTrack, - setGroupDefaultDevice, - setGroupPlayerState -} from 'server/controllers' -import { Group, type IGroup, type ISpotifyAuth } from 'server/models' -import { apiAuthRequest, Viewset, type ApiArgs } from 'server/utils' - -const groupViewset = new Viewset(Group) - -export const assignSpotifyAccountView = apiAuthRequest(async (req, res, next) => { - /** - @swagger - #swagger.tags = ['Group'] - #swagger.responses[200] = { - schema: { - "id": "66e9f064f4b6247a0c26291e", - "ownerId": "66e8a2e7f4b6247a0c262910", - "name": "group", - "spotifyAuthId": "66e9fbbcb14c1ccc11b3d8fd" - }, - description: "Monitor updated" - } - */ - const { user } = res.locals - const spotifyEmail = String(req.body.spotifyEmail) - const id = String(req.params.id) - - const group = await assignSpotifyToGroup(user, id, spotifyEmail) - const serialized: IGroup = group.serialize() - - return serialized -}) - -export const getGroupCurrentTrackView = apiAuthRequest(async (req, res, next) => { - /** - @swagger - #swagger.tags = ['Group'] - #swagger.responses[200] = { - schema: { - "id": "66e9f064f4b6247a0c26291e", - "ownerId": "66e8a2e7f4b6247a0c262910", - "name": "group", - "spotifyAuthId": "66e9fbbcb14c1ccc11b3d8fd" - }, - description: "Success" - } - */ - const id = String(req.params.id) - const track: PlaybackState = await getGroupTrack(id) - - return track -}) - -export const getGroupDevicesView = apiAuthRequest(async (req, res) => { - /** - @swagger - #swagger.tags = ['Group'] - #swagger.responses[200] = { - schema: { - devices: [ - { - "id": "ff25d0139c6039819da122cacbdb275fe83e5286", - "is_active": false, - "is_private_session": false, - "is_restricted": false, - "name": "Nabeel’s MacBook Air", - "supports_volume": true, - "type": "Computer", - "volume_percent": 81 - } - ] - }, - description: "Success" - } - */ - const id = String(req.params.id) - const devices: Devices = await getGroupDevices(id) - - return devices -}) -export const setGroupDefaultDeviceView = apiAuthRequest(async (req, res) => { - /** - @swagger - #swagger.tags = ['Group'] - #swagger.responses[200] = { - schema: { - "spotifyLogin": "http://localhost:8000/api/spotify/login/", - "documenation": "http://localhost:8000/api/docs/" - }, - description: "Monitor updated" - } - */ - const id = String(req.params.id) - const deviceId = String(req.body.deviceId) - - const group = await setGroupDefaultDevice(id, deviceId) - const serialized: IGroup = group.serialize() - - return serialized -}) - -export const setGroupPlayerStateView = apiAuthRequest(async (req, res, next) => { - /** - @swagger - #swagger.tags = ['Group'] - */ - const id = String(req.params.id) - const state = String(req.body.state) as 'play' | 'pause' - - await setGroupPlayerState(id, state) -}) - -export const getGroupSpotifyAuthView = apiAuthRequest(async (req, res, next) => { - /** - @swagger - #swagger.tags = ['Group'] - */ - const id = String(req.params.id) - const auth = await getGroupSpotifyAuth(id) - const serialized: ISpotifyAuth = auth.serialize() - - return serialized -}) - -export const groupCreateView = async (...args: ApiArgs) => { - /** - @swagger - #swagger.tags = ['Group'] - #swagger.parameters['body'] = { - in: "body", - name: "body", - description: "Group Object", - required: true, - schema: {$ref: "#/definitions/IGroupFields"} - } - #swagger.responses[200] = { - schema: { $ref: "#/definitions/IGroup" } - } - */ - const group: IGroup = await groupViewset.create(...args) - - return group -} - -export const groupListView = async (...args: ApiArgs) => { - /** - @swagger - #swagger.tags = ['Group'] - */ - const groups: IGroup[] = await groupViewset.list(...args) - - return groups -} -export const groupGetView = async (...args: ApiArgs) => { - /** - @swagger - #swagger.tags = ['Group'] - */ - const group: IGroup = await groupViewset.get(...args) - - return group -} -export const groupUpdateView = async (...args: ApiArgs) => { - /** - @swagger - #swagger.tags = ['Group'] - */ - const group: IGroup = await groupViewset.update(...args) - - return group -} -export const groupPartialUpdateView = async (...args: ApiArgs) => { - /** - @swagger - #swagger.tags = ['Group'] - */ - const group: IGroup = await groupViewset.partialUpdate(...args) - - return group -} -export const groupDeleteView = async (...args: ApiArgs) => { - /** - @swagger - #swagger.tags = ['Group'] - */ - const group: IGroup = await groupViewset.delete(...args) - - return group -} diff --git a/server/views/spotifyAuthViews.ts b/server/views/spotifyAuthViews.ts deleted file mode 100644 index 1d16e9f..0000000 --- a/server/views/spotifyAuthViews.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { getSpotifyRedirectUri } from 'server/lib' -import { SpotifyAuth, User } from 'server/models' -import { SpotifyService } from 'server/services' -import { apiAuthRequest, apiRequest, httpSeeOther, UnauthorizedError } from 'server/utils' - -export const spotifyLoginView = apiAuthRequest(async (req, res) => { - /** - @swagger - #swagger.tags = ['Spotify'] - */ - const { user } = res.locals - let { redirectUri, groupId } = req.query - redirectUri = String(redirectUri) - - const spotifyLoginUri = getSpotifyRedirectUri({ - userId: user._id.toString(), - finalRedirect: redirectUri - }) - - return httpSeeOther(res, spotifyLoginUri) -}) - -export const spotifyLoginCallbackView = apiRequest(async (req, res) => { - /** - @swagger - #swagger.tags = ['Spotify'] - */ - let { code, state } = req.query - code = String(code) - - const parsedState = JSON.parse(JSON.parse(JSON.stringify(state))) // TODO: Fix double parse - const { userId, finalRedirect } = parsedState - if (!userId) throw new Error('Spotify state mismatch error.') - - const user: User | null = await User.findById(userId) - if (!user) throw new UnauthorizedError() - - const spotifyUser = await SpotifyService.authenticateUser(user._id.toString(), code) - const profile = await spotifyUser.getProfile() - - if (finalRedirect && String(finalRedirect) !== 'undefined' && finalRedirect !== '') { - return httpSeeOther(res, finalRedirect) - } else { - return profile - } -}) - -export const removeSpotifyConnection = apiAuthRequest(async (req, res, next) => { - /** - @swagger - #swagger.tags = ['Spotify'] - */ - const { user } = res.locals - const spotifyEmail = String(req.body.spotifyEmail) - - const deleted = await SpotifyAuth.deleteOne({ - spotifyEmail: spotifyEmail, - userId: user._id.toString() - }) - return deleted.deletedCount -}) diff --git a/server/views/tests/baseViews.test.ts b/server/views/tests/baseViews.test.ts deleted file mode 100644 index 980c666..0000000 --- a/server/views/tests/baseViews.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @fileoverview Test for general api routes. - */ -import type { NextFunction, Request, Response } from 'express' -import httpMocks from 'node-mocks-http' -import * as views from '../baseViews' - -describe('Base controller', () => { - let req: Request - let res: Response - let next: NextFunction - - beforeEach(() => { - res = httpMocks.createResponse() - next = jest.fn() - }) - - it('should return ok', async () => { - req = httpMocks.createRequest({ - method: 'GET' - }) - - await views.healthcheck(req, res, next) - expect(res.statusCode).toBe(200) - }) -}) diff --git a/server/views/tests/userViews.test.ts b/server/views/tests/userViews.test.ts deleted file mode 100644 index 5b5ddf3..0000000 --- a/server/views/tests/userViews.test.ts +++ /dev/null @@ -1,187 +0,0 @@ -import type { NextFunction, Request, Response } from 'express' -import httpMocks from 'node-mocks-http' - -import { User } from 'server/models' -import { AuthService } from 'server/services' -import { getMockResJson } from 'server/utils' - -import type { AuthResponse } from 'server/middleware' -import * as views from '../userViews' - -describe('User Controller', () => { - let req: Request - let res: Response - let authRes: AuthResponse - let next: NextFunction - - const originalPassword: string = 'abc123' - const createUser = async (): Promise => { - return await AuthService.registerUser({ - email: 'john.doe@example.com', - password: originalPassword - }) - } - - beforeEach(async () => { - res = httpMocks.createResponse() - next = jest.fn() - }) - - it('should register a user', async () => { - const pre = await User.find({}) - expect(pre).toHaveLength(0) - - req = httpMocks.createRequest({ - method: 'POST', - body: { - email: 'test', - password: 'test' - } - }) - - const resData = await views.registerUserView(req, res, next) - expect(resData.statusCode).toBe(201) - - const body = getMockResJson(resData) - expect(body).toHaveProperty('email') - expect(body).not.toHaveProperty('password') - }) - - it('should login a user', async () => { - const user = await createUser() - - req = httpMocks.createRequest({ - method: 'POST', - body: { - email: user.email, - password: originalPassword - } - }) - - const resData = await views.loginUserView(req, res, next) - expect(resData.statusCode).toBe(200) - - const body = getMockResJson(resData) - expect(body).toHaveProperty('token') // TODO: Test if token works - }) - - // TODO: How to handle middleware in unit tests? - // it('should get a user', async () => { - // const user = await createUser() - - // req = httpMocks.createRequest({ - // method: 'GET', - // params: { - // id: user._id - // } - // }) - // const admin = await AuthService.registerUser({ - // email: 'admin@example.com', - // password: originalPassword - // }) - // authRes = httpMocks.createResponse({ locals: { user: admin } }) - - // const resData = await views.userGetView(req, authRes, next) - // expect(resData.statusCode).toBe(200) - - // const body = getMockResJson(resData) - // expect(body).toHaveProperty('id') - // const obj = body - - // expect(String(obj.id)).toEqual(String(user._id)) - // }) - - // it('should partially update a user', async () => { - // const user = await createUser() - // await user.updateOne({ email: 'user@example.com' }) - // const newemail = 'user-changed@example.com' - - // req = httpMocks.createRequest({ - // method: 'PATCH', - // params: { - // id: user._id.toString() - // }, - // body: { - // email: newemail - // } - // }) - // const admin = await AuthService.registerUser({ - // email: 'admin@example.com', - // password: originalPassword - // }) - // authRes = httpMocks.createResponse({ locals: { user: admin } }) - - // const resData = await views.userPartialUpdateView(req, authRes, next) - // expect(resData.statusCode).toBe(200) - - // const body = getMockResJson(resData) - // expect(body).toHaveProperty('email') - // expect(body).not.toHaveProperty('password') - // const obj = JSON.parse(JSON.stringify(body)) - - // expect(obj.email).toEqual(newemail) - // }) - - // it('should update all fields on a user', async () => { - // const user = await createUser() - // await user.updateOne({ email: 'Pre-update', password: 'pre-update-pass' }) - // const newemail = 'Post-update-change' - // const newPassword = 'Post-update-pass' - - // req = httpMocks.createRequest({ - // method: 'PATCH', - // params: { - // id: user._id - // }, - // body: { - // email: newemail, - // password: newPassword - // } - // }) - // const admin = await AuthService.registerUser({ - // email: 'admin@example.com', - // password: originalPassword - // }) - // authRes = httpMocks.createResponse({ locals: { user: admin } }) - - // const resData = await views.userUpdateView(req, authRes, next) - // expect(resData.statusCode).toBe(200) - - // const body = getMockResJson(resData) - // expect(body).toHaveProperty('email') - // expect(body).not.toHaveProperty('password') - - // const obj = JSON.parse(JSON.stringify(body)) - // expect(obj.email).toEqual(newemail) - // }) - - // it('should delete a user', async () => { - // const user = await createUser() - - // req = httpMocks.createRequest({ - // method: 'DELETE', - // params: { - // id: user._id - // } - // }) - // const admin = await AuthService.registerUser({ - // email: 'admin@example.com', - // password: originalPassword - // }) - // authRes = httpMocks.createResponse({ locals: { user: admin } }) - - // const resData = await views.userDeleteView(req, authRes, next) - // expect(resData.statusCode).toBe(200) - - // // Check if deleted user is returned - // const body = getMockResJson(resData) - // expect(body).toHaveProperty('id') - // const obj = JSON.parse(JSON.stringify(body)) - - // expect(String(obj.id)).toEqual(String(user._id)) - - // // Check that user is deleted - // const usersInDb = await User.find({}) - // expect(usersInDb).toHaveLength(0) - // }) -}) diff --git a/server/views/userViews.ts b/server/views/userViews.ts deleted file mode 100644 index e258732..0000000 --- a/server/views/userViews.ts +++ /dev/null @@ -1,208 +0,0 @@ -import { - getUserSpotifyEmails, - getUserToken, - registerUser, - requestPasswordReset, - resetPassword -} from 'server/controllers' -import { cleanUser, Group, User, type IUser } from 'server/models' -import { apiAuthRequest, apiRequest, httpCreated, Viewset, type ApiArgs } from 'server/utils' - -export const registerUserView = apiRequest( - async (req, res, next) => { - /** - @swagger - #swagger.tags = ['User'] - #swagger.summary = "Register new user" - #swagger.description = "Create a new user account" - */ - const { email, password } = req.body - if (!email || !password) throw new Error('Missing email or password.') - - const user = await registerUser(email, password) - const serialized: IUser = user.serialize() - - /* - #swagger.responses[200] = { - description: 'Return created user', - schema: { $ref: '#/definitions/IUser' } - } - */ - return serialized - }, - { onSuccess: httpCreated } -) -export const loginUserView = apiRequest(async (req, res, next) => { - /** - @swagger - #swagger.tags = ['User'] - #swagger.summary = "Get token for logging in a user" - */ - const { email, password } = req.body - if (!email || !password) throw new Error('Missing email or password.') - const token = await getUserToken(email, password) - - /* - #swagger.responses[200] = { - schema: { - "token": "example-token" - }, - } - */ - return { token } -}) - -export const currentUserView = apiAuthRequest(async (req, res, next) => { - /** - @swagger - #swagger.tags = ['User'] - #swagger.summary = "Get info about the authenticated user" - - */ - const { user } = res.locals - const userSerialized: IUser = user.serialize() - const userGroups = await Group.find({ ownerId: user._id }) - - const groups = userGroups.map((group) => ({ id: group._id, name: group.name })) - - /* - #swagger.responses[200] = { - schema: { $ref: "#/definitions/IUserDetails" }, - } - */ - return { ...userSerialized, groups } -}) - -export const updateCurrentUserView = apiAuthRequest(async (req, res, next) => { - const attrs: Partial = { - firstName: req.body.firstName, - lastName: req.body.lastName, - image: req.body.image - } - const { user } = res.locals - - return await User.findOneAndUpdate({ id: user._id }, attrs, { new: true }).exec() -}) - -// TODO: Remove authentication requirement, send email to user -export const requestPasswordResetView = apiRequest(async (req, res, next) => { - /** - @swagger - #swagger.tags = ['User'] - #swagger.summary = "Request a password reset for authenticated user (TODO)" - #swagger.responses[200] = { - schema: { - "status": 200, - "type": "Ok" - }, - description: "" - } - */ - const { email } = req.body - if (!email) throw new Error('Missing email.') - - await requestPasswordReset(email) -}) - -export const resetPasswordView = apiRequest(async (req, res, next) => { - /** - @swagger - #swagger.tags = ['User'] - #swagger.summary = "Allow user to reset password from reset request (TODO)" - #swagger.responses[200] = { - schema: { - "status": 200, - "type": "Ok" - }, - description: "" - } - */ - // FIXME: Insecure password reset, HIGH security risk - const { email, password } = req.body - if (!email || !password) throw new Error('Missing email or password.') - - await resetPassword(email, password) -}) - -export const connectedSpotifyAccounts = apiAuthRequest(async (req, res, next) => { - /** - @swagger - #swagger.tags = ['User'] - #swagger.summary = "Get connected spotify accounts for user" - #swagger.responses[200] = { - schema: { - - }, - description: "" - } - */ - const { user } = res.locals - const emails: string[] = await getUserSpotifyEmails(user) - - return emails -}) - -const UserViewset = new Viewset(User, cleanUser) - -export const userCreateView = apiAuthRequest(async (...args: ApiArgs) => { - /** - @swagger - #swagger.summary = "Create a new user" - #swagger.tags = ['User'] - - */ - const user: IUser = await UserViewset.create(...args) - - return user -}) - -export const userListView = apiAuthRequest(async (...args: ApiArgs) => { - /** - @swagger - #swagger.summary = "Get a list of all users" - #swagger.tags = ['User'] - */ - const users: IUser[] = await UserViewset.list(...args) - - return users -}) -export const userGetView = apiAuthRequest(async (...args: ApiArgs) => { - /** - @swaggeď - #swagger.summary = "Get a single user by id" - #swagger.tags = ['User'] - */ - const user: IUser = await UserViewset.get(...args) - - return user -}) -export const userUpdateView = apiAuthRequest(async (...args: ApiArgs) => { - /** - @swagger - #swagger.summary = "Update all fields on a user" - #swagger.tags = ['User'] - */ - const user: IUser = await UserViewset.update(...args) - - return user -}) -export const userPartialUpdateView = apiAuthRequest(async (...args: ApiArgs) => { - /** - @swagger - #swagger.summary = "Update some fields on a user" - #swagger.tags = ['User'] - */ - const user: IUser = await UserViewset.partialUpdate(...args) - - return user -}) -export const userDeleteView = apiAuthRequest(async (...args: ApiArgs) => { - /** - @swagger - #swagger.summary = "Delete a user by id" - #swagger.tags = ['User'] - */ - const user: IUser = await UserViewset.delete(...args) - - return user -}) diff --git a/src/app.controller.spec.ts b/src/app.controller.spec.ts new file mode 100644 index 0000000..d22f389 --- /dev/null +++ b/src/app.controller.spec.ts @@ -0,0 +1,22 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; + +describe('AppController', () => { + let appController: AppController; + + beforeEach(async () => { + const app: TestingModule = await Test.createTestingModule({ + controllers: [AppController], + providers: [AppService], + }).compile(); + + appController = app.get(AppController); + }); + + describe('root', () => { + it('should return "Hello World!"', () => { + expect(appController.getHello()).toBe('Hello World!'); + }); + }); +}); diff --git a/src/app.controller.ts b/src/app.controller.ts new file mode 100644 index 0000000..cce879e --- /dev/null +++ b/src/app.controller.ts @@ -0,0 +1,12 @@ +import { Controller, Get } from '@nestjs/common'; +import { AppService } from './app.service'; + +@Controller() +export class AppController { + constructor(private readonly appService: AppService) {} + + @Get() + getHello(): string { + return this.appService.getHello(); + } +} diff --git a/src/app.module.ts b/src/app.module.ts new file mode 100644 index 0000000..2cc1344 --- /dev/null +++ b/src/app.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; +import { SpotifyModule } from './spotify/spotify.module'; +import { TrackQueueModule } from './track-queue/track-queue.module'; + +@Module({ + imports: [SpotifyModule, TrackQueueModule], + controllers: [AppController], + providers: [AppService], +}) +export class AppModule {} diff --git a/src/app.service.ts b/src/app.service.ts new file mode 100644 index 0000000..927d7cc --- /dev/null +++ b/src/app.service.ts @@ -0,0 +1,8 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class AppService { + getHello(): string { + return 'Hello World!'; + } +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..13cad38 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,8 @@ +import { NestFactory } from '@nestjs/core'; +import { AppModule } from './app.module'; + +async function bootstrap() { + const app = await NestFactory.create(AppModule); + await app.listen(3000); +} +bootstrap(); diff --git a/server/models/utils/testGroup.ts b/src/spotify/schemas/spotify-auth.schema.ts similarity index 100% rename from server/models/utils/testGroup.ts rename to src/spotify/schemas/spotify-auth.schema.ts diff --git a/src/spotify/spotify.controller.ts b/src/spotify/spotify.controller.ts new file mode 100644 index 0000000..eeb9761 --- /dev/null +++ b/src/spotify/spotify.controller.ts @@ -0,0 +1,4 @@ +import { Controller } from '@nestjs/common'; + +@Controller('spotify') +export class SpotifyController {} diff --git a/src/spotify/spotify.module.ts b/src/spotify/spotify.module.ts new file mode 100644 index 0000000..5967662 --- /dev/null +++ b/src/spotify/spotify.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { SpotifyController } from './spotify.controller'; +import { SpotifyService } from './spotify.service'; + +@Module({ + controllers: [SpotifyController], + providers: [SpotifyService] +}) +export class SpotifyModule {} diff --git a/src/spotify/spotify.service.ts b/src/spotify/spotify.service.ts new file mode 100644 index 0000000..1973493 --- /dev/null +++ b/src/spotify/spotify.service.ts @@ -0,0 +1,4 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class SpotifyService {} diff --git a/src/spotify/tests/spotify.controller.spec.ts b/src/spotify/tests/spotify.controller.spec.ts new file mode 100644 index 0000000..36a5e5b --- /dev/null +++ b/src/spotify/tests/spotify.controller.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { SpotifyController } from '../spotify.controller'; + +describe('SpotifyController', () => { + let controller: SpotifyController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [SpotifyController], + }).compile(); + + controller = module.get(SpotifyController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/spotify/tests/spotify.service.spec.ts b/src/spotify/tests/spotify.service.spec.ts new file mode 100644 index 0000000..c140cd8 --- /dev/null +++ b/src/spotify/tests/spotify.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { SpotifyService } from '../spotify.service'; + +describe('SpotifyService', () => { + let service: SpotifyService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [SpotifyService], + }).compile(); + + service = module.get(SpotifyService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/track-queue/tests/track-queue.service.spec.ts b/src/track-queue/tests/track-queue.service.spec.ts new file mode 100644 index 0000000..eeae67d --- /dev/null +++ b/src/track-queue/tests/track-queue.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { TrackQueueService } from '../track-queue.service'; + +describe('TrackQueueService', () => { + let service: TrackQueueService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [TrackQueueService], + }).compile(); + + service = module.get(TrackQueueService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/server/services/tests/trackQueue.test.ts b/src/track-queue/tests/trackQueue.test.ts similarity index 96% rename from server/services/tests/trackQueue.test.ts rename to src/track-queue/tests/trackQueue.test.ts index 9c130dd..539f244 100644 --- a/server/services/tests/trackQueue.test.ts +++ b/src/track-queue/tests/trackQueue.test.ts @@ -1,5 +1,4 @@ -import { TrackQueueItem } from '../trackQueue'; -import { TrackQueue } from '../trackQueue'; +import { TrackQueueService as TrackQueue } from '../track-queue.service'; import type { Track } from '@spotify/web-api-ts-sdk'; // describe('TrackQueue Tests', () => { diff --git a/src/track-queue/track-queue.module.ts b/src/track-queue/track-queue.module.ts new file mode 100644 index 0000000..a273d78 --- /dev/null +++ b/src/track-queue/track-queue.module.ts @@ -0,0 +1,7 @@ +import { Module } from '@nestjs/common'; +import { TrackQueueService } from './track-queue.service'; + +@Module({ + providers: [TrackQueueService] +}) +export class TrackQueueModule {} diff --git a/server/services/trackQueue.ts b/src/track-queue/track-queue.service.ts similarity index 94% rename from server/services/trackQueue.ts rename to src/track-queue/track-queue.service.ts index 6de8786..0bdb585 100644 --- a/server/services/trackQueue.ts +++ b/src/track-queue/track-queue.service.ts @@ -1,11 +1,12 @@ +import { Injectable } from '@nestjs/common'; import type { Track } from '@spotify/web-api-ts-sdk' -import { NotImplementedError } from 'server/utils' export class TrackQueueItem { constructor(public track: Track) {} } -export class TrackQueue { +@Injectable() +export class TrackQueueService { protected tracks: TrackQueueItem[] = []; constructor(readonly groupId: string) {} @@ -44,4 +45,4 @@ export class TrackQueue { // Insert the track at the new position this.tracks.splice(pos, 0, removedTrack); } -} \ No newline at end of file +} diff --git a/test/app.e2e-spec.ts b/test/app.e2e-spec.ts new file mode 100644 index 0000000..50cda62 --- /dev/null +++ b/test/app.e2e-spec.ts @@ -0,0 +1,24 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { INestApplication } from '@nestjs/common'; +import * as request from 'supertest'; +import { AppModule } from './../src/app.module'; + +describe('AppController (e2e)', () => { + let app: INestApplication; + + beforeEach(async () => { + const moduleFixture: TestingModule = await Test.createTestingModule({ + imports: [AppModule], + }).compile(); + + app = moduleFixture.createNestApplication(); + await app.init(); + }); + + it('/ (GET)', () => { + return request(app.getHttpServer()) + .get('/') + .expect(200) + .expect('Hello World!'); + }); +}); diff --git a/test/jest-e2e.json b/test/jest-e2e.json new file mode 100644 index 0000000..e9d912f --- /dev/null +++ b/test/jest-e2e.json @@ -0,0 +1,9 @@ +{ + "moduleFileExtensions": ["js", "json", "ts"], + "rootDir": ".", + "testEnvironment": "node", + "testRegex": ".e2e-spec.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + } +} diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 0000000..0c5babc --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["node_modules", "test", "dist", "**/*spec.ts", "_deprecated", ] +} diff --git a/tsconfig.json b/tsconfig.json index 71a776b..95f5641 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,141 +1,21 @@ { - "ts-node": { - // Do not forget to `npm i -D tsconfig-paths` - "require": ["tsconfig-paths/register"] - }, "compilerOptions": { - /* 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. */ - // "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": "." /* Specify the root folder within your source files. */, - "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */, - "baseUrl": "." /* Specify the base directory to resolve non-relative module names. */, - "paths": { - // "src/*": ["web-socket/*", "./*"], - "server/*": ["./server/*"], - "websocket/*": ["./websocket/*"], - "common/*": ["./common/*"], - "*": ["./*", "./server/*", "./websocket/*"] - } /* 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": [ - "./node_modules/@types", - "server/types", - "websocket/types" - ] /* Specify multiple folders that act like './node_modules/@types'. */, - // "types": ["./node_modules/@types", "./src/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. */ - // "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. */ - "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. */ - - /* 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. */ - // "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": "./dist" /* Specify an output folder for all emitted files. */, - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ - // "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. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - - /* 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. */ - "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": false /* 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. */, - // "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": false /* Enable error reporting when local variables aren't read. */, - "noUnusedParameters": false /* 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. */ - }, - "include": [ - "./server", - "./server/**/*.ts", - "./server/**/*.json", - "./server/types", - "./websocket", - "./common", - "common/lib/kafka.ts", // "./server/core/docs/swagger.ts", - "common/lib/logger.ts" // "./src/core/docs/api/monitor.doc.ts", - ], - "exclude": [ - "node_modules/", - "coverage", - "logs", - "_depricated", - "./node_modules", - "./node_modules/*" - ] + "module": "commonjs", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "ES2021", + "sourceMap": true, + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": false, + "noImplicitAny": false, + "strictBindCallApply": false, + "forceConsistentCasingInFileNames": false, + "noFallthroughCasesInSwitch": false + } } diff --git a/websocket/Dockerfile b/websocket/Dockerfile deleted file mode 100644 index dfcd9a0..0000000 --- a/websocket/Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -# Development Image -################################################ -FROM node:20-bookworm - -WORKDIR /app - -COPY ./package.json /app/package.json -COPY ./package-lock.json /app/package-lock.json -COPY ./packages /app/packages - -ARG NODE_ENV=development - -USER root - -RUN npm install -g npm && \ - npm install -g typescript && \ - npm install -g rimraf && \ - npm install - -COPY ./tsconfig.json /app/tsconfig.json -COPY ./jest.config.ts /app/jest.config.ts -COPY ./websocket/ /app/websocket - -RUN npm run build - -EXPOSE 8000 -VOLUME ["/app/websocket"] - -CMD ["npm", "start"] diff --git a/websocket/config/constants.ts b/websocket/config/constants.ts deleted file mode 100644 index 97048c5..0000000 --- a/websocket/config/constants.ts +++ /dev/null @@ -1,14 +0,0 @@ -import dotenv from 'dotenv' -import 'dotenv/config' - -type nodenv = 'development' | 'production' | 'test' | 'network' - -export const HOST = process.env.HOST ?? 'localhost' -export const PORT = Number(process.env.PORT) ?? 8000 -export const NODE_ENV: nodenv = (process.env.NODE_ENV as nodenv) || 'development' - -if (NODE_ENV === 'test') { - dotenv.config() - process.env.LOG_LEVEL = 'warn' -} -export const BYPASS_AUTH: boolean = process.env.BYPASS_AUTH === '1' diff --git a/websocket/config/index.ts b/websocket/config/index.ts deleted file mode 100644 index d0f76cf..0000000 --- a/websocket/config/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @module config - * @description Project configuration files. - * - * These files aid in the initialization of the server, and define - * fundamental elements like the database, server, and global constants. - */ - -export * from './constants' -export * from './server' diff --git a/websocket/config/router.ts b/websocket/config/router.ts deleted file mode 100644 index 078ca63..0000000 --- a/websocket/config/router.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Router, type Request, type Response } from 'express' - -const router = Router() - -const healthCheck = (req: Request, res: Response) => { - return res.status(200).send() -} - -router.get('/', healthCheck) -router.get('/health', healthCheck) - -export { router } diff --git a/websocket/config/server.ts b/websocket/config/server.ts deleted file mode 100644 index c9e2f49..0000000 --- a/websocket/config/server.ts +++ /dev/null @@ -1,28 +0,0 @@ -import express from 'express' -import http from 'http' -import { logger } from '@jukebox/lib' -import { socketHandlers } from 'websocket/events/socketHandlers' -import { startSocket } from 'websocket/lib' - -import morgan from 'morgan' -import { authMiddleware } from 'websocket/middleware' -import { router } from './router' - -const server = express() -const urlencodedParser = express.urlencoded({ extended: false }) - -server.use(urlencodedParser) -server.use( - morgan(':remote-addr :method :url :status :res[content-length] - :response-time ms', { - stream: { write: (message) => logger.http(message, { service: 'express' }) } - }) -) -server.use(router) - -const httpServer = http.createServer(server) -const io = startSocket(httpServer) - -io.use(authMiddleware) -io.use(socketHandlers) - -export { io, httpServer as server } diff --git a/websocket/controllers/controller.ts b/websocket/controllers/controller.ts deleted file mode 100644 index 59bcc67..0000000 --- a/websocket/controllers/controller.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { CustomSocket } from "websocket/types" - -export const handleSocketSubscribe = (socket: CustomSocket, data: { [resource: string]: string[] }) => { - console.log('Handling subscribe: ', data) - const rooms: string[] = [] - for (const [resource, ids] of Object.entries(data)) { - for (const id of ids) { - rooms.push(`${resource}-${id}`) - } - } - - socket.join(rooms) -} \ No newline at end of file diff --git a/websocket/controllers/index.ts b/websocket/controllers/index.ts deleted file mode 100644 index 64380b0..0000000 --- a/websocket/controllers/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @module controllers - * @description Service and Resource Controllers - * - * Naming: - * [action][resource]() - * Ex: createMonitor() - * - * Controllers interface between the different domains of the application - * in order to provide a strucutred internal api for views, events, and - * other services to access. - */ -export * from './controller' diff --git a/websocket/events/consumers.ts b/websocket/events/consumers.ts deleted file mode 100644 index 049ee64..0000000 --- a/websocket/events/consumers.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Kafka Consumers - */ - -import { createConsumer, logger } from '@jukebox/lib' -import { socketEmit } from 'websocket/lib' - -export const registerKafkaConsumers = () => { - createConsumer('ping-pong', (data) => { - socketEmit('ping-pong', data) - const logData = data ?? 'No data received.' - logger.info(`Pong: ${logData}`) - }) -} diff --git a/websocket/events/index.ts b/websocket/events/index.ts deleted file mode 100644 index fd61533..0000000 --- a/websocket/events/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** - * @module Events - * @description Manage ingress and egress of data from Kafka - * or other event driven data controllers. - */ -export * from './consumers' diff --git a/websocket/events/producers.ts b/websocket/events/producers.ts deleted file mode 100644 index a0816f9..0000000 --- a/websocket/events/producers.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Kafka Producers - */ - -import { createProducer } from '@jukebox/lib' - -export const producePing = createProducer('ping-pong') diff --git a/websocket/events/socketHandlers.ts b/websocket/events/socketHandlers.ts deleted file mode 100644 index 06cc871..0000000 --- a/websocket/events/socketHandlers.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { handleSocketSubscribe } from 'websocket/controllers' -import type { CustomSocket, SocketNext } from 'websocket/types' -import { producePing } from './producers' - -export const socketHandlers = (socket: CustomSocket, next: SocketNext) => { - socket.on('subscribe', (data) => handleSocketSubscribe(socket, data)) - socket.on('ping-pong', (data) => producePing(new Date().toLocaleTimeString(), data)) - - next() -} diff --git a/websocket/index.ts b/websocket/index.ts deleted file mode 100644 index f420350..0000000 --- a/websocket/index.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Main entrypoint. - * - * Everything used while in a running state is initialized - * in this file. No business logic should be defined here. - */ - -if (process.env.NODE_ENV === 'production') { - require('module-alias/register') -} - -import { HOST, NODE_ENV, PORT, io, server } from 'websocket/config' -import { registerKafkaConsumers } from 'websocket/events' -import { logger } from '@jukebox/lib' - -// const PORT = process.env.PORT || '8333' - -io.on('connection', () => { - logger.debug('Client connected to socket.') -}) - -if (NODE_ENV === 'production' || NODE_ENV === 'network') { - registerKafkaConsumers() -} - -/** Start server */ -server.listen(PORT, () => { - logger.info(`Socket listening at http://${HOST}:${PORT}`) -}) diff --git a/websocket/lib/index.ts b/websocket/lib/index.ts deleted file mode 100644 index c94d5c1..0000000 --- a/websocket/lib/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @module lib - * @description External library managers. - * - * Use this directory to create proxy classes and functions for libraries like Axios, - * Kafka, etc. This will aid in keeping the codebase safe against deprecation. - */ -export * from './socket-io' diff --git a/websocket/lib/socket-io.ts b/websocket/lib/socket-io.ts deleted file mode 100644 index 0d64501..0000000 --- a/websocket/lib/socket-io.ts +++ /dev/null @@ -1,22 +0,0 @@ -import http from 'http' -import { Server } from 'socket.io' -import { io } from 'websocket/config' -import type { CustomSocket, ServerEmitEvents } from 'websocket/types' - -export const startSocket = ( - server: http.Server -) => - new Server(server, { - // cors: { - // origin: '*', - // // credentials: true - // } - }) - -export const socketEmit = (ev: string, data: any, room?: string | string[]) => { - if (room) { - io.to(room).emit(ev, data) - } else { - io.emit(ev, data) - } -} diff --git a/websocket/middleware/authMiddleware.ts b/websocket/middleware/authMiddleware.ts deleted file mode 100644 index b2c0ead..0000000 --- a/websocket/middleware/authMiddleware.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { BYPASS_AUTH } from 'websocket/config' -import { logger } from '@jukebox/lib' -import type { CustomSocket, SocketNext } from 'websocket/types' - -export const authMiddleware = (socket: CustomSocket, next: SocketNext) => { - if (BYPASS_AUTH) return next() - - const userId = socket.handshake.auth.userId - - if (!userId) { - logger.warn('Client does not have valid user id.') - return next(new Error('Must include valid user id.')) - } - socket.data.userId = userId - next() -} diff --git a/websocket/middleware/index.ts b/websocket/middleware/index.ts deleted file mode 100644 index 67f072e..0000000 --- a/websocket/middleware/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -/** - * SocketIO Middleware - */ -export * from './authMiddleware' \ No newline at end of file diff --git a/websocket/types/index.ts b/websocket/types/index.ts deleted file mode 100644 index 3a066cb..0000000 --- a/websocket/types/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { Socket } from 'socket.io' -import type { ExtendedError } from 'socket.io/dist/namespace' -import type { DefaultEventsMap, EventsMap } from 'socket.io/dist/typed-events' - -interface SocketData { - userId: string -} - -interface ServerToClientEvents extends DefaultEventsMap {} -interface ClientToServerEvents extends DefaultEventsMap {} -interface InterServerEvents extends DefaultEventsMap {} -export interface ServerEmitEvents extends EventsMap { - // 'monitor-responses': (data: any) => void - [event: string]: (data: any) => any -} - -export type CustomSocket = Socket< - ClientToServerEvents, - ServerToClientEvents, - InterServerEvents, - SocketData -> -export type SocketNext = (err?: ExtendedError | undefined) => void diff --git a/websocket/utils/exceptions/generalExceptions.ts b/websocket/utils/exceptions/generalExceptions.ts deleted file mode 100644 index cde31d4..0000000 --- a/websocket/utils/exceptions/generalExceptions.ts +++ /dev/null @@ -1,6 +0,0 @@ -export class NotImplementedError extends Error { - constructor(methodName: string) { - super(`Method ${methodName} is not implemented.`) - this.name = 'NotImplementedError' - } -} diff --git a/websocket/utils/exceptions/index.ts b/websocket/utils/exceptions/index.ts deleted file mode 100644 index a91c47d..0000000 --- a/websocket/utils/exceptions/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { NotImplementedError } from './generalExceptions' diff --git a/websocket/utils/index.ts b/websocket/utils/index.ts deleted file mode 100644 index 3e0724e..0000000 --- a/websocket/utils/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './exceptions' -export * from './utils' diff --git a/websocket/utils/utils.ts b/websocket/utils/utils.ts deleted file mode 100644 index 66822b7..0000000 --- a/websocket/utils/utils.ts +++ /dev/null @@ -1 +0,0 @@ -export const getRoom = (resource: string, id: string) => `${resource}-${id}` \ No newline at end of file From 2555dd1db621aa3c4ee11ae2dd48c1937a8a2798 Mon Sep 17 00:00:00 2001 From: Isaac Hunter Date: Sat, 5 Oct 2024 14:45:25 -0400 Subject: [PATCH 02/10] revert readme --- README.md | 153 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 93 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index c997880..d2c7801 100644 --- a/README.md +++ b/README.md @@ -1,85 +1,118 @@ -

- Nest Logo -

- -[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 -[circleci-url]: https://circleci.com/gh/nestjs/nest - -

A progressive Node.js framework for building efficient and scalable server-side applications.

-

-NPM Version -Package License -NPM Downloads -CircleCI -Coverage -Discord -Backers on Open Collective -Sponsors on Open Collective - Donate us - Support us - Follow us on Twitter -

- +# OSC Jukebox Server + +[![Unit Testing](https://github.com/ufosc/Jukebox-Server/actions/workflows/test-api.yml/badge.svg)](https://github.com/ufosc/Jukebox-Server/actions/workflows/test-api.yml) +[![Code Linting](https://github.com/ufosc/Jukebox-Server/actions/workflows/code-linting.yml/badge.svg)](https://github.com/ufosc/Jukebox-Server/actions/workflows/code-linting.yml) + +Welcome to the Jukebox Server! To get the server running, you only need Node.js installed on your computer. If you want to contribute to the DevOps portion, you will also need docker and docker-compose installed. + +## Table of Contents + +- [Table of Contents](#table-of-contents) +- [Description](#description) +- [Project Install One-Liner](#project-install-one-liner) +- [Getting started](#getting-started) +- [Technology Stack (with documentation link)](#technology-stack-with-documentation-link) +- [Workflow](#workflow) +- [Testing](#testing) ## Description -[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. +The Jukebox Server is a Node.js-based server that connects with Spotify's API, allowing users to manage and potentially play music and function like a Jukebox. Required software includes Docker, Docker Compose, and Git. +This project has two Github pages this is designated for the Backend Development. If you are interested in the Frontend Development please link here. + +## Project Install One-Liner + +Copy and paste the following command into your terminal to clone the repository and get the server up and running. -## Project setup +This assumes you have **Docker**, **Docker Compose**, and **Git** installed. -```bash -$ npm install +```sh +git clone git@github.com:ufosc/Jukebox-Server.git && cd Jukebox-Server && cp sample.env .env && docker-compose up --build ``` -## Compile and run the project +## Getting started -```bash -# development -$ npm run start +Follow these steps to download the project locally and get it running with nodemon. + +1. Clone the repository: + +```sh +git clone https://github.com/ufosc/Jukebox-Server.git +cd Jukebox-Server +``` + +2. Set up the environment: + +```sh +cp sample.env .env +``` -# watch mode -$ npm run start:dev +3. Build and run the Docker containers: -# production mode -$ npm run start:prod +```sh +docker-compose build +docker-compose up ``` -## Run tests +We use Docker Compose to manage the server and its dependencies, including databases and other containers. While you can run the server using `npm run dev`, Docker Compose provides more reliability. -```bash -# unit tests -$ npm run test +Once the server is running, visit to authenticate with Spotify. -# e2e tests -$ npm run test:e2e +## Technology Stack (with documentation link) -# test coverage -$ npm run test:cov +| Use | Tech | +| ---------------------- | --------------------------------------------------------------------------------------- | +| Language | [TypeScript](https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.html) | +| Backend Runtime | [Node.js](https://nodejs.dev/en/learn/) | +| Backend Framework | [Express.js](https://expressjs.com/en/4x/api.html#express) | +| SQL Database | [Postgres](https://node-postgres.com/) | +| Unit Tests | [Jest](https://jestjs.io/docs/getting-started) | +| Auto Documentation | [Swagger](https://swagger.io/docs/specification/about/) | +| Infrastructure as Code | [Terraform](https://developer.hashicorp.com/terraform/docs) | +| Hosting | [AWS](https://docs.aws.amazon.com/) | +| Containerization | [Docker](https://docs.docker.com/get-started/) | + +## Workflow + +1. Start by reviewing the [issues list](https://github.com/ufosc/Jukebox-Server/issues) and pick a task or propose a new feature. + +2. Clone the main branch onto your local system: + +```sh +git clone git@github.com:ufosc/Jukebox-Server.git && cd Jukebox-Server && cp sample.env .env && docker-compose up --build +``` + +3. Create a feature branch: + +```sh +git checkout -b feature/[insert name here] ``` -## Resources +_Ensure your branch focuses on a specific, fully working feature e.g. documentation, implementing new authentication logic. [Read more about feature branch workflow here](https://craftquest.io/guides/git/git-workflows/feature-branch-workflow)._ + +Before submitting a pull request, write at least three unit tests. If possible, follow the Test-Driven Development (TDD) paradigm, which involves writing tests before coding the feature itself. [Learn more about TDD here](https://www.browserstack.com/guide/what-is-test-driven-development). + +4. Push your feature branch and submit a pull request (PR). Your PR will be reviewed and tested by a maintainer before merging. -Check out a few resources that may come in handy when working with NestJS: +## Testing -- Visit the [NestJS Documentation](https://docs.nestjs.com) to learn more about the framework. -- For questions and support, please visit our [Discord channel](https://discord.gg/G7Qnnhy). -- To dive deeper and get more hands-on experience, check out our official video [courses](https://courses.nestjs.com/). -- Visualize your application graph and interact with the NestJS application in real-time using [NestJS Devtools](https://devtools.nestjs.com). -- Need help with your project (part-time to full-time)? Check out our official [enterprise support](https://enterprise.nestjs.com). -- To stay in the loop and get updates, follow us on [X](https://x.com/nestframework) and [LinkedIn](https://linkedin.com/company/nestjs). -- Looking for a job, or have a job to offer? Check out our official [Jobs board](https://jobs.nestjs.com). +We use Jest for unit testing. **At least 3 unit tests** must accompany any new feature. -## Support +Example of Jest Formatting: -Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). +``` +const converter = require('../app/converter'); -## Stay in touch +// Example test +test('Jukebox Unit Test', () => { + expect(converter.convertPlaylist('playlist-id')).toBe('expected-output'); +}); +``` -- Author - [Kamil Myśliwiec](https://twitter.com/kammysliwiec) -- Website - [https://nestjs.com](https://nestjs.com/) -- Twitter - [@nestframework](https://twitter.com/nestframework) +To run the tests, use the following command. This will execute Jest, which will look for test files inside the `/test` directory: -## License +```sh +docker-compose run --rm api sh -c "npm test" +``` -Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE). +When writing new tests, write them inside this `/test` directory. From 7de4f26ebad33404d5d7f969b06085d222c2728b Mon Sep 17 00:00:00 2001 From: Isaac Hunter Date: Sat, 5 Oct 2024 15:02:17 -0400 Subject: [PATCH 03/10] run server, setup websocket --- src/app.gateway.spec.ts | 18 ++++++++++++++++++ src/app.gateway.ts | 10 ++++++++++ src/app.module.ts | 3 ++- .../{trackQueue.test.ts => trackQueue.spec.ts} | 3 ++- src/track-queue/track-queue.service.ts | 16 ++++++++++++---- tsconfig.build.json | 2 +- 6 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 src/app.gateway.spec.ts create mode 100644 src/app.gateway.ts rename src/track-queue/tests/{trackQueue.test.ts => trackQueue.spec.ts} (96%) diff --git a/src/app.gateway.spec.ts b/src/app.gateway.spec.ts new file mode 100644 index 0000000..ce7a9b9 --- /dev/null +++ b/src/app.gateway.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AppGateway } from './app.gateway'; + +describe('AppGateway', () => { + let gateway: AppGateway; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [AppGateway], + }).compile(); + + gateway = module.get(AppGateway); + }); + + it('should be defined', () => { + expect(gateway).toBeDefined(); + }); +}); diff --git a/src/app.gateway.ts b/src/app.gateway.ts new file mode 100644 index 0000000..c3c6b90 --- /dev/null +++ b/src/app.gateway.ts @@ -0,0 +1,10 @@ +import { SubscribeMessage, WebSocketGateway } from '@nestjs/websockets'; + +@WebSocketGateway() +export class AppGateway { + @SubscribeMessage('message') + handleMessage(client: any, payload: any): string { + console.log('websocket payload:', payload) + return 'Hello world!'; + } +} diff --git a/src/app.module.ts b/src/app.module.ts index 2cc1344..716d99f 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -3,10 +3,11 @@ import { AppController } from './app.controller'; import { AppService } from './app.service'; import { SpotifyModule } from './spotify/spotify.module'; import { TrackQueueModule } from './track-queue/track-queue.module'; +import { AppGateway } from './app.gateway'; @Module({ imports: [SpotifyModule, TrackQueueModule], controllers: [AppController], - providers: [AppService], + providers: [AppService, AppGateway], }) export class AppModule {} diff --git a/src/track-queue/tests/trackQueue.test.ts b/src/track-queue/tests/trackQueue.spec.ts similarity index 96% rename from src/track-queue/tests/trackQueue.test.ts rename to src/track-queue/tests/trackQueue.spec.ts index 539f244..342b361 100644 --- a/src/track-queue/tests/trackQueue.test.ts +++ b/src/track-queue/tests/trackQueue.spec.ts @@ -1,4 +1,4 @@ -import { TrackQueueService as TrackQueue } from '../track-queue.service'; +import { TrackQueue } from '../track-queue.service'; import type { Track } from '@spotify/web-api-ts-sdk'; // describe('TrackQueue Tests', () => { @@ -73,6 +73,7 @@ import type { Track } from '@spotify/web-api-ts-sdk'; describe('Test TackQue', () => { const queue = new TrackQueue("testid"); + // queue.setGroupId("testid") // queue.push(sometrack) it('should push to queue', () => { // expect(queue.peek()).toBe(sometrack); diff --git a/src/track-queue/track-queue.service.ts b/src/track-queue/track-queue.service.ts index 0bdb585..ddbf69e 100644 --- a/src/track-queue/track-queue.service.ts +++ b/src/track-queue/track-queue.service.ts @@ -1,15 +1,19 @@ import { Injectable } from '@nestjs/common'; -import type { Track } from '@spotify/web-api-ts-sdk' +import type { Track } from '@spotify/web-api-ts-sdk'; export class TrackQueueItem { constructor(public track: Track) {} } -@Injectable() -export class TrackQueueService { +// @Injectable() +export class TrackQueue { protected tracks: TrackQueueItem[] = []; + // private groupId: string = ''; constructor(readonly groupId: string) {} + public setGroupId(groupId: string) { + // this.groupId = groupId; + } // Pushes a track to the end of the queue and returns the new length public push(track: Track): number { @@ -31,7 +35,7 @@ export class TrackQueueService { // Moves a track to a new position in the queue public setPosition(track: Track, pos: number) { - const currentIndex = this.tracks.findIndex(item => item.track === track); + const currentIndex = this.tracks.findIndex((item) => item.track === track); if (currentIndex === -1) { throw new Error('Track not found'); } @@ -46,3 +50,7 @@ export class TrackQueueService { this.tracks.splice(pos, 0, removedTrack); } } + + +@Injectable() +export class TrackQueueService {} diff --git a/tsconfig.build.json b/tsconfig.build.json index 0c5babc..5e744f0 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -1,4 +1,4 @@ { "extends": "./tsconfig.json", - "exclude": ["node_modules", "test", "dist", "**/*spec.ts", "_deprecated", ] + "exclude": ["node_modules", "test", "dist", "**/*spec.ts", "_deprecated", "_deprecated*"] } From f60675a28c9c664a7454f72f009aff814449ddc9 Mon Sep 17 00:00:00 2001 From: Isaac Hunter Date: Sat, 5 Oct 2024 15:34:23 -0400 Subject: [PATCH 04/10] dockerize server, configure compose files --- .dockerignore | 5 +++- .eslintrc.js | 19 +++++++++++- .prettierrc | 6 ++-- Dockerfile | 32 ++++++++++++++++++++ docker-compose.network.yml | 48 ++++++------------------------ docker-compose.prod.yml | 60 -------------------------------------- docker-compose.yml | 11 +++---- package-lock.json | 38 +++++++++++++++++++++++- package.json | 2 ++ src/app.module.ts | 15 +++++----- src/config/constants.ts | 26 +++++++++++++++++ src/config/index.ts | 1 + src/main.ts | 3 +- 13 files changed, 147 insertions(+), 119 deletions(-) create mode 100644 Dockerfile delete mode 100644 docker-compose.prod.yml create mode 100644 src/config/constants.ts create mode 100644 src/config/index.ts diff --git a/.dockerignore b/.dockerignore index 16432bb..48292fa 100644 --- a/.dockerignore +++ b/.dockerignore @@ -6,7 +6,10 @@ !package.json !package-lock.json !tsconfig.json +!tsconfig.build.json !jest.config.ts !common/ !websocket/ -!packages/ \ No newline at end of file +!packages/ +!src/ +!nest-cli.json \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index 259de13..aa2366a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -5,7 +5,7 @@ module.exports = { tsconfigRootDir: __dirname, sourceType: 'module', }, - plugins: ['@typescript-eslint/eslint-plugin'], + plugins: ['@typescript-eslint/eslint-plugin', 'prefer-arrow-functions'], extends: [ 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended', @@ -20,6 +20,23 @@ module.exports = { '@typescript-eslint/interface-name-prefix': 'off', '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off', + + '@typescript-eslint/consistent-type-imports': 'warn', + '@typescript-eslint/no-unused-vars': 'off', + '@typescript-eslint/no-redeclare': 'off', + '@typescript-eslint/space-before-function-paren': 'off', '@typescript-eslint/no-explicit-any': 'off', + 'prefer-const': 'warn', + 'prettier/prettier': 'warn', + 'prefer-arrow-functions/prefer-arrow-functions': [ + 'warn', + { + allowNamedFunctions: false, + classPropertiesAllowed: false, + disallowPrototype: false, + returnStyle: 'unchanged', + singleReturnOnly: false + } + ] }, }; diff --git a/.prettierrc b/.prettierrc index dcb7279..773be00 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,6 @@ { "singleQuote": true, - "trailingComma": "all" -} \ No newline at end of file + "trailingComma": "all", + "semi": false, + "printWidth": 100 +} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..463de48 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +FROM node:20-bookworm + +WORKDIR /app + +COPY ./package*.json ./ + +USER root + +RUN npm install -g npm && \ + npm install -g typescript && \ + npm install + +COPY ./tsconfig*.json ./ +COPY ./nest-cli.json ./ +COPY ./src ./src + +RUN npm run build + +# RUN adduser --no-create-home --system --disabled-password --disabled-login --group app-user && \ +# mkdir -p /vol/web/media && \ +# mkdir -p /vol/web/static && \ +# mkdir -p /app/dist && \ +# chown -R app-user:app-user /vol && \ +# chmod -R 755 /vol/web && \ +# chown -R app-user:app-user /app/dist && \ +# chmod -R 755 /app/dist + +# USER app-user +EXPOSE 8000 +VOLUME ["/app/src"] + +CMD ["npm", "run", "start:prod"] diff --git a/docker-compose.network.yml b/docker-compose.network.yml index 7e2a7b1..a6f86d8 100644 --- a/docker-compose.network.yml +++ b/docker-compose.network.yml @@ -3,9 +3,9 @@ services: restart: always build: context: . - # dockerfile: ./server.Dockerfile - dockerfile: ./server/Dockerfile container_name: server-jbx + networks: + - cluster environment: - NODE_ENV=network - PORT=9000 @@ -24,11 +24,9 @@ services: - mongodb - kafka volumes: - - ./server:/app/server - - ./packages:/app/packages - networks: - - cluster - command: npm run dev:server + - ./src:/app/src + - ./package.json:/app/package.json + command: npm run start:network proxy: build: @@ -43,8 +41,8 @@ services: - client-dist:/vol/client environment: - SERVER_URI=server-jbx:9000 - - WEBSOCKET_URI=websocket-jbx:9001 - attach: false + - WEBSOCKET_URI=server-jbx:9000 + # attach: false mongodb: image: mongo:6.0.9 @@ -60,7 +58,7 @@ services: command: mongod --quiet --logpath /dev/null --bind_ip_all networks: - cluster - + #################################### # Kafka Config #################################### @@ -96,7 +94,7 @@ services: networks: - cluster attach: false - + kafka-api: image: 'docker-spring-boot-postgres:latest' build: @@ -108,34 +106,6 @@ services: - SPRING_PROFILES_ACTIVE=dev depends_on: - kafka - - #################################### - # Web Socket Config - #################################### - websocket: - build: - context: ./ - dockerfile: ./websocket/Dockerfile - restart: always - ports: - - 9001:9001 - container_name: websocket-jbx - volumes: - - ./websocket:/app/websocket - - ./packages:/app/packages - - ./package.json:/app/package.json - environment: - - HOST=0.0.0.0 - - PORT=9001 - - NODE_ENV=network - - LOG_LEVEL=debug - - KAFKA_BROKERS=kafka-jbx:9092 - - KAFKA_GROUP_ID=websocket-jbx - - LOG_NS=websocket - # - BYPASS_AUTH=1 - command: npm run dev:websocket - networks: - - cluster volumes: client-dist: diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml deleted file mode 100644 index 118d818..0000000 --- a/docker-compose.prod.yml +++ /dev/null @@ -1,60 +0,0 @@ -services: - api: - restart: always - container_name: api - build: - context: . - networks: - - cluster - environment: - - NODE_ENV=${NODE_ENV} - - PORT=${PORT} - - HOST=${HOST} - - JWT_SECRET_KEY=${JWT_SECRET_KEY} - - TOKEN_HEADER_KEY=${TOKEN_HEADER_KEY} - - MONGO_URI=${MONGO_URI} - - SP_ID=${SP_ID} - - SP_SECRET=${SP_SECRET} - ports: - - 8000:8000 - depends_on: - - mongodb - volumes: - - ./server:/app/server - - proxy: - build: - context: ./proxy/ - ports: - - 80:80 - networks: - - cluster - depends_on: - - api - volumes: - - client-dist:/vol/client - - mongodb: - image: mongo:6.0.9 - container_name: mongodb - restart: always - ports: - - 27017:27017 - networks: - - cluster - volumes: - - mongo-data:/data/db - environment: - - MONGO_INITDB_ROOT_USERNAME=${MONGO_USER} - - MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD} - command: mongod --quiet --logpath /dev/null --bind_ip_all - -volumes: - client-dist: - name: client-dist - mongo-data: - -networks: - cluster: - name: jukebox_cluster - driver: bridge diff --git a/docker-compose.yml b/docker-compose.yml index 2d67fa3..dbac4ac 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,8 +2,7 @@ services: server: restart: always build: - context: ./ - dockerfile: ./server/Dockerfile + context: . args: - NODE_ENV=development environment: @@ -26,11 +25,9 @@ services: depends_on: - mongodb volumes: - - ./server:/app/server - - ./jest.config.ts:/app/jest.config.ts - - ./packages:/app/packages - # - ./dist:/app/dist - command: npm run dev + - ./src:/app/src + - ./package.json:/app/package.json + command: npm run start:dev mongodb: image: mongo:6.0.9 diff --git a/package-lock.json b/package-lock.json index e8813e0..545a873 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "UNLICENSED", "dependencies": { "@nestjs/common": "^10.0.0", + "@nestjs/config": "^3.2.3", "@nestjs/core": "^10.0.0", "@nestjs/mongoose": "^10.0.10", "@nestjs/platform-express": "^10.0.0", @@ -1840,6 +1841,21 @@ } } }, + "node_modules/@nestjs/config": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-3.2.3.tgz", + "integrity": "sha512-p6yv/CvoBewJ72mBq4NXgOAi2rSQNWx3a+IMJLVKS2uiwFCOQQuiIatGwq6MRjXV3Jr+B41iUO8FIf4xBrZ4/w==", + "license": "MIT", + "dependencies": { + "dotenv": "16.4.5", + "dotenv-expand": "10.0.0", + "lodash": "4.17.21" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "rxjs": "^7.1.0" + } + }, "node_modules/@nestjs/core": { "version": "10.4.4", "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.4.tgz", @@ -4112,6 +4128,27 @@ "node": ">=6.0.0" } }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dotenv-expand": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", + "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -6702,7 +6739,6 @@ "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true, "license": "MIT" }, "node_modules/lodash.memoize": { diff --git a/package.json b/package.json index de1621b..0307a3e 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", "start": "nest start", "start:dev": "nest start --watch", + "start:network": "nest start --watch --preserveWatchOutput", "start:debug": "nest start --debug --watch", "start:prod": "node dist/main", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", @@ -21,6 +22,7 @@ }, "dependencies": { "@nestjs/common": "^10.0.0", + "@nestjs/config": "^3.2.3", "@nestjs/core": "^10.0.0", "@nestjs/mongoose": "^10.0.10", "@nestjs/platform-express": "^10.0.0", diff --git a/src/app.module.ts b/src/app.module.ts index 716d99f..f2ef1ca 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,12 +1,13 @@ -import { Module } from '@nestjs/common'; -import { AppController } from './app.controller'; -import { AppService } from './app.service'; -import { SpotifyModule } from './spotify/spotify.module'; -import { TrackQueueModule } from './track-queue/track-queue.module'; -import { AppGateway } from './app.gateway'; +import { Module } from '@nestjs/common' +import { ConfigModule } from '@nestjs/config' +import { AppController } from './app.controller' +import { AppGateway } from './app.gateway' +import { AppService } from './app.service' +import { SpotifyModule } from './spotify/spotify.module' +import { TrackQueueModule } from './track-queue/track-queue.module' @Module({ - imports: [SpotifyModule, TrackQueueModule], + imports: [ConfigModule.forRoot(), SpotifyModule, TrackQueueModule], controllers: [AppController], providers: [AppService, AppGateway], }) diff --git a/src/config/constants.ts b/src/config/constants.ts new file mode 100644 index 0000000..66eaba2 --- /dev/null +++ b/src/config/constants.ts @@ -0,0 +1,26 @@ +import 'dotenv/config' + +type nodenv = 'development' | 'production' | 'test' | 'network' + +// export const NODE_ENV: nodenv = (process.env.NODE_ENV as nodenv) || 'development' +export const HOST: string = process.env.HOST || 'localhost' +export const PORT = process.env.PORT || 3000 +export const MONGO_URI = process.env.MONGO_URI || 'mongodb://localhost:27017/mongo-jukebox' +export const BASE_URL = process.env.BASE_URL || `http://${HOST}:${PORT}` + +export const JWT_SECRET_KEY: string = process.env.JWT_SECRET_KEY || 'secret' +export const JWT_ISSUER = process.env.JWT_ISSUER || 'jukebox' +export const JWT_ALGORITHM = 'HS256' +export const AUTH_TOKEN_COOKIE_NAME = 'dev-auth-token' +// export const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || '1h' + +export const SPOTIFY_CLIENT_ID = process.env.SPOTIFY_CLIENT_ID || 'changeme' +export const SPOTIFY_CLIENT_SECRET = process.env.SPOTIFY_CLIENT_SECRET || 'changeme' +export const SPOTIFY_REDIRECT_PATH = '/api/spotify/login-callback/' +export const SPOTIFY_REDIRECT_URI = BASE_URL + SPOTIFY_REDIRECT_PATH + +// export const LOG_LEVEL = process.env.LOG_LEVEL || 'warn' +// export const LOG_NS = process.env.LOG_NS || 'server' + +// export const KAFKA_BROKERS = process.env.KAFKA_BROKERS?.split(',') ?? ['kafka:9092'] +// export const KAFKA_GROUP_ID = process.env.KAFKA_GROUP_ID ?? 'jbx-server' diff --git a/src/config/index.ts b/src/config/index.ts new file mode 100644 index 0000000..363c822 --- /dev/null +++ b/src/config/index.ts @@ -0,0 +1 @@ +export * from './constants' \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 13cad38..006992a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,8 +1,9 @@ import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; +import { PORT } from './config' async function bootstrap() { const app = await NestFactory.create(AppModule); - await app.listen(3000); + await app.listen(PORT); } bootstrap(); From 190e0b0b9bb7b34229d4b1a2d0d6a2dfb4e97207 Mon Sep 17 00:00:00 2001 From: Isaac Hunter Date: Sat, 5 Oct 2024 16:47:06 -0400 Subject: [PATCH 05/10] add user auth interceptor, decorator --- docker-compose.yml | 4 +- package-lock.json | 68 +++++++++++++++++++++- package.json | 1 + src/app.module.ts | 9 ++- src/auth/auth.interceptor.spec.ts | 7 +++ src/auth/auth.interceptor.ts | 25 ++++++++ src/auth/current-user.decorator.ts | 12 ++++ src/config/constants.ts | 4 +- src/main.ts | 16 +++-- src/spotify/schemas/spotify-auth.schema.ts | 0 src/spotify/schemas/spotify-link.schema.ts | 33 +++++++++++ src/spotify/spotify.controller.ts | 17 +++++- src/spotify/spotify.module.ts | 11 ++-- src/types/index.d.ts | 5 ++ src/utils/index.ts | 1 + src/utils/mock/index.ts | 1 + src/utils/mock/mockUser.ts | 5 ++ 17 files changed, 201 insertions(+), 18 deletions(-) create mode 100644 src/auth/auth.interceptor.spec.ts create mode 100644 src/auth/auth.interceptor.ts create mode 100644 src/auth/current-user.decorator.ts delete mode 100644 src/spotify/schemas/spotify-auth.schema.ts create mode 100644 src/spotify/schemas/spotify-link.schema.ts create mode 100644 src/types/index.d.ts create mode 100644 src/utils/index.ts create mode 100644 src/utils/mock/index.ts create mode 100644 src/utils/mock/mockUser.ts diff --git a/docker-compose.yml b/docker-compose.yml index dbac4ac..da731d7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,9 +4,9 @@ services: build: context: . args: - - NODE_ENV=development + - NODE_ENV=dev environment: - - NODE_ENV=development + - NODE_ENV=dev - PORT=8000 - HOST=localhost - JWT_SECRET_KEY=changeme diff --git a/package-lock.json b/package-lock.json index 545a873..e35c9bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@nestjs/mongoose": "^10.0.10", "@nestjs/platform-express": "^10.0.0", "@nestjs/platform-socket.io": "^10.4.4", + "@nestjs/swagger": "^7.4.2", "@nestjs/websockets": "^10.4.4", "@spotify/web-api-ts-sdk": "^1.2.0", "mongoose": "^8.7.0", @@ -1672,6 +1673,12 @@ "node": ">=8" } }, + "node_modules/@microsoft/tsdoc": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.0.tgz", + "integrity": "sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==", + "license": "MIT" + }, "node_modules/@mongodb-js/saslprep": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", @@ -1894,6 +1901,26 @@ } } }, + "node_modules/@nestjs/mapped-types": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.5.tgz", + "integrity": "sha512-bSJv4pd6EY99NX9CjBIyn4TVDoSit82DUZlL4I3bqNfy5Gt+gXTa86i3I/i0iIV9P4hntcGM5GyO+FhZAhxtyg==", + "license": "MIT", + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "class-transformer": "^0.4.0 || ^0.5.0", + "class-validator": "^0.13.0 || ^0.14.0", + "reflect-metadata": "^0.1.12 || ^0.2.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, "node_modules/@nestjs/mongoose": { "version": "10.0.10", "resolved": "https://registry.npmjs.org/@nestjs/mongoose/-/mongoose-10.0.10.tgz", @@ -1970,6 +1997,39 @@ "dev": true, "license": "MIT" }, + "node_modules/@nestjs/swagger": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-7.4.2.tgz", + "integrity": "sha512-Mu6TEn1M/owIvAx2B4DUQObQXqo2028R2s9rSZ/hJEgBK95+doTwS0DjmVA2wTeZTyVtXOoN7CsoM5pONBzvKQ==", + "license": "MIT", + "dependencies": { + "@microsoft/tsdoc": "^0.15.0", + "@nestjs/mapped-types": "2.0.5", + "js-yaml": "4.1.0", + "lodash": "4.17.21", + "path-to-regexp": "3.3.0", + "swagger-ui-dist": "5.17.14" + }, + "peerDependencies": { + "@fastify/static": "^6.0.0 || ^7.0.0", + "@nestjs/common": "^9.0.0 || ^10.0.0", + "@nestjs/core": "^9.0.0 || ^10.0.0", + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12 || ^0.2.0" + }, + "peerDependenciesMeta": { + "@fastify/static": { + "optional": true + }, + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, "node_modules/@nestjs/testing": { "version": "10.4.4", "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.4.tgz", @@ -3048,7 +3108,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, "license": "Python-2.0" }, "node_modules/array-flatten": { @@ -6566,7 +6625,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -8736,6 +8794,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/swagger-ui-dist": { + "version": "5.17.14", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.14.tgz", + "integrity": "sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==", + "license": "Apache-2.0" + }, "node_modules/symbol-observable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", diff --git a/package.json b/package.json index 0307a3e..261776c 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "@nestjs/mongoose": "^10.0.10", "@nestjs/platform-express": "^10.0.0", "@nestjs/platform-socket.io": "^10.4.4", + "@nestjs/swagger": "^7.4.2", "@nestjs/websockets": "^10.4.4", "@spotify/web-api-ts-sdk": "^1.2.0", "mongoose": "^8.7.0", diff --git a/src/app.module.ts b/src/app.module.ts index f2ef1ca..4369b87 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,13 +1,20 @@ import { Module } from '@nestjs/common' import { ConfigModule } from '@nestjs/config' +import { MongooseModule } from '@nestjs/mongoose' import { AppController } from './app.controller' import { AppGateway } from './app.gateway' import { AppService } from './app.service' +import { MONGO_URI } from './config' import { SpotifyModule } from './spotify/spotify.module' import { TrackQueueModule } from './track-queue/track-queue.module' @Module({ - imports: [ConfigModule.forRoot(), SpotifyModule, TrackQueueModule], + imports: [ + ConfigModule.forRoot(), + MongooseModule.forRoot(MONGO_URI), + SpotifyModule, + TrackQueueModule, + ], controllers: [AppController], providers: [AppService, AppGateway], }) diff --git a/src/auth/auth.interceptor.spec.ts b/src/auth/auth.interceptor.spec.ts new file mode 100644 index 0000000..13fdabe --- /dev/null +++ b/src/auth/auth.interceptor.spec.ts @@ -0,0 +1,7 @@ +import { AuthInterceptor } from './auth.interceptor'; + +describe('AuthInterceptor', () => { + it('should be defined', () => { + expect(new AuthInterceptor()).toBeDefined(); + }); +}); diff --git a/src/auth/auth.interceptor.ts b/src/auth/auth.interceptor.ts new file mode 100644 index 0000000..e264244 --- /dev/null +++ b/src/auth/auth.interceptor.ts @@ -0,0 +1,25 @@ +import { + CallHandler, + ExecutionContext, + Injectable, + NestInterceptor, + NotImplementedException, +} from '@nestjs/common' +import { Observable } from 'rxjs' +import { NODE_ENV } from 'src/config' +import { mockUser } from 'src/utils' + +@Injectable() +export class AuthInterceptor implements NestInterceptor { + intercept(context: ExecutionContext, next: CallHandler): Observable { + const request = context.switchToHttp().getRequest() + + if (NODE_ENV === 'dev') { + request.user = mockUser + } else { + throw new NotImplementedException() + } + + return next.handle() + } +} diff --git a/src/auth/current-user.decorator.ts b/src/auth/current-user.decorator.ts new file mode 100644 index 0000000..e6c411e --- /dev/null +++ b/src/auth/current-user.decorator.ts @@ -0,0 +1,12 @@ +import { createParamDecorator, ExecutionContext, UnauthorizedException } from '@nestjs/common' + +export const CurrentUser = createParamDecorator((data: never, context: ExecutionContext) => { + const request = context.switchToHttp().getRequest() + const { user } = request + + if (!user) { + throw new UnauthorizedException() + } + + return user as IUser +}) diff --git a/src/config/constants.ts b/src/config/constants.ts index 66eaba2..2df5142 100644 --- a/src/config/constants.ts +++ b/src/config/constants.ts @@ -1,8 +1,8 @@ import 'dotenv/config' -type nodenv = 'development' | 'production' | 'test' | 'network' +type nodenv = 'dev' | 'production' | 'test' | 'network' -// export const NODE_ENV: nodenv = (process.env.NODE_ENV as nodenv) || 'development' +export const NODE_ENV: nodenv = (process.env.NODE_ENV as nodenv) || 'dev' export const HOST: string = process.env.HOST || 'localhost' export const PORT = process.env.PORT || 3000 export const MONGO_URI = process.env.MONGO_URI || 'mongodb://localhost:27017/mongo-jukebox' diff --git a/src/main.ts b/src/main.ts index 006992a..8b8e840 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,9 +1,15 @@ -import { NestFactory } from '@nestjs/core'; -import { AppModule } from './app.module'; +import { NestFactory } from '@nestjs/core' +import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger' +import { AppModule } from './app.module' import { PORT } from './config' async function bootstrap() { - const app = await NestFactory.create(AppModule); - await app.listen(PORT); + const app = await NestFactory.create(AppModule) + + const swaggerConfig = new DocumentBuilder().setTitle('Jukebox API').build() + const swaggerDocument = SwaggerModule.createDocument(app, swaggerConfig) + SwaggerModule.setup('/api/docs', app, swaggerDocument) + + await app.listen(PORT) } -bootstrap(); +bootstrap() diff --git a/src/spotify/schemas/spotify-auth.schema.ts b/src/spotify/schemas/spotify-auth.schema.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/spotify/schemas/spotify-link.schema.ts b/src/spotify/schemas/spotify-link.schema.ts new file mode 100644 index 0000000..55bb1c7 --- /dev/null +++ b/src/spotify/schemas/spotify-link.schema.ts @@ -0,0 +1,33 @@ +import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose' +import { HydratedDocument } from 'mongoose' + +@Schema() +export class SpotifyLink { + @Prop() + accessToken: string + + @Prop() + refreshToken: string + + @Prop() + userId: string + + @Prop({ required: true, unique: true }) + spotifyEmail: string + + @Prop() + expiresIn: number + + @Prop() + expiresAt: Date + + @Prop() + tokenType: string + + isExpired() { + return this.expiresAt.getTime() <= Date.now() + } +} + +export const SpotifyLinkSchema = SchemaFactory.createForClass(SpotifyLink) +export type SpotifyLinkDocument = HydratedDocument diff --git a/src/spotify/spotify.controller.ts b/src/spotify/spotify.controller.ts index eeb9761..48d1f17 100644 --- a/src/spotify/spotify.controller.ts +++ b/src/spotify/spotify.controller.ts @@ -1,4 +1,17 @@ -import { Controller } from '@nestjs/common'; +import { Controller, Get, UseInterceptors } from '@nestjs/common' +import { AuthInterceptor } from 'src/auth/auth.interceptor' +import { CurrentUser } from 'src/auth/current-user.decorator' @Controller('spotify') -export class SpotifyController {} +export class SpotifyController { + @Get('login') + @UseInterceptors(AuthInterceptor) + login(@CurrentUser() user: IUser) { + console.log('Current user:', user) + + return + } + + @Get('login/success') + loginSuccessCallback() {} +} diff --git a/src/spotify/spotify.module.ts b/src/spotify/spotify.module.ts index 5967662..35337e9 100644 --- a/src/spotify/spotify.module.ts +++ b/src/spotify/spotify.module.ts @@ -1,9 +1,12 @@ -import { Module } from '@nestjs/common'; -import { SpotifyController } from './spotify.controller'; -import { SpotifyService } from './spotify.service'; +import { Module } from '@nestjs/common' +import { MongooseModule } from '@nestjs/mongoose' +import { SpotifyLink, SpotifyLinkSchema } from './schemas/spotify-link.schema' +import { SpotifyController } from './spotify.controller' +import { SpotifyService } from './spotify.service' @Module({ controllers: [SpotifyController], - providers: [SpotifyService] + providers: [SpotifyService], + imports: [MongooseModule.forFeature([{ name: SpotifyLink.name, schema: SpotifyLinkSchema }])], }) export class SpotifyModule {} diff --git a/src/types/index.d.ts b/src/types/index.d.ts new file mode 100644 index 0000000..b20cedd --- /dev/null +++ b/src/types/index.d.ts @@ -0,0 +1,5 @@ +declare interface IUser { + email: string + firstName: string + lastName: string +} diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..218ab33 --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1 @@ +export * from './mock' diff --git a/src/utils/mock/index.ts b/src/utils/mock/index.ts new file mode 100644 index 0000000..5bed7e0 --- /dev/null +++ b/src/utils/mock/index.ts @@ -0,0 +1 @@ +export * from './mockUser' \ No newline at end of file diff --git a/src/utils/mock/mockUser.ts b/src/utils/mock/mockUser.ts new file mode 100644 index 0000000..7e172dd --- /dev/null +++ b/src/utils/mock/mockUser.ts @@ -0,0 +1,5 @@ +export const mockUser = { + email: 'user@example.com', + firstName: 'John', + lastName: 'Doe', +} From 5ad92770c74b950a6dff72c77e7206d7ff4ab3a4 Mon Sep 17 00:00:00 2001 From: Isaac Hunter Date: Sat, 5 Oct 2024 19:39:21 -0400 Subject: [PATCH 06/10] re-add spotify auth and link --- package-lock.json | 82 +++++++++++- package.json | 3 + src/config/constants.ts | 13 +- src/main.ts | 9 +- src/spotify/dto/spotify-auth-query.dto.ts | 28 ++++ src/spotify/dto/spotify-link.dto.ts | 12 ++ src/spotify/dto/spotify-tokens.dto.ts | 22 ++++ .../pipes/spotify-auth-query.pipe.spec.ts | 7 + src/spotify/pipes/spotify-auth-query.pipe.ts | 14 ++ src/spotify/schemas/spotify-link.schema.ts | 12 +- src/spotify/spotify.controller.ts | 30 ++++- src/spotify/spotify.module.ts | 9 +- src/spotify/spotify.service.ts | 120 +++++++++++++++++- src/types/index.d.ts | 1 + .../filters/http-exception.filter.spec.ts | 7 + src/utils/filters/http-exception.filter.ts | 21 +++ src/utils/filters/index.ts | 1 + src/utils/index.ts | 1 + src/utils/mock/mockUser.ts | 3 +- 19 files changed, 377 insertions(+), 18 deletions(-) create mode 100644 src/spotify/dto/spotify-auth-query.dto.ts create mode 100644 src/spotify/dto/spotify-link.dto.ts create mode 100644 src/spotify/dto/spotify-tokens.dto.ts create mode 100644 src/spotify/pipes/spotify-auth-query.pipe.spec.ts create mode 100644 src/spotify/pipes/spotify-auth-query.pipe.ts create mode 100644 src/utils/filters/http-exception.filter.spec.ts create mode 100644 src/utils/filters/http-exception.filter.ts create mode 100644 src/utils/filters/index.ts diff --git a/package-lock.json b/package-lock.json index e35c9bf..774bd61 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,9 @@ "@nestjs/swagger": "^7.4.2", "@nestjs/websockets": "^10.4.4", "@spotify/web-api-ts-sdk": "^1.2.0", + "axios": "^1.7.7", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.1", "mongoose": "^8.7.0", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1" @@ -2502,6 +2505,12 @@ "@types/superagent": "^8.1.0" } }, + "node_modules/@types/validator": { + "version": "13.12.2", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.2.tgz", + "integrity": "sha512-6SlHBzUW8Jhf3liqrGGXyTJSIFe4nqlJ5A5KaMZ2l/vbM3Wh3KSybots/wfWVzNLK4D1NZluDlSQIbIEPx6oyA==", + "license": "MIT" + }, "node_modules/@types/webidl-conversions": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", @@ -3141,9 +3150,19 @@ "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/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -3676,6 +3695,23 @@ "dev": true, "license": "MIT" }, + "node_modules/class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==", + "license": "MIT" + }, + "node_modules/class-validator": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.1.tgz", + "integrity": "sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==", + "license": "MIT", + "dependencies": { + "@types/validator": "^13.11.8", + "libphonenumber-js": "^1.10.53", + "validator": "^13.9.0" + } + }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -3811,7 +3847,6 @@ "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" @@ -4108,7 +4143,6 @@ "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" @@ -5035,6 +5069,26 @@ "dev": true, "license": "ISC" }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/foreground-child": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", @@ -5109,7 +5163,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -6760,6 +6813,12 @@ "node": ">= 0.8.0" } }, + "node_modules/libphonenumber-js": { + "version": "1.11.11", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.11.tgz", + "integrity": "sha512-mF3KaORjJQR6JBNcOkluDcJKhtoQT4VTLRMrX1v/wlBayL4M8ybwEDeryyPcrSEJmD0rVwHUbBarpZwN5NfPFQ==", + "license": "MIT" + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -7823,6 +7882,12 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -9429,6 +9494,15 @@ "node": ">=10.12.0" } }, + "node_modules/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index 261776c..f184998 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,9 @@ "@nestjs/swagger": "^7.4.2", "@nestjs/websockets": "^10.4.4", "@spotify/web-api-ts-sdk": "^1.2.0", + "axios": "^1.7.7", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.1", "mongoose": "^8.7.0", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1" diff --git a/src/config/constants.ts b/src/config/constants.ts index 2df5142..a47eb90 100644 --- a/src/config/constants.ts +++ b/src/config/constants.ts @@ -16,8 +16,19 @@ export const AUTH_TOKEN_COOKIE_NAME = 'dev-auth-token' export const SPOTIFY_CLIENT_ID = process.env.SPOTIFY_CLIENT_ID || 'changeme' export const SPOTIFY_CLIENT_SECRET = process.env.SPOTIFY_CLIENT_SECRET || 'changeme' -export const SPOTIFY_REDIRECT_PATH = '/api/spotify/login-callback/' +export const SPOTIFY_REDIRECT_PATH = '/api/v1/spotify/login/success/' export const SPOTIFY_REDIRECT_URI = BASE_URL + SPOTIFY_REDIRECT_PATH +export const SPOTIFY_SCOPES = [ + 'user-read-private', + 'user-read-email', + 'playlist-modify-public', + 'playlist-modify-private', + 'user-read-playback-state', + 'user-modify-playback-state', + 'user-read-currently-playing', + 'app-remote-control', + 'streaming', +] // export const LOG_LEVEL = process.env.LOG_LEVEL || 'warn' // export const LOG_NS = process.env.LOG_NS || 'server' diff --git a/src/main.ts b/src/main.ts index 8b8e840..95e6158 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,10 +1,17 @@ +import { ValidationPipe } from '@nestjs/common' import { NestFactory } from '@nestjs/core' import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger' import { AppModule } from './app.module' import { PORT } from './config' +import { HttpExceptionFilter } from './utils' async function bootstrap() { - const app = await NestFactory.create(AppModule) + const app = await NestFactory.create(AppModule, { + logger: ['debug', 'error', 'fatal', 'log', 'verbose', 'warn'], + }) + app.useGlobalPipes(new ValidationPipe({ transform: true })) + app.setGlobalPrefix('api/v1') + app.useGlobalFilters(new HttpExceptionFilter()) const swaggerConfig = new DocumentBuilder().setTitle('Jukebox API').build() const swaggerDocument = SwaggerModule.createDocument(app, swaggerConfig) diff --git a/src/spotify/dto/spotify-auth-query.dto.ts b/src/spotify/dto/spotify-auth-query.dto.ts new file mode 100644 index 0000000..b0d10b1 --- /dev/null +++ b/src/spotify/dto/spotify-auth-query.dto.ts @@ -0,0 +1,28 @@ +import { Transform, Type } from 'class-transformer' +import { IsOptional, IsUrl, ValidateNested } from 'class-validator' + +export class SpotifyAuthStateDto { + @Type(() => String) + userId: string + + @Type(() => String) + @IsOptional() + @IsUrl() + finalRedirect?: string +} + +export class SpotifyAuthQueryDto { + @Type(() => String) + code: string + + // @Type(() => SpotifyAuthQueryDto) + // @Transform(({ value }) => { + // if (typeof value === 'string') { + // value = JSON.parse(value) + // } + + // return value + // }) + // @ValidateNested() + state: SpotifyAuthStateDto +} diff --git a/src/spotify/dto/spotify-link.dto.ts b/src/spotify/dto/spotify-link.dto.ts new file mode 100644 index 0000000..54383a1 --- /dev/null +++ b/src/spotify/dto/spotify-link.dto.ts @@ -0,0 +1,12 @@ +import { SpotifyTokensDto } from './spotify-tokens.dto' + +export class CreateSpotifyLinkDto { + userId: string + spotifyEmail: string + tokens: SpotifyTokensDto +} + +export class UpdateSpotifyLinkDto { + accessToken: string + expiresIn: number +} diff --git a/src/spotify/dto/spotify-tokens.dto.ts b/src/spotify/dto/spotify-tokens.dto.ts new file mode 100644 index 0000000..d023ee9 --- /dev/null +++ b/src/spotify/dto/spotify-tokens.dto.ts @@ -0,0 +1,22 @@ +export class SpotifyTokensDto { + accessToken: string + refreshToken: string + expiresIn: number + tokenType: string + + constructor(data: any) { + this.accessToken = data.access_token ?? data.accessToken + this.refreshToken = data.refresh_token ?? data.refreshToken + this.expiresIn = data.expires_in ?? data.expiresIn + this.tokenType = data.token_type ?? data.tokenType + } + + getSnakeCase() { + return { + access_token: this.accessToken, + refresh_token: this.refreshToken, + expires_in: this.expiresIn, + token_type: this.tokenType, + } + } +} diff --git a/src/spotify/pipes/spotify-auth-query.pipe.spec.ts b/src/spotify/pipes/spotify-auth-query.pipe.spec.ts new file mode 100644 index 0000000..6a170b3 --- /dev/null +++ b/src/spotify/pipes/spotify-auth-query.pipe.spec.ts @@ -0,0 +1,7 @@ +import { SpotifyAuthQueryPipe } from './spotify-auth-query.pipe'; + +describe('SpotifyAuthQueryPipe', () => { + it('should be defined', () => { + expect(new SpotifyAuthQueryPipe()).toBeDefined(); + }); +}); diff --git a/src/spotify/pipes/spotify-auth-query.pipe.ts b/src/spotify/pipes/spotify-auth-query.pipe.ts new file mode 100644 index 0000000..a36fd18 --- /dev/null +++ b/src/spotify/pipes/spotify-auth-query.pipe.ts @@ -0,0 +1,14 @@ +import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common' +import { plainToInstance } from 'class-transformer' +import { SpotifyAuthQueryDto } from '../dto/spotify-auth-query.dto' + +@Injectable() +export class SpotifyAuthQueryPipe implements PipeTransform { + transform(value: SpotifyAuthQueryDto, { metatype }: ArgumentMetadata) { + if (!metatype) { + return value + } + + return plainToInstance(metatype, value) + } +} diff --git a/src/spotify/schemas/spotify-link.schema.ts b/src/spotify/schemas/spotify-link.schema.ts index 55bb1c7..ce45ee2 100644 --- a/src/spotify/schemas/spotify-link.schema.ts +++ b/src/spotify/schemas/spotify-link.schema.ts @@ -1,8 +1,8 @@ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose' -import { HydratedDocument } from 'mongoose' +import { Document, HydratedDocument } from 'mongoose' @Schema() -export class SpotifyLink { +export class SpotifyLink extends Document { @Prop() accessToken: string @@ -27,7 +27,13 @@ export class SpotifyLink { isExpired() { return this.expiresAt.getTime() <= Date.now() } + + syncExpiresAt() { + this.expiresAt = new Date(Date.now() + this.expiresIn * 1000) + } } -export const SpotifyLinkSchema = SchemaFactory.createForClass(SpotifyLink) export type SpotifyLinkDocument = HydratedDocument +export const SpotifyLinkSchema = SchemaFactory.createForClass(SpotifyLink) + +SpotifyLinkSchema.loadClass(SpotifyLink) diff --git a/src/spotify/spotify.controller.ts b/src/spotify/spotify.controller.ts index 48d1f17..f6e331a 100644 --- a/src/spotify/spotify.controller.ts +++ b/src/spotify/spotify.controller.ts @@ -1,17 +1,37 @@ -import { Controller, Get, UseInterceptors } from '@nestjs/common' +import { Controller, Get, Query, Res, UseInterceptors } from '@nestjs/common' +import { Response } from 'express' import { AuthInterceptor } from 'src/auth/auth.interceptor' import { CurrentUser } from 'src/auth/current-user.decorator' +import { SpotifyAuthQueryDto } from './dto/spotify-auth-query.dto' +import { SpotifyAuthQueryPipe } from './pipes/spotify-auth-query.pipe' +import { SpotifyService } from './spotify.service' @Controller('spotify') export class SpotifyController { + constructor(protected spotifyService: SpotifyService) {} + @Get('login') @UseInterceptors(AuthInterceptor) - login(@CurrentUser() user: IUser) { - console.log('Current user:', user) + login(@CurrentUser() user: IUser, @Res() res: Response, @Query() query: { redirectUri: string }) { + const url = this.spotifyService.getSpotifyRedirectUri(user.id, query.redirectUri) - return + return res.redirect(url) } @Get('login/success') - loginSuccessCallback() {} + async loginSuccessCallback( + @Res() res: Response, + @Query(new SpotifyAuthQueryPipe()) query: SpotifyAuthQueryDto, + ) { + const { code, state } = query + const { userId, finalRedirect } = state + + const profile = await this.spotifyService.handleAuthCode(userId, code) + + if (finalRedirect) { + return res.redirect(finalRedirect) + } else { + return res.json(profile) + } + } } diff --git a/src/spotify/spotify.module.ts b/src/spotify/spotify.module.ts index 35337e9..a575314 100644 --- a/src/spotify/spotify.module.ts +++ b/src/spotify/spotify.module.ts @@ -1,12 +1,19 @@ import { Module } from '@nestjs/common' import { MongooseModule } from '@nestjs/mongoose' +import Axios from 'axios' import { SpotifyLink, SpotifyLinkSchema } from './schemas/spotify-link.schema' import { SpotifyController } from './spotify.controller' import { SpotifyService } from './spotify.service' @Module({ controllers: [SpotifyController], - providers: [SpotifyService], + providers: [ + SpotifyService, + { + provide: Axios.Axios, + useValue: Axios.create(), + }, + ], imports: [MongooseModule.forFeature([{ name: SpotifyLink.name, schema: SpotifyLinkSchema }])], }) export class SpotifyModule {} diff --git a/src/spotify/spotify.service.ts b/src/spotify/spotify.service.ts index 1973493..2328926 100644 --- a/src/spotify/spotify.service.ts +++ b/src/spotify/spotify.service.ts @@ -1,4 +1,120 @@ -import { Injectable } from '@nestjs/common'; +import { BadRequestException, Injectable } from '@nestjs/common' +import { InjectModel } from '@nestjs/mongoose' +import { SpotifyApi } from '@spotify/web-api-ts-sdk' +import { Axios } from 'axios' +import { Model } from 'mongoose' +import { stringify } from 'querystring' +import { + SPOTIFY_CLIENT_ID, + SPOTIFY_CLIENT_SECRET, + SPOTIFY_REDIRECT_URI, + SPOTIFY_SCOPES, +} from 'src/config' +import { CreateSpotifyLinkDto, UpdateSpotifyLinkDto } from './dto/spotify-link.dto' +import { SpotifyTokensDto } from './dto/spotify-tokens.dto' +import { SpotifyLink } from './schemas/spotify-link.schema' @Injectable() -export class SpotifyService {} +export class SpotifyService { + constructor( + @InjectModel(SpotifyLink.name) private spotifyLinkModel: Model, + protected axios: Axios, + ) {} + + private getSdk(tokens: SpotifyTokensDto) { + return SpotifyApi.withAccessToken(SPOTIFY_CLIENT_ID, tokens.getSnakeCase()) + } + + private async authenticateSpotify(code: string): Promise { + const body = { + grant_type: 'authorization_code', + code: code, + redirect_uri: SPOTIFY_REDIRECT_URI, + } + const authBuffer = Buffer.from(SPOTIFY_CLIENT_ID + ':' + SPOTIFY_CLIENT_SECRET) + + const res = await this.axios + .post('https://accounts.spotify.com/api/token', body, { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Authorization: 'Basic ' + authBuffer.toString('base64'), + }, + }) + .catch((error) => { + throw new BadRequestException(error?.response?.data?.error_description || error) + }) + + if (res.status > 299 || !res.data) { + throw new BadRequestException('Unable to authenticate with Spotify') + } + + return new SpotifyTokensDto(res.data) + } + + public getSpotifyRedirectUri(userId: string, finalRedirect?: string) { + const state = JSON.stringify({ userId, finalRedirect }) + const url = + 'https://accounts.spotify.com/authorize?' + + stringify({ + response_type: 'code', + client_id: SPOTIFY_CLIENT_ID, + scope: SPOTIFY_SCOPES.join(','), + redirect_uri: SPOTIFY_REDIRECT_URI, + state: state, + }) + + return url + } + + public async handleAuthCode(userId: string, code: string) { + const tokens = await this.authenticateSpotify(code) + const sdk = this.getSdk(tokens) + const profile = await sdk.currentUser.profile() + + await this.updateOrCreateLink(userId, profile.email, tokens) + + return profile + } + + private async createLink(attrs: CreateSpotifyLinkDto) { + const { userId, spotifyEmail, tokens } = attrs + const link = new this.spotifyLinkModel({ + userId, + spotifyEmail, + ...tokens, + }) + link.syncExpiresAt() + await link.save() + + return link + } + + private async updateLink(id: string, attrs: UpdateSpotifyLinkDto) { + const link = this.spotifyLinkModel + .findByIdAndUpdate( + id, + attrs, + { new: true }, + ) + .exec() + + if (!link) { + throw new BadRequestException(`Cannot find preexisting spotify account link with id ${id}`) + } + + return link + } + + private async updateOrCreateLink(userId: string, spotifyEmail: string, tokens: SpotifyTokensDto) { + const existing = await this.spotifyLinkModel.findOne({ userId, spotifyEmail }) + + if (!existing) { + await this.createLink({ userId, spotifyEmail, tokens }) + } else { + await this.updateLink(existing._id.toString(), { + accessToken: tokens.accessToken, + expiresIn: tokens.expiresIn, + }) + } + } +} diff --git a/src/types/index.d.ts b/src/types/index.d.ts index b20cedd..7326155 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -1,4 +1,5 @@ declare interface IUser { + id: string email: string firstName: string lastName: string diff --git a/src/utils/filters/http-exception.filter.spec.ts b/src/utils/filters/http-exception.filter.spec.ts new file mode 100644 index 0000000..8f016dd --- /dev/null +++ b/src/utils/filters/http-exception.filter.spec.ts @@ -0,0 +1,7 @@ +import { HttpExceptionFilter } from './http-exception.filter'; + +describe('HttpExceptionFilter', () => { + it('should be defined', () => { + expect(new HttpExceptionFilter()).toBeDefined(); + }); +}); diff --git a/src/utils/filters/http-exception.filter.ts b/src/utils/filters/http-exception.filter.ts new file mode 100644 index 0000000..8edce69 --- /dev/null +++ b/src/utils/filters/http-exception.filter.ts @@ -0,0 +1,21 @@ +import { ArgumentsHost, Catch, ExceptionFilter, HttpException, Logger } from '@nestjs/common' +import { Request, Response } from 'express' + +@Catch(HttpException) +export class HttpExceptionFilter implements ExceptionFilter { + catch(exception: HttpException, host: ArgumentsHost) { + const ctx = host.switchToHttp() + const response = ctx.getResponse() + const request = ctx.getRequest() + const status = exception.getStatus() + const type = exception.name + + Logger.error(exception, exception.stack) + + return response.status(status).json({ + statusCode: status, + type, + message: exception.message, + }) + } +} diff --git a/src/utils/filters/index.ts b/src/utils/filters/index.ts new file mode 100644 index 0000000..a84099e --- /dev/null +++ b/src/utils/filters/index.ts @@ -0,0 +1 @@ +export * from './http-exception.filter' diff --git a/src/utils/index.ts b/src/utils/index.ts index 218ab33..3be2e20 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1 +1,2 @@ export * from './mock' +export * from './filters' \ No newline at end of file diff --git a/src/utils/mock/mockUser.ts b/src/utils/mock/mockUser.ts index 7e172dd..384ecc9 100644 --- a/src/utils/mock/mockUser.ts +++ b/src/utils/mock/mockUser.ts @@ -1,4 +1,5 @@ -export const mockUser = { +export const mockUser: IUser = { + id: 'abc123', email: 'user@example.com', firstName: 'John', lastName: 'Doe', From 57684342e4ab5672c28707ab3b4385095caf74b8 Mon Sep 17 00:00:00 2001 From: Isaac Hunter Date: Sun, 6 Oct 2024 02:20:49 -0400 Subject: [PATCH 07/10] create jukebox resource, add api docs --- nest-cli.json | 3 +- package-lock.json | 18 +++++++- package.json | 3 +- src/app.module.ts | 2 + src/jukebox/dto/create-jukebox.dto.ts | 9 ++++ src/jukebox/dto/jukebox.dto.ts | 16 +++++++ src/jukebox/dto/update-jukebox.dto.ts | 11 +++++ src/jukebox/jukebox.controller.ts | 37 +++++++++++++++ src/jukebox/jukebox.module.ts | 12 +++++ src/jukebox/jukebox.service.ts | 47 ++++++++++++++++++++ src/jukebox/schemas/jukebox.schema.ts | 23 ++++++++++ src/jukebox/tests/jukebox.controller.spec.ts | 20 +++++++++ src/jukebox/tests/jukebox.service.spec.ts | 18 ++++++++ src/main.ts | 7 ++- src/spotify/dto/spotify-link.dto.ts | 22 +++++++++ src/spotify/spotify.controller.ts | 2 + 16 files changed, 246 insertions(+), 4 deletions(-) create mode 100644 src/jukebox/dto/create-jukebox.dto.ts create mode 100644 src/jukebox/dto/jukebox.dto.ts create mode 100644 src/jukebox/dto/update-jukebox.dto.ts create mode 100644 src/jukebox/jukebox.controller.ts create mode 100644 src/jukebox/jukebox.module.ts create mode 100644 src/jukebox/jukebox.service.ts create mode 100644 src/jukebox/schemas/jukebox.schema.ts create mode 100644 src/jukebox/tests/jukebox.controller.spec.ts create mode 100644 src/jukebox/tests/jukebox.service.spec.ts diff --git a/nest-cli.json b/nest-cli.json index f9aa683..e8552c2 100644 --- a/nest-cli.json +++ b/nest-cli.json @@ -3,6 +3,7 @@ "collection": "@nestjs/schematics", "sourceRoot": "src", "compilerOptions": { - "deleteOutDir": true + "deleteOutDir": true, + "plugins": ["@nestjs/swagger"] } } diff --git a/package-lock.json b/package-lock.json index 774bd61..68b83ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,8 @@ "class-validator": "^0.14.1", "mongoose": "^8.7.0", "reflect-metadata": "^0.2.0", - "rxjs": "^7.8.1" + "rxjs": "^7.8.1", + "swagger-ui-express": "^5.0.1" }, "devDependencies": { "@nestjs/cli": "^10.0.0", @@ -8865,6 +8866,21 @@ "integrity": "sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==", "license": "Apache-2.0" }, + "node_modules/swagger-ui-express": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.1.tgz", + "integrity": "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==", + "license": "MIT", + "dependencies": { + "swagger-ui-dist": ">=5.0.0" + }, + "engines": { + "node": ">= v0.10.32" + }, + "peerDependencies": { + "express": ">=4.0.0 || >=5.0.0-beta" + } + }, "node_modules/symbol-observable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", diff --git a/package.json b/package.json index f184998..41e1bfa 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,8 @@ "class-validator": "^0.14.1", "mongoose": "^8.7.0", "reflect-metadata": "^0.2.0", - "rxjs": "^7.8.1" + "rxjs": "^7.8.1", + "swagger-ui-express": "^5.0.1" }, "devDependencies": { "@nestjs/cli": "^10.0.0", diff --git a/src/app.module.ts b/src/app.module.ts index 4369b87..822d926 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -7,6 +7,7 @@ import { AppService } from './app.service' import { MONGO_URI } from './config' import { SpotifyModule } from './spotify/spotify.module' import { TrackQueueModule } from './track-queue/track-queue.module' +import { JukeboxModule } from './jukebox/jukebox.module'; @Module({ imports: [ @@ -14,6 +15,7 @@ import { TrackQueueModule } from './track-queue/track-queue.module' MongooseModule.forRoot(MONGO_URI), SpotifyModule, TrackQueueModule, + JukeboxModule, ], controllers: [AppController], providers: [AppService, AppGateway], diff --git a/src/jukebox/dto/create-jukebox.dto.ts b/src/jukebox/dto/create-jukebox.dto.ts new file mode 100644 index 0000000..e0be279 --- /dev/null +++ b/src/jukebox/dto/create-jukebox.dto.ts @@ -0,0 +1,9 @@ +import { ApiProperty } from '@nestjs/swagger' + +export class CreateJukeboxDto { + @ApiProperty() + name: string + + @ApiProperty() + clubId: string +} diff --git a/src/jukebox/dto/jukebox.dto.ts b/src/jukebox/dto/jukebox.dto.ts new file mode 100644 index 0000000..9f4f933 --- /dev/null +++ b/src/jukebox/dto/jukebox.dto.ts @@ -0,0 +1,16 @@ +import { ApiProperty } from '@nestjs/swagger' +import { SpotifyLinkDto } from 'src/spotify/dto/spotify-link.dto' + +export class JukeboxDto { + @ApiProperty({ type: 'string' }) + name: string + + @ApiProperty() + clubId: string + + @ApiProperty() + spotifyLinks: SpotifyLinkDto[] + + @ApiProperty() + activeSpotifyLink?: SpotifyLinkDto +} diff --git a/src/jukebox/dto/update-jukebox.dto.ts b/src/jukebox/dto/update-jukebox.dto.ts new file mode 100644 index 0000000..8ca888c --- /dev/null +++ b/src/jukebox/dto/update-jukebox.dto.ts @@ -0,0 +1,11 @@ +import { ApiProperty, PartialType } from '@nestjs/swagger' +import { SpotifyLinkDto } from 'src/spotify/dto/spotify-link.dto' +import { CreateJukeboxDto } from './create-jukebox.dto' + +export class UpdateJukeboxDto extends PartialType(CreateJukeboxDto) { + @ApiProperty() + name: string + + @ApiProperty() + activeSpotifyLink: SpotifyLinkDto +} diff --git a/src/jukebox/jukebox.controller.ts b/src/jukebox/jukebox.controller.ts new file mode 100644 index 0000000..f0c7dc0 --- /dev/null +++ b/src/jukebox/jukebox.controller.ts @@ -0,0 +1,37 @@ +import { Body, Controller, Delete, Get, Param, Patch, Post, Response } from '@nestjs/common' +import { ApiTags } from '@nestjs/swagger' +import { CreateJukeboxDto } from './dto/create-jukebox.dto' +import { JukeboxDto } from './dto/jukebox.dto' +import { UpdateJukeboxDto } from './dto/update-jukebox.dto' +import { JukeboxService } from './jukebox.service' + +@ApiTags('jukeboxes') +@Controller('jukebox') +export class JukeboxController { + constructor(private readonly jukeboxService: JukeboxService) {} + + @Post('jukeboxes') + create(@Body() createJukeboxDto: CreateJukeboxDto): Promise { + return this.jukeboxService.create(createJukeboxDto) + } + + @Get('jukeboxes') + findAll(): Promise { + return this.jukeboxService.findAll() + } + + @Get('jukeboxes/:id') + findOne(@Param('id') id: string): Promise { + return this.jukeboxService.findOne(id) + } + + @Patch('jukeboxes/:id') + update(@Param('id') id: string, @Body() updateJukeboxDto: UpdateJukeboxDto): Promise { + return this.jukeboxService.update(id, updateJukeboxDto) + } + + @Delete('jukeboxes/:id') + remove(@Param('id') id: string): Promise { + return this.jukeboxService.remove(id) + } +} diff --git a/src/jukebox/jukebox.module.ts b/src/jukebox/jukebox.module.ts new file mode 100644 index 0000000..ee3d1ce --- /dev/null +++ b/src/jukebox/jukebox.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common' +import { MongooseModule } from '@nestjs/mongoose' +import { JukeboxController } from './jukebox.controller' +import { JukeboxService } from './jukebox.service' +import { Jukebox, JukeboxSchema } from './schemas/jukebox.schema' + +@Module({ + controllers: [JukeboxController], + providers: [JukeboxService], + imports: [MongooseModule.forFeature([{ name: Jukebox.name, schema: JukeboxSchema }])], +}) +export class JukeboxModule {} diff --git a/src/jukebox/jukebox.service.ts b/src/jukebox/jukebox.service.ts new file mode 100644 index 0000000..7fcfc50 --- /dev/null +++ b/src/jukebox/jukebox.service.ts @@ -0,0 +1,47 @@ +import { Injectable, NotFoundException } from '@nestjs/common' +import { InjectModel } from '@nestjs/mongoose' +import { Model } from 'mongoose' +import { CreateJukeboxDto } from './dto/create-jukebox.dto' +import { UpdateJukeboxDto } from './dto/update-jukebox.dto' +import { Jukebox } from './schemas/jukebox.schema' + +@Injectable() +export class JukeboxService { + constructor(@InjectModel(Jukebox.name) private jukeboxModel: Model) {} + + create(createJukeboxDto: CreateJukeboxDto) { + const jukebox = new this.jukeboxModel(createJukeboxDto) + return jukebox.save() + } + + findAll() { + return this.jukeboxModel.find().exec() + } + + findOne(id: string) { + const jukebox = this.jukeboxModel.findById(id).exec() + if (!jukebox) { + throw new NotFoundException('Jukebox not found') + } + + return jukebox + } + + update(id: string, updateJukeboxDto: UpdateJukeboxDto) { + const jukebox = this.jukeboxModel.findByIdAndUpdate(id, updateJukeboxDto, { new: true }).exec() + if (!jukebox) { + throw new NotFoundException(`Jukebox with id ${id} not found`) + } + + return jukebox + } + + remove(id: string) { + const jukebox = this.jukeboxModel.findByIdAndDelete(id).exec() + if (!jukebox) { + throw new NotFoundException(`Jukebox with id ${id} not found`) + } + + return jukebox + } +} diff --git a/src/jukebox/schemas/jukebox.schema.ts b/src/jukebox/schemas/jukebox.schema.ts new file mode 100644 index 0000000..932d45e --- /dev/null +++ b/src/jukebox/schemas/jukebox.schema.ts @@ -0,0 +1,23 @@ +import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose' +import { Document, HydratedDocument, Schema as MSchema } from 'mongoose' +import { SpotifyLink } from 'src/spotify/schemas/spotify-link.schema' + +@Schema() +export class Jukebox extends Document { + @Prop() + name: string + + @Prop() + clubId: string + + @Prop({ type: Array, ref: SpotifyLink.name }) + spotifyLinks: SpotifyLink[] + + @Prop({ type: MSchema.Types.ObjectId, ref: SpotifyLink.name }) + activeSpotifyLink?: SpotifyLink +} + +export type JukeboxDocument = HydratedDocument +export const JukeboxSchema = SchemaFactory.createForClass(Jukebox) + +JukeboxSchema.loadClass(Jukebox) diff --git a/src/jukebox/tests/jukebox.controller.spec.ts b/src/jukebox/tests/jukebox.controller.spec.ts new file mode 100644 index 0000000..694bac4 --- /dev/null +++ b/src/jukebox/tests/jukebox.controller.spec.ts @@ -0,0 +1,20 @@ +import { Test, TestingModule } from '@nestjs/testing' +import { JukeboxController } from '../jukebox.controller' +import { JukeboxService } from '../jukebox.service' + +describe('JukeboxController', () => { + let controller: JukeboxController + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [JukeboxController], + providers: [JukeboxService], + }).compile() + + controller = module.get(JukeboxController) + }) + + it('should be defined', () => { + expect(controller).toBeDefined() + }) +}) diff --git a/src/jukebox/tests/jukebox.service.spec.ts b/src/jukebox/tests/jukebox.service.spec.ts new file mode 100644 index 0000000..b16b3b3 --- /dev/null +++ b/src/jukebox/tests/jukebox.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing' +import { JukeboxService } from '../jukebox.service' + +describe('JukeboxService', () => { + let service: JukeboxService + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [JukeboxService], + }).compile() + + service = module.get(JukeboxService) + }) + + it('should be defined', () => { + expect(service).toBeDefined() + }) +}) diff --git a/src/main.ts b/src/main.ts index 95e6158..99e8b92 100644 --- a/src/main.ts +++ b/src/main.ts @@ -13,7 +13,12 @@ async function bootstrap() { app.setGlobalPrefix('api/v1') app.useGlobalFilters(new HttpExceptionFilter()) - const swaggerConfig = new DocumentBuilder().setTitle('Jukebox API').build() + const swaggerConfig = new DocumentBuilder() + .setTitle('Jukebox API') + .setVersion('1.0.0') + .addTag('jukeboxes') + .addTag('spotify') + .build() const swaggerDocument = SwaggerModule.createDocument(app, swaggerConfig) SwaggerModule.setup('/api/docs', app, swaggerDocument) diff --git a/src/spotify/dto/spotify-link.dto.ts b/src/spotify/dto/spotify-link.dto.ts index 54383a1..928c25a 100644 --- a/src/spotify/dto/spotify-link.dto.ts +++ b/src/spotify/dto/spotify-link.dto.ts @@ -1,3 +1,5 @@ +import { ApiProperty, PartialType } from '@nestjs/swagger' +import { SpotifyLink } from '../schemas/spotify-link.schema' import { SpotifyTokensDto } from './spotify-tokens.dto' export class CreateSpotifyLinkDto { @@ -10,3 +12,23 @@ export class UpdateSpotifyLinkDto { accessToken: string expiresIn: number } + +export class SpotifyLinkDto extends PartialType(SpotifyLink) { + @ApiProperty() + accessToken: string + + @ApiProperty() + userId: string + + @ApiProperty() + spotifyEmail: string + + @ApiProperty() + expiresIn: number + + @ApiProperty() + expiresAt: Date + + @ApiProperty() + tokenType: string +} diff --git a/src/spotify/spotify.controller.ts b/src/spotify/spotify.controller.ts index f6e331a..22186d7 100644 --- a/src/spotify/spotify.controller.ts +++ b/src/spotify/spotify.controller.ts @@ -1,4 +1,5 @@ import { Controller, Get, Query, Res, UseInterceptors } from '@nestjs/common' +import { ApiTags } from '@nestjs/swagger' import { Response } from 'express' import { AuthInterceptor } from 'src/auth/auth.interceptor' import { CurrentUser } from 'src/auth/current-user.decorator' @@ -6,6 +7,7 @@ import { SpotifyAuthQueryDto } from './dto/spotify-auth-query.dto' import { SpotifyAuthQueryPipe } from './pipes/spotify-auth-query.pipe' import { SpotifyService } from './spotify.service' +@ApiTags('spotify') @Controller('spotify') export class SpotifyController { constructor(protected spotifyService: SpotifyService) {} From 33363daf81e287c6f776c10d4b79c52ffc033e32 Mon Sep 17 00:00:00 2001 From: Isaac Hunter Date: Sun, 6 Oct 2024 14:43:31 -0400 Subject: [PATCH 08/10] add club manager to proxy --- docker-compose.network.yml | 6 +++++ docs/Network-Mode.md | 52 ++++++++++++++++++++++++++++++++++++++ proxy/default.conf.tpl | 41 +++++++++++++++++++++++++++++- src/main.ts | 2 +- 4 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 docs/Network-Mode.md diff --git a/docker-compose.network.yml b/docker-compose.network.yml index a6f86d8..2a5e37f 100644 --- a/docker-compose.network.yml +++ b/docker-compose.network.yml @@ -39,9 +39,12 @@ services: - server volumes: - client-dist:/vol/client + - club-static:/vol/static environment: - SERVER_URI=server-jbx:9000 - WEBSOCKET_URI=server-jbx:9000 + - CLUB_MANAGER_URI=club-app-network:9000 + # attach: false mongodb: @@ -111,6 +114,9 @@ volumes: client-dist: name: client-dist mongo-data: + club-static: + name: club-static + # external: true networks: cluster: diff --git a/docs/Network-Mode.md b/docs/Network-Mode.md new file mode 100644 index 0000000..f57b424 --- /dev/null +++ b/docs/Network-Mode.md @@ -0,0 +1,52 @@ +# Working in Network Mode + +## Helpful Commands + +To run all of the services in docker-compose.network: + +```sh +docker-compose -f docker-compose.network.yml up +``` + +When working with NGINX, you will often need to restart it after each edit, so this would ideally run separate. The suggested solution is to run the Jukebox server independent of the proxy container. In one terminal run: + +```sh +docker-compose -f docker-compose.network.yml up server +``` + +and in another terminal run: + +```sh +docker-compose -f docker-compose.network.yml up proxy +``` + +This allows you to restart the proxy after changes using: + +```sh +docker-compose -f docker-compose.network.yml up proxy --build --force-recreate +``` + +### When Running with Club Manager Repo + +Start the services in this order: + +1. Start jukebox server + + ```sh + # dir: Jukebox-Server/ + docker-compose -f docker-compose.network.yml up server + ``` + +2. Start Club Manager + + ```sh + # dir: Club-Manager/ + docker-compose -f docker-compose.network.yml up + ``` + +3. Start Proxy + + ```sh + # dir: Jukebox-Server/ + docker-compose -f docker-compose.network.yml up proxy --build --force-recreate + ``` diff --git a/proxy/default.conf.tpl b/proxy/default.conf.tpl index 59e5d90..f289922 100644 --- a/proxy/default.conf.tpl +++ b/proxy/default.conf.tpl @@ -18,7 +18,22 @@ server { underscores_in_headers on; - location /api { + location /static { + alias /vol/static; + } + + location ~* ^/api/v[0-9]/(spotify|jukebox) { + proxy_pass http://apiserver; + + proxy_set_header Host "$host:$server_port"; + proxy_set_header X-Forwarded-For "$proxy_add_x_forwarded_for"; + proxy_set_header Token "$http_token"; + + proxy_pass_header Token; + proxy_pass_header Authorization; + } + + location ~* ^/api/v[0-9]/docs/jukebox { proxy_pass http://apiserver; proxy_set_header Host "$host:$server_port"; @@ -29,6 +44,30 @@ server { proxy_pass_header Authorization; } + location ~* ^/api/v[0-9]/(user|club) { + uwsgi_pass "$CLUB_MANAGER_URI"; + + proxy_set_header Host "$host"; + proxy_set_header X-Forwarded-For "$proxy_add_x_forwarded_for"; + uwsgi_pass_header Token; + + client_max_body_size 32M; + include /etc/nginx/uwsgi_params; + } + + location ~* ^/api/v[0-9]/(docs|schema)/club-manager { + uwsgi_pass "$CLUB_MANAGER_URI"; + + proxy_set_header Host "$host"; + proxy_set_header X-Forwarded-For "$proxy_add_x_forwarded_for"; + uwsgi_pass_header Token; + + client_max_body_size 32M; + include /etc/nginx/uwsgi_params; + } + + + location /socket.io { # Basic config: https://socket.io/docs/v4/reverse-proxy/ # Sticky sessions: https://socket.io/docs/v4/using-multiple-nodes/#nginx-configuration diff --git a/src/main.ts b/src/main.ts index 99e8b92..3119163 100644 --- a/src/main.ts +++ b/src/main.ts @@ -20,7 +20,7 @@ async function bootstrap() { .addTag('spotify') .build() const swaggerDocument = SwaggerModule.createDocument(app, swaggerConfig) - SwaggerModule.setup('/api/docs', app, swaggerDocument) + SwaggerModule.setup('/api/v1/docs/jukebox', app, swaggerDocument) await app.listen(PORT) } From 3d5a81bab7442be2f8ce332c936584d5d03bb4c0 Mon Sep 17 00:00:00 2001 From: Isaac Hunter Date: Mon, 7 Oct 2024 11:11:53 -0400 Subject: [PATCH 09/10] fix unit tests to pass --- nest-cli.json | 1 + package.json | 7 +++-- src/jukebox/tests/jukebox.controller.spec.ts | 8 ++++- src/jukebox/tests/jukebox.service.spec.ts | 8 ++++- src/spotify/tests/spotify.controller.spec.ts | 31 ++++++++++++++------ src/spotify/tests/spotify.service.spec.ts | 31 +++++++++++++------- tsconfig.json | 7 ++++- 7 files changed, 69 insertions(+), 24 deletions(-) diff --git a/nest-cli.json b/nest-cli.json index e8552c2..82d0650 100644 --- a/nest-cli.json +++ b/nest-cli.json @@ -2,6 +2,7 @@ "$schema": "https://json.schemastore.org/nest-cli", "collection": "@nestjs/schematics", "sourceRoot": "src", + "entryFile": "src/main.ts", "compilerOptions": { "deleteOutDir": true, "plugins": ["@nestjs/swagger"] diff --git a/package.json b/package.json index 41e1bfa..5b8a9a0 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,8 @@ "json", "ts" ], - "rootDir": "src", + "rootDir": ".", + "roots": ["./src"], "testRegex": ".*\\.spec\\.ts$", "transform": { "^.+\\.(t|j)s$": "ts-jest" @@ -76,6 +77,8 @@ "**/*.(t|j)s" ], "coverageDirectory": "../coverage", - "testEnvironment": "node" + "testEnvironment": "node", + "moduleDirectories": ["src", "node_modules"], + "modulePaths": ["."] } } diff --git a/src/jukebox/tests/jukebox.controller.spec.ts b/src/jukebox/tests/jukebox.controller.spec.ts index 694bac4..77e2676 100644 --- a/src/jukebox/tests/jukebox.controller.spec.ts +++ b/src/jukebox/tests/jukebox.controller.spec.ts @@ -1,6 +1,9 @@ +import { getModelToken } from '@nestjs/mongoose' import { Test, TestingModule } from '@nestjs/testing' +import { Model } from 'mongoose' import { JukeboxController } from '../jukebox.controller' import { JukeboxService } from '../jukebox.service' +import { Jukebox } from '../schemas/jukebox.schema' describe('JukeboxController', () => { let controller: JukeboxController @@ -8,7 +11,10 @@ describe('JukeboxController', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [JukeboxController], - providers: [JukeboxService], + providers: [ + JukeboxService, + { provide: getModelToken(Jukebox.name), useValue: Model }, + ], }).compile() controller = module.get(JukeboxController) diff --git a/src/jukebox/tests/jukebox.service.spec.ts b/src/jukebox/tests/jukebox.service.spec.ts index b16b3b3..fe9ab0c 100644 --- a/src/jukebox/tests/jukebox.service.spec.ts +++ b/src/jukebox/tests/jukebox.service.spec.ts @@ -1,12 +1,18 @@ +import { getModelToken } from '@nestjs/mongoose' import { Test, TestingModule } from '@nestjs/testing' +import { Model } from 'mongoose' import { JukeboxService } from '../jukebox.service' +import { Jukebox } from '../schemas/jukebox.schema' describe('JukeboxService', () => { let service: JukeboxService beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - providers: [JukeboxService], + providers: [ + JukeboxService, + { provide: getModelToken(Jukebox.name), useValue: Model }, + ], }).compile() service = module.get(JukeboxService) diff --git a/src/spotify/tests/spotify.controller.spec.ts b/src/spotify/tests/spotify.controller.spec.ts index 36a5e5b..671ba97 100644 --- a/src/spotify/tests/spotify.controller.spec.ts +++ b/src/spotify/tests/spotify.controller.spec.ts @@ -1,18 +1,31 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { SpotifyController } from '../spotify.controller'; +import { getModelToken } from '@nestjs/mongoose' +import { Test, TestingModule } from '@nestjs/testing' +import { Model } from 'mongoose' +import { SpotifyLink } from '../schemas/spotify-link.schema' +import { SpotifyController } from '../spotify.controller' +import { SpotifyService } from '../spotify.service' +import Axios from 'axios' describe('SpotifyController', () => { - let controller: SpotifyController; + let controller: SpotifyController beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [SpotifyController], - }).compile(); + providers: [ + SpotifyService, + { provide: getModelToken(SpotifyLink.name), useValue: Model }, + { + provide: Axios.Axios, + useValue: Axios.create(), + }, + ], + }).compile() - controller = module.get(SpotifyController); - }); + controller = module.get(SpotifyController) + }) it('should be defined', () => { - expect(controller).toBeDefined(); - }); -}); + expect(controller).toBeDefined() + }) +}) diff --git a/src/spotify/tests/spotify.service.spec.ts b/src/spotify/tests/spotify.service.spec.ts index c140cd8..1b26d76 100644 --- a/src/spotify/tests/spotify.service.spec.ts +++ b/src/spotify/tests/spotify.service.spec.ts @@ -1,18 +1,29 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { SpotifyService } from '../spotify.service'; +import { getModelToken } from '@nestjs/mongoose' +import { Test, TestingModule } from '@nestjs/testing' +import Axios from 'axios' +import { Model } from 'mongoose' +import { SpotifyLink } from '../schemas/spotify-link.schema' +import { SpotifyService } from '../spotify.service' describe('SpotifyService', () => { - let service: SpotifyService; + let service: SpotifyService beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - providers: [SpotifyService], - }).compile(); + providers: [ + SpotifyService, + { provide: getModelToken(SpotifyLink.name), useValue: Model }, + { + provide: Axios.Axios, + useValue: Axios.create(), + }, + ], + }).compile() - service = module.get(SpotifyService); - }); + service = module.get(SpotifyService) + }) it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); + expect(service).toBeDefined() + }) +}) diff --git a/tsconfig.json b/tsconfig.json index 95f5641..d3a09d7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { "module": "commonjs", + "moduleResolution": "node", "declaration": true, "removeComments": true, "emitDecoratorMetadata": true, @@ -10,12 +11,16 @@ "sourceMap": true, "outDir": "./dist", "baseUrl": "./", + "rootDir": "./", "incremental": true, "skipLibCheck": true, "strictNullChecks": false, "noImplicitAny": false, "strictBindCallApply": false, "forceConsistentCasingInFileNames": false, - "noFallthroughCasesInSwitch": false + "noFallthroughCasesInSwitch": false, + "paths": { + "src/*": ["./*", "./src/*", "src/*"] + } } } From 535200503d68e6d04f04361b812af724339cbc75 Mon Sep 17 00:00:00 2001 From: Isaac Hunter Date: Mon, 7 Oct 2024 11:16:26 -0400 Subject: [PATCH 10/10] add linting command to package.json for ci --- nest-cli.json | 1 - package-lock.json | 14 ++ package.json | 17 +- src/app.controller.spec.ts | 23 +-- src/app.controller.ts | 6 +- src/app.gateway.spec.ts | 19 +- src/app.gateway.ts | 4 +- src/app.module.ts | 2 +- src/app.service.ts | 4 +- src/auth/auth.interceptor.spec.ts | 8 +- src/auth/current-user.decorator.ts | 3 +- src/config/index.ts | 2 +- src/jukebox/tests/jukebox.controller.spec.ts | 3 +- src/jukebox/tests/jukebox.service.spec.ts | 3 +- src/main.ts | 2 +- src/spotify/dto/spotify-link.dto.ts | 10 +- src/spotify/dto/spotify-tokens.dto.ts | 2 +- .../pipes/spotify-auth-query.pipe.spec.ts | 8 +- src/spotify/spotify.service.ts | 8 +- src/spotify/tests/spotify.controller.spec.ts | 3 +- src/spotify/tests/spotify.service.spec.ts | 3 +- .../tests/track-queue.service.spec.ts | 19 +- src/track-queue/tests/trackQueue.spec.ts | 164 +++++++++--------- src/track-queue/track-queue.module.ts | 6 +- src/track-queue/track-queue.service.ts | 29 ++-- .../filters/http-exception.filter.spec.ts | 8 +- src/utils/index.ts | 2 +- src/utils/mock/index.ts | 2 +- test/app.e2e-spec.ts | 28 ++- 29 files changed, 212 insertions(+), 191 deletions(-) diff --git a/nest-cli.json b/nest-cli.json index 82d0650..e8552c2 100644 --- a/nest-cli.json +++ b/nest-cli.json @@ -2,7 +2,6 @@ "$schema": "https://json.schemastore.org/nest-cli", "collection": "@nestjs/schematics", "sourceRoot": "src", - "entryFile": "src/main.ts", "compilerOptions": { "deleteOutDir": true, "plugins": ["@nestjs/swagger"] diff --git a/package-lock.json b/package-lock.json index 68b83ff..5e43863 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,6 +38,7 @@ "@typescript-eslint/parser": "^8.0.0", "eslint": "^8.42.0", "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prefer-arrow-functions": "^3.4.1", "eslint-plugin-prettier": "^5.0.0", "jest": "^29.5.0", "prettier": "^3.0.0", @@ -4498,6 +4499,19 @@ "eslint": ">=7.0.0" } }, + "node_modules/eslint-plugin-prefer-arrow-functions": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prefer-arrow-functions/-/eslint-plugin-prefer-arrow-functions-3.4.1.tgz", + "integrity": "sha512-c8NP0E8xpkRqDq2eDSRr+wA4jwkwOEVNnZx4YY3O0V9M7OhtKdQIj5zmzIXwu+ueURmbwYrnz65sEoLLoIVZpg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "eslint": ">=8.0.0" + } + }, "node_modules/eslint-plugin-prettier": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", diff --git a/package.json b/package.json index 5b8a9a0..f53710b 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "start:network": "nest start --watch --preserveWatchOutput", "start:debug": "nest start --debug --watch", "start:prod": "node dist/main", - "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\"", + "lint:fix": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "test": "jest", "test:watch": "jest --watch", "test:cov": "jest --coverage", @@ -50,6 +51,7 @@ "@typescript-eslint/parser": "^8.0.0", "eslint": "^8.42.0", "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prefer-arrow-functions": "^3.4.1", "eslint-plugin-prettier": "^5.0.0", "jest": "^29.5.0", "prettier": "^3.0.0", @@ -68,7 +70,9 @@ "ts" ], "rootDir": ".", - "roots": ["./src"], + "roots": [ + "./src" + ], "testRegex": ".*\\.spec\\.ts$", "transform": { "^.+\\.(t|j)s$": "ts-jest" @@ -78,7 +82,12 @@ ], "coverageDirectory": "../coverage", "testEnvironment": "node", - "moduleDirectories": ["src", "node_modules"], - "modulePaths": ["."] + "moduleDirectories": [ + "src", + "node_modules" + ], + "modulePaths": [ + "." + ] } } diff --git a/src/app.controller.spec.ts b/src/app.controller.spec.ts index d22f389..67a5855 100644 --- a/src/app.controller.spec.ts +++ b/src/app.controller.spec.ts @@ -1,22 +1,23 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AppController } from './app.controller'; -import { AppService } from './app.service'; +import type { TestingModule } from '@nestjs/testing' +import { Test } from '@nestjs/testing' +import { AppController } from './app.controller' +import { AppService } from './app.service' describe('AppController', () => { - let appController: AppController; + let appController: AppController beforeEach(async () => { const app: TestingModule = await Test.createTestingModule({ controllers: [AppController], providers: [AppService], - }).compile(); + }).compile() - appController = app.get(AppController); - }); + appController = app.get(AppController) + }) describe('root', () => { it('should return "Hello World!"', () => { - expect(appController.getHello()).toBe('Hello World!'); - }); - }); -}); + expect(appController.getHello()).toBe('Hello World!') + }) + }) +}) diff --git a/src/app.controller.ts b/src/app.controller.ts index cce879e..4e88eca 100644 --- a/src/app.controller.ts +++ b/src/app.controller.ts @@ -1,5 +1,5 @@ -import { Controller, Get } from '@nestjs/common'; -import { AppService } from './app.service'; +import { Controller, Get } from '@nestjs/common' +import { AppService } from './app.service' @Controller() export class AppController { @@ -7,6 +7,6 @@ export class AppController { @Get() getHello(): string { - return this.appService.getHello(); + return this.appService.getHello() } } diff --git a/src/app.gateway.spec.ts b/src/app.gateway.spec.ts index ce7a9b9..25389ae 100644 --- a/src/app.gateway.spec.ts +++ b/src/app.gateway.spec.ts @@ -1,18 +1,19 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AppGateway } from './app.gateway'; +import type { TestingModule } from '@nestjs/testing' +import { Test } from '@nestjs/testing' +import { AppGateway } from './app.gateway' describe('AppGateway', () => { - let gateway: AppGateway; + let gateway: AppGateway beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [AppGateway], - }).compile(); + }).compile() - gateway = module.get(AppGateway); - }); + gateway = module.get(AppGateway) + }) it('should be defined', () => { - expect(gateway).toBeDefined(); - }); -}); + expect(gateway).toBeDefined() + }) +}) diff --git a/src/app.gateway.ts b/src/app.gateway.ts index c3c6b90..5e2ff30 100644 --- a/src/app.gateway.ts +++ b/src/app.gateway.ts @@ -1,10 +1,10 @@ -import { SubscribeMessage, WebSocketGateway } from '@nestjs/websockets'; +import { SubscribeMessage, WebSocketGateway } from '@nestjs/websockets' @WebSocketGateway() export class AppGateway { @SubscribeMessage('message') handleMessage(client: any, payload: any): string { console.log('websocket payload:', payload) - return 'Hello world!'; + return 'Hello world!' } } diff --git a/src/app.module.ts b/src/app.module.ts index 822d926..b8f0fe5 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -7,7 +7,7 @@ import { AppService } from './app.service' import { MONGO_URI } from './config' import { SpotifyModule } from './spotify/spotify.module' import { TrackQueueModule } from './track-queue/track-queue.module' -import { JukeboxModule } from './jukebox/jukebox.module'; +import { JukeboxModule } from './jukebox/jukebox.module' @Module({ imports: [ diff --git a/src/app.service.ts b/src/app.service.ts index 927d7cc..bc13055 100644 --- a/src/app.service.ts +++ b/src/app.service.ts @@ -1,8 +1,8 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common' @Injectable() export class AppService { getHello(): string { - return 'Hello World!'; + return 'Hello World!' } } diff --git a/src/auth/auth.interceptor.spec.ts b/src/auth/auth.interceptor.spec.ts index 13fdabe..1b475a7 100644 --- a/src/auth/auth.interceptor.spec.ts +++ b/src/auth/auth.interceptor.spec.ts @@ -1,7 +1,7 @@ -import { AuthInterceptor } from './auth.interceptor'; +import { AuthInterceptor } from './auth.interceptor' describe('AuthInterceptor', () => { it('should be defined', () => { - expect(new AuthInterceptor()).toBeDefined(); - }); -}); + expect(new AuthInterceptor()).toBeDefined() + }) +}) diff --git a/src/auth/current-user.decorator.ts b/src/auth/current-user.decorator.ts index e6c411e..4728de8 100644 --- a/src/auth/current-user.decorator.ts +++ b/src/auth/current-user.decorator.ts @@ -1,4 +1,5 @@ -import { createParamDecorator, ExecutionContext, UnauthorizedException } from '@nestjs/common' +import type { ExecutionContext } from '@nestjs/common' +import { createParamDecorator, UnauthorizedException } from '@nestjs/common' export const CurrentUser = createParamDecorator((data: never, context: ExecutionContext) => { const request = context.switchToHttp().getRequest() diff --git a/src/config/index.ts b/src/config/index.ts index 363c822..f87cf01 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -1 +1 @@ -export * from './constants' \ No newline at end of file +export * from './constants' diff --git a/src/jukebox/tests/jukebox.controller.spec.ts b/src/jukebox/tests/jukebox.controller.spec.ts index 77e2676..aeb2bdc 100644 --- a/src/jukebox/tests/jukebox.controller.spec.ts +++ b/src/jukebox/tests/jukebox.controller.spec.ts @@ -1,5 +1,6 @@ import { getModelToken } from '@nestjs/mongoose' -import { Test, TestingModule } from '@nestjs/testing' +import type { TestingModule } from '@nestjs/testing' +import { Test } from '@nestjs/testing' import { Model } from 'mongoose' import { JukeboxController } from '../jukebox.controller' import { JukeboxService } from '../jukebox.service' diff --git a/src/jukebox/tests/jukebox.service.spec.ts b/src/jukebox/tests/jukebox.service.spec.ts index fe9ab0c..5b656c5 100644 --- a/src/jukebox/tests/jukebox.service.spec.ts +++ b/src/jukebox/tests/jukebox.service.spec.ts @@ -1,5 +1,6 @@ import { getModelToken } from '@nestjs/mongoose' -import { Test, TestingModule } from '@nestjs/testing' +import type { TestingModule } from '@nestjs/testing' +import { Test } from '@nestjs/testing' import { Model } from 'mongoose' import { JukeboxService } from '../jukebox.service' import { Jukebox } from '../schemas/jukebox.schema' diff --git a/src/main.ts b/src/main.ts index 3119163..b54ef82 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,7 +5,7 @@ import { AppModule } from './app.module' import { PORT } from './config' import { HttpExceptionFilter } from './utils' -async function bootstrap() { +const bootstrap = async () => { const app = await NestFactory.create(AppModule, { logger: ['debug', 'error', 'fatal', 'log', 'verbose', 'warn'], }) diff --git a/src/spotify/dto/spotify-link.dto.ts b/src/spotify/dto/spotify-link.dto.ts index 928c25a..cfea1fb 100644 --- a/src/spotify/dto/spotify-link.dto.ts +++ b/src/spotify/dto/spotify-link.dto.ts @@ -16,19 +16,19 @@ export class UpdateSpotifyLinkDto { export class SpotifyLinkDto extends PartialType(SpotifyLink) { @ApiProperty() accessToken: string - + @ApiProperty() userId: string - + @ApiProperty() spotifyEmail: string - + @ApiProperty() expiresIn: number - + @ApiProperty() expiresAt: Date - + @ApiProperty() tokenType: string } diff --git a/src/spotify/dto/spotify-tokens.dto.ts b/src/spotify/dto/spotify-tokens.dto.ts index d023ee9..6f1c56e 100644 --- a/src/spotify/dto/spotify-tokens.dto.ts +++ b/src/spotify/dto/spotify-tokens.dto.ts @@ -10,7 +10,7 @@ export class SpotifyTokensDto { this.expiresIn = data.expires_in ?? data.expiresIn this.tokenType = data.token_type ?? data.tokenType } - + getSnakeCase() { return { access_token: this.accessToken, diff --git a/src/spotify/pipes/spotify-auth-query.pipe.spec.ts b/src/spotify/pipes/spotify-auth-query.pipe.spec.ts index 6a170b3..f211bd0 100644 --- a/src/spotify/pipes/spotify-auth-query.pipe.spec.ts +++ b/src/spotify/pipes/spotify-auth-query.pipe.spec.ts @@ -1,7 +1,7 @@ -import { SpotifyAuthQueryPipe } from './spotify-auth-query.pipe'; +import { SpotifyAuthQueryPipe } from './spotify-auth-query.pipe' describe('SpotifyAuthQueryPipe', () => { it('should be defined', () => { - expect(new SpotifyAuthQueryPipe()).toBeDefined(); - }); -}); + expect(new SpotifyAuthQueryPipe()).toBeDefined() + }) +}) diff --git a/src/spotify/spotify.service.ts b/src/spotify/spotify.service.ts index 2328926..1d27e54 100644 --- a/src/spotify/spotify.service.ts +++ b/src/spotify/spotify.service.ts @@ -90,13 +90,7 @@ export class SpotifyService { } private async updateLink(id: string, attrs: UpdateSpotifyLinkDto) { - const link = this.spotifyLinkModel - .findByIdAndUpdate( - id, - attrs, - { new: true }, - ) - .exec() + const link = this.spotifyLinkModel.findByIdAndUpdate(id, attrs, { new: true }).exec() if (!link) { throw new BadRequestException(`Cannot find preexisting spotify account link with id ${id}`) diff --git a/src/spotify/tests/spotify.controller.spec.ts b/src/spotify/tests/spotify.controller.spec.ts index 671ba97..01a66cb 100644 --- a/src/spotify/tests/spotify.controller.spec.ts +++ b/src/spotify/tests/spotify.controller.spec.ts @@ -1,5 +1,6 @@ import { getModelToken } from '@nestjs/mongoose' -import { Test, TestingModule } from '@nestjs/testing' +import type { TestingModule } from '@nestjs/testing' +import { Test } from '@nestjs/testing' import { Model } from 'mongoose' import { SpotifyLink } from '../schemas/spotify-link.schema' import { SpotifyController } from '../spotify.controller' diff --git a/src/spotify/tests/spotify.service.spec.ts b/src/spotify/tests/spotify.service.spec.ts index 1b26d76..1a03bce 100644 --- a/src/spotify/tests/spotify.service.spec.ts +++ b/src/spotify/tests/spotify.service.spec.ts @@ -1,5 +1,6 @@ import { getModelToken } from '@nestjs/mongoose' -import { Test, TestingModule } from '@nestjs/testing' +import type { TestingModule } from '@nestjs/testing' +import { Test } from '@nestjs/testing' import Axios from 'axios' import { Model } from 'mongoose' import { SpotifyLink } from '../schemas/spotify-link.schema' diff --git a/src/track-queue/tests/track-queue.service.spec.ts b/src/track-queue/tests/track-queue.service.spec.ts index eeae67d..6434ae5 100644 --- a/src/track-queue/tests/track-queue.service.spec.ts +++ b/src/track-queue/tests/track-queue.service.spec.ts @@ -1,18 +1,19 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { TrackQueueService } from '../track-queue.service'; +import type { TestingModule } from '@nestjs/testing' +import { Test } from '@nestjs/testing' +import { TrackQueueService } from '../track-queue.service' describe('TrackQueueService', () => { - let service: TrackQueueService; + let service: TrackQueueService beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [TrackQueueService], - }).compile(); + }).compile() - service = module.get(TrackQueueService); - }); + service = module.get(TrackQueueService) + }) it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); + expect(service).toBeDefined() + }) +}) diff --git a/src/track-queue/tests/trackQueue.spec.ts b/src/track-queue/tests/trackQueue.spec.ts index 342b361..06b8ec2 100644 --- a/src/track-queue/tests/trackQueue.spec.ts +++ b/src/track-queue/tests/trackQueue.spec.ts @@ -1,105 +1,105 @@ -import { TrackQueue } from '../track-queue.service'; -import type { Track } from '@spotify/web-api-ts-sdk'; +import { TrackQueue } from '../track-queue.service' +import type { Track } from '@spotify/web-api-ts-sdk' // describe('TrackQueue Tests', () => { - let queue: TrackQueue; - const sometrack: Track = { - id: '1', - name: 'Test Track', - duration_ms: 300000, - album: { - id: 'album-id', - name: 'Test Album', - album_type: 'album', - album_group: 'album', - artists: [], - available_markets: [], - href: 'https://api.spotify.com/v1/albums/album-id', - images: [], - release_date: '2021-01-01', - release_date_precision: 'day', - total_tracks: 10, - type: 'album', - uri: 'spotify:album:album-id', - copyrights: [ - { text: '© 2021 Test Label', type: 'C' }, - { text: '℗ 2021 Test Label', type: 'P' } - ], - external_ids: { - upc: '123456789012', - ean: '1234567890123', - isrc: 'USUM71702776' - }, - external_urls: { - spotify: 'https://open.spotify.com/album/album-id' - }, - genres: ['pop'], - label: 'Test Label', - popularity: 75 - }, +let queue: TrackQueue +const sometrack: Track = { + id: '1', + name: 'Test Track', + duration_ms: 300000, + album: { + id: 'album-id', + name: 'Test Album', + album_type: 'album', + album_group: 'album', + artists: [], + available_markets: [], + href: 'https://api.spotify.com/v1/albums/album-id', + images: [], + release_date: '2021-01-01', + release_date_precision: 'day', + total_tracks: 10, + type: 'album', + uri: 'spotify:album:album-id', + copyrights: [ + { text: '© 2021 Test Label', type: 'C' }, + { text: '℗ 2021 Test Label', type: 'P' }, + ], external_ids: { upc: '123456789012', ean: '1234567890123', - isrc: 'USUM71702776' + isrc: 'USUM71702776', }, - popularity: 0, - artists: [ - { - id: 'artist1', - name: 'Artist 1', - href: '', - external_urls: { - spotify: 'https://open.spotify.com/artist/1' - }, - type: 'artist', - uri: 'spotify:artist:1' - } - ], - available_markets: [], - disc_number: 1, - episode: false, - explicit: false, external_urls: { - spotify: 'https://open.spotify.com/track/1' + spotify: 'https://open.spotify.com/album/album-id', + }, + genres: ['pop'], + label: 'Test Label', + popularity: 75, + }, + external_ids: { + upc: '123456789012', + ean: '1234567890123', + isrc: 'USUM71702776', + }, + popularity: 0, + artists: [ + { + id: 'artist1', + name: 'Artist 1', + href: '', + external_urls: { + spotify: 'https://open.spotify.com/artist/1', + }, + type: 'artist', + uri: 'spotify:artist:1', }, - href: 'https://api.spotify.com/v1/tracks/1', - is_local: false, - preview_url: null, - track: true, - track_number: 1, - type: 'track', - uri: 'spotify:track:1' - }; + ], + available_markets: [], + disc_number: 1, + episode: false, + explicit: false, + external_urls: { + spotify: 'https://open.spotify.com/track/1', + }, + href: 'https://api.spotify.com/v1/tracks/1', + is_local: false, + preview_url: null, + track: true, + track_number: 1, + type: 'track', + uri: 'spotify:track:1', +} describe('Test TackQue', () => { - const queue = new TrackQueue("testid"); + const queue = new TrackQueue('testid') // queue.setGroupId("testid") // queue.push(sometrack) it('should push to queue', () => { // expect(queue.peek()).toBe(sometrack); - }); + }) it('should pop tracks in the correct order', () => { - queue.push(sometrack); - const anotherTrack = { ...sometrack, id: '2', name: 'Another Track' }; - queue.push(anotherTrack); + queue.push(sometrack) + const anotherTrack = { ...sometrack, id: '2', name: 'Another Track' } + queue.push(anotherTrack) - expect(queue.pop()).toBe(sometrack); - expect(queue.pop()).toBe(anotherTrack); - }); + expect(queue.pop()).toBe(sometrack) + expect(queue.pop()).toBe(anotherTrack) + }) it('should not pop a track if only peeked', () => { - queue.push(sometrack); - expect(queue.peek()).toBe(sometrack); - expect(queue.peek()).toBe(sometrack); // Queue should remain unchanged - expect(queue.pop()).toBe(sometrack); // Now pop should return the track - }); + queue.push(sometrack) + expect(queue.peek()).toBe(sometrack) + expect(queue.peek()).toBe(sometrack) // Queue should remain unchanged + expect(queue.pop()).toBe(sometrack) // Now pop should return the track + }) it('should return undefined when popping an empty queue', () => { - expect(queue.pop()).toBeUndefined(); - }); + expect(queue.pop()).toBeUndefined() + }) it('should return undefined when peeking an empty queue', () => { - expect(queue.peek()).toBeUndefined(); - }); -}); + expect(queue.peek()).toBeUndefined() + }) +}) diff --git a/src/track-queue/track-queue.module.ts b/src/track-queue/track-queue.module.ts index a273d78..fa6dc24 100644 --- a/src/track-queue/track-queue.module.ts +++ b/src/track-queue/track-queue.module.ts @@ -1,7 +1,7 @@ -import { Module } from '@nestjs/common'; -import { TrackQueueService } from './track-queue.service'; +import { Module } from '@nestjs/common' +import { TrackQueueService } from './track-queue.service' @Module({ - providers: [TrackQueueService] + providers: [TrackQueueService], }) export class TrackQueueModule {} diff --git a/src/track-queue/track-queue.service.ts b/src/track-queue/track-queue.service.ts index ddbf69e..cec7971 100644 --- a/src/track-queue/track-queue.service.ts +++ b/src/track-queue/track-queue.service.ts @@ -1,5 +1,5 @@ -import { Injectable } from '@nestjs/common'; -import type { Track } from '@spotify/web-api-ts-sdk'; +import { Injectable } from '@nestjs/common' +import type { Track } from '@spotify/web-api-ts-sdk' export class TrackQueueItem { constructor(public track: Track) {} @@ -7,7 +7,7 @@ export class TrackQueueItem { // @Injectable() export class TrackQueue { - protected tracks: TrackQueueItem[] = []; + protected tracks: TrackQueueItem[] = [] // private groupId: string = ''; constructor(readonly groupId: string) {} @@ -17,40 +17,39 @@ export class TrackQueue { // Pushes a track to the end of the queue and returns the new length public push(track: Track): number { - this.tracks.push(new TrackQueueItem(track)); - return this.tracks.length; + this.tracks.push(new TrackQueueItem(track)) + return this.tracks.length } // Pops a track from the front of the queue public pop(): Track | undefined { - const item = this.tracks.shift(); // Remove the first item - return item ? item.track : undefined; // Return the track or undefined if the queue was empty + const item = this.tracks.shift() // Remove the first item + return item ? item.track : undefined // Return the track or undefined if the queue was empty } // Peeks at the track at the front of the queue without removing it public peek(): Track | undefined { - const item = this.tracks[0]; // Get the first item - return item ? item.track : undefined; // Return the track or undefined if the queue is empty + const item = this.tracks[0] // Get the first item + return item ? item.track : undefined // Return the track or undefined if the queue is empty } // Moves a track to a new position in the queue public setPosition(track: Track, pos: number) { - const currentIndex = this.tracks.findIndex((item) => item.track === track); + const currentIndex = this.tracks.findIndex((item) => item.track === track) if (currentIndex === -1) { - throw new Error('Track not found'); + throw new Error('Track not found') } // Remove the track from its current position - const [removedTrack] = this.tracks.splice(currentIndex, 1); + const [removedTrack] = this.tracks.splice(currentIndex, 1) // Ensure the new position is within bounds - pos = Math.max(0, Math.min(pos, this.tracks.length)); + pos = Math.max(0, Math.min(pos, this.tracks.length)) // Insert the track at the new position - this.tracks.splice(pos, 0, removedTrack); + this.tracks.splice(pos, 0, removedTrack) } } - @Injectable() export class TrackQueueService {} diff --git a/src/utils/filters/http-exception.filter.spec.ts b/src/utils/filters/http-exception.filter.spec.ts index 8f016dd..0548dab 100644 --- a/src/utils/filters/http-exception.filter.spec.ts +++ b/src/utils/filters/http-exception.filter.spec.ts @@ -1,7 +1,7 @@ -import { HttpExceptionFilter } from './http-exception.filter'; +import { HttpExceptionFilter } from './http-exception.filter' describe('HttpExceptionFilter', () => { it('should be defined', () => { - expect(new HttpExceptionFilter()).toBeDefined(); - }); -}); + expect(new HttpExceptionFilter()).toBeDefined() + }) +}) diff --git a/src/utils/index.ts b/src/utils/index.ts index 3be2e20..4171012 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,2 +1,2 @@ export * from './mock' -export * from './filters' \ No newline at end of file +export * from './filters' diff --git a/src/utils/mock/index.ts b/src/utils/mock/index.ts index 5bed7e0..0ca5333 100644 --- a/src/utils/mock/index.ts +++ b/src/utils/mock/index.ts @@ -1 +1 @@ -export * from './mockUser' \ No newline at end of file +export * from './mockUser' diff --git a/test/app.e2e-spec.ts b/test/app.e2e-spec.ts index 50cda62..dcfca8e 100644 --- a/test/app.e2e-spec.ts +++ b/test/app.e2e-spec.ts @@ -1,24 +1,22 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { INestApplication } from '@nestjs/common'; -import * as request from 'supertest'; -import { AppModule } from './../src/app.module'; +import type { TestingModule } from '@nestjs/testing' +import { Test } from '@nestjs/testing' +import type { INestApplication } from '@nestjs/common' +import * as request from 'supertest' +import { AppModule } from './../src/app.module' describe('AppController (e2e)', () => { - let app: INestApplication; + let app: INestApplication beforeEach(async () => { const moduleFixture: TestingModule = await Test.createTestingModule({ imports: [AppModule], - }).compile(); + }).compile() - app = moduleFixture.createNestApplication(); - await app.init(); - }); + app = moduleFixture.createNestApplication() + await app.init() + }) it('/ (GET)', () => { - return request(app.getHttpServer()) - .get('/') - .expect(200) - .expect('Hello World!'); - }); -}); + return request(app.getHttpServer()).get('/').expect(200).expect('Hello World!') + }) +})