├── .gitignore ├── .env.example ├── src ├── @types │ ├── ErrorMessage.d.ts │ ├── User.d.ts │ ├── Review.d.ts │ ├── Book.d.ts │ └── SkoobResponse.d.ts ├── utils │ ├── connect.ts │ ├── convert.ts │ └── amazon.ts ├── controllers │ ├── index.ts │ ├── bookshelf.ts │ ├── users.ts │ ├── books.ts │ └── reviews.ts ├── lib │ └── fetch.ts ├── routes.ts └── routes │ ├── search.ts │ ├── users.ts │ ├── reviews.ts │ └── books.ts ├── tsconfig.json ├── index.ts ├── package.json ├── readme.md ├── swagger.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /.vscode 3 | 4 | .env -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | SKOOB_AUTH={SKOOB_COOKIES} 2 | MONGO_URI={MONGODB_URI} 3 | -------------------------------------------------------------------------------- /src/@types/ErrorMessage.d.ts: -------------------------------------------------------------------------------- 1 | type ErrorMessage = { 2 | error: string; 3 | }; 4 | -------------------------------------------------------------------------------- /src/@types/User.d.ts: -------------------------------------------------------------------------------- 1 | type User = { 2 | id: string; 3 | name: string; 4 | nickname: string; 5 | profilePicture: string; 6 | skoob?: string; 7 | totalPages: number; 8 | following: boolean; 9 | friends: boolean; 10 | }; 11 | -------------------------------------------------------------------------------- /src/utils/connect.ts: -------------------------------------------------------------------------------- 1 | import { MongoClient } from "mongodb"; 2 | 3 | async function connect() { 4 | const client = await MongoClient.connect(process.env.MONGO_URI!); 5 | return client.db("skoob-api"); 6 | } 7 | 8 | export default connect; 9 | -------------------------------------------------------------------------------- /src/@types/Review.d.ts: -------------------------------------------------------------------------------- 1 | type Review = { 2 | book_id: string; 3 | author_id: string; 4 | author: string; 5 | title: string | null; 6 | date: string; 7 | body: string; 8 | rating: number; 9 | profilePicture: string | null; 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "esModuleInterop": true, 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "skipLibCheck": true, 8 | "resolveJsonModule": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/controllers/index.ts: -------------------------------------------------------------------------------- 1 | import { getBooksByTitle, getBookById } from "./books"; 2 | import { getBookshelf } from "./bookshelf"; 3 | import { getUserById } from "./users"; 4 | import { getUserReviews, getBookReviews } from "./reviews"; 5 | 6 | export { getBooksByTitle, getBookById, getUserById, getUserReviews, getBookReviews, getBookshelf }; 7 | -------------------------------------------------------------------------------- /src/lib/fetch.ts: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import dotenv from "dotenv"; 3 | dotenv.config(); 4 | 5 | const api = axios.create({ 6 | baseURL: "https://www.skoob.com.br", 7 | responseEncoding: "binary", 8 | headers: { 9 | Cookie: process.env.SKOOB_AUTH!, 10 | }, 11 | }); 12 | 13 | async function fetch(route: string): Promise { 14 | const { data } = await api.get(route); 15 | return data as T; 16 | } 17 | 18 | export default fetch; 19 | -------------------------------------------------------------------------------- /src/routes.ts: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import userRoutes from "./routes/users"; 3 | import bookRoutes from "./routes/books"; 4 | import searchRoutes from "./routes/search"; 5 | import reviewRoutes from "./routes/reviews"; 6 | 7 | const router = Router(); 8 | 9 | 10 | router.use("/users", userRoutes); 11 | router.use("/books", bookRoutes); 12 | router.use("/search", searchRoutes); 13 | router.use("/reviews", reviewRoutes); 14 | 15 | 16 | export default router; 17 | -------------------------------------------------------------------------------- /src/controllers/bookshelf.ts: -------------------------------------------------------------------------------- 1 | import fetch from "../lib/fetch"; 2 | 3 | import { convertBookshelf } from "../utils/convert"; 4 | 5 | export async function getBookshelf(userId: string): Promise { 6 | const { response, cod_error } = await fetch>(`/v1/bookcase/books/${userId}/shelf_id:0/limit:1000000`); 7 | if (cod_error) return null; 8 | const convertedBookshelf = convertBookshelf(response); 9 | return convertedBookshelf; 10 | } 11 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import cors from "cors"; 3 | 4 | import routes from "./src/routes"; 5 | 6 | import swagger from "swagger-ui-express"; 7 | import swaggerDocument from "./swagger.json"; 8 | 9 | const port = process.env.PORT || 3000; 10 | const app = express(); 11 | 12 | app.use(cors()); 13 | app.use(express.json()); 14 | app.use("/api", routes); 15 | app.use("/docs", swagger.serve, swagger.setup(swaggerDocument)); 16 | 17 | app.listen(port, () => { 18 | console.log(`Server is running on port ${port}`); 19 | }); 20 | -------------------------------------------------------------------------------- /src/routes/search.ts: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import { getBooksByTitle } from "../controllers"; 3 | const router = Router(); 4 | 5 | router.get("/books/:title", async (req, res) => { 6 | const { title } = req.params; 7 | const { limit } = req.query as { limit?: number; tag?: string }; 8 | if (!title.trim()) 9 | return res.status(400).send({ 10 | error: "Título não informado.", 11 | }); 12 | const book = await getBooksByTitle(title, limit); 13 | res.status(200).json(book); 14 | }); 15 | 16 | export default router; 17 | -------------------------------------------------------------------------------- /src/@types/Book.d.ts: -------------------------------------------------------------------------------- 1 | type Book = { 2 | id: number; 3 | book_id: number; 4 | title: string; 5 | subtitle: string; 6 | year: number; 7 | pages: number; 8 | author: string; 9 | synopsis: string; 10 | publisher: string; 11 | cover: string; 12 | skoob_url: string; 13 | isbn_10?: string | null; 14 | isbn_13?: string | null; 15 | amazon_info?: { 16 | amazon_url: string | null; 17 | price: number | null; 18 | ttl: number; 19 | in_stock: boolean; 20 | }; 21 | }; 22 | 23 | // Bookshelf 24 | 25 | interface BookshelfBook { 26 | rating: number; 27 | type: number; 28 | favorite: boolean; 29 | wished: boolean; 30 | review_date: Date | null; 31 | read_date: Date | null; 32 | edition: Book; 33 | } 34 | 35 | type Bookshelf = BookshelfBook[]; 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "skoob-api", 3 | "version": "1.0.0", 4 | "main": "index.ts", 5 | "license": "MIT", 6 | "scripts": { 7 | "start": "ts-node --files index.ts", 8 | "dev": "ts-node-dev --respawn --files index.ts" 9 | }, 10 | "devDependencies": { 11 | "@types/cors": "^2.8.12", 12 | "@types/express": "^4.17.13", 13 | "@types/node": "^18.0.6", 14 | "ts-node": "^10.9.1", 15 | "ts-node-dev": "^2.0.0", 16 | "typescript": "^4.7.4" 17 | }, 18 | "dependencies": { 19 | "@types/swagger-ui-express": "^4.1.3", 20 | "axios": "^0.27.2", 21 | "cheerio": "^1.0.0-rc.12", 22 | "cors": "^2.8.5", 23 | "dotenv": "^16.0.1", 24 | "express": "^4.18.1", 25 | "mongodb": "^4.8.0", 26 | "swagger-ui-express": "^4.6.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/routes/users.ts: -------------------------------------------------------------------------------- 1 | import { Router, Response } from "express"; 2 | import { getUserById, getBookshelf } from "../controllers"; 3 | 4 | const router = Router(); 5 | 6 | router.get("/:id", async (req, res: Response) => { 7 | const { id } = req.params as { id: string }; 8 | if (!id) return res.status(400).send({ error: "Id não informado." }); 9 | try { 10 | const user = await getUserById(id); 11 | if (!user) return res.status(404).send({ error: "Usuário não encontrado." }); 12 | return res.status(200).json(user); 13 | } catch (err) { 14 | console.log(err); 15 | return res.status(500).send({ 16 | error: "Internal server error.", 17 | }); 18 | } 19 | }); 20 | 21 | router.get("/:id/bookshelf", async (req, res: Response) => { 22 | const { id } = req.params as { id: string }; 23 | if (!id) return res.status(400).json({ error: "Id não informado." }); 24 | const bookshelf = await getBookshelf(id); 25 | if (!bookshelf) return res.status(404).json({ error: "Usuário não encontrado." }); 26 | return res.status(200).json(bookshelf); 27 | }); 28 | 29 | export default router; 30 | -------------------------------------------------------------------------------- /src/utils/convert.ts: -------------------------------------------------------------------------------- 1 | /** Recebe um um objeto do tipo SkoobBook e retorna um do tipo Book */ 2 | function convertBook(book: SkoobBook): Book { 3 | const { id, livro_id, titulo, subtitulo, ano, paginas, autor, sinopse, editora, capa_grande, url } = book; 4 | return { 5 | id: id, 6 | book_id: livro_id, 7 | title: titulo, 8 | subtitle: subtitulo, 9 | year: ano, 10 | pages: paginas, 11 | author: autor, 12 | synopsis: sinopse, 13 | publisher: editora, 14 | cover: capa_grande, 15 | skoob_url: url, 16 | }; 17 | } 18 | 19 | /** Recebe um objeto do tipo SkoobBookshelf e retorna um do tipo Bookshelf */ 20 | export const convertBookshelf = (bookshelf: SkoobBookshelf): Bookshelf => { 21 | return bookshelf.map(book => { 22 | const { tipo, ranking, desejado, favorito, paginas, dt_leitura, dt_resenha, edicao } = book; 23 | return { 24 | type: parseInt(tipo), 25 | rating: ranking, 26 | wished: !!desejado, 27 | favorite: !!favorito, 28 | pages: paginas ?? null, 29 | review_date: dt_resenha ? new Date(dt_resenha) : null, 30 | read_date: dt_leitura ? new Date(dt_leitura) : null, 31 | edition: convertBook(edicao), 32 | }; 33 | }); 34 | }; 35 | -------------------------------------------------------------------------------- /src/routes/reviews.ts: -------------------------------------------------------------------------------- 1 | import { Response, Router } from "express"; 2 | import { getBookReviews, getUserReviews } from "../controllers"; 3 | const router = Router(); 4 | 5 | router.get("/users/:id", async (req, res: Response) => { 6 | const { id } = req.params as { id: string }; 7 | if (!id) return res.status(400).send({ error: "Id não informado." }); 8 | try { 9 | const reviews = await getUserReviews(id); 10 | if (!reviews) return res.status(200).json({ error: "Usuário não possui reviews." }); 11 | return res.status(200).json(reviews); 12 | } catch (err) { 13 | console.log(err); 14 | return res.status(500).send({ error: "Internal server error" }); 15 | } 16 | }); 17 | 18 | router.get("/books/:id", async (req, res: Response) => { 19 | const { id } = req.params as { id: string }; 20 | if (!id) return res.status(400).json({ error: "Id não informado." }); 21 | try { 22 | const reviews = await getBookReviews(id); 23 | if (!reviews) return res.status(200).json({ error: "Livro não possui reviews." }); 24 | return res.status(200).json(reviews); 25 | } catch (err) { 26 | console.log(err); 27 | return res.status(500).send({ error: "Internal server error" }); 28 | } 29 | }); 30 | 31 | export default router; 32 | -------------------------------------------------------------------------------- /src/utils/amazon.ts: -------------------------------------------------------------------------------- 1 | import * as cheerio from "cheerio"; 2 | import axios from "axios"; 3 | 4 | /** Recebe url da amazon de um livro e retorna seu preço. Pode retornar null caso não encontre */ 5 | const getBookPrice = async (amazonURL: string | null): Promise => { 6 | if (!amazonURL) return null; 7 | try { 8 | const page = await axios.get(amazonURL, { responseEncoding: "binary" }); 9 | const $ = cheerio.load(page.data.toString("ISO-8859-1")); 10 | const price = $("span#price").text().split("Â")[1].trim().replace(",", "."); 11 | 12 | return parseFloat(price); 13 | } catch (err) { 14 | console.log("Couldn't fetch price of", amazonURL); 15 | return null; 16 | } 17 | }; 18 | 19 | /** Recebe url do skoob e retorna array com ISBN 10 e 13 ou null */ 20 | const getBookISBN = async (skoobURL: string): Promise => { 21 | const page = await axios.get(`https://skoob.com.br${skoobURL}`, { responseEncoding: "binary" }); 22 | const $ = cheerio.load(page.data.toString("ISO-8859-1")); 23 | let isbn: string[] = []; 24 | $("div[class='sidebar-desc']") 25 | .children() 26 | .each((i, el) => { 27 | let text = $(el).text(); 28 | if (text) { 29 | isbn.push(text); 30 | } 31 | }); 32 | if (isbn.length >= 3) { 33 | isbn.pop(); 34 | } 35 | return isbn.length >= 2 ? isbn : null; 36 | }; 37 | 38 | /** Recebe ISBN 13 de um livro e retorna o link da amazon do produto */ 39 | const getAmazonUrl = async (isbn: string) => { 40 | const amazonURL = `https://amazon.com.br/dp/${isbn}`; 41 | return amazonURL; 42 | }; 43 | 44 | export { getBookISBN, getAmazonUrl, getBookPrice }; 45 | -------------------------------------------------------------------------------- /src/controllers/users.ts: -------------------------------------------------------------------------------- 1 | import fetch from "../lib/fetch"; 2 | import connect from "../utils/connect"; 3 | 4 | import { WithId } from "mongodb"; 5 | 6 | // TODO: Aproveitar o request para a estante do usuário para salvá-la no banco de dados 7 | // `getUserPages` retorna o números de páginas lidas por determinado usuário 8 | async function getUserPages(userId: string) { 9 | let totalPages = 0; 10 | let { response } = await fetch>(`/v1/bookcase/books/${userId}/shelf_id:0/limit:1000000`); 11 | 12 | response.forEach((book: any) => { 13 | totalPages += book.paginas_lidas; 14 | }); 15 | return totalPages; 16 | } 17 | 18 | async function getUser(userId: string): Promise { 19 | const userPages = await getUserPages(userId); 20 | const { response, cod_error } = await fetch>(`/v1/user/${userId}`); 21 | if (cod_error) return null; 22 | const { id, nome, apelido, foto_grande, skoob, following, friends } = response; 23 | const user: User = { 24 | id: id.toString(), 25 | name: nome, 26 | nickname: apelido, 27 | skoob, 28 | profilePicture: foto_grande, 29 | following: !!following.status, 30 | friends: !!friends.status, 31 | totalPages: userPages, 32 | }; 33 | return user; 34 | } 35 | 36 | async function getUserById(userId: string): Promise { 37 | const db = await connect(); 38 | const user = await db.collection("users").findOne({ id: userId }); 39 | const { _id, ...userWithoutId } = user as WithId; 40 | if (user) return userWithoutId; 41 | const newUser = await getUser(userId); 42 | if (!newUser) return null; 43 | await db.collection("users").insertOne(newUser); 44 | return newUser; 45 | } 46 | 47 | export { getUserById }; 48 | -------------------------------------------------------------------------------- /src/routes/books.ts: -------------------------------------------------------------------------------- 1 | import { Router, Response } from "express"; 2 | import { getBookById } from "../controllers"; 3 | import { getAmazonUrl, getBookPrice } from "../utils/amazon"; 4 | import { updateBook } from "../controllers/books"; 5 | 6 | const router = Router(); 7 | 8 | router.get("/:id", async (req, res: Response) => { 9 | const { id } = req.params as { id: string }; 10 | 11 | if (!id) return res.status(400).send({ error: "Id não informado." }); 12 | try { 13 | const book = await getBookById(id); 14 | if (!book) return res.status(404).send({ error: "Id inválido." }); 15 | return res.status(200).send(book); 16 | } catch (err) { 17 | console.log(err); 18 | return res.status(500).send({ 19 | error: "Internal server error", 20 | }); 21 | } 22 | }); 23 | 24 | type PriceResponse = { 25 | price: number | null; 26 | amazon_url: string | null; 27 | ttl: number; // timestamp 28 | }; 29 | 30 | router.get("/:id/price", async (req, res: Response) => { 31 | const { id } = req.params; 32 | const { tag } = req.query as { tag: string }; 33 | if (!id) return res.status(400).send({ error: "Id não informado." }); 34 | try { 35 | const book: Book = await getBookById(id); 36 | if (!book) return res.status(404).send({ error: "Id inválido." }); 37 | if (!book.isbn_13) return res.status(404).send({ error: "Não foi possível encontrar o preço do livro." }); 38 | if (book.amazon_info && book.amazon_info.ttl >= Date.now()) return res.status(200).send(book.amazon_info); // cache 39 | 40 | let amazonURL = await getAmazonUrl(book.isbn_13); 41 | const price = await getBookPrice(amazonURL); 42 | const ttl = Date.now() + 1000 * 60 * 60 * 24 * 7; // 7 days 43 | if (amazonURL && tag) amazonURL += `?tag=${tag}`; 44 | updateBook(id, { ...book, amazon_info: { price, amazon_url: amazonURL, ttl, in_stock: price ? true : false } }); 45 | return res.status(200).send({ price, ttl, amazon_url: amazonURL }); 46 | } catch (err) { 47 | console.log(err); 48 | return res.status(500).send({ 49 | error: "Internal server error", 50 | }); 51 | } 52 | }); 53 | 54 | export default router; 55 | -------------------------------------------------------------------------------- /src/@types/SkoobResponse.d.ts: -------------------------------------------------------------------------------- 1 | interface SkoobBook { 2 | id: number; 3 | livro_id: number; 4 | titulo: string; 5 | nome_portugues: string; 6 | subtitulo: string; 7 | subtitulo_portugues: string; 8 | idioma: string; 9 | mes: number; 10 | ano: number; 11 | paginas: number; 12 | edicao: number; 13 | editora: string; 14 | sinopse: string; 15 | edicoes: number; 16 | leitores: number; 17 | autor: string; 18 | capitulo_url: string; 19 | capa_grande: string; 20 | capa_media: string; 21 | capa_pequena: string; 22 | capa_mini: string; 23 | capa_micro: string; 24 | capa_nano: string; 25 | img_url: string; 26 | url: string; 27 | tempo_leitura: { 28 | horas: number; 29 | minutos: number; 30 | segundos: number; 31 | }; 32 | } 33 | 34 | type SkoobUser = { 35 | id: number; 36 | nome: string; 37 | apelido: string; 38 | cidade: string; 39 | estado: string; 40 | uf: string; 41 | foto_mini: string; 42 | foto_pequena: string; 43 | foto_media: string; 44 | foto_grande: string; 45 | foto: string; 46 | foto_placeholder: string; 47 | url: string; 48 | skoob: string; 49 | verified: string; 50 | beta: 1 | 0; 51 | ano: number; 52 | mes: number; 53 | about: string; 54 | random: number; 55 | premium: 1 | 0; 56 | termo: string; 57 | following: { success: 1 | 0; status: 1 | 0; description: string }; 58 | friends: { success: 1 | 0; status: 1 | 0; description: string }; 59 | }; 60 | 61 | interface SkoobResponse { 62 | success: boolean; 63 | response: T; 64 | cod_error?: number; 65 | cod_description?: string; 66 | logged_id?: number; 67 | modified?: string; 68 | } 69 | 70 | type SearchResult = { 71 | results: Book[]; 72 | }; 73 | 74 | interface SkoobBookshelfBook { 75 | id: number; 76 | livro_id: number; 77 | ranking: number; 78 | tipo: string; 79 | favorito: 1 | 0; 80 | desejado: 1 | 0; 81 | troco: 1 | 0; 82 | tenho: 1 | 0; 83 | emprestei: 1 | 0; 84 | paginas: number | ""; 85 | dt_resenha: string | ""; 86 | dt_leitura: string | ""; 87 | meta: number; 88 | spoiler: 1 | 0; 89 | media: number; 90 | update?: 1; 91 | edicao: SkoobBook; 92 | } 93 | 94 | type SkoobBookshelf = SkoobBookshelfBook[]; 95 | -------------------------------------------------------------------------------- /src/controllers/books.ts: -------------------------------------------------------------------------------- 1 | import fetch from "../lib/fetch"; 2 | import connect from "../utils/connect"; 3 | 4 | import { getAmazonUrl, getBookISBN, getBookPrice } from "../utils/amazon"; 5 | 6 | /** Retorna lista de livros que contém o termo passado como parâmetro */ 7 | async function getBooksByTitle(title: string, limit?: number): Promise { 8 | const { results } = await fetch(`/search/v1?q=${title}&limit=${limit || 3}`); 9 | return results; 10 | } 11 | 12 | /** Retorna detalhes do livro com id passado como parâmetro */ 13 | async function getBookById(bookId: string): Promise { 14 | try { 15 | const db = await connect(); 16 | let book = await db.collection("books").findOne({ id: parseInt(bookId) }); 17 | if (book) { 18 | const { _id, ...bookWithoutId } = book!; 19 | return bookWithoutId; 20 | } 21 | console.log("Book not found in database. Fetching from Skoob..."); 22 | const { response } = await fetch>(`/v1/book/${bookId}`); 23 | const fetchedBook = await formatBook(response); 24 | await db.collection("books").insertOne({ ...fetchedBook }); 25 | return fetchedBook; 26 | } catch (err) { 27 | throw err; 28 | } 29 | } 30 | 31 | /** Transforma o livro retornado pelo Skoob em um livro com melhor formatação */ 32 | async function formatBook(book: any): Promise { 33 | const { id, livro_id, titulo, subtitulo, ano, paginas, autor, sinopse, editora, capa_grande, url } = book; 34 | const isbn = await getBookISBN(url); 35 | let price = null; 36 | let amazon_url = null; 37 | let ttl = 0; 38 | if (isbn) amazon_url = await getAmazonUrl(isbn[1]); 39 | if (amazon_url) price = await getBookPrice(amazon_url); 40 | if (price) ttl = Date.now() + 1000 * 60 * 60 * 24 * 7; // 7 dias 41 | 42 | const formattedBook: Book = { 43 | id, 44 | book_id: livro_id, 45 | title: titulo, 46 | subtitle: subtitulo, 47 | year: ano, 48 | pages: paginas, 49 | author: autor, 50 | synopsis: sinopse.trim(), 51 | publisher: editora, 52 | skoob_url: url, 53 | cover: capa_grande, 54 | isbn_10: isbn ? isbn[0] : null, 55 | isbn_13: isbn ? isbn[1] : null, 56 | amazon_info: { 57 | amazon_url, 58 | price, 59 | ttl, 60 | in_stock: price !== null ? true : false, 61 | }, 62 | }; 63 | 64 | return formattedBook; 65 | } 66 | 67 | async function updateBook(book_id: string, newBook: Book) { 68 | try { 69 | const db = await connect(); 70 | const book = await db.collection("books").findOne({ 71 | id: Number(book_id), 72 | }); 73 | if (!book) return; 74 | console.log("Updating book in database..."); 75 | await db 76 | .collection("books") 77 | .updateOne({ id: Number(book_id) }, { $set: newBook }) 78 | .then(() => console.log("Book updated!")); 79 | } catch (err) { 80 | console.log(err); 81 | } 82 | } 83 | 84 | export { getBooksByTitle, getBookById, updateBook }; 85 | -------------------------------------------------------------------------------- /src/controllers/reviews.ts: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import * as cheerio from "cheerio"; 3 | import { WithId } from "mongodb"; 4 | 5 | import connect from "../utils/connect"; 6 | 7 | /** Retorna todas as páginas html de reviews de um usuário específico. */ 8 | async function fetchPages(userId: string): Promise { 9 | const page = await axios.get(`https://www.skoob.com.br/estante/resenhas/${userId}`, { responseEncoding: "binary" }); 10 | const $ = cheerio.load(page.data.toString("ISO-8859-1")); 11 | const pageCount = Math.ceil(parseInt($(".contador").children().first().text().split(" ")[0]) / 5); 12 | if (!pageCount) return [page.data]; 13 | let pages = new Array(pageCount).fill(null); 14 | return await Promise.all( 15 | pages.map(async (page, index) => { 16 | let response = await axios.get(`https://www.skoob.com.br/estante/resenhas/${userId}/mpage:${index + 1}`, { responseEncoding: "binary" }); 17 | return response.data; 18 | }) 19 | ); 20 | } 21 | 22 | /** Retorna todas as reviews de um usuário específico. */ 23 | async function getUserReviews(userId: string): Promise { 24 | const reviews: Review[] = []; 25 | const pages = await fetchPages(userId); 26 | pages.forEach((page: any) => { 27 | const $ = cheerio.load(page, { decodeEntities: false }); 28 | const bookId = $("a.l15").attr("href")?.split("/")[2]; 29 | $("div.curva2-5").each((i, el) => { 30 | const element = $(el); 31 | if (element.children().length === 1) { 32 | const author = element 33 | .first() 34 | .find("strong") 35 | .text() 36 | .split(/(?=[A-Z])/)[0]; 37 | 38 | let title: string[] | string = element.first().find("strong").text(); 39 | const date = element.first().find("span").text().trim(); 40 | const reviewContent = element.first().contents().text(); 41 | if (title) title = title.split(author)[1]; 42 | // o formato de date é "dd/mm/yyyy". Provavelmente seria melhor trocar para uma Date do Javascript. 43 | 44 | const review: Review = { 45 | author_id: userId, 46 | book_id: bookId!, 47 | author: author.trim(), 48 | title: title ?? null, 49 | date, 50 | body: title ? reviewContent.split(date)[1].trim().split(title)[1] : reviewContent.split(date)[1].trim() + "", 51 | rating: parseInt($(element).parent().find("star-rating").attr("rate")!), 52 | profilePicture: $(page).find(".round-4").find("img").attr("src") ?? null, 53 | }; 54 | reviews.push(review); 55 | } 56 | }); 57 | }); 58 | if (reviews.length === 0) return null; 59 | const db = await connect(); 60 | await db.collection("reviews").insertMany({ ...reviews }); 61 | return reviews; 62 | } 63 | /** Retorna todas as reviews (salvas no banco de dados) de um livro */ 64 | async function getBookReviews(bookId: string): Promise { 65 | const db = await connect(); 66 | const reviews = await db.collection("reviews").find({ book_id: bookId }).toArray(); 67 | const withoutIdReviews = reviews.map((review: WithId): Review => { 68 | const { _id, ...withoutId } = review; 69 | return withoutId; 70 | }); 71 | return withoutIdReviews.length === 0 ? null : withoutIdReviews; 72 | } 73 | 74 | export { getUserReviews, getBookReviews }; 75 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Skoob API (WIP 🛠️) 2 | 3 | Esta API foi criada para ajudar a desenvolver aplicações que utilizam informações do [Skoob](https://skoob.com.br). 4 | 5 | A API utiliza uma mistura de informações da API do Skoob e web scraping no site da Amazon para obter mais detalhes sobre o livro. 6 | 7 | ## Tecnologias e ferramentas utilizadas 8 | 9 | [Node.js](https://nodejs.org/) [Express.js](https://expressjs.com/) [Typescript](https://www.typescriptlang.org/) [MongoDB](https://www.mongodb.com/) [CheerioJS](https://github.com/cheeriojs/cheerio) [Axios](https://github.com/axios/axios) 10 | 11 | ## Variáveis de ambiente 12 | 13 | Antes de iniciar o servidor você deve criar um arquivo `.env` na raiz do projeto com as seguintes variáveis de ambiente: 14 | 15 | - `SKOOB_AUTH` - Cookies de autenticação de uma conta Skoob 16 | - Para conseguir os cookies, acesse o [Skoob](https://skoob.com.br), faça login, ou crie uma conta, e depois use `document.cookie` no console para copiar os cookies. 17 | - `MONGO_URI` - URI do banco de dados MongoDB 18 | - Exemplo: `mongodb://localhost:27017/skoob` 19 | 20 | ## Instalação 21 | 22 | Antes de instalar, certifique-se de ter [Node.js](https://nodejs.org/) e [Yarn](https://yarnpkg.com/) instalados. 23 | 24 | Faça o clone do repositório e instale as dependências: 25 | 26 | ```bash 27 | # Clonar repositório 28 | git clone https://github.com/Rapoxo/skoob-api.git 29 | cd skoob-api 30 | 31 | # Instalar dependências 32 | yarn 33 | 34 | # Iniciar servidor 35 | yarn dev 36 | ``` 37 | 38 | ## Rotas da API 39 | 40 | | Rota | Descrição | [Tipo de retorno](https://github.com/Rapoxo/skoob-api/tree/main/src/%40types) | 41 | | :----------------------------------------- | :------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------- | 42 | | `/reviews/users/${userId}` | Retorna todas as resenhas de um usuário. | `Review[]` | 43 | | `/reviews/books/${bookId}` | Retorna todas as resenhas de um livro. | `Review[]` | 44 | | `/books/${bookId}` | Retorna os dados de um livro. | `Book` | 45 | | `/books/${bookId}/price?tag=${amazon_tag}` | Retorna preço e link da Amazon de um livro. A query `amazon_tag` Pode ser usada para adicionar link de afiliado da amazon. | `Price` | 46 | | `/users/${userId}` | Retorna os dados de um usuário. | `User` | 47 | | `/users/${userId}/bookshelf` | Retorna estante de livros de um usuário. | `Bookshelf` | 48 | | `/search/books/${query}?limit=${limit}` | Retorna `limit` livros que contenham o termo `query`. A quantidade padrão é de 3 livros. | `Book[]` | 49 | 50 | ## Todo list 51 | 52 | - [ ] Deploy na Vercel 53 | - [ ] Rota de preços 54 | - [x] Retorna preço e link da Amazon de um livro 55 | - [x] Faz cache dos preços no banco de dados 56 | - [ ] Retorna opções de preço do livro físico e digital (se disponíveis) 57 | - [ ] Rota de resenhas 58 | - [x] Lista todas as resenhas de um usuário 59 | - [ ] Lista todas as resenhas de um livro 60 | 61 | ## Bugs conhecidos 62 | 63 | - Por enquanto nenhum bug foi encontrado. Mas se você encontrar um, por favor, envie um [issue](https://github.com/Rapoxo/skoob-api/issues/new) 64 | -------------------------------------------------------------------------------- /swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.0", 3 | "info": { 4 | "version": "1.0.0", 5 | "title": "Skoob API", 6 | "description": "Descrição da API.", 7 | "contact": { 8 | "name": "Fernando Arruda", 9 | "email": "fernando.arruda.131@ufrn.edu.br" 10 | } 11 | }, 12 | "servers": [ 13 | { 14 | "url": "http://localhost:3000/api", 15 | "description": "Servidor de desenvolvimento." 16 | }, 17 | { 18 | "url": "https://skoob-api.onrender.com/api", 19 | "description": "Servidor de produção." 20 | 21 | } 22 | ], 23 | "paths": { 24 | "/books/{id}": { 25 | "get": { 26 | "description": "Retorna um livro pelo seu ID.", 27 | "parameters": [ 28 | { 29 | "name": "id", 30 | "in": "path", 31 | "description": "O ID do livro.", 32 | "required": true, 33 | "schema": { 34 | "type": "string" 35 | } 36 | } 37 | ], 38 | "responses": { 39 | "200": { 40 | "description": "OK", 41 | "content": { 42 | "application/json": { 43 | "schema": { 44 | "$ref": "#/components/schemas/Book" 45 | } 46 | } 47 | } 48 | }, 49 | "400": { 50 | "description": "Requisição inválida.", 51 | "content": { 52 | "application/json": { 53 | "schema": { 54 | "$ref": "#/components/schemas/ErrorMessage" 55 | } 56 | } 57 | } 58 | }, 59 | "404": { 60 | "description": "Não encontrado.", 61 | "content": { 62 | "application/json": { 63 | "schema": { 64 | "$ref": "#/components/schemas/ErrorMessage" 65 | } 66 | } 67 | } 68 | }, 69 | "500": { 70 | "description": "Erro interno do servidor.", 71 | "content": { 72 | "application/json": { 73 | "schema": { 74 | "$ref": "#/components/schemas/ErrorMessage" 75 | } 76 | } 77 | } 78 | } 79 | } 80 | } 81 | }, 82 | "/users/{id}": { 83 | "get": { 84 | "description": "Retorna um usuário pelo ID.", 85 | "parameters": [ 86 | { 87 | "name": "id", 88 | "in": "path", 89 | "description": "ID do usuário.", 90 | "required": true, 91 | "schema": { 92 | "type": "string" 93 | } 94 | } 95 | ], 96 | "responses": { 97 | "200": { 98 | "description": "Usuário encontrado.", 99 | "content": { 100 | "application/json": { 101 | "schema": { 102 | "$ref": "#/components/schemas/User" 103 | } 104 | } 105 | } 106 | }, 107 | "400": { 108 | "description": "Parâmetros inválidos.", 109 | "content": { 110 | "application/json": { 111 | "schema": { 112 | "$ref": "#/components/schemas/ErrorMessage" 113 | } 114 | } 115 | } 116 | }, 117 | "404": { 118 | "description": "Usuário não encontrado.", 119 | "content": { 120 | "application/json": { 121 | "schema": { 122 | "$ref": "#/components/schemas/ErrorMessage" 123 | } 124 | } 125 | } 126 | }, 127 | "500": { 128 | "description": "Erro interno do servidor.", 129 | "content": { 130 | "application/json": { 131 | "schema": { 132 | "$ref": "#/components/schemas/ErrorMessage" 133 | } 134 | } 135 | } 136 | } 137 | } 138 | } 139 | }, 140 | "/users/{id}/bookshelf": { 141 | "get": { 142 | "description": "Retorna a estante de livros de um usuário pelo ID.", 143 | "parameters": [ 144 | { 145 | "name": "id", 146 | "in": "path", 147 | "description": "ID do usuário.", 148 | "required": true, 149 | "schema": { 150 | "type": "string" 151 | } 152 | } 153 | ], 154 | "responses": { 155 | "200": { 156 | "description": "Estante de livros encontrada.", 157 | "content": { 158 | "application/json": { 159 | "schema": { 160 | "$ref": "#/components/schemas/Bookshelf" 161 | } 162 | } 163 | } 164 | }, 165 | "400": { 166 | "description": "Parâmetros inválidos.", 167 | "content": { 168 | "application/json": { 169 | "schema": { 170 | "$ref": "#/components/schemas/ErrorMessage" 171 | } 172 | } 173 | } 174 | }, 175 | "404": { 176 | "description": "Usuário não encontrado.", 177 | "content": { 178 | "application/json": { 179 | "schema": { 180 | "$ref": "#/components/schemas/ErrorMessage" 181 | } 182 | } 183 | } 184 | } 185 | } 186 | } 187 | }, 188 | "/search/books/{title}": { 189 | "get": { 190 | "description": "Retorna uma lista de livros que contém o título informado.", 191 | "parameters": [ 192 | { 193 | "name": "title", 194 | "in": "path", 195 | "description": "Título do livro.", 196 | "required": true, 197 | "schema": { 198 | "type": "string" 199 | } 200 | } 201 | ], 202 | "responses": { 203 | "200": { 204 | "description": "OK", 205 | "content": { 206 | "application/json": { 207 | "schema": { 208 | "type": "array", 209 | "items": { 210 | "$ref": "#/components/schemas/Book" 211 | } 212 | } 213 | } 214 | } 215 | }, 216 | "400": { 217 | "description": "Requisição inválida.", 218 | "content": { 219 | "application/json": { 220 | "schema": { 221 | "$ref": "#/components/schemas/ErrorMessage" 222 | } 223 | } 224 | } 225 | } 226 | } 227 | } 228 | } 229 | }, 230 | "components": { 231 | "schemas": { 232 | "User": { 233 | "type": "object", 234 | "properties": { 235 | "id": { 236 | "type": "string" 237 | }, 238 | "name": { 239 | "type": "string" 240 | }, 241 | "nickname": { 242 | "type": "string" 243 | }, 244 | "profilePicture": { 245 | "type": "string" 246 | }, 247 | "skoob": { 248 | "type": "string" 249 | }, 250 | "totalPages": { 251 | "type": "integer", 252 | "format": "int32" 253 | }, 254 | "following": { 255 | "type": "boolean" 256 | }, 257 | "friends": { 258 | "type": "boolean" 259 | } 260 | }, 261 | "required": ["id", "name", "nickname", "profilePicture", "totalPages", "following", "friends"] 262 | }, 263 | "Book": { 264 | "type": "object", 265 | "properties": { 266 | "id": { 267 | "type": "integer" 268 | }, 269 | "book_id": { 270 | "type": "integer" 271 | }, 272 | "title": { 273 | "type": "string" 274 | }, 275 | "subtitle": { 276 | "type": "string" 277 | }, 278 | "year": { 279 | "type": "integer" 280 | }, 281 | "pages": { 282 | "type": "integer" 283 | }, 284 | "author": { 285 | "type": "string" 286 | }, 287 | "synopsis": { 288 | "type": "string" 289 | }, 290 | "publisher": { 291 | "type": "string" 292 | }, 293 | "cover": { 294 | "type": "string" 295 | }, 296 | "skoob_url": { 297 | "type": "string" 298 | }, 299 | "isbn_10": { 300 | "type": "string" 301 | }, 302 | "isbn_13": { 303 | "type": "string" 304 | }, 305 | "amazon_info": { 306 | "type": "object", 307 | "properties": { 308 | "amazon_url": { 309 | "type": "string" 310 | }, 311 | "price": { 312 | "oneOf": [ 313 | { 314 | "type": "number" 315 | }, 316 | { 317 | "type": "string" 318 | } 319 | ] 320 | }, 321 | "ttl": { 322 | "type": "integer" 323 | }, 324 | "in_stock": { 325 | "type": "boolean" 326 | } 327 | } 328 | } 329 | } 330 | }, 331 | "BookshelfBook": { 332 | "type": "object", 333 | "properties": { 334 | "rating": { 335 | "type": "number" 336 | }, 337 | "type": { 338 | "type": "number" 339 | }, 340 | "favorite": { 341 | "type": "boolean" 342 | }, 343 | "wished": { 344 | "type": "boolean" 345 | }, 346 | "review_date": { 347 | "type": "string", 348 | "format": "date-time" 349 | }, 350 | "read_date": { 351 | "type": "string", 352 | "format": "date-time" 353 | }, 354 | "edition": { 355 | "$ref": "#/components/schemas/Book" 356 | } 357 | } 358 | }, 359 | "Bookshelf": { 360 | "type": "array", 361 | "items": { 362 | "$ref": "#/components/schemas/BookshelfBook" 363 | } 364 | }, 365 | "ErrorMessage": { 366 | "type": "string" 367 | } 368 | } 369 | } 370 | } 371 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@cspotcode/source-map-support@^0.8.0": 6 | version "0.8.1" 7 | resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" 8 | integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== 9 | dependencies: 10 | "@jridgewell/trace-mapping" "0.3.9" 11 | 12 | "@jridgewell/resolve-uri@^3.0.3": 13 | version "3.1.0" 14 | resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" 15 | integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== 16 | 17 | "@jridgewell/sourcemap-codec@^1.4.10": 18 | version "1.4.14" 19 | resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" 20 | integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== 21 | 22 | "@jridgewell/trace-mapping@0.3.9": 23 | version "0.3.9" 24 | resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" 25 | integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== 26 | dependencies: 27 | "@jridgewell/resolve-uri" "^3.0.3" 28 | "@jridgewell/sourcemap-codec" "^1.4.10" 29 | 30 | "@tsconfig/node10@^1.0.7": 31 | version "1.0.9" 32 | resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" 33 | integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== 34 | 35 | "@tsconfig/node12@^1.0.7": 36 | version "1.0.11" 37 | resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" 38 | integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== 39 | 40 | "@tsconfig/node14@^1.0.0": 41 | version "1.0.3" 42 | resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" 43 | integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== 44 | 45 | "@tsconfig/node16@^1.0.2": 46 | version "1.0.3" 47 | resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" 48 | integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== 49 | 50 | "@types/body-parser@*": 51 | version "1.19.2" 52 | resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" 53 | integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== 54 | dependencies: 55 | "@types/connect" "*" 56 | "@types/node" "*" 57 | 58 | "@types/connect@*": 59 | version "3.4.35" 60 | resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" 61 | integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== 62 | dependencies: 63 | "@types/node" "*" 64 | 65 | "@types/cors@^2.8.12": 66 | version "2.8.12" 67 | resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080" 68 | integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw== 69 | 70 | "@types/express-serve-static-core@^4.17.18": 71 | version "4.17.29" 72 | resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.29.tgz#2a1795ea8e9e9c91b4a4bbe475034b20c1ec711c" 73 | integrity sha512-uMd++6dMKS32EOuw1Uli3e3BPgdLIXmezcfHv7N4c1s3gkhikBplORPpMq3fuWkxncZN1reb16d5n8yhQ80x7Q== 74 | dependencies: 75 | "@types/node" "*" 76 | "@types/qs" "*" 77 | "@types/range-parser" "*" 78 | 79 | "@types/express-serve-static-core@^4.17.33": 80 | version "4.17.34" 81 | resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.34.tgz#c119e85b75215178bc127de588e93100698ab4cc" 82 | integrity sha512-fvr49XlCGoUj2Pp730AItckfjat4WNb0lb3kfrLWffd+RLeoGAMsq7UOy04PAPtoL01uKwcp6u8nhzpgpDYr3w== 83 | dependencies: 84 | "@types/node" "*" 85 | "@types/qs" "*" 86 | "@types/range-parser" "*" 87 | "@types/send" "*" 88 | 89 | "@types/express@*": 90 | version "4.17.17" 91 | resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.17.tgz#01d5437f6ef9cfa8668e616e13c2f2ac9a491ae4" 92 | integrity sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q== 93 | dependencies: 94 | "@types/body-parser" "*" 95 | "@types/express-serve-static-core" "^4.17.33" 96 | "@types/qs" "*" 97 | "@types/serve-static" "*" 98 | 99 | "@types/express@^4.17.13": 100 | version "4.17.13" 101 | resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" 102 | integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== 103 | dependencies: 104 | "@types/body-parser" "*" 105 | "@types/express-serve-static-core" "^4.17.18" 106 | "@types/qs" "*" 107 | "@types/serve-static" "*" 108 | 109 | "@types/mime@^1": 110 | version "1.3.2" 111 | resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" 112 | integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== 113 | 114 | "@types/node@*", "@types/node@^18.0.6": 115 | version "18.0.6" 116 | resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.6.tgz#0ba49ac517ad69abe7a1508bc9b3a5483df9d5d7" 117 | integrity sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw== 118 | 119 | "@types/qs@*": 120 | version "6.9.7" 121 | resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" 122 | integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== 123 | 124 | "@types/range-parser@*": 125 | version "1.2.4" 126 | resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" 127 | integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== 128 | 129 | "@types/send@*": 130 | version "0.17.1" 131 | resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.1.tgz#ed4932b8a2a805f1fe362a70f4e62d0ac994e301" 132 | integrity sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q== 133 | dependencies: 134 | "@types/mime" "^1" 135 | "@types/node" "*" 136 | 137 | "@types/serve-static@*": 138 | version "1.13.10" 139 | resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" 140 | integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ== 141 | dependencies: 142 | "@types/mime" "^1" 143 | "@types/node" "*" 144 | 145 | "@types/strip-bom@^3.0.0": 146 | version "3.0.0" 147 | resolved "https://registry.yarnpkg.com/@types/strip-bom/-/strip-bom-3.0.0.tgz#14a8ec3956c2e81edb7520790aecf21c290aebd2" 148 | integrity sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ== 149 | 150 | "@types/strip-json-comments@0.0.30": 151 | version "0.0.30" 152 | resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1" 153 | integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ== 154 | 155 | "@types/swagger-ui-express@^4.1.3": 156 | version "4.1.3" 157 | resolved "https://registry.yarnpkg.com/@types/swagger-ui-express/-/swagger-ui-express-4.1.3.tgz#7adbbbf5343b45869debef1e9ff39c9ba73e380f" 158 | integrity sha512-jqCjGU/tGEaqIplPy3WyQg+Nrp6y80DCFnDEAvVKWkJyv0VivSSDCChkppHRHAablvInZe6pijDFMnavtN0vqA== 159 | dependencies: 160 | "@types/express" "*" 161 | "@types/serve-static" "*" 162 | 163 | "@types/webidl-conversions@*": 164 | version "6.1.1" 165 | resolved "https://registry.yarnpkg.com/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz#e33bc8ea812a01f63f90481c666334844b12a09e" 166 | integrity sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q== 167 | 168 | "@types/whatwg-url@^8.2.1": 169 | version "8.2.2" 170 | resolved "https://registry.yarnpkg.com/@types/whatwg-url/-/whatwg-url-8.2.2.tgz#749d5b3873e845897ada99be4448041d4cc39e63" 171 | integrity sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA== 172 | dependencies: 173 | "@types/node" "*" 174 | "@types/webidl-conversions" "*" 175 | 176 | accepts@~1.3.8: 177 | version "1.3.8" 178 | resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" 179 | integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== 180 | dependencies: 181 | mime-types "~2.1.34" 182 | negotiator "0.6.3" 183 | 184 | acorn-walk@^8.1.1: 185 | version "8.2.0" 186 | resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" 187 | integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== 188 | 189 | acorn@^8.4.1: 190 | version "8.8.0" 191 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" 192 | integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== 193 | 194 | anymatch@~3.1.2: 195 | version "3.1.2" 196 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" 197 | integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== 198 | dependencies: 199 | normalize-path "^3.0.0" 200 | picomatch "^2.0.4" 201 | 202 | arg@^4.1.0: 203 | version "4.1.3" 204 | resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" 205 | integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== 206 | 207 | array-flatten@1.1.1: 208 | version "1.1.1" 209 | resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" 210 | integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== 211 | 212 | asynckit@^0.4.0: 213 | version "0.4.0" 214 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 215 | integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== 216 | 217 | axios@^0.27.2: 218 | version "0.27.2" 219 | resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" 220 | integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ== 221 | dependencies: 222 | follow-redirects "^1.14.9" 223 | form-data "^4.0.0" 224 | 225 | balanced-match@^1.0.0: 226 | version "1.0.2" 227 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 228 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 229 | 230 | base64-js@^1.3.1: 231 | version "1.5.1" 232 | resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" 233 | integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== 234 | 235 | binary-extensions@^2.0.0: 236 | version "2.2.0" 237 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" 238 | integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== 239 | 240 | body-parser@1.20.0: 241 | version "1.20.0" 242 | resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5" 243 | integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg== 244 | dependencies: 245 | bytes "3.1.2" 246 | content-type "~1.0.4" 247 | debug "2.6.9" 248 | depd "2.0.0" 249 | destroy "1.2.0" 250 | http-errors "2.0.0" 251 | iconv-lite "0.4.24" 252 | on-finished "2.4.1" 253 | qs "6.10.3" 254 | raw-body "2.5.1" 255 | type-is "~1.6.18" 256 | unpipe "1.0.0" 257 | 258 | boolbase@^1.0.0: 259 | version "1.0.0" 260 | resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" 261 | integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== 262 | 263 | brace-expansion@^1.1.7: 264 | version "1.1.11" 265 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 266 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 267 | dependencies: 268 | balanced-match "^1.0.0" 269 | concat-map "0.0.1" 270 | 271 | braces@~3.0.2: 272 | version "3.0.2" 273 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 274 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 275 | dependencies: 276 | fill-range "^7.0.1" 277 | 278 | bson@^4.6.5: 279 | version "4.6.5" 280 | resolved "https://registry.yarnpkg.com/bson/-/bson-4.6.5.tgz#1a410148c20eef4e40d484878a037a7036e840fb" 281 | integrity sha512-uqrgcjyOaZsHfz7ea8zLRCLe1u+QGUSzMZmvXqO24CDW7DWoW1qiN9folSwa7hSneTSgM2ykDIzF5kcQQ8cwNw== 282 | dependencies: 283 | buffer "^5.6.0" 284 | 285 | buffer-from@^1.0.0: 286 | version "1.1.2" 287 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" 288 | integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== 289 | 290 | buffer@^5.6.0: 291 | version "5.7.1" 292 | resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" 293 | integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== 294 | dependencies: 295 | base64-js "^1.3.1" 296 | ieee754 "^1.1.13" 297 | 298 | bytes@3.1.2: 299 | version "3.1.2" 300 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" 301 | integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== 302 | 303 | call-bind@^1.0.0: 304 | version "1.0.2" 305 | resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" 306 | integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== 307 | dependencies: 308 | function-bind "^1.1.1" 309 | get-intrinsic "^1.0.2" 310 | 311 | cheerio-select@^2.1.0: 312 | version "2.1.0" 313 | resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" 314 | integrity sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g== 315 | dependencies: 316 | boolbase "^1.0.0" 317 | css-select "^5.1.0" 318 | css-what "^6.1.0" 319 | domelementtype "^2.3.0" 320 | domhandler "^5.0.3" 321 | domutils "^3.0.1" 322 | 323 | cheerio@^1.0.0-rc.12: 324 | version "1.0.0-rc.12" 325 | resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.12.tgz#788bf7466506b1c6bf5fae51d24a2c4d62e47683" 326 | integrity sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q== 327 | dependencies: 328 | cheerio-select "^2.1.0" 329 | dom-serializer "^2.0.0" 330 | domhandler "^5.0.3" 331 | domutils "^3.0.1" 332 | htmlparser2 "^8.0.1" 333 | parse5 "^7.0.0" 334 | parse5-htmlparser2-tree-adapter "^7.0.0" 335 | 336 | chokidar@^3.5.1: 337 | version "3.5.3" 338 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" 339 | integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== 340 | dependencies: 341 | anymatch "~3.1.2" 342 | braces "~3.0.2" 343 | glob-parent "~5.1.2" 344 | is-binary-path "~2.1.0" 345 | is-glob "~4.0.1" 346 | normalize-path "~3.0.0" 347 | readdirp "~3.6.0" 348 | optionalDependencies: 349 | fsevents "~2.3.2" 350 | 351 | combined-stream@^1.0.8: 352 | version "1.0.8" 353 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" 354 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== 355 | dependencies: 356 | delayed-stream "~1.0.0" 357 | 358 | concat-map@0.0.1: 359 | version "0.0.1" 360 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 361 | integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== 362 | 363 | content-disposition@0.5.4: 364 | version "0.5.4" 365 | resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" 366 | integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== 367 | dependencies: 368 | safe-buffer "5.2.1" 369 | 370 | content-type@~1.0.4: 371 | version "1.0.4" 372 | resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" 373 | integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== 374 | 375 | cookie-signature@1.0.6: 376 | version "1.0.6" 377 | resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" 378 | integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== 379 | 380 | cookie@0.5.0: 381 | version "0.5.0" 382 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" 383 | integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== 384 | 385 | cors@^2.8.5: 386 | version "2.8.5" 387 | resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" 388 | integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== 389 | dependencies: 390 | object-assign "^4" 391 | vary "^1" 392 | 393 | create-require@^1.1.0: 394 | version "1.1.1" 395 | resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" 396 | integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== 397 | 398 | css-select@^5.1.0: 399 | version "5.1.0" 400 | resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" 401 | integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== 402 | dependencies: 403 | boolbase "^1.0.0" 404 | css-what "^6.1.0" 405 | domhandler "^5.0.2" 406 | domutils "^3.0.1" 407 | nth-check "^2.0.1" 408 | 409 | css-what@^6.1.0: 410 | version "6.1.0" 411 | resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" 412 | integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== 413 | 414 | debug@2.6.9: 415 | version "2.6.9" 416 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 417 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 418 | dependencies: 419 | ms "2.0.0" 420 | 421 | delayed-stream@~1.0.0: 422 | version "1.0.0" 423 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 424 | integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== 425 | 426 | denque@^2.0.1: 427 | version "2.1.0" 428 | resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" 429 | integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw== 430 | 431 | depd@2.0.0: 432 | version "2.0.0" 433 | resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" 434 | integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== 435 | 436 | destroy@1.2.0: 437 | version "1.2.0" 438 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" 439 | integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== 440 | 441 | diff@^4.0.1: 442 | version "4.0.2" 443 | resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" 444 | integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== 445 | 446 | dom-serializer@^2.0.0: 447 | version "2.0.0" 448 | resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" 449 | integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== 450 | dependencies: 451 | domelementtype "^2.3.0" 452 | domhandler "^5.0.2" 453 | entities "^4.2.0" 454 | 455 | domelementtype@^2.3.0: 456 | version "2.3.0" 457 | resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" 458 | integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== 459 | 460 | domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3: 461 | version "5.0.3" 462 | resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" 463 | integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== 464 | dependencies: 465 | domelementtype "^2.3.0" 466 | 467 | domutils@^3.0.1: 468 | version "3.0.1" 469 | resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.0.1.tgz#696b3875238338cb186b6c0612bd4901c89a4f1c" 470 | integrity sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q== 471 | dependencies: 472 | dom-serializer "^2.0.0" 473 | domelementtype "^2.3.0" 474 | domhandler "^5.0.1" 475 | 476 | dotenv@^16.0.1: 477 | version "16.0.1" 478 | resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.1.tgz#8f8f9d94876c35dac989876a5d3a82a267fdce1d" 479 | integrity sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ== 480 | 481 | dynamic-dedupe@^0.3.0: 482 | version "0.3.0" 483 | resolved "https://registry.yarnpkg.com/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz#06e44c223f5e4e94d78ef9db23a6515ce2f962a1" 484 | integrity sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ== 485 | dependencies: 486 | xtend "^4.0.0" 487 | 488 | ee-first@1.1.1: 489 | version "1.1.1" 490 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 491 | integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== 492 | 493 | encodeurl@~1.0.2: 494 | version "1.0.2" 495 | resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" 496 | integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== 497 | 498 | entities@^4.2.0, entities@^4.3.0: 499 | version "4.3.1" 500 | resolved "https://registry.yarnpkg.com/entities/-/entities-4.3.1.tgz#c34062a94c865c322f9d67b4384e4169bcede6a4" 501 | integrity sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg== 502 | 503 | escape-html@~1.0.3: 504 | version "1.0.3" 505 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 506 | integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== 507 | 508 | etag@~1.8.1: 509 | version "1.8.1" 510 | resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" 511 | integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== 512 | 513 | express@^4.18.1: 514 | version "4.18.1" 515 | resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf" 516 | integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q== 517 | dependencies: 518 | accepts "~1.3.8" 519 | array-flatten "1.1.1" 520 | body-parser "1.20.0" 521 | content-disposition "0.5.4" 522 | content-type "~1.0.4" 523 | cookie "0.5.0" 524 | cookie-signature "1.0.6" 525 | debug "2.6.9" 526 | depd "2.0.0" 527 | encodeurl "~1.0.2" 528 | escape-html "~1.0.3" 529 | etag "~1.8.1" 530 | finalhandler "1.2.0" 531 | fresh "0.5.2" 532 | http-errors "2.0.0" 533 | merge-descriptors "1.0.1" 534 | methods "~1.1.2" 535 | on-finished "2.4.1" 536 | parseurl "~1.3.3" 537 | path-to-regexp "0.1.7" 538 | proxy-addr "~2.0.7" 539 | qs "6.10.3" 540 | range-parser "~1.2.1" 541 | safe-buffer "5.2.1" 542 | send "0.18.0" 543 | serve-static "1.15.0" 544 | setprototypeof "1.2.0" 545 | statuses "2.0.1" 546 | type-is "~1.6.18" 547 | utils-merge "1.0.1" 548 | vary "~1.1.2" 549 | 550 | fill-range@^7.0.1: 551 | version "7.0.1" 552 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 553 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 554 | dependencies: 555 | to-regex-range "^5.0.1" 556 | 557 | finalhandler@1.2.0: 558 | version "1.2.0" 559 | resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" 560 | integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== 561 | dependencies: 562 | debug "2.6.9" 563 | encodeurl "~1.0.2" 564 | escape-html "~1.0.3" 565 | on-finished "2.4.1" 566 | parseurl "~1.3.3" 567 | statuses "2.0.1" 568 | unpipe "~1.0.0" 569 | 570 | follow-redirects@^1.14.9: 571 | version "1.15.1" 572 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" 573 | integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== 574 | 575 | form-data@^4.0.0: 576 | version "4.0.0" 577 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" 578 | integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== 579 | dependencies: 580 | asynckit "^0.4.0" 581 | combined-stream "^1.0.8" 582 | mime-types "^2.1.12" 583 | 584 | forwarded@0.2.0: 585 | version "0.2.0" 586 | resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" 587 | integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== 588 | 589 | fresh@0.5.2: 590 | version "0.5.2" 591 | resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" 592 | integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== 593 | 594 | fs.realpath@^1.0.0: 595 | version "1.0.0" 596 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 597 | integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== 598 | 599 | fsevents@~2.3.2: 600 | version "2.3.2" 601 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" 602 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== 603 | 604 | function-bind@^1.1.1: 605 | version "1.1.1" 606 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 607 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 608 | 609 | get-intrinsic@^1.0.2: 610 | version "1.1.2" 611 | resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598" 612 | integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA== 613 | dependencies: 614 | function-bind "^1.1.1" 615 | has "^1.0.3" 616 | has-symbols "^1.0.3" 617 | 618 | glob-parent@~5.1.2: 619 | version "5.1.2" 620 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 621 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 622 | dependencies: 623 | is-glob "^4.0.1" 624 | 625 | glob@^7.1.3: 626 | version "7.2.3" 627 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" 628 | integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== 629 | dependencies: 630 | fs.realpath "^1.0.0" 631 | inflight "^1.0.4" 632 | inherits "2" 633 | minimatch "^3.1.1" 634 | once "^1.3.0" 635 | path-is-absolute "^1.0.0" 636 | 637 | has-symbols@^1.0.3: 638 | version "1.0.3" 639 | resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" 640 | integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== 641 | 642 | has@^1.0.3: 643 | version "1.0.3" 644 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 645 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 646 | dependencies: 647 | function-bind "^1.1.1" 648 | 649 | htmlparser2@^8.0.1: 650 | version "8.0.1" 651 | resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.1.tgz#abaa985474fcefe269bc761a779b544d7196d010" 652 | integrity sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA== 653 | dependencies: 654 | domelementtype "^2.3.0" 655 | domhandler "^5.0.2" 656 | domutils "^3.0.1" 657 | entities "^4.3.0" 658 | 659 | http-errors@2.0.0: 660 | version "2.0.0" 661 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" 662 | integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== 663 | dependencies: 664 | depd "2.0.0" 665 | inherits "2.0.4" 666 | setprototypeof "1.2.0" 667 | statuses "2.0.1" 668 | toidentifier "1.0.1" 669 | 670 | iconv-lite@0.4.24: 671 | version "0.4.24" 672 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 673 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 674 | dependencies: 675 | safer-buffer ">= 2.1.2 < 3" 676 | 677 | ieee754@^1.1.13: 678 | version "1.2.1" 679 | resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" 680 | integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== 681 | 682 | inflight@^1.0.4: 683 | version "1.0.6" 684 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 685 | integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== 686 | dependencies: 687 | once "^1.3.0" 688 | wrappy "1" 689 | 690 | inherits@2, inherits@2.0.4: 691 | version "2.0.4" 692 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 693 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 694 | 695 | ip@^2.0.0: 696 | version "2.0.0" 697 | resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" 698 | integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== 699 | 700 | ipaddr.js@1.9.1: 701 | version "1.9.1" 702 | resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" 703 | integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== 704 | 705 | is-binary-path@~2.1.0: 706 | version "2.1.0" 707 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 708 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 709 | dependencies: 710 | binary-extensions "^2.0.0" 711 | 712 | is-core-module@^2.9.0: 713 | version "2.9.0" 714 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" 715 | integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== 716 | dependencies: 717 | has "^1.0.3" 718 | 719 | is-extglob@^2.1.1: 720 | version "2.1.1" 721 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 722 | integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 723 | 724 | is-glob@^4.0.1, is-glob@~4.0.1: 725 | version "4.0.3" 726 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 727 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 728 | dependencies: 729 | is-extglob "^2.1.1" 730 | 731 | is-number@^7.0.0: 732 | version "7.0.0" 733 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 734 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 735 | 736 | make-error@^1.1.1: 737 | version "1.3.6" 738 | resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" 739 | integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== 740 | 741 | media-typer@0.3.0: 742 | version "0.3.0" 743 | resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" 744 | integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== 745 | 746 | memory-pager@^1.0.2: 747 | version "1.5.0" 748 | resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5" 749 | integrity sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg== 750 | 751 | merge-descriptors@1.0.1: 752 | version "1.0.1" 753 | resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" 754 | integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== 755 | 756 | methods@~1.1.2: 757 | version "1.1.2" 758 | resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" 759 | integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== 760 | 761 | mime-db@1.52.0: 762 | version "1.52.0" 763 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" 764 | integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== 765 | 766 | mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: 767 | version "2.1.35" 768 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" 769 | integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== 770 | dependencies: 771 | mime-db "1.52.0" 772 | 773 | mime@1.6.0: 774 | version "1.6.0" 775 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" 776 | integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== 777 | 778 | minimatch@^3.1.1: 779 | version "3.1.2" 780 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" 781 | integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== 782 | dependencies: 783 | brace-expansion "^1.1.7" 784 | 785 | minimist@^1.2.6: 786 | version "1.2.6" 787 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" 788 | integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== 789 | 790 | mkdirp@^1.0.4: 791 | version "1.0.4" 792 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" 793 | integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== 794 | 795 | mongodb-connection-string-url@^2.5.2: 796 | version "2.5.3" 797 | resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.3.tgz#c0c572b71570e58be2bd52b33dffd1330cfb6990" 798 | integrity sha512-f+/WsED+xF4B74l3k9V/XkTVj5/fxFH2o5ToKXd8Iyi5UhM+sO9u0Ape17Mvl/GkZaFtM0HQnzAG5OTmhKw+tQ== 799 | dependencies: 800 | "@types/whatwg-url" "^8.2.1" 801 | whatwg-url "^11.0.0" 802 | 803 | mongodb@^4.8.0: 804 | version "4.8.0" 805 | resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-4.8.0.tgz#8287c85b43781c042c272d00ff3a143b68698671" 806 | integrity sha512-a0eVzm1e1kxwnzJV1wZXIS54KegM2y6wXTXOGTSAxr/E2YOUkl/zGBHNSI4z+6z+YQtVdzDqy1nJ4n5MxYJRnQ== 807 | dependencies: 808 | bson "^4.6.5" 809 | denque "^2.0.1" 810 | mongodb-connection-string-url "^2.5.2" 811 | socks "^2.6.2" 812 | optionalDependencies: 813 | saslprep "^1.0.3" 814 | 815 | ms@2.0.0: 816 | version "2.0.0" 817 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 818 | integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== 819 | 820 | ms@2.1.3: 821 | version "2.1.3" 822 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 823 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 824 | 825 | negotiator@0.6.3: 826 | version "0.6.3" 827 | resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" 828 | integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== 829 | 830 | normalize-path@^3.0.0, normalize-path@~3.0.0: 831 | version "3.0.0" 832 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 833 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 834 | 835 | nth-check@^2.0.1: 836 | version "2.1.1" 837 | resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" 838 | integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== 839 | dependencies: 840 | boolbase "^1.0.0" 841 | 842 | object-assign@^4: 843 | version "4.1.1" 844 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 845 | integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== 846 | 847 | object-inspect@^1.9.0: 848 | version "1.12.2" 849 | resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" 850 | integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== 851 | 852 | on-finished@2.4.1: 853 | version "2.4.1" 854 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" 855 | integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== 856 | dependencies: 857 | ee-first "1.1.1" 858 | 859 | once@^1.3.0: 860 | version "1.4.0" 861 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 862 | integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== 863 | dependencies: 864 | wrappy "1" 865 | 866 | parse5-htmlparser2-tree-adapter@^7.0.0: 867 | version "7.0.0" 868 | resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1" 869 | integrity sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g== 870 | dependencies: 871 | domhandler "^5.0.2" 872 | parse5 "^7.0.0" 873 | 874 | parse5@^7.0.0: 875 | version "7.0.0" 876 | resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.0.0.tgz#51f74a5257f5fcc536389e8c2d0b3802e1bfa91a" 877 | integrity sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g== 878 | dependencies: 879 | entities "^4.3.0" 880 | 881 | parseurl@~1.3.3: 882 | version "1.3.3" 883 | resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" 884 | integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== 885 | 886 | path-is-absolute@^1.0.0: 887 | version "1.0.1" 888 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 889 | integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== 890 | 891 | path-parse@^1.0.7: 892 | version "1.0.7" 893 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" 894 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== 895 | 896 | path-to-regexp@0.1.7: 897 | version "0.1.7" 898 | resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" 899 | integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== 900 | 901 | picomatch@^2.0.4, picomatch@^2.2.1: 902 | version "2.3.1" 903 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 904 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 905 | 906 | proxy-addr@~2.0.7: 907 | version "2.0.7" 908 | resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" 909 | integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== 910 | dependencies: 911 | forwarded "0.2.0" 912 | ipaddr.js "1.9.1" 913 | 914 | punycode@^2.1.1: 915 | version "2.1.1" 916 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 917 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 918 | 919 | qs@6.10.3: 920 | version "6.10.3" 921 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" 922 | integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== 923 | dependencies: 924 | side-channel "^1.0.4" 925 | 926 | range-parser@~1.2.1: 927 | version "1.2.1" 928 | resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" 929 | integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== 930 | 931 | raw-body@2.5.1: 932 | version "2.5.1" 933 | resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" 934 | integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== 935 | dependencies: 936 | bytes "3.1.2" 937 | http-errors "2.0.0" 938 | iconv-lite "0.4.24" 939 | unpipe "1.0.0" 940 | 941 | readdirp@~3.6.0: 942 | version "3.6.0" 943 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" 944 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== 945 | dependencies: 946 | picomatch "^2.2.1" 947 | 948 | resolve@^1.0.0: 949 | version "1.22.1" 950 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" 951 | integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== 952 | dependencies: 953 | is-core-module "^2.9.0" 954 | path-parse "^1.0.7" 955 | supports-preserve-symlinks-flag "^1.0.0" 956 | 957 | rimraf@^2.6.1: 958 | version "2.7.1" 959 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" 960 | integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== 961 | dependencies: 962 | glob "^7.1.3" 963 | 964 | safe-buffer@5.2.1: 965 | version "5.2.1" 966 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 967 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 968 | 969 | "safer-buffer@>= 2.1.2 < 3": 970 | version "2.1.2" 971 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 972 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 973 | 974 | saslprep@^1.0.3: 975 | version "1.0.3" 976 | resolved "https://registry.yarnpkg.com/saslprep/-/saslprep-1.0.3.tgz#4c02f946b56cf54297e347ba1093e7acac4cf226" 977 | integrity sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag== 978 | dependencies: 979 | sparse-bitfield "^3.0.3" 980 | 981 | send@0.18.0: 982 | version "0.18.0" 983 | resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" 984 | integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== 985 | dependencies: 986 | debug "2.6.9" 987 | depd "2.0.0" 988 | destroy "1.2.0" 989 | encodeurl "~1.0.2" 990 | escape-html "~1.0.3" 991 | etag "~1.8.1" 992 | fresh "0.5.2" 993 | http-errors "2.0.0" 994 | mime "1.6.0" 995 | ms "2.1.3" 996 | on-finished "2.4.1" 997 | range-parser "~1.2.1" 998 | statuses "2.0.1" 999 | 1000 | serve-static@1.15.0: 1001 | version "1.15.0" 1002 | resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" 1003 | integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== 1004 | dependencies: 1005 | encodeurl "~1.0.2" 1006 | escape-html "~1.0.3" 1007 | parseurl "~1.3.3" 1008 | send "0.18.0" 1009 | 1010 | setprototypeof@1.2.0: 1011 | version "1.2.0" 1012 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" 1013 | integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== 1014 | 1015 | side-channel@^1.0.4: 1016 | version "1.0.4" 1017 | resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" 1018 | integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== 1019 | dependencies: 1020 | call-bind "^1.0.0" 1021 | get-intrinsic "^1.0.2" 1022 | object-inspect "^1.9.0" 1023 | 1024 | smart-buffer@^4.2.0: 1025 | version "4.2.0" 1026 | resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" 1027 | integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== 1028 | 1029 | socks@^2.6.2: 1030 | version "2.7.0" 1031 | resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.0.tgz#f9225acdb841e874dca25f870e9130990f3913d0" 1032 | integrity sha512-scnOe9y4VuiNUULJN72GrM26BNOjVsfPXI+j+98PkyEfsIXroa5ofyjT+FzGvn/xHs73U2JtoBYAVx9Hl4quSA== 1033 | dependencies: 1034 | ip "^2.0.0" 1035 | smart-buffer "^4.2.0" 1036 | 1037 | source-map-support@^0.5.12: 1038 | version "0.5.21" 1039 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" 1040 | integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== 1041 | dependencies: 1042 | buffer-from "^1.0.0" 1043 | source-map "^0.6.0" 1044 | 1045 | source-map@^0.6.0: 1046 | version "0.6.1" 1047 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 1048 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 1049 | 1050 | sparse-bitfield@^3.0.3: 1051 | version "3.0.3" 1052 | resolved "https://registry.yarnpkg.com/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz#ff4ae6e68656056ba4b3e792ab3334d38273ca11" 1053 | integrity sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ== 1054 | dependencies: 1055 | memory-pager "^1.0.2" 1056 | 1057 | statuses@2.0.1: 1058 | version "2.0.1" 1059 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" 1060 | integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== 1061 | 1062 | strip-bom@^3.0.0: 1063 | version "3.0.0" 1064 | resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" 1065 | integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== 1066 | 1067 | strip-json-comments@^2.0.0: 1068 | version "2.0.1" 1069 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" 1070 | integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== 1071 | 1072 | supports-preserve-symlinks-flag@^1.0.0: 1073 | version "1.0.0" 1074 | resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" 1075 | integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== 1076 | 1077 | swagger-ui-dist@>=4.11.0: 1078 | version "4.18.3" 1079 | resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-4.18.3.tgz#5529b7ca19d442c1adf0aea0802fff45c1ea29b5" 1080 | integrity sha512-QW280Uvt234+TLo9NMPRa2Sj17RoorbQlR2eEY4R6Cs0LbdXhiO14YWX9OPBkBdiN64GQYz4zU8wlHLVi81lBg== 1081 | 1082 | swagger-ui-express@^4.6.3: 1083 | version "4.6.3" 1084 | resolved "https://registry.yarnpkg.com/swagger-ui-express/-/swagger-ui-express-4.6.3.tgz#870d0892654fe80e6970a2d680e22521acd2dc19" 1085 | integrity sha512-CDje4PndhTD2HkgyKH3pab+LKspDeB/NhPN2OF1j+piYIamQqBYwAXWESOT1Yju2xFg51bRW9sUng2WxDjzArw== 1086 | dependencies: 1087 | swagger-ui-dist ">=4.11.0" 1088 | 1089 | to-regex-range@^5.0.1: 1090 | version "5.0.1" 1091 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 1092 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1093 | dependencies: 1094 | is-number "^7.0.0" 1095 | 1096 | toidentifier@1.0.1: 1097 | version "1.0.1" 1098 | resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" 1099 | integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== 1100 | 1101 | tr46@^3.0.0: 1102 | version "3.0.0" 1103 | resolved "https://registry.yarnpkg.com/tr46/-/tr46-3.0.0.tgz#555c4e297a950617e8eeddef633c87d4d9d6cbf9" 1104 | integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA== 1105 | dependencies: 1106 | punycode "^2.1.1" 1107 | 1108 | tree-kill@^1.2.2: 1109 | version "1.2.2" 1110 | resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" 1111 | integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== 1112 | 1113 | ts-node-dev@^2.0.0: 1114 | version "2.0.0" 1115 | resolved "https://registry.yarnpkg.com/ts-node-dev/-/ts-node-dev-2.0.0.tgz#bdd53e17ab3b5d822ef519928dc6b4a7e0f13065" 1116 | integrity sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w== 1117 | dependencies: 1118 | chokidar "^3.5.1" 1119 | dynamic-dedupe "^0.3.0" 1120 | minimist "^1.2.6" 1121 | mkdirp "^1.0.4" 1122 | resolve "^1.0.0" 1123 | rimraf "^2.6.1" 1124 | source-map-support "^0.5.12" 1125 | tree-kill "^1.2.2" 1126 | ts-node "^10.4.0" 1127 | tsconfig "^7.0.0" 1128 | 1129 | ts-node@^10.4.0, ts-node@^10.9.1: 1130 | version "10.9.1" 1131 | resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" 1132 | integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== 1133 | dependencies: 1134 | "@cspotcode/source-map-support" "^0.8.0" 1135 | "@tsconfig/node10" "^1.0.7" 1136 | "@tsconfig/node12" "^1.0.7" 1137 | "@tsconfig/node14" "^1.0.0" 1138 | "@tsconfig/node16" "^1.0.2" 1139 | acorn "^8.4.1" 1140 | acorn-walk "^8.1.1" 1141 | arg "^4.1.0" 1142 | create-require "^1.1.0" 1143 | diff "^4.0.1" 1144 | make-error "^1.1.1" 1145 | v8-compile-cache-lib "^3.0.1" 1146 | yn "3.1.1" 1147 | 1148 | tsconfig@^7.0.0: 1149 | version "7.0.0" 1150 | resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-7.0.0.tgz#84538875a4dc216e5c4a5432b3a4dec3d54e91b7" 1151 | integrity sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw== 1152 | dependencies: 1153 | "@types/strip-bom" "^3.0.0" 1154 | "@types/strip-json-comments" "0.0.30" 1155 | strip-bom "^3.0.0" 1156 | strip-json-comments "^2.0.0" 1157 | 1158 | type-is@~1.6.18: 1159 | version "1.6.18" 1160 | resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" 1161 | integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== 1162 | dependencies: 1163 | media-typer "0.3.0" 1164 | mime-types "~2.1.24" 1165 | 1166 | typescript@^4.7.4: 1167 | version "4.7.4" 1168 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" 1169 | integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== 1170 | 1171 | unpipe@1.0.0, unpipe@~1.0.0: 1172 | version "1.0.0" 1173 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 1174 | integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== 1175 | 1176 | utils-merge@1.0.1: 1177 | version "1.0.1" 1178 | resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" 1179 | integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== 1180 | 1181 | v8-compile-cache-lib@^3.0.1: 1182 | version "3.0.1" 1183 | resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" 1184 | integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== 1185 | 1186 | vary@^1, vary@~1.1.2: 1187 | version "1.1.2" 1188 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" 1189 | integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== 1190 | 1191 | webidl-conversions@^7.0.0: 1192 | version "7.0.0" 1193 | resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" 1194 | integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== 1195 | 1196 | whatwg-url@^11.0.0: 1197 | version "11.0.0" 1198 | resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" 1199 | integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ== 1200 | dependencies: 1201 | tr46 "^3.0.0" 1202 | webidl-conversions "^7.0.0" 1203 | 1204 | wrappy@1: 1205 | version "1.0.2" 1206 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1207 | integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== 1208 | 1209 | xtend@^4.0.0: 1210 | version "4.0.2" 1211 | resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" 1212 | integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== 1213 | 1214 | yn@3.1.1: 1215 | version "3.1.1" 1216 | resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" 1217 | integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== 1218 | --------------------------------------------------------------------------------