├── .gitignore ├── src ├── utils │ ├── constant.js │ ├── catch-async.js │ └── reform-transaction.js ├── middleware │ ├── error-handler.js │ └── error-validation.js ├── features │ ├── products │ │ ├── products.validation.js │ │ ├── index.js │ │ └── products.service.js │ └── transactions │ │ ├── transactions.validation.js │ │ ├── index.js │ │ └── transactions.service.js ├── index.js └── routes │ └── index.js ├── .env.example ├── package.json ├── prisma └── schema.prisma └── pnpm-lock.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | # Keep environment variables out of version control 3 | .env 4 | -------------------------------------------------------------------------------- /src/utils/constant.js: -------------------------------------------------------------------------------- 1 | export const PENDING_PAYMENT = 'PENDING_PAYMENT'; 2 | export const PAID = 'PAID'; 3 | export const CANCELED = 'CANCELED'; -------------------------------------------------------------------------------- /src/utils/catch-async.js: -------------------------------------------------------------------------------- 1 | export const catchAsync = (fn) => { 2 | return (req, res, next) => { 3 | fn(req, res, next).catch((error) => { 4 | next(error) 5 | }) 6 | } 7 | } -------------------------------------------------------------------------------- /src/middleware/error-handler.js: -------------------------------------------------------------------------------- 1 | export const errorHandler = (err, req, res, next) => { 2 | console.log('error', err); 3 | res.status(500).json({ 4 | status: 'error', 5 | message: err.message 6 | }) 7 | } -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | PORT=8000 2 | DATABASE_URL="mysql://xxx:yyy@localhost:3306/zzz" 3 | MIDTRANS_APP_URL="https://app.sandbox.midtrans.com" 4 | MIDTRANS_API_URL="https://api.sandbox.midtrans.com" 5 | MIDTRANS_SERVER_KEY="xxxxx-xxxx-xxxx-xxxx-xxxx" 6 | FRONT_END_URL="http://localhost:5173" -------------------------------------------------------------------------------- /src/features/products/products.validation.js: -------------------------------------------------------------------------------- 1 | import { check } from "express-validator"; 2 | import { errorValidation } from "../../middleware/error-validation.js"; 3 | 4 | export const validateProduct = [ 5 | check('name').isLength({ min: 3 }).withMessage('Name must be at least 3 characters long'), 6 | check('price').isNumeric().withMessage('Price must be a number'), 7 | errorValidation, 8 | ] -------------------------------------------------------------------------------- /src/middleware/error-validation.js: -------------------------------------------------------------------------------- 1 | import { validationResult } from 'express-validator'; 2 | 3 | export const errorValidation = (req, res, next) => { 4 | const errors = validationResult(req) 5 | 6 | if (!errors.isEmpty()) { 7 | return res.status(400).json({ 8 | status: 'error', 9 | errors: errors.array() 10 | }); 11 | } 12 | next(); 13 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import cors from 'cors'; 3 | import routes from './routes/index.js'; 4 | import { errorHandler } from './middleware/error-handler.js'; 5 | 6 | const app = express(); 7 | const PORT = process.env.PORT || 8000; 8 | 9 | app.use(express.json()); 10 | app.use(cors()); 11 | 12 | app.use(routes); 13 | 14 | app.use(errorHandler); 15 | 16 | app.listen(PORT, () => { 17 | console.log(`⚡️[server]: Server is running at https://localhost:${PORT}`); 18 | }); 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "midtrans-snap-api", 3 | "version": "1.0.0", 4 | "type": "module", 5 | "description": "", 6 | "main": "index.js", 7 | "scripts": { 8 | "dev": "nodemon src/index.js" 9 | }, 10 | "keywords": [], 11 | "author": "Prawito Hudoro", 12 | "license": "ISC", 13 | "dependencies": { 14 | "@prisma/client": "5.5.2", 15 | "cors": "^2.8.5", 16 | "express": "^4.18.2", 17 | "express-validator": "^7.0.1", 18 | "nanoid": "^5.0.2", 19 | "nodemon": "^3.0.1", 20 | "prisma": "^5.5.2", 21 | "uuid": "^9.0.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/features/products/index.js: -------------------------------------------------------------------------------- 1 | import { productService } from './products.service.js'; 2 | 3 | export const getProducts = async (req, res) => { 4 | const products = await productService.getProducts(); 5 | 6 | res.json({ 7 | status: 'success', 8 | data: products 9 | }) 10 | } 11 | 12 | export const createProduct = async (req, res) => { 13 | const { name, price } = req.body; 14 | const product = await productService.createProduct({name, price}); 15 | 16 | res.json({ 17 | status: 'success', 18 | data: product 19 | }) 20 | }; -------------------------------------------------------------------------------- /src/utils/reform-transaction.js: -------------------------------------------------------------------------------- 1 | export const reformTransaction = (transaction) => { 2 | return { 3 | id: transaction.id, 4 | total: transaction.total, 5 | status: transaction.status, 6 | customer_name: transaction.customer_name, 7 | customer_email: transaction.customer_email, 8 | snap_token: transaction.snap_token, 9 | snap_redirect_url: transaction.snap_redirect_url, 10 | payment_method: transaction.payment_method, 11 | products: transaction.transactions_items.map((transactionItem) => ({ 12 | id: transactionItem.product_id, 13 | name: transactionItem.product_name, 14 | price: transactionItem.price, 15 | quantity: transactionItem.quantity, 16 | image: transactionItem.products.image 17 | })) 18 | } 19 | } -------------------------------------------------------------------------------- /src/features/products/products.service.js: -------------------------------------------------------------------------------- 1 | import { v4 as uuidv4 } from 'uuid'; 2 | import { PrismaClient } from '@prisma/client'; 3 | 4 | const prisma = new PrismaClient(); 5 | 6 | class ProductService { 7 | async createProduct({name, price}) { 8 | const id = uuidv4(); 9 | return prisma.product.create({ 10 | data: { 11 | id, 12 | name, 13 | price, 14 | image: `https://picsum.photos/143/108?random=${id}` 15 | } 16 | }) 17 | } 18 | 19 | async getProducts() { 20 | return prisma.product.findMany(); 21 | } 22 | 23 | async getProductsByIds({products}) { 24 | return prisma.product.findMany({ 25 | where: { 26 | id: { 27 | in: products.map((product) => product.id) 28 | } 29 | } 30 | }) 31 | } 32 | } 33 | 34 | export const productService = new ProductService(); -------------------------------------------------------------------------------- /src/features/transactions/transactions.validation.js: -------------------------------------------------------------------------------- 1 | import { check } from "express-validator" 2 | import { errorValidation } from "../../middleware/error-validation.js" 3 | import { CANCELED, PAID, PENDING_PAYMENT } from "../../utils/constant.js" 4 | 5 | export const validateTransactionStatus = [ 6 | check('status').isIn([PENDING_PAYMENT, PAID, CANCELED]).withMessage('Status must be one of PENDING_PAYMENT, PAID, CANCELED'), 7 | errorValidation, 8 | ] 9 | 10 | export const validateTransaction = [ 11 | check('products').isArray().withMessage('Products must be an array'), 12 | check('products.*.id').isUUID().withMessage('Product id must be a valid UUID'), 13 | check('products.*.quantity').isInt({ min: 1 }).withMessage('Quantity must be at least 1'), 14 | check('customer_name').isLength({ min: 3 }).withMessage('Customer name must be at least 3 characters long'), 15 | check('customer_email').isEmail().withMessage('Customer email must be a valid email'), 16 | errorValidation, 17 | ] -------------------------------------------------------------------------------- /src/routes/index.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import { createTransaction, getTransactionById, getTransactions, updateTransactionStatus } from "../features/transactions/index.js"; 3 | import { validateTransaction, validateTransactionStatus } from "../features/transactions/transactions.validation.js"; 4 | import { createProduct, getProducts } from "../features/products/index.js"; 5 | import { validateProduct } from "../features/products/products.validation.js"; 6 | import { catchAsync } from "../utils/catch-async.js"; 7 | 8 | const router = express.Router(); 9 | 10 | router.get('/', (req, res) => { 11 | res.send('Hello World!'); 12 | }); 13 | 14 | // transactions 15 | router.post('/transactions', validateTransaction, catchAsync(createTransaction)); 16 | router.get('/transactions', catchAsync(getTransactions)); 17 | router.get('/transactions/:transaction_id', catchAsync(getTransactionById)); 18 | router.put('/transactions/:transaction_id', validateTransactionStatus, catchAsync(updateTransactionStatus)); 19 | 20 | // products 21 | router.post('/products', validateProduct, catchAsync(createProduct)); 22 | router.get('/products', catchAsync(getProducts)); 23 | 24 | export default router; -------------------------------------------------------------------------------- /prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | generator client { 2 | provider = "prisma-client-js" 3 | } 4 | 5 | datasource db { 6 | provider = "mysql" 7 | url = env("DATABASE_URL") 8 | } 9 | 10 | model Product { 11 | id String @id @db.VarChar(110) 12 | name String @db.VarChar(255) 13 | price Int 14 | image String? @db.VarChar(255) 15 | created_at DateTime? @default(now()) @db.Timestamp(0) 16 | updated_at DateTime? @default(now()) @db.Timestamp(0) 17 | transactions_items TransactionsItem[] 18 | 19 | @@map("products") 20 | } 21 | 22 | model Transaction { 23 | id String @id @db.VarChar(110) 24 | total Int 25 | status transactions_status 26 | customer_name String @db.VarChar(255) 27 | customer_email String @db.VarChar(255) 28 | snap_token String? @db.VarChar(255) 29 | snap_redirect_url String? @db.VarChar(255) 30 | payment_method String? @db.VarChar(110) 31 | created_at DateTime? @default(now()) @db.Timestamp(0) 32 | updated_at DateTime? @default(now()) @db.Timestamp(0) 33 | transactions_items TransactionsItem[] 34 | 35 | @@map("transactions") 36 | } 37 | 38 | model TransactionsItem { 39 | id String @id @db.VarChar(110) 40 | transaction_id String @db.VarChar(110) 41 | product_id String @db.VarChar(110) 42 | product_name String @db.VarChar(255) 43 | price Int 44 | quantity Int 45 | created_at DateTime? @default(now()) @db.Timestamp(0) 46 | updated_at DateTime? @default(now()) @db.Timestamp(0) 47 | transactions Transaction @relation(fields: [transaction_id], references: [id], onUpdate: Restrict, map: "transactions_items_ibfk_1") 48 | products Product @relation(fields: [product_id], references: [id], onUpdate: Restrict, map: "transactions_items_ibfk_2") 49 | 50 | @@index([product_id], map: "product_id") 51 | @@index([transaction_id], map: "transaction_id") 52 | @@map("transactions_items") 53 | } 54 | 55 | enum transactions_status { 56 | PENDING_PAYMENT 57 | PAID 58 | CANCELED 59 | } 60 | -------------------------------------------------------------------------------- /src/features/transactions/index.js: -------------------------------------------------------------------------------- 1 | import { nanoid } from 'nanoid'; 2 | import { transactionService } from './transactions.service.js'; 3 | import { reformTransaction } from '../../utils/reform-transaction.js'; 4 | import { productService } from '../products/products.service.js'; 5 | import { PENDING_PAYMENT } from '../../utils/constant.js'; 6 | 7 | export const createTransaction = async (req, res) => { 8 | const { products, customer_name, customer_email } = req.body; 9 | 10 | const productsFromDB = await productService.getProductsByIds({products}); 11 | 12 | if (productsFromDB.length === 0) { 13 | return res.status(400).json({ 14 | status: 'error', 15 | message: 'Products not found' 16 | }) 17 | } 18 | 19 | productsFromDB.forEach((product) => { 20 | const productFromRequest = products.find((productFromRequest) => productFromRequest.id === product.id); 21 | product.quantity = productFromRequest.quantity; 22 | }); 23 | 24 | const transaction_id = `TRX-${nanoid(4)}-${nanoid(8)}`; 25 | const gross_amount = productsFromDB.reduce((acc, product) => acc + (product.quantity * product.price), 0); 26 | 27 | await Promise.all([ 28 | transactionService.createTransaction({ 29 | transaction_id, 30 | gross_amount, 31 | customer_name, 32 | customer_email, 33 | snap_token: null, 34 | snap_redirect_url: null 35 | }), 36 | transactionService.createTransactionItems({ 37 | products: productsFromDB, 38 | transaction_id 39 | }) 40 | ]); 41 | 42 | res.json({ 43 | status: 'success', 44 | data: { 45 | id: transaction_id, 46 | status: PENDING_PAYMENT, 47 | customer_name, 48 | customer_email, 49 | products: productsFromDB, 50 | snap_token: null, 51 | snap_redirect_url: null, 52 | } 53 | }) 54 | 55 | }; 56 | 57 | export const getTransactions = async (req, res) => { 58 | const { status } = req.query; 59 | const transactions = await transactionService.getTransactions({status}); 60 | 61 | res.json({ 62 | status: 'success', 63 | data: transactions.map((transaction) => reformTransaction(transaction)) 64 | }) 65 | }; 66 | 67 | export const getTransactionById = async (req, res) => { 68 | const { transaction_id } = req.params; 69 | const transaction = await transactionService.getTransactionById({transaction_id}); 70 | 71 | if(!transaction) { 72 | return res.status(404).json({ 73 | status: 'error', 74 | message: 'Transaction not found' 75 | }) 76 | } 77 | 78 | res.json({ 79 | status: 'success', 80 | data: reformTransaction(transaction), 81 | }) 82 | }; 83 | 84 | export const updateTransactionStatus = async (req, res) => { 85 | const { transaction_id } = req.params; 86 | const { status } = req.body; 87 | const transaction = await transactionService.updateTransactionStatus({transaction_id, status}); 88 | 89 | res.json({ 90 | status: 'success', 91 | data: transaction 92 | }) 93 | }; -------------------------------------------------------------------------------- /src/features/transactions/transactions.service.js: -------------------------------------------------------------------------------- 1 | import { PrismaClient } from '@prisma/client'; 2 | import { nanoid } from 'nanoid'; 3 | 4 | import { PENDING_PAYMENT } from "../../utils/constant.js"; 5 | 6 | const prisma = new PrismaClient(); 7 | 8 | class TransactionService { 9 | async createTransaction({transaction_id, gross_amount, customer_name, customer_email, snap_token = null, snap_redirect_url = null}) { 10 | return prisma.transaction.create({ 11 | data: { 12 | id: transaction_id, 13 | total: gross_amount, 14 | status: PENDING_PAYMENT, 15 | customer_name, 16 | customer_email, 17 | snap_token, 18 | snap_redirect_url, 19 | }, 20 | }); 21 | } 22 | 23 | async createTransactionItems({products, transaction_id}) { 24 | return prisma.transactionsItem.createMany({ 25 | data: products.map((product) => ({ 26 | id: `TRX-ITEM-${nanoid(10)}`, 27 | transaction_id, 28 | product_id: product.id, 29 | product_name: product.name, 30 | price: product.price, 31 | quantity: product.quantity 32 | })) 33 | }); 34 | } 35 | 36 | // get all transactions 37 | async getTransactions({status}) { 38 | let where = {}; 39 | if (status) { 40 | where = { 41 | status 42 | } 43 | } 44 | 45 | return prisma.transaction.findMany({ 46 | where, 47 | include: { 48 | transactions_items: { 49 | include: { 50 | products: { 51 | select: { 52 | id: true, 53 | name: true, 54 | price: true, 55 | image: true 56 | } 57 | } 58 | } 59 | }, 60 | } 61 | }); 62 | } 63 | 64 | // get transaction by id 65 | async getTransactionById({transaction_id}) { 66 | return prisma.transaction.findUnique({ 67 | where: { 68 | id: transaction_id 69 | }, 70 | include: { 71 | transactions_items: { 72 | include: { 73 | products: { 74 | select: { 75 | id: true, 76 | name: true, 77 | price: true, 78 | image: true 79 | } 80 | } 81 | } 82 | }, 83 | } 84 | }) 85 | } 86 | 87 | // update transaction status 88 | async updateTransactionStatus({transaction_id, status, payment_method = null}) { 89 | return prisma.transaction.update({ 90 | where: { 91 | id: transaction_id 92 | }, 93 | data: { 94 | status, 95 | payment_method 96 | } 97 | }); 98 | } 99 | } 100 | 101 | export const transactionService = new TransactionService(); -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '6.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | dependencies: 8 | '@prisma/client': 9 | specifier: 5.5.2 10 | version: 5.5.2(prisma@5.5.2) 11 | cors: 12 | specifier: ^2.8.5 13 | version: 2.8.5 14 | express: 15 | specifier: ^4.18.2 16 | version: 4.18.2 17 | express-validator: 18 | specifier: ^7.0.1 19 | version: 7.0.1 20 | nanoid: 21 | specifier: ^5.0.2 22 | version: 5.0.2 23 | nodemon: 24 | specifier: ^3.0.1 25 | version: 3.0.1 26 | prisma: 27 | specifier: ^5.5.2 28 | version: 5.5.2 29 | uuid: 30 | specifier: ^9.0.1 31 | version: 9.0.1 32 | 33 | packages: 34 | 35 | /@prisma/client@5.5.2(prisma@5.5.2): 36 | resolution: {integrity: sha512-54XkqR8M+fxbzYqe+bIXimYnkkcGqgOh0dn0yWtIk6CQT4IUCAvNFNcQZwk2KqaLU+/1PHTSWrcHtx4XjluR5w==} 37 | engines: {node: '>=16.13'} 38 | requiresBuild: true 39 | peerDependencies: 40 | prisma: '*' 41 | peerDependenciesMeta: 42 | prisma: 43 | optional: true 44 | dependencies: 45 | '@prisma/engines-version': 5.5.1-1.aebc046ce8b88ebbcb45efe31cbe7d06fd6abc0a 46 | prisma: 5.5.2 47 | dev: false 48 | 49 | /@prisma/engines-version@5.5.1-1.aebc046ce8b88ebbcb45efe31cbe7d06fd6abc0a: 50 | resolution: {integrity: sha512-O+qHFnZvAyOFk1tUco2/VdiqS0ym42a3+6CYLScllmnpbyiTplgyLt2rK/B9BTjYkSHjrgMhkG47S0oqzdIckA==} 51 | dev: false 52 | 53 | /@prisma/engines@5.5.2: 54 | resolution: {integrity: sha512-Be5hoNF8k+lkB3uEMiCHbhbfF6aj1GnrTBnn5iYFT7GEr3TsOEp1soviEcBR0tYCgHbxjcIxJMhdbvxALJhAqg==} 55 | requiresBuild: true 56 | dev: false 57 | 58 | /abbrev@1.1.1: 59 | resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} 60 | dev: false 61 | 62 | /accepts@1.3.8: 63 | resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} 64 | engines: {node: '>= 0.6'} 65 | dependencies: 66 | mime-types: 2.1.35 67 | negotiator: 0.6.3 68 | dev: false 69 | 70 | /anymatch@3.1.3: 71 | resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} 72 | engines: {node: '>= 8'} 73 | dependencies: 74 | normalize-path: 3.0.0 75 | picomatch: 2.3.1 76 | dev: false 77 | 78 | /array-flatten@1.1.1: 79 | resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} 80 | dev: false 81 | 82 | /balanced-match@1.0.2: 83 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 84 | dev: false 85 | 86 | /binary-extensions@2.2.0: 87 | resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} 88 | engines: {node: '>=8'} 89 | dev: false 90 | 91 | /body-parser@1.20.1: 92 | resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} 93 | engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} 94 | dependencies: 95 | bytes: 3.1.2 96 | content-type: 1.0.5 97 | debug: 2.6.9 98 | depd: 2.0.0 99 | destroy: 1.2.0 100 | http-errors: 2.0.0 101 | iconv-lite: 0.4.24 102 | on-finished: 2.4.1 103 | qs: 6.11.0 104 | raw-body: 2.5.1 105 | type-is: 1.6.18 106 | unpipe: 1.0.0 107 | transitivePeerDependencies: 108 | - supports-color 109 | dev: false 110 | 111 | /brace-expansion@1.1.11: 112 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 113 | dependencies: 114 | balanced-match: 1.0.2 115 | concat-map: 0.0.1 116 | dev: false 117 | 118 | /braces@3.0.2: 119 | resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} 120 | engines: {node: '>=8'} 121 | dependencies: 122 | fill-range: 7.0.1 123 | dev: false 124 | 125 | /bytes@3.1.2: 126 | resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} 127 | engines: {node: '>= 0.8'} 128 | dev: false 129 | 130 | /call-bind@1.0.5: 131 | resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} 132 | dependencies: 133 | function-bind: 1.1.2 134 | get-intrinsic: 1.2.2 135 | set-function-length: 1.1.1 136 | dev: false 137 | 138 | /chokidar@3.5.3: 139 | resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} 140 | engines: {node: '>= 8.10.0'} 141 | dependencies: 142 | anymatch: 3.1.3 143 | braces: 3.0.2 144 | glob-parent: 5.1.2 145 | is-binary-path: 2.1.0 146 | is-glob: 4.0.3 147 | normalize-path: 3.0.0 148 | readdirp: 3.6.0 149 | optionalDependencies: 150 | fsevents: 2.3.3 151 | dev: false 152 | 153 | /concat-map@0.0.1: 154 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 155 | dev: false 156 | 157 | /content-disposition@0.5.4: 158 | resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} 159 | engines: {node: '>= 0.6'} 160 | dependencies: 161 | safe-buffer: 5.2.1 162 | dev: false 163 | 164 | /content-type@1.0.5: 165 | resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} 166 | engines: {node: '>= 0.6'} 167 | dev: false 168 | 169 | /cookie-signature@1.0.6: 170 | resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} 171 | dev: false 172 | 173 | /cookie@0.5.0: 174 | resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} 175 | engines: {node: '>= 0.6'} 176 | dev: false 177 | 178 | /cors@2.8.5: 179 | resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} 180 | engines: {node: '>= 0.10'} 181 | dependencies: 182 | object-assign: 4.1.1 183 | vary: 1.1.2 184 | dev: false 185 | 186 | /debug@2.6.9: 187 | resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} 188 | peerDependencies: 189 | supports-color: '*' 190 | peerDependenciesMeta: 191 | supports-color: 192 | optional: true 193 | dependencies: 194 | ms: 2.0.0 195 | dev: false 196 | 197 | /debug@3.2.7(supports-color@5.5.0): 198 | resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} 199 | peerDependencies: 200 | supports-color: '*' 201 | peerDependenciesMeta: 202 | supports-color: 203 | optional: true 204 | dependencies: 205 | ms: 2.1.3 206 | supports-color: 5.5.0 207 | dev: false 208 | 209 | /define-data-property@1.1.1: 210 | resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} 211 | engines: {node: '>= 0.4'} 212 | dependencies: 213 | get-intrinsic: 1.2.2 214 | gopd: 1.0.1 215 | has-property-descriptors: 1.0.1 216 | dev: false 217 | 218 | /depd@2.0.0: 219 | resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} 220 | engines: {node: '>= 0.8'} 221 | dev: false 222 | 223 | /destroy@1.2.0: 224 | resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} 225 | engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} 226 | dev: false 227 | 228 | /ee-first@1.1.1: 229 | resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} 230 | dev: false 231 | 232 | /encodeurl@1.0.2: 233 | resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} 234 | engines: {node: '>= 0.8'} 235 | dev: false 236 | 237 | /escape-html@1.0.3: 238 | resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} 239 | dev: false 240 | 241 | /etag@1.8.1: 242 | resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} 243 | engines: {node: '>= 0.6'} 244 | dev: false 245 | 246 | /express-validator@7.0.1: 247 | resolution: {integrity: sha512-oB+z9QOzQIE8FnlINqyIFA8eIckahC6qc8KtqLdLJcU3/phVyuhXH3bA4qzcrhme+1RYaCSwrq+TlZ/kAKIARA==} 248 | engines: {node: '>= 8.0.0'} 249 | dependencies: 250 | lodash: 4.17.21 251 | validator: 13.11.0 252 | dev: false 253 | 254 | /express@4.18.2: 255 | resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} 256 | engines: {node: '>= 0.10.0'} 257 | dependencies: 258 | accepts: 1.3.8 259 | array-flatten: 1.1.1 260 | body-parser: 1.20.1 261 | content-disposition: 0.5.4 262 | content-type: 1.0.5 263 | cookie: 0.5.0 264 | cookie-signature: 1.0.6 265 | debug: 2.6.9 266 | depd: 2.0.0 267 | encodeurl: 1.0.2 268 | escape-html: 1.0.3 269 | etag: 1.8.1 270 | finalhandler: 1.2.0 271 | fresh: 0.5.2 272 | http-errors: 2.0.0 273 | merge-descriptors: 1.0.1 274 | methods: 1.1.2 275 | on-finished: 2.4.1 276 | parseurl: 1.3.3 277 | path-to-regexp: 0.1.7 278 | proxy-addr: 2.0.7 279 | qs: 6.11.0 280 | range-parser: 1.2.1 281 | safe-buffer: 5.2.1 282 | send: 0.18.0 283 | serve-static: 1.15.0 284 | setprototypeof: 1.2.0 285 | statuses: 2.0.1 286 | type-is: 1.6.18 287 | utils-merge: 1.0.1 288 | vary: 1.1.2 289 | transitivePeerDependencies: 290 | - supports-color 291 | dev: false 292 | 293 | /fill-range@7.0.1: 294 | resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} 295 | engines: {node: '>=8'} 296 | dependencies: 297 | to-regex-range: 5.0.1 298 | dev: false 299 | 300 | /finalhandler@1.2.0: 301 | resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} 302 | engines: {node: '>= 0.8'} 303 | dependencies: 304 | debug: 2.6.9 305 | encodeurl: 1.0.2 306 | escape-html: 1.0.3 307 | on-finished: 2.4.1 308 | parseurl: 1.3.3 309 | statuses: 2.0.1 310 | unpipe: 1.0.0 311 | transitivePeerDependencies: 312 | - supports-color 313 | dev: false 314 | 315 | /forwarded@0.2.0: 316 | resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} 317 | engines: {node: '>= 0.6'} 318 | dev: false 319 | 320 | /fresh@0.5.2: 321 | resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} 322 | engines: {node: '>= 0.6'} 323 | dev: false 324 | 325 | /fsevents@2.3.3: 326 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 327 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 328 | os: [darwin] 329 | requiresBuild: true 330 | dev: false 331 | optional: true 332 | 333 | /function-bind@1.1.2: 334 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 335 | dev: false 336 | 337 | /get-intrinsic@1.2.2: 338 | resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} 339 | dependencies: 340 | function-bind: 1.1.2 341 | has-proto: 1.0.1 342 | has-symbols: 1.0.3 343 | hasown: 2.0.0 344 | dev: false 345 | 346 | /glob-parent@5.1.2: 347 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 348 | engines: {node: '>= 6'} 349 | dependencies: 350 | is-glob: 4.0.3 351 | dev: false 352 | 353 | /gopd@1.0.1: 354 | resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} 355 | dependencies: 356 | get-intrinsic: 1.2.2 357 | dev: false 358 | 359 | /has-flag@3.0.0: 360 | resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} 361 | engines: {node: '>=4'} 362 | dev: false 363 | 364 | /has-property-descriptors@1.0.1: 365 | resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} 366 | dependencies: 367 | get-intrinsic: 1.2.2 368 | dev: false 369 | 370 | /has-proto@1.0.1: 371 | resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} 372 | engines: {node: '>= 0.4'} 373 | dev: false 374 | 375 | /has-symbols@1.0.3: 376 | resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} 377 | engines: {node: '>= 0.4'} 378 | dev: false 379 | 380 | /hasown@2.0.0: 381 | resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} 382 | engines: {node: '>= 0.4'} 383 | dependencies: 384 | function-bind: 1.1.2 385 | dev: false 386 | 387 | /http-errors@2.0.0: 388 | resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} 389 | engines: {node: '>= 0.8'} 390 | dependencies: 391 | depd: 2.0.0 392 | inherits: 2.0.4 393 | setprototypeof: 1.2.0 394 | statuses: 2.0.1 395 | toidentifier: 1.0.1 396 | dev: false 397 | 398 | /iconv-lite@0.4.24: 399 | resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} 400 | engines: {node: '>=0.10.0'} 401 | dependencies: 402 | safer-buffer: 2.1.2 403 | dev: false 404 | 405 | /ignore-by-default@1.0.1: 406 | resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} 407 | dev: false 408 | 409 | /inherits@2.0.4: 410 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 411 | dev: false 412 | 413 | /ipaddr.js@1.9.1: 414 | resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} 415 | engines: {node: '>= 0.10'} 416 | dev: false 417 | 418 | /is-binary-path@2.1.0: 419 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} 420 | engines: {node: '>=8'} 421 | dependencies: 422 | binary-extensions: 2.2.0 423 | dev: false 424 | 425 | /is-extglob@2.1.1: 426 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 427 | engines: {node: '>=0.10.0'} 428 | dev: false 429 | 430 | /is-glob@4.0.3: 431 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 432 | engines: {node: '>=0.10.0'} 433 | dependencies: 434 | is-extglob: 2.1.1 435 | dev: false 436 | 437 | /is-number@7.0.0: 438 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 439 | engines: {node: '>=0.12.0'} 440 | dev: false 441 | 442 | /lodash@4.17.21: 443 | resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} 444 | dev: false 445 | 446 | /lru-cache@6.0.0: 447 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} 448 | engines: {node: '>=10'} 449 | dependencies: 450 | yallist: 4.0.0 451 | dev: false 452 | 453 | /media-typer@0.3.0: 454 | resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} 455 | engines: {node: '>= 0.6'} 456 | dev: false 457 | 458 | /merge-descriptors@1.0.1: 459 | resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} 460 | dev: false 461 | 462 | /methods@1.1.2: 463 | resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} 464 | engines: {node: '>= 0.6'} 465 | dev: false 466 | 467 | /mime-db@1.52.0: 468 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} 469 | engines: {node: '>= 0.6'} 470 | dev: false 471 | 472 | /mime-types@2.1.35: 473 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} 474 | engines: {node: '>= 0.6'} 475 | dependencies: 476 | mime-db: 1.52.0 477 | dev: false 478 | 479 | /mime@1.6.0: 480 | resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} 481 | engines: {node: '>=4'} 482 | hasBin: true 483 | dev: false 484 | 485 | /minimatch@3.1.2: 486 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 487 | dependencies: 488 | brace-expansion: 1.1.11 489 | dev: false 490 | 491 | /ms@2.0.0: 492 | resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} 493 | dev: false 494 | 495 | /ms@2.1.3: 496 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 497 | dev: false 498 | 499 | /nanoid@5.0.2: 500 | resolution: {integrity: sha512-2ustYUX1R2rL/Br5B/FMhi8d5/QzvkJ912rBYxskcpu0myTHzSZfTr1LAS2Sm7jxRUObRrSBFoyzwAhL49aVSg==} 501 | engines: {node: ^18 || >=20} 502 | hasBin: true 503 | dev: false 504 | 505 | /negotiator@0.6.3: 506 | resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} 507 | engines: {node: '>= 0.6'} 508 | dev: false 509 | 510 | /nodemon@3.0.1: 511 | resolution: {integrity: sha512-g9AZ7HmkhQkqXkRc20w+ZfQ73cHLbE8hnPbtaFbFtCumZsjyMhKk9LajQ07U5Ux28lvFjZ5X7HvWR1xzU8jHVw==} 512 | engines: {node: '>=10'} 513 | hasBin: true 514 | dependencies: 515 | chokidar: 3.5.3 516 | debug: 3.2.7(supports-color@5.5.0) 517 | ignore-by-default: 1.0.1 518 | minimatch: 3.1.2 519 | pstree.remy: 1.1.8 520 | semver: 7.5.4 521 | simple-update-notifier: 2.0.0 522 | supports-color: 5.5.0 523 | touch: 3.1.0 524 | undefsafe: 2.0.5 525 | dev: false 526 | 527 | /nopt@1.0.10: 528 | resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==} 529 | hasBin: true 530 | dependencies: 531 | abbrev: 1.1.1 532 | dev: false 533 | 534 | /normalize-path@3.0.0: 535 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} 536 | engines: {node: '>=0.10.0'} 537 | dev: false 538 | 539 | /object-assign@4.1.1: 540 | resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} 541 | engines: {node: '>=0.10.0'} 542 | dev: false 543 | 544 | /object-inspect@1.13.1: 545 | resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} 546 | dev: false 547 | 548 | /on-finished@2.4.1: 549 | resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} 550 | engines: {node: '>= 0.8'} 551 | dependencies: 552 | ee-first: 1.1.1 553 | dev: false 554 | 555 | /parseurl@1.3.3: 556 | resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} 557 | engines: {node: '>= 0.8'} 558 | dev: false 559 | 560 | /path-to-regexp@0.1.7: 561 | resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} 562 | dev: false 563 | 564 | /picomatch@2.3.1: 565 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 566 | engines: {node: '>=8.6'} 567 | dev: false 568 | 569 | /prisma@5.5.2: 570 | resolution: {integrity: sha512-WQtG6fevOL053yoPl6dbHV+IWgKo25IRN4/pwAGqcWmg7CrtoCzvbDbN9fXUc7QS2KK0LimHIqLsaCOX/vHl8w==} 571 | engines: {node: '>=16.13'} 572 | hasBin: true 573 | requiresBuild: true 574 | dependencies: 575 | '@prisma/engines': 5.5.2 576 | dev: false 577 | 578 | /proxy-addr@2.0.7: 579 | resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} 580 | engines: {node: '>= 0.10'} 581 | dependencies: 582 | forwarded: 0.2.0 583 | ipaddr.js: 1.9.1 584 | dev: false 585 | 586 | /pstree.remy@1.1.8: 587 | resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} 588 | dev: false 589 | 590 | /qs@6.11.0: 591 | resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} 592 | engines: {node: '>=0.6'} 593 | dependencies: 594 | side-channel: 1.0.4 595 | dev: false 596 | 597 | /range-parser@1.2.1: 598 | resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} 599 | engines: {node: '>= 0.6'} 600 | dev: false 601 | 602 | /raw-body@2.5.1: 603 | resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} 604 | engines: {node: '>= 0.8'} 605 | dependencies: 606 | bytes: 3.1.2 607 | http-errors: 2.0.0 608 | iconv-lite: 0.4.24 609 | unpipe: 1.0.0 610 | dev: false 611 | 612 | /readdirp@3.6.0: 613 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} 614 | engines: {node: '>=8.10.0'} 615 | dependencies: 616 | picomatch: 2.3.1 617 | dev: false 618 | 619 | /safe-buffer@5.2.1: 620 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 621 | dev: false 622 | 623 | /safer-buffer@2.1.2: 624 | resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} 625 | dev: false 626 | 627 | /semver@7.5.4: 628 | resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} 629 | engines: {node: '>=10'} 630 | hasBin: true 631 | dependencies: 632 | lru-cache: 6.0.0 633 | dev: false 634 | 635 | /send@0.18.0: 636 | resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} 637 | engines: {node: '>= 0.8.0'} 638 | dependencies: 639 | debug: 2.6.9 640 | depd: 2.0.0 641 | destroy: 1.2.0 642 | encodeurl: 1.0.2 643 | escape-html: 1.0.3 644 | etag: 1.8.1 645 | fresh: 0.5.2 646 | http-errors: 2.0.0 647 | mime: 1.6.0 648 | ms: 2.1.3 649 | on-finished: 2.4.1 650 | range-parser: 1.2.1 651 | statuses: 2.0.1 652 | transitivePeerDependencies: 653 | - supports-color 654 | dev: false 655 | 656 | /serve-static@1.15.0: 657 | resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} 658 | engines: {node: '>= 0.8.0'} 659 | dependencies: 660 | encodeurl: 1.0.2 661 | escape-html: 1.0.3 662 | parseurl: 1.3.3 663 | send: 0.18.0 664 | transitivePeerDependencies: 665 | - supports-color 666 | dev: false 667 | 668 | /set-function-length@1.1.1: 669 | resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} 670 | engines: {node: '>= 0.4'} 671 | dependencies: 672 | define-data-property: 1.1.1 673 | get-intrinsic: 1.2.2 674 | gopd: 1.0.1 675 | has-property-descriptors: 1.0.1 676 | dev: false 677 | 678 | /setprototypeof@1.2.0: 679 | resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} 680 | dev: false 681 | 682 | /side-channel@1.0.4: 683 | resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} 684 | dependencies: 685 | call-bind: 1.0.5 686 | get-intrinsic: 1.2.2 687 | object-inspect: 1.13.1 688 | dev: false 689 | 690 | /simple-update-notifier@2.0.0: 691 | resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} 692 | engines: {node: '>=10'} 693 | dependencies: 694 | semver: 7.5.4 695 | dev: false 696 | 697 | /statuses@2.0.1: 698 | resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} 699 | engines: {node: '>= 0.8'} 700 | dev: false 701 | 702 | /supports-color@5.5.0: 703 | resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} 704 | engines: {node: '>=4'} 705 | dependencies: 706 | has-flag: 3.0.0 707 | dev: false 708 | 709 | /to-regex-range@5.0.1: 710 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 711 | engines: {node: '>=8.0'} 712 | dependencies: 713 | is-number: 7.0.0 714 | dev: false 715 | 716 | /toidentifier@1.0.1: 717 | resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} 718 | engines: {node: '>=0.6'} 719 | dev: false 720 | 721 | /touch@3.1.0: 722 | resolution: {integrity: sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==} 723 | hasBin: true 724 | dependencies: 725 | nopt: 1.0.10 726 | dev: false 727 | 728 | /type-is@1.6.18: 729 | resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} 730 | engines: {node: '>= 0.6'} 731 | dependencies: 732 | media-typer: 0.3.0 733 | mime-types: 2.1.35 734 | dev: false 735 | 736 | /undefsafe@2.0.5: 737 | resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} 738 | dev: false 739 | 740 | /unpipe@1.0.0: 741 | resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} 742 | engines: {node: '>= 0.8'} 743 | dev: false 744 | 745 | /utils-merge@1.0.1: 746 | resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} 747 | engines: {node: '>= 0.4.0'} 748 | dev: false 749 | 750 | /uuid@9.0.1: 751 | resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} 752 | hasBin: true 753 | dev: false 754 | 755 | /validator@13.11.0: 756 | resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==} 757 | engines: {node: '>= 0.10'} 758 | dev: false 759 | 760 | /vary@1.1.2: 761 | resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} 762 | engines: {node: '>= 0.8'} 763 | dev: false 764 | 765 | /yallist@4.0.0: 766 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} 767 | dev: false 768 | --------------------------------------------------------------------------------