From dd54e56c86d4e4c2c5c3a2cc3711e9b5de92f5a2 Mon Sep 17 00:00:00 2001 From: Naveen MC <8493007+mcnaveen@users.noreply.github.com> Date: Sun, 25 Aug 2024 19:19:38 +0530 Subject: [PATCH 1/3] refactor(core): :recycle: do refactor and add more language support --- README.md | 60 +- data/chinese/words.json | 102 ++ data/dutch/words.json | 1 - data/french/words.json | 52 + data/japanese/words.json | 502 +++++++++ data/spanish/words.json | 52 + data/turkish/words.json | 623 +++++++++++ index.js | 16 +- pnpm-lock.yaml | 2245 ++++++++++++++++++++++++++++++++++++++ routes/dutch.js | 35 - routes/en.js | 122 --- routes/english.js | 50 + routes/home.js | 5 +- routes/language.js | 45 + routes/pronounce.js | 30 - utils/headers.js | 10 - utils/index.js | 50 + utils/randomNum.js | 7 - 18 files changed, 3761 insertions(+), 246 deletions(-) create mode 100644 data/chinese/words.json create mode 100644 data/french/words.json create mode 100644 data/japanese/words.json create mode 100644 data/spanish/words.json create mode 100644 data/turkish/words.json create mode 100644 pnpm-lock.yaml delete mode 100644 routes/dutch.js delete mode 100644 routes/en.js create mode 100644 routes/english.js create mode 100644 routes/language.js delete mode 100644 routes/pronounce.js delete mode 100644 utils/headers.js create mode 100644 utils/index.js delete mode 100644 utils/randomNum.js diff --git a/README.md b/README.md index 21f4785..9b0fffb 100644 --- a/README.md +++ b/README.md @@ -10,18 +10,29 @@ 🦄 Get Random Words (with pronunciation) for Free using this API +## 🌍 Languages + +- English +- Dutch +- Spanish +- French +- Chinese +- Japanese + ## 🚀 API -- Free API - `https://random-words-api.vercel.app/word` +- English Random Words - `https://random-words-api.vercel.app/word` - Dutch Random Words - `https://random-words-api.vercel.app/word/dutch` -- Get Pronunciation for a Word - `https://random-words-api.vercel.app/pronounce/` +- Spanish Random Words - `https://random-words-api.vercel.app/word/spanish` +- French Random Words - `https://random-words-api.vercel.app/word/french` +- Chinese Random Words - `https://random-words-api.vercel.app/word/chinese` +- Japanese Random Words - `https://random-words-api.vercel.app/word/japanese` +- Turkish Random Words - `https://random-words-api.vercel.app/word/turkish` - PWA Demo - [Check Here](https://words.sanweb.info/) -## 🎛 Route Options - -- Base URL: `https://random-words-api.vercel.app/word` - +## 🎛 Route Options (English Only) +- Base URL: `https://random-words-api.vercel.app/word/english` ```text - /noun - /sentence @@ -68,28 +79,6 @@ ] ``` -## 🌐 Sample Pronunciation Request - -- API: `https://random-words-api.vercel.app/pronounce` -- Method: `POST` - -```sh -POST http://localhost:3000/pronounce -Content-Type: application/json - -{ - "word": "This is amazing" -} -``` - -## 📣 Sample Pronunciation Response - -```json -{ - "pronunciation": "this is amasink" -} -``` - - Check [api.rest](/test/api.rest) file for more details ## 💡 Learn New word @@ -101,16 +90,16 @@ Content-Type: application/json ```sh # Clone the Repo -git clone https://github.com/mcnaveen/Random-Words-API random-words +git clone https://github.com/mcnaveen/random-words-api random-words-api # Cd into Directory cd random-words # Install Dependencies -yarn install +npm install # Start the Development Server -yarn start +npm run dev ``` ## 🔀 Deploying to Heroku @@ -132,6 +121,15 @@ OR Project - Give Forked Repo URL - Go Live ``` +## 😇 Add New Language +- Create a new folder in `data` with the full language name `ex: english` +- Add the words in the `words.json` file +- It should be an array of objects with `id`, `word`, and `definition` properties +- The `id` should be a unique number for each word +- The `word` should be the word in the language +- The `definition` should be the definition of the word in English +- The `pronunciation` should be the pronunciation of the word in the language (Optional) + ## :question: How to Contribute? Make your changes and follow the below instructions. We follow conventional commits. diff --git a/data/chinese/words.json b/data/chinese/words.json new file mode 100644 index 0000000..6a8c7aa --- /dev/null +++ b/data/chinese/words.json @@ -0,0 +1,102 @@ +[ + {"id": 1, "word": "爱", "definition": "love"}, + {"id": 2, "word": "朋友", "definition": "friend"}, + {"id": 3, "word": "学校", "definition": "school"}, + {"id": 4, "word": "书", "definition": "book"}, + {"id": 5, "word": "电脑", "definition": "computer"}, + {"id": 6, "word": "家庭", "definition": "family"}, + {"id": 7, "word": "工作", "definition": "work"}, + {"id": 8, "word": "幸福", "definition": "happiness"}, + {"id": 9, "word": "水", "definition": "water"}, + {"id": 10, "word": "食物", "definition": "food"}, + {"id": 11, "word": "汽车", "definition": "car"}, + {"id": 12, "word": "电影", "definition": "movie"}, + {"id": 13, "word": "音乐", "definition": "music"}, + {"id": 14, "word": "城市", "definition": "city"}, + {"id": 15, "word": "旅行", "definition": "travel"}, + {"id": 16, "word": "健康", "definition": "health"}, + {"id": 17, "word": "运动", "definition": "exercise"}, + {"id": 18, "word": "老师", "definition": "teacher"}, + {"id": 19, "word": "学生", "definition": "student"}, + {"id": 20, "word": "电话", "definition": "telephone"}, + {"id": 21, "word": "电影", "definition": "film"}, + {"id": 22, "word": "艺术", "definition": "art"}, + {"id": 23, "word": "文化", "definition": "culture"}, + {"id": 24, "word": "语言", "definition": "language"}, + {"id": 25, "word": "历史", "definition": "history"}, + {"id": 26, "word": "科学", "definition": "science"}, + {"id": 27, "word": "数学", "definition": "mathematics"}, + {"id": 28, "word": "经济", "definition": "economics"}, + {"id": 29, "word": "政治", "definition": "politics"}, + {"id": 30, "word": "社会", "definition": "society"}, + {"id": 31, "word": "文学", "definition": "literature"}, + {"id": 32, "word": "哲学", "definition": "philosophy"}, + {"id": 33, "word": "法律", "definition": "law"}, + {"id": 34, "word": "医学", "definition": "medicine"}, + {"id": 35, "word": "工程", "definition": "engineering"}, + {"id": 36, "word": "计算机", "definition": "computer science"}, + {"id": 37, "word": "互联网", "definition": "internet"}, + {"id": 38, "word": "技术", "definition": "technology"}, + {"id": 39, "word": "交通", "definition": "transportation"}, + {"id": 40, "word": "自然", "definition": "nature"}, + {"id": 41, "word": "环境", "definition": "environment"}, + {"id": 42, "word": "空气", "definition": "air"}, + {"id": 43, "word": "土地", "definition": "land"}, + {"id": 44, "word": "能源", "definition": "energy"}, + {"id": 45, "word": "气候", "definition": "climate"}, + {"id": 46, "word": "动物", "definition": "animal"}, + {"id": 47, "word": "植物", "definition": "plant"}, + {"id": 48, "word": "海洋", "definition": "ocean"}, + {"id": 49, "word": "山", "definition": "mountain"}, + {"id": 50, "word": "河流", "definition": "river"}, + {"id": 51, "word": "湖泊", "definition": "lake"}, + {"id": 52, "word": "天气", "definition": "weather"}, + {"id": 53, "word": "风", "definition": "wind"}, + {"id": 54, "word": "雨", "definition": "rain"}, + {"id": 55, "word": "雪", "definition": "snow"}, + {"id": 56, "word": "太阳", "definition": "sun"}, + {"id": 57, "word": "月亮", "definition": "moon"}, + {"id": 58, "word": "星星", "definition": "star"}, + {"id": 59, "word": "宇宙", "definition": "universe"}, + {"id": 60, "word": "银河", "definition": "galaxy"}, + {"id": 61, "word": "太空", "definition": "space"}, + {"id": 62, "word": "星座", "definition": "constellation"}, + {"id": 63, "word": "地球", "definition": "Earth"}, + {"id": 64, "word": "太阳系", "definition": "solar system"}, + {"id": 65, "word": "黑洞", "definition": "black hole"}, + {"id": 66, "word": "星球", "definition": "planet"}, + {"id": 67, "word": "卫星", "definition": "satellite"}, + {"id": 68, "word": "宇航员", "definition": "astronaut"}, + {"id": 69, "word": "火箭", "definition": "rocket"}, + {"id": 70, "word": "飞船", "definition": "spaceship"}, + {"id": 71, "word": "探测器", "definition": "probe"}, + {"id": 72, "word": "任务", "definition": "mission"}, + {"id": 73, "word": "实验", "definition": "experiment"}, + {"id": 74, "word": "理论", "definition": "theory"}, + {"id": 75, "word": "发现", "definition": "discovery"}, + {"id": 76, "word": "研究", "definition": "research"}, + {"id": 77, "word": "数据", "definition": "data"}, + {"id": 78, "word": "信息", "definition": "information"}, + {"id": 79, "word": "知识", "definition": "knowledge"}, + {"id": 80, "word": "智慧", "definition": "wisdom"}, + {"id": 81, "word": "思考", "definition": "thinking"}, + {"id": 82, "word": "解决", "definition": "solve"}, + {"id": 83, "word": "创新", "definition": "innovation"}, + {"id": 84, "word": "发明", "definition": "invention"}, + {"id": 85, "word": "创造", "definition": "create"}, + {"id": 86, "word": "艺术家", "definition": "artist"}, + {"id": 87, "word": "画家", "definition": "painter"}, + {"id": 88, "word": "音乐家", "definition": "musician"}, + {"id": 89, "word": "作家", "definition": "writer"}, + {"id": 90, "word": "导演", "definition": "director"}, + {"id": 91, "word": "演员", "definition": "actor"}, + {"id": 92, "word": "舞蹈", "definition": "dance"}, + {"id": 93, "word": "戏剧", "definition": "drama"}, + {"id": 94, "word": "文学作品", "definition": "literary work"}, + {"id": 95, "word": "小说", "definition": "novel"}, + {"id": 96, "word": "诗歌", "definition": "poetry"}, + {"id": 97, "word": "散文", "definition": "prose"}, + {"id": 98, "word": "历史书", "definition": "history book"}, + {"id": 99, "word": "百科全书", "definition": "encyclopedia"}, + {"id": 100, "word": "字典", "definition": "dictionary"} +] diff --git a/data/dutch/words.json b/data/dutch/words.json index 8ba8e91..d4df7ac 100644 --- a/data/dutch/words.json +++ b/data/dutch/words.json @@ -2500,4 +2500,3 @@ "definition": "Affairs" } ] - diff --git a/data/french/words.json b/data/french/words.json new file mode 100644 index 0000000..c4202d4 --- /dev/null +++ b/data/french/words.json @@ -0,0 +1,52 @@ +[ + { "id": 1, "word": "amour", "definition": "love" }, + { "id": 2, "word": "ami", "definition": "friend" }, + { "id": 3, "word": "école", "definition": "school" }, + { "id": 4, "word": "livre", "definition": "book" }, + { "id": 5, "word": "ordinateur", "definition": "computer" }, + { "id": 6, "word": "famille", "definition": "family" }, + { "id": 7, "word": "travail", "definition": "work" }, + { "id": 8, "word": "bonheur", "definition": "happiness" }, + { "id": 9, "word": "eau", "definition": "water" }, + { "id": 10, "word": "nourriture", "definition": "food" }, + { "id": 11, "word": "voiture", "definition": "car" }, + { "id": 12, "word": "film", "definition": "movie" }, + { "id": 13, "word": "musique", "definition": "music" }, + { "id": 14, "word": "ville", "definition": "city" }, + { "id": 15, "word": "voyage", "definition": "travel" }, + { "id": 16, "word": "santé", "definition": "health" }, + { "id": 17, "word": "exercice", "definition": "exercise" }, + { "id": 18, "word": "enseignant", "definition": "teacher" }, + { "id": 19, "word": "élève", "definition": "student" }, + { "id": 20, "word": "téléphone", "definition": "telephone" }, + { "id": 21, "word": "maison", "definition": "house" }, + { "id": 22, "word": "porte", "definition": "door" }, + { "id": 23, "word": "fenêtre", "definition": "window" }, + { "id": 24, "word": "chaise", "definition": "chair" }, + { "id": 25, "word": "table", "definition": "table" }, + { "id": 26, "word": "soupe", "definition": "soup" }, + { "id": 27, "word": "pain", "definition": "bread" }, + { "id": 28, "word": "lait", "definition": "milk" }, + { "id": 29, "word": "fruit", "definition": "fruit" }, + { "id": 30, "word": "légume", "definition": "vegetable" }, + { "id": 31, "word": "enfant", "definition": "child" }, + { "id": 32, "word": "adulte", "definition": "adult" }, + { "id": 33, "word": "étoile", "definition": "star" }, + { "id": 34, "word": "lune", "definition": "moon" }, + { "id": 35, "word": "soleil", "definition": "sun" }, + { "id": 36, "word": "nuage", "definition": "cloud" }, + { "id": 37, "word": "pluie", "definition": "rain" }, + { "id": 38, "word": "vent", "definition": "wind" }, + { "id": 39, "word": "neige", "definition": "snow" }, + { "id": 40, "word": "mer", "definition": "sea" }, + { "id": 41, "word": "montagne", "definition": "mountain" }, + { "id": 42, "word": "rivière", "definition": "river" }, + { "id": 43, "word": "lac", "definition": "lake" }, + { "id": 44, "word": "plage", "definition": "beach" }, + { "id": 45, "word": "forêt", "definition": "forest" }, + { "id": 46, "word": "désert", "definition": "desert" }, + { "id": 47, "word": "île", "definition": "island" }, + { "id": 48, "word": "village", "definition": "village" }, + { "id": 49, "word": "citoyen", "definition": "citizen" }, + { "id": 50, "word": "gens", "definition": "people" } +] diff --git a/data/japanese/words.json b/data/japanese/words.json new file mode 100644 index 0000000..300088a --- /dev/null +++ b/data/japanese/words.json @@ -0,0 +1,502 @@ +[ + { "id": 1, "word": "こんにちは", "definition": "Hello" }, + { "id": 2, "word": "さようなら", "definition": "Goodbye" }, + { "id": 3, "word": "ありがとう", "definition": "Thank you" }, + { "id": 4, "word": "はい", "definition": "Yes" }, + { "id": 5, "word": "いいえ", "definition": "No" }, + { "id": 6, "word": "おはよう", "definition": "Good morning" }, + { "id": 7, "word": "こんばんは", "definition": "Good evening" }, + { "id": 8, "word": "おやすみ", "definition": "Good night" }, + { "id": 9, "word": "すみません", "definition": "Excuse me" }, + { "id": 10, "word": "どういたしまして", "definition": "You're welcome" }, + { "id": 11, "word": "はい、そうです", "definition": "Yes, that's right" }, + { "id": 12, "word": "いいえ、違います", "definition": "No, that's wrong" }, + { "id": 13, "word": "お元気ですか", "definition": "How are you?" }, + { "id": 14, "word": "元気です", "definition": "I am fine" }, + { "id": 15, "word": "お名前は何ですか", "definition": "What is your name?" }, + { "id": 16, "word": "私の名前は", "definition": "My name is" }, + { "id": 17, "word": "どこですか", "definition": "Where is it?" }, + { "id": 18, "word": "ここ", "definition": "Here" }, + { "id": 19, "word": "そこ", "definition": "There" }, + { "id": 20, "word": "あそこ", "definition": "Over there" }, + { "id": 21, "word": "何時ですか", "definition": "What time is it?" }, + { "id": 22, "word": "今", "definition": "Now" }, + { "id": 23, "word": "朝", "definition": "Morning" }, + { "id": 24, "word": "昼", "definition": "Afternoon" }, + { "id": 25, "word": "夜", "definition": "Night" }, + { "id": 26, "word": "月曜日", "definition": "Monday" }, + { "id": 27, "word": "火曜日", "definition": "Tuesday" }, + { "id": 28, "word": "水曜日", "definition": "Wednesday" }, + { "id": 29, "word": "木曜日", "definition": "Thursday" }, + { "id": 30, "word": "金曜日", "definition": "Friday" }, + { "id": 31, "word": "土曜日", "definition": "Saturday" }, + { "id": 32, "word": "日曜日", "definition": "Sunday" }, + { "id": 33, "word": "春", "definition": "Spring" }, + { "id": 34, "word": "夏", "definition": "Summer" }, + { "id": 35, "word": "秋", "definition": "Autumn" }, + { "id": 36, "word": "冬", "definition": "Winter" }, + { "id": 37, "word": "天気", "definition": "Weather" }, + { "id": 38, "word": "晴れ", "definition": "Sunny" }, + { "id": 39, "word": "雨", "definition": "Rain" }, + { "id": 40, "word": "雪", "definition": "Snow" }, + { "id": 41, "word": "風", "definition": "Wind" }, + { "id": 42, "word": "雲", "definition": "Cloud" }, + { "id": 43, "word": "気温", "definition": "Temperature" }, + { "id": 44, "word": "寒い", "definition": "Cold" }, + { "id": 45, "word": "暑い", "definition": "Hot" }, + { "id": 46, "word": "涼しい", "definition": "Cool" }, + { "id": 47, "word": "暖かい", "definition": "Warm" }, + { "id": 48, "word": "食べる", "definition": "To eat" }, + { "id": 49, "word": "飲む", "definition": "To drink" }, + { "id": 50, "word": "見る", "definition": "To see" }, + { "id": 51, "word": "聞く", "definition": "To listen" }, + { "id": 52, "word": "話す", "definition": "To speak" }, + { "id": 53, "word": "読む", "definition": "To read" }, + { "id": 54, "word": "書く", "definition": "To write" }, + { "id": 55, "word": "行く", "definition": "To go" }, + { "id": 56, "word": "来る", "definition": "To come" }, + { "id": 57, "word": "買う", "definition": "To buy" }, + { "id": 58, "word": "売る", "definition": "To sell" }, + { "id": 59, "word": "作る", "definition": "To make" }, + { "id": 60, "word": "使う", "definition": "To use" }, + { "id": 61, "word": "遊ぶ", "definition": "To play" }, + { "id": 62, "word": "働く", "definition": "To work" }, + { "id": 63, "word": "休む", "definition": "To rest" }, + { "id": 64, "word": "学ぶ", "definition": "To learn" }, + { "id": 65, "word": "教える", "definition": "To teach" }, + { "id": 66, "word": "知る", "definition": "To know" }, + { "id": 67, "word": "思う", "definition": "To think" }, + { "id": 68, "word": "感じる", "definition": "To feel" }, + { "id": 69, "word": "信じる", "definition": "To believe" }, + { "id": 70, "word": "待つ", "definition": "To wait" }, + { "id": 71, "word": "走る", "definition": "To run" }, + { "id": 72, "word": "泳ぐ", "definition": "To swim" }, + { "id": 73, "word": "飛ぶ", "definition": "To fly" }, + { "id": 74, "word": "乗る", "definition": "To ride" }, + { "id": 75, "word": "降りる", "definition": "To get off" }, + { "id": 76, "word": "入る", "definition": "To enter" }, + { "id": 77, "word": "出る", "definition": "To exit" }, + { "id": 78, "word": "見る", "definition": "To watch" }, + { "id": 79, "word": "聞こえる", "definition": "To be heard" }, + { "id": 80, "word": "話せる", "definition": "To be able to speak" }, + { "id": 81, "word": "知っている", "definition": "To know" }, + { "id": 82, "word": "理解する", "definition": "To understand" }, + { "id": 83, "word": "忘れる", "definition": "To forget" }, + { "id": 84, "word": "思い出す", "definition": "To remember" }, + { "id": 85, "word": "選ぶ", "definition": "To choose" }, + { "id": 86, "word": "決める", "definition": "To decide" }, + { "id": 87, "word": "始める", "definition": "To start" }, + { "id": 88, "word": "終わる", "definition": "To finish" }, + { "id": 89, "word": "続ける", "definition": "To continue" }, + { "id": 90, "word": "変える", "definition": "To change" }, + { "id": 91, "word": "直す", "definition": "To fix" }, + { "id": 92, "word": "選択する", "definition": "To select" }, + { "id": 93, "word": "計画する", "definition": "To plan" }, + { "id": 94, "word": "準備する", "definition": "To prepare" }, + { "id": 95, "word": "掃除する", "definition": "To clean" }, + { "id": 96, "word": "洗う", "definition": "To wash" }, + { "id": 97, "word": "料理する", "definition": "To cook" }, + { "id": 98, "word": "食事する", "definition": "To dine" }, + { "id": 99, "word": "運転する", "definition": "To drive" }, + { "id": 100, "word": "旅行する", "definition": "To travel" }, + { "id": 101, "word": "遊びに行く", "definition": "To go out to play" }, + { "id": 102, "word": "買い物する", "definition": "To go shopping" }, + { "id": 103, "word": "散歩する", "definition": "To take a walk" }, + { "id": 104, "word": "運動する", "definition": "To exercise" }, + { "id": 105, "word": "勉強する", "definition": "To study" }, + { "id": 106, "word": "仕事をする", "definition": "To work" }, + { "id": 107, "word": "休暇を取る", "definition": "To take a vacation" }, + { "id": 108, "word": "遊ぶ", "definition": "To have fun" }, + { "id": 109, "word": "楽しむ", "definition": "To enjoy" }, + { "id": 110, "word": "笑う", "definition": "To laugh" }, + { "id": 111, "word": "泣く", "definition": "To cry" }, + { "id": 112, "word": "怒る", "definition": "To get angry" }, + { "id": 113, "word": "驚く", "definition": "To be surprised" }, + { "id": 114, "word": "喜ぶ", "definition": "To be happy" }, + { "id": 115, "word": "悲しむ", "definition": "To be sad" }, + { "id": 116, "word": "愛する", "definition": "To love" }, + { "id": 117, "word": "嫌う", "definition": "To hate" }, + { "id": 118, "word": "信じる", "definition": "To trust" }, + { "id": 119, "word": "疑う", "definition": "To doubt" }, + { "id": 120, "word": "助ける", "definition": "To help" }, + { "id": 121, "word": "支える", "definition": "To support" }, + { "id": 122, "word": "守る", "definition": "To protect" }, + { "id": 123, "word": "攻撃する", "definition": "To attack" }, + { "id": 124, "word": "戦う", "definition": "To fight" }, + { "id": 125, "word": "勝つ", "definition": "To win" }, + { "id": 126, "word": "負ける", "definition": "To lose" }, + { "id": 127, "word": "競争する", "definition": "To compete" }, + { "id": 128, "word": "協力する", "definition": "To cooperate" }, + { "id": 129, "word": "約束する", "definition": "To promise" }, + { "id": 130, "word": "信頼する", "definition": "To rely on" }, + { "id": 131, "word": "感謝する", "definition": "To appreciate" }, + { "id": 132, "word": "謝る", "definition": "To apologize" }, + { "id": 133, "word": "許す", "definition": "To forgive" }, + { "id": 134, "word": "理解する", "definition": "To comprehend" }, + { "id": 135, "word": "説明する", "definition": "To explain" }, + { "id": 136, "word": "示す", "definition": "To show" }, + { "id": 137, "word": "教える", "definition": "To inform" }, + { "id": 138, "word": "伝える", "definition": "To convey" }, + { "id": 139, "word": "表現する", "definition": "To express" }, + { "id": 140, "word": "描く", "definition": "To draw" }, + { "id": 141, "word": "作成する", "definition": "To create" }, + { "id": 142, "word": "発表する", "definition": "To present" }, + { "id": 143, "word": "発見する", "definition": "To discover" }, + { "id": 144, "word": "発展する", "definition": "To develop" }, + { "id": 145, "word": "進む", "definition": "To advance" }, + { "id": 146, "word": "成長する", "definition": "To grow" }, + { "id": 147, "word": "変化する", "definition": "To change" }, + { "id": 148, "word": "進化する", "definition": "To evolve" }, + { "id": 149, "word": "改善する", "definition": "To improve" }, + { "id": 150, "word": "修正する", "definition": "To correct" }, + { "id": 151, "word": "更新する", "definition": "To update" }, + { "id": 152, "word": "調整する", "definition": "To adjust" }, + { "id": 153, "word": "整理する", "definition": "To organize" }, + { "id": 154, "word": "計画する", "definition": "To plan" }, + { "id": 155, "word": "準備する", "definition": "To prepare" }, + { "id": 156, "word": "実行する", "definition": "To execute" }, + { "id": 157, "word": "確認する", "definition": "To confirm" }, + { "id": 158, "word": "評価する", "definition": "To evaluate" }, + { "id": 159, "word": "分析する", "definition": "To analyze" }, + { "id": 160, "word": "調査する", "definition": "To investigate" }, + { "id": 161, "word": "研究する", "definition": "To research" }, + { "id": 162, "word": "発表する", "definition": "To announce" }, + { "id": 163, "word": "報告する", "definition": "To report" }, + { "id": 164, "word": "記録する", "definition": "To record" }, + { "id": 165, "word": "保存する", "definition": "To save" }, + { "id": 166, "word": "共有する", "definition": "To share" }, + { "id": 167, "word": "配布する", "definition": "To distribute" }, + { "id": 168, "word": "提供する", "definition": "To provide" }, + { "id": 169, "word": "支援する", "definition": "To assist" }, + { "id": 170, "word": "協力する", "definition": "To collaborate" }, + { "id": 171, "word": "参加する", "definition": "To participate" }, + { "id": 172, "word": "出席する", "definition": "To attend" }, + { "id": 173, "word": "退席する", "definition": "To leave" }, + { "id": 174, "word": "連絡する", "definition": "To contact" }, + { "id": 175, "word": "相談する", "definition": "To consult" }, + { "id": 176, "word": "提案する", "definition": "To suggest" }, + { "id": 177, "word": "依頼する", "definition": "To request" }, + { "id": 178, "word": "承認する", "definition": "To approve" }, + { "id": 179, "word": "拒否する", "definition": "To reject" }, + { "id": 180, "word": "確認する", "definition": "To verify" }, + { "id": 181, "word": "承諾する", "definition": "To consent" }, + { "id": 182, "word": "約束する", "definition": "To promise" }, + { "id": 183, "word": "契約する", "definition": "To contract" }, + { "id": 184, "word": "解決する", "definition": "To resolve" }, + { "id": 185, "word": "解決策", "definition": "Solution" }, + { "id": 186, "word": "問題", "definition": "Problem" }, + { "id": 187, "word": "課題", "definition": "Challenge" }, + { "id": 188, "word": "目標", "definition": "Goal" }, + { "id": 189, "word": "目的", "definition": "Objective" }, + { "id": 190, "word": "計画", "definition": "Plan" }, + { "id": 191, "word": "戦略", "definition": "Strategy" }, + { "id": 192, "word": "方針", "definition": "Policy" }, + { "id": 193, "word": "手段", "definition": "Means" }, + { "id": 194, "word": "方法", "definition": "Method" }, + { "id": 195, "word": "技術", "definition": "Technology" }, + { "id": 196, "word": "知識", "definition": "Knowledge" }, + { "id": 197, "word": "情報", "definition": "Information" }, + { "id": 198, "word": "データ", "definition": "Data" }, + { "id": 199, "word": "分析", "definition": "Analysis" }, + { "id": 200, "word": "結果", "definition": "Result" }, + { "id": 201, "word": "成果", "definition": "Achievement" }, + { "id": 202, "word": "評価", "definition": "Evaluation" }, + { "id": 203, "word": "改善", "definition": "Improvement" }, + { "id": 204, "word": "進展", "definition": "Progress" }, + { "id": 205, "word": "発展", "definition": "Development" }, + { "id": 206, "word": "成長", "definition": "Growth" }, + { "id": 207, "word": "変化", "definition": "Change" }, + { "id": 208, "word": "進化", "definition": "Evolution" }, + { "id": 209, "word": "革新", "definition": "Innovation" }, + { "id": 210, "word": "創造", "definition": "Creation" }, + { "id": 211, "word": "発明", "definition": "Invention" }, + { "id": 212, "word": "発見", "definition": "Discovery" }, + { "id": 213, "word": "探求", "definition": "Exploration" }, + { "id": 214, "word": "研究", "definition": "Research" }, + { "id": 215, "word": "調査", "definition": "Investigation" }, + { "id": 216, "word": "分析", "definition": "Analysis" }, + { "id": 217, "word": "評価", "definition": "Assessment" }, + { "id": 218, "word": "報告", "definition": "Report" }, + { "id": 219, "word": "記録", "definition": "Record" }, + { "id": 220, "word": "保存", "definition": "Preservation" }, + { "id": 221, "word": "共有", "definition": "Sharing" }, + { "id": 222, "word": "配布", "definition": "Distribution" }, + { "id": 223, "word": "提供", "definition": "Provision" }, + { "id": 224, "word": "支援", "definition": "Support" }, + { "id": 225, "word": "協力", "definition": "Cooperation" }, + { "id": 226, "word": "参加", "definition": "Participation" }, + { "id": 227, "word": "出席", "definition": "Attendance" }, + { "id": 228, "word": "退席", "definition": "Absence" }, + { "id": 229, "word": "連絡", "definition": "Contact" }, + { "id": 230, "word": "相談", "definition": "Consultation" }, + { "id": 231, "word": "提案", "definition": "Proposal" }, + { "id": 232, "word": "依頼", "definition": "Request" }, + { "id": 233, "word": "承認", "definition": "Approval" }, + { "id": 234, "word": "拒否", "definition": "Rejection" }, + { "id": 235, "word": "確認", "definition": "Confirmation" }, + { "id": 236, "word": "承諾", "definition": "Consent" }, + { "id": 237, "word": "約束", "definition": "Promise" }, + { "id": 238, "word": "契約", "definition": "Contract" }, + { "id": 239, "word": "解決", "definition": "Resolution" }, + { "id": 240, "word": "問題", "definition": "Issue" }, + { "id": 241, "word": "課題", "definition": "Task" }, + { "id": 242, "word": "目標", "definition": "Target" }, + { "id": 243, "word": "目的", "definition": "Aim" }, + { "id": 244, "word": "計画", "definition": "Scheme" }, + { "id": 245, "word": "戦略", "definition": "Tactics" }, + { "id": 246, "word": "方針", "definition": "Guideline" }, + { "id": 247, "word": "手段", "definition": "Method" }, + { "id": 248, "word": "方法", "definition": "Procedure" }, + { "id": 249, "word": "技術", "definition": "Skill" }, + { "id": 250, "word": "知識", "definition": "Wisdom" }, + { "id": 251, "word": "情報", "definition": "Intelligence" }, + { "id": 252, "word": "データ", "definition": "Statistics" }, + { "id": 253, "word": "分析", "definition": "Examination" }, + { "id": 254, "word": "結果", "definition": "Outcome" }, + { "id": 255, "word": "成果", "definition": "Success" }, + { "id": 256, "word": "評価", "definition": "Review" }, + { "id": 257, "word": "改善", "definition": "Enhancement" }, + { "id": 258, "word": "進展", "definition": "Advancement" }, + { "id": 259, "word": "発展", "definition": "Progression" }, + { "id": 260, "word": "成長", "definition": "Development" }, + { "id": 261, "word": "変化", "definition": "Transformation" }, + { "id": 262, "word": "進化", "definition": "Metamorphosis" }, + { "id": 263, "word": "革新", "definition": "Revolution" }, + { "id": 264, "word": "創造", "definition": "Creation" }, + { "id": 265, "word": "発明", "definition": "Invention" }, + { "id": 266, "word": "発見", "definition": "Discovery" }, + { "id": 267, "word": "探求", "definition": "Quest" }, + { "id": 268, "word": "研究", "definition": "Study" }, + { "id": 269, "word": "調査", "definition": "Survey" }, + { "id": 270, "word": "分析", "definition": "Scrutiny" }, + { "id": 271, "word": "評価", "definition": "Assessment" }, + { "id": 272, "word": "報告", "definition": "Report" }, + { "id": 273, "word": "記録", "definition": "Documentation" }, + { "id": 274, "word": "保存", "definition": "Conservation" }, + { "id": 275, "word": "共有", "definition": "Distribution" }, + { "id": 276, "word": "配布", "definition": "Dispersion" }, + { "id": 277, "word": "提供", "definition": "Supply" }, + { "id": 278, "word": "支援", "definition": "Aid" }, + { "id": 279, "word": "協力", "definition": "Collaboration" }, + { "id": 280, "word": "参加", "definition": "Engagement" }, + { "id": 281, "word": "出席", "definition": "Presence" }, + { "id": 282, "word": "退席", "definition": "Departure" }, + { "id": 283, "word": "連絡", "definition": "Communication" }, + { "id": 284, "word": "相談", "definition": "Advice" }, + { "id": 285, "word": "提案", "definition": "Suggestion" }, + { "id": 286, "word": "依頼", "definition": "Solicitation" }, + { "id": 287, "word": "承認", "definition": "Validation" }, + { "id": 288, "word": "拒否", "definition": "Denial" }, + { "id": 289, "word": "確認", "definition": "Verification" }, + { "id": 290, "word": "承諾", "definition": "Agreement" }, + { "id": 291, "word": "約束", "definition": "Commitment" }, + { "id": 292, "word": "契約", "definition": "Pact" }, + { "id": 293, "word": "解決", "definition": "Solution" }, + { "id": 294, "word": "問題", "definition": "Challenge" }, + { "id": 295, "word": "課題", "definition": "Issue" }, + { "id": 296, "word": "目標", "definition": "Aim" }, + { "id": 297, "word": "目的", "definition": "Intention" }, + { "id": 298, "word": "計画", "definition": "Blueprint" }, + { "id": 299, "word": "戦略", "definition": "Plan" }, + { "id": 300, "word": "方針", "definition": "Direction" }, + { "id": 301, "word": "手段", "definition": "Approach" }, + { "id": 302, "word": "方法", "definition": "Technique" }, + { "id": 303, "word": "技術", "definition": "Expertise" }, + { "id": 304, "word": "知識", "definition": "Insight" }, + { "id": 305, "word": "情報", "definition": "Data" }, + { "id": 306, "word": "データ", "definition": "Information" }, + { "id": 307, "word": "分析", "definition": "Examination" }, + { "id": 308, "word": "結果", "definition": "Outcome" }, + { "id": 309, "word": "成果", "definition": "Result" }, + { "id": 310, "word": "評価", "definition": "Review" }, + { "id": 311, "word": "改善", "definition": "Enhancement" }, + { "id": 312, "word": "進展", "definition": "Progress" }, + { "id": 313, "word": "発展", "definition": "Growth" }, + { "id": 314, "word": "成長", "definition": "Development" }, + { "id": 315, "word": "変化", "definition": "Alteration" }, + { "id": 316, "word": "進化", "definition": "Evolution" }, + { "id": 317, "word": "革新", "definition": "Innovation" }, + { "id": 318, "word": "創造", "definition": "Creation" }, + { "id": 319, "word": "発明", "definition": "Invention" }, + { "id": 320, "word": "発見", "definition": "Discovery" }, + { "id": 321, "word": "探求", "definition": "Exploration" }, + { "id": 322, "word": "研究", "definition": "Research" }, + { "id": 323, "word": "調査", "definition": "Investigation" }, + { "id": 324, "word": "分析", "definition": "Analysis" }, + { "id": 325, "word": "評価", "definition": "Assessment" }, + { "id": 326, "word": "報告", "definition": "Report" }, + { "id": 327, "word": "記録", "definition": "Record" }, + { "id": 328, "word": "保存", "definition": "Preservation" }, + { "id": 329, "word": "共有", "definition": "Sharing" }, + { "id": 330, "word": "配布", "definition": "Distribution" }, + { "id": 331, "word": "提供", "definition": "Provision" }, + { "id": 332, "word": "支援", "definition": "Support" }, + { "id": 333, "word": "協力", "definition": "Cooperation" }, + { "id": 334, "word": "参加", "definition": "Participation" }, + { "id": 335, "word": "出席", "definition": "Attendance" }, + { "id": 336, "word": "退席", "definition": "Absence" }, + { "id": 337, "word": "連絡", "definition": "Contact" }, + { "id": 338, "word": "相談", "definition": "Consultation" }, + { "id": 339, "word": "提案", "definition": "Proposal" }, + { "id": 340, "word": "依頼", "definition": "Request" }, + { "id": 341, "word": "承認", "definition": "Approval" }, + { "id": 342, "word": "拒否", "definition": "Rejection" }, + { "id": 343, "word": "確認", "definition": "Confirmation" }, + { "id": 344, "word": "承諾", "definition": "Consent" }, + { "id": 345, "word": "約束", "definition": "Promise" }, + { "id": 346, "word": "契約", "definition": "Contract" }, + { "id": 347, "word": "解決", "definition": "Solution" }, + { "id": 348, "word": "問題", "definition": "Challenge" }, + { "id": 349, "word": "課題", "definition": "Issue" }, + { "id": 350, "word": "目標", "definition": "Aim" }, + { "id": 351, "word": "目的", "definition": "Intention" }, + { "id": 352, "word": "計画", "definition": "Blueprint" }, + { "id": 353, "word": "戦略", "definition": "Plan" }, + { "id": 354, "word": "方針", "definition": "Direction" }, + { "id": 355, "word": "手段", "definition": "Approach" }, + { "id": 356, "word": "方法", "definition": "Technique" }, + { "id": 357, "word": "技術", "definition": "Expertise" }, + { "id": 358, "word": "知識", "definition": "Insight" }, + { "id": 359, "word": "情報", "definition": "Data" }, + { "id": 360, "word": "データ", "definition": "Information" }, + { "id": 361, "word": "分析", "definition": "Examination" }, + { "id": 362, "word": "結果", "definition": "Outcome" }, + { "id": 363, "word": "成果", "definition": "Result" }, + { "id": 364, "word": "評価", "definition": "Review" }, + { "id": 365, "word": "改善", "definition": "Enhancement" }, + { "id": 366, "word": "進展", "definition": "Progress" }, + { "id": 367, "word": "発展", "definition": "Growth" }, + { "id": 368, "word": "成長", "definition": "Development" }, + { "id": 369, "word": "変化", "definition": "Alteration" }, + { "id": 370, "word": "進化", "definition": "Evolution" }, + { "id": 371, "word": "革新", "definition": "Innovation" }, + { "id": 372, "word": "創造", "definition": "Creation" }, + { "id": 373, "word": "発明", "definition": "Invention" }, + { "id": 374, "word": "発見", "definition": "Discovery" }, + { "id": 375, "word": "探求", "definition": "Exploration" }, + { "id": 376, "word": "研究", "definition": "Research" }, + { "id": 377, "word": "調査", "definition": "Investigation" }, + { "id": 378, "word": "分析", "definition": "Analysis" }, + { "id": 379, "word": "評価", "definition": "Assessment" }, + { "id": 380, "word": "報告", "definition": "Report" }, + { "id": 381, "word": "記録", "definition": "Record" }, + { "id": 382, "word": "保存", "definition": "Preservation" }, + { "id": 383, "word": "共有", "definition": "Sharing" }, + { "id": 384, "word": "配布", "definition": "Distribution" }, + { "id": 385, "word": "提供", "definition": "Provision" }, + { "id": 386, "word": "支援", "definition": "Support" }, + { "id": 387, "word": "協力", "definition": "Cooperation" }, + { "id": 388, "word": "参加", "definition": "Participation" }, + { "id": 389, "word": "出席", "definition": "Attendance" }, + { "id": 390, "word": "退席", "definition": "Absence" }, + { "id": 391, "word": "連絡", "definition": "Contact" }, + { "id": 392, "word": "相談", "definition": "Consultation" }, + { "id": 393, "word": "提案", "definition": "Proposal" }, + { "id": 394, "word": "依頼", "definition": "Request" }, + { "id": 395, "word": "承認", "definition": "Approval" }, + { "id": 396, "word": "拒否", "definition": "Rejection" }, + { "id": 397, "word": "確認", "definition": "Confirmation" }, + { "id": 398, "word": "承諾", "definition": "Consent" }, + { "id": 399, "word": "約束", "definition": "Promise" }, + { "id": 400, "word": "契約", "definition": "Contract" }, + { "id": 401, "word": "解決", "definition": "Solution" }, + { "id": 402, "word": "問題", "definition": "Challenge" }, + { "id": 403, "word": "課題", "definition": "Issue" }, + { "id": 404, "word": "目標", "definition": "Aim" }, + { "id": 405, "word": "目的", "definition": "Intention" }, + { "id": 406, "word": "計画", "definition": "Blueprint" }, + { "id": 407, "word": "戦略", "definition": "Plan" }, + { "id": 408, "word": "方針", "definition": "Direction" }, + { "id": 409, "word": "手段", "definition": "Approach" }, + { "id": 410, "word": "方法", "definition": "Technique" }, + { "id": 411, "word": "技術", "definition": "Expertise" }, + { "id": 412, "word": "知識", "definition": "Insight" }, + { "id": 413, "word": "情報", "definition": "Data" }, + { "id": 414, "word": "データ", "definition": "Information" }, + { "id": 415, "word": "分析", "definition": "Examination" }, + { "id": 416, "word": "結果", "definition": "Outcome" }, + { "id": 417, "word": "成果", "definition": "Result" }, + { "id": 418, "word": "評価", "definition": "Review" }, + { "id": 419, "word": "改善", "definition": "Enhancement" }, + { "id": 420, "word": "進展", "definition": "Progress" }, + { "id": 421, "word": "発展", "definition": "Growth" }, + { "id": 422, "word": "成長", "definition": "Development" }, + { "id": 423, "word": "変化", "definition": "Alteration" }, + { "id": 424, "word": "進化", "definition": "Evolution" }, + { "id": 425, "word": "革新", "definition": "Innovation" }, + { "id": 426, "word": "創造", "definition": "Creation" }, + { "id": 427, "word": "発明", "definition": "Invention" }, + { "id": 428, "word": "発見", "definition": "Discovery" }, + { "id": 429, "word": "探求", "definition": "Exploration" }, + { "id": 430, "word": "研究", "definition": "Research" }, + { "id": 431, "word": "調査", "definition": "Investigation" }, + { "id": 432, "word": "分析", "definition": "Analysis" }, + { "id": 433, "word": "評価", "definition": "Assessment" }, + { "id": 434, "word": "報告", "definition": "Report" }, + { "id": 435, "word": "記録", "definition": "Record" }, + { "id": 436, "word": "保存", "definition": "Preservation" }, + { "id": 437, "word": "共有", "definition": "Sharing" }, + { "id": 438, "word": "配布", "definition": "Distribution" }, + { "id": 439, "word": "提供", "definition": "Provision" }, + { "id": 440, "word": "支援", "definition": "Support" }, + { "id": 441, "word": "協力", "definition": "Cooperation" }, + { "id": 442, "word": "参加", "definition": "Participation" }, + { "id": 443, "word": "出席", "definition": "Attendance" }, + { "id": 444, "word": "退席", "definition": "Absence" }, + { "id": 445, "word": "連絡", "definition": "Contact" }, + { "id": 446, "word": "相談", "definition": "Consultation" }, + { "id": 447, "word": "提案", "definition": "Proposal" }, + { "id": 448, "word": "依頼", "definition": "Request" }, + { "id": 449, "word": "承認", "definition": "Approval" }, + { "id": 450, "word": "拒否", "definition": "Rejection" }, + { "id": 451, "word": "確認", "definition": "Confirmation" }, + { "id": 452, "word": "承諾", "definition": "Consent" }, + { "id": 453, "word": "約束", "definition": "Promise" }, + { "id": 454, "word": "契約", "definition": "Contract" }, + { "id": 455, "word": "解決", "definition": "Solution" }, + { "id": 456, "word": "問題", "definition": "Challenge" }, + { "id": 457, "word": "課題", "definition": "Issue" }, + { "id": 458, "word": "目標", "definition": "Aim" }, + { "id": 459, "word": "目的", "definition": "Intention" }, + { "id": 460, "word": "計画", "definition": "Blueprint" }, + { "id": 461, "word": "戦略", "definition": "Plan" }, + { "id": 462, "word": "方針", "definition": "Direction" }, + { "id": 463, "word": "手段", "definition": "Approach" }, + { "id": 464, "word": "方法", "definition": "Technique" }, + { "id": 465, "word": "技術", "definition": "Expertise" }, + { "id": 466, "word": "知識", "definition": "Insight" }, + { "id": 467, "word": "情報", "definition": "Data" }, + { "id": 468, "word": "データ", "definition": "Information" }, + { "id": 469, "word": "分析", "definition": "Examination" }, + { "id": 470, "word": "結果", "definition": "Outcome" }, + { "id": 471, "word": "成果", "definition": "Result" }, + { "id": 472, "word": "評価", "definition": "Review" }, + { "id": 473, "word": "改善", "definition": "Enhancement" }, + { "id": 474, "word": "進展", "definition": "Progress" }, + { "id": 475, "word": "発展", "definition": "Growth" }, + { "id": 476, "word": "成長", "definition": "Development" }, + { "id": 477, "word": "変化", "definition": "Alteration" }, + { "id": 478, "word": "進化", "definition": "Evolution" }, + { "id": 479, "word": "革新", "definition": "Innovation" }, + { "id": 480, "word": "創造", "definition": "Creation" }, + { "id": 481, "word": "発明", "definition": "Invention" }, + { "id": 482, "word": "発見", "definition": "Discovery" }, + { "id": 483, "word": "探求", "definition": "Exploration" }, + { "id": 484, "word": "研究", "definition": "Research" }, + { "id": 485, "word": "調査", "definition": "Investigation" }, + { "id": 486, "word": "分析", "definition": "Analysis" }, + { "id": 487, "word": "評価", "definition": "Assessment" }, + { "id": 488, "word": "報告", "definition": "Report" }, + { "id": 489, "word": "記録", "definition": "Record" }, + { "id": 490, "word": "保存", "definition": "Preservation" }, + { "id": 491, "word": "共有", "definition": "Sharing" }, + { "id": 492, "word": "配布", "definition": "Distribution" }, + { "id": 493, "word": "提供", "definition": "Provision" }, + { "id": 494, "word": "支援", "definition": "Support" }, + { "id": 495, "word": "協力", "definition": "Cooperation" }, + { "id": 496, "word": "参加", "definition": "Participation" }, + { "id": 497, "word": "出席", "definition": "Attendance" }, + { "id": 498, "word": "退席", "definition": "Absence" }, + { "id": 499, "word": "連絡", "definition": "Contact" }, + { "id": 500, "word": "相談", "definition": "Consultation" } +] diff --git a/data/spanish/words.json b/data/spanish/words.json new file mode 100644 index 0000000..94895e4 --- /dev/null +++ b/data/spanish/words.json @@ -0,0 +1,52 @@ +[ + {"id": 1, "word": "amor", "definition": "love"}, + {"id": 2, "word": "amigo", "definition": "friend"}, + {"id": 3, "word": "escuela", "definition": "school"}, + {"id": 4, "word": "libro", "definition": "book"}, + {"id": 5, "word": "computadora", "definition": "computer"}, + {"id": 6, "word": "familia", "definition": "family"}, + {"id": 7, "word": "trabajo", "definition": "work"}, + {"id": 8, "word": "felicidad", "definition": "happiness"}, + {"id": 9, "word": "agua", "definition": "water"}, + {"id": 10, "word": "comida", "definition": "food"}, + {"id": 11, "word": "automóvil", "definition": "car"}, + {"id": 12, "word": "película", "definition": "movie"}, + {"id": 13, "word": "música", "definition": "music"}, + {"id": 14, "word": "ciudad", "definition": "city"}, + {"id": 15, "word": "viaje", "definition": "travel"}, + {"id": 16, "word": "salud", "definition": "health"}, + {"id": 17, "word": "ejercicio", "definition": "exercise"}, + {"id": 18, "word": "profesor", "definition": "teacher"}, + {"id": 19, "word": "estudiante", "definition": "student"}, + {"id": 20, "word": "teléfono", "definition": "telephone"}, + {"id": 21, "word": "casa", "definition": "house"}, + {"id": 22, "word": "puerta", "definition": "door"}, + {"id": 23, "word": "ventana", "definition": "window"}, + {"id": 24, "word": "silla", "definition": "chair"}, + {"id": 25, "word": "mesa", "definition": "table"}, + {"id": 26, "word": "sopa", "definition": "soup"}, + {"id": 27, "word": "pan", "definition": "bread"}, + {"id": 28, "word": "leche", "definition": "milk"}, + {"id": 29, "word": "fruta", "definition": "fruit"}, + {"id": 30, "word": "verdura", "definition": "vegetable"}, + {"id": 31, "word": "niño", "definition": "child"}, + {"id": 32, "word": "adulto", "definition": "adult"}, + {"id": 33, "word": "estrella", "definition": "star"}, + {"id": 34, "word": "luna", "definition": "moon"}, + {"id": 35, "word": "sol", "definition": "sun"}, + {"id": 36, "word": "nube", "definition": "cloud"}, + {"id": 37, "word": "lluvia", "definition": "rain"}, + {"id": 38, "word": "viento", "definition": "wind"}, + {"id": 39, "word": "nieve", "definition": "snow"}, + {"id": 40, "word": "mar", "definition": "sea"}, + {"id": 41, "word": "montaña", "definition": "mountain"}, + {"id": 42, "word": "río", "definition": "river"}, + {"id": 43, "word": "lago", "definition": "lake"}, + {"id": 44, "word": "playa", "definition": "beach"}, + {"id": 45, "word": "bosque", "definition": "forest"}, + {"id": 46, "word": "desierto", "definition": "desert"}, + {"id": 47, "word": "isla", "definition": "island"}, + {"id": 48, "word": "pueblo", "definition": "town"}, + {"id": 49, "word": "ciudadano", "definition": "citizen"}, + {"id": 50, "word": "gente", "definition": "people"} +] diff --git a/data/turkish/words.json b/data/turkish/words.json new file mode 100644 index 0000000..2ce97f5 --- /dev/null +++ b/data/turkish/words.json @@ -0,0 +1,623 @@ +[ + { + "id": 1, + "word": "Merhaba", + "definition": "Hello" + }, + { + "id": 2, + "word": "Ev", + "definition": "House" + }, + { + "id": 3, + "word": "Su", + "definition": "Water" + }, + { + "id": 4, + "word": "Kitap", + "definition": "Book" + }, + { + "id": 5, + "word": "Arkadaş", + "definition": "Friend" + }, + { + "id": 6, + "word": "Güneş", + "definition": "Sun" + }, + { + "id": 7, + "word": "Ay", + "definition": "Moon" + }, + { + "id": 8, + "word": "Yıldız", + "definition": "Star" + }, + { + "id": 9, + "word": "Ağaç", + "definition": "Tree" + }, + { + "id": 10, + "word": "Çiçek", + "definition": "Flower" + }, + { + "id": 11, + "word": "Araba", + "definition": "Car" + }, + { + "id": 12, + "word": "Okul", + "definition": "School" + }, + { + "id": 13, + "word": "Öğretmen", + "definition": "Teacher" + }, + { + "id": 14, + "word": "Öğrenci", + "definition": "Student" + }, + { + "id": 15, + "word": "Aile", + "definition": "Family" + }, + { + "id": 16, + "word": "Anne", + "definition": "Mother" + }, + { + "id": 17, + "word": "Baba", + "definition": "Father" + }, + { + "id": 18, + "word": "Kardeş", + "definition": "Sibling" + }, + { + "id": 19, + "word": "Sevgi", + "definition": "Love" + }, + { + "id": 20, + "word": "Mutluluk", + "definition": "Happiness" + }, + { + "id": 21, + "word": "Zaman", + "definition": "Time" + }, + { + "id": 22, + "word": "Yemek", + "definition": "Food" + }, + { + "id": 23, + "word": "İçmek", + "definition": "To drink" + }, + { + "id": 24, + "word": "Uyumak", + "definition": "To sleep" + }, + { + "id": 25, + "word": "Çalışmak", + "definition": "To work" + }, + { + "id": 26, + "word": "Oyun", + "definition": "Game" + }, + { + "id": 27, + "word": "Müzik", + "definition": "Music" + }, + { + "id": 28, + "word": "Dans", + "definition": "Dance" + }, + { + "id": 29, + "word": "Spor", + "definition": "Sport" + }, + { + "id": 30, + "word": "Renk", + "definition": "Color" + }, + { + "id": 31, + "word": "Kırmızı", + "definition": "Red" + }, + { + "id": 32, + "word": "Mavi", + "definition": "Blue" + }, + { + "id": 33, + "word": "Yeşil", + "definition": "Green" + }, + { + "id": 34, + "word": "Sarı", + "definition": "Yellow" + }, + { + "id": 35, + "word": "Siyah", + "definition": "Black" + }, + { + "id": 36, + "word": "Beyaz", + "definition": "White" + }, + { + "id": 37, + "word": "Gün", + "definition": "Day" + }, + { + "id": 38, + "word": "Gece", + "definition": "Night" + }, + { + "id": 39, + "word": "Sabah", + "definition": "Morning" + }, + { + "id": 40, + "word": "Akşam", + "definition": "Evening" + }, + { + "id": 41, + "word": "Yıl", + "definition": "Year" + }, + { + "id": 42, + "word": "Ay", + "definition": "Month" + }, + { + "id": 43, + "word": "Hafta", + "definition": "Week" + }, + { + "id": 44, + "word": "Saat", + "definition": "Hour" + }, + { + "id": 45, + "word": "Dakika", + "definition": "Minute" + }, + { + "id": 46, + "word": "Saniye", + "definition": "Second" + }, + { + "id": 47, + "word": "Dil", + "definition": "Language" + }, + { + "id": 48, + "word": "Kelime", + "definition": "Word" + }, + { + "id": 49, + "word": "Cümle", + "definition": "Sentence" + }, + { + "id": 50, + "word": "Paragraf", + "definition": "Paragraph" + }, + { + "id": 51, + "word": "Sayı", + "definition": "Number" + }, + { + "id": 52, + "word": "Bir", + "definition": "One" + }, + { + "id": 53, + "word": "İki", + "definition": "Two" + }, + { + "id": 54, + "word": "Üç", + "definition": "Three" + }, + { + "id": 55, + "word": "Dört", + "definition": "Four" + }, + { + "id": 56, + "word": "Beş", + "definition": "Five" + }, + { + "id": 57, + "word": "On", + "definition": "Ten" + }, + { + "id": 58, + "word": "Yüz", + "definition": "Hundred" + }, + { + "id": 59, + "word": "Bin", + "definition": "Thousand" + }, + { + "id": 60, + "word": "Milyon", + "definition": "Million" + }, + { + "id": 61, + "word": "Hayvan", + "definition": "Animal" + }, + { + "id": 62, + "word": "Köpek", + "definition": "Dog" + }, + { + "id": 63, + "word": "Kedi", + "definition": "Cat" + }, + { + "id": 64, + "word": "Kuş", + "definition": "Bird" + }, + { + "id": 65, + "word": "Balık", + "definition": "Fish" + }, + { + "id": 66, + "word": "At", + "definition": "Horse" + }, + { + "id": 67, + "word": "İnek", + "definition": "Cow" + }, + { + "id": 68, + "word": "Tavuk", + "definition": "Chicken" + }, + { + "id": 69, + "word": "Koyun", + "definition": "Sheep" + }, + { + "id": 70, + "word": "Aslan", + "definition": "Lion" + }, + { + "id": 71, + "word": "Kaplan", + "definition": "Tiger" + }, + { + "id": 72, + "word": "Fil", + "definition": "Elephant" + }, + { + "id": 73, + "word": "Maymun", + "definition": "Monkey" + }, + { + "id": 74, + "word": "Yılan", + "definition": "Snake" + }, + { + "id": 75, + "word": "Kurbağa", + "definition": "Frog" + }, + { + "id": 76, + "word": "Böcek", + "definition": "Insect" + }, + { + "id": 77, + "word": "Arı", + "definition": "Bee" + }, + { + "id": 78, + "word": "Kelebek", + "definition": "Butterfly" + }, + { + "id": 79, + "word": "Karınca", + "definition": "Ant" + }, + { + "id": 80, + "word": "Örümcek", + "definition": "Spider" + }, + { + "id": 81, + "word": "Vücut", + "definition": "Body" + }, + { + "id": 82, + "word": "Baş", + "definition": "Head" + }, + { + "id": 83, + "word": "Göz", + "definition": "Eye" + }, + { + "id": 84, + "word": "Kulak", + "definition": "Ear" + }, + { + "id": 85, + "word": "Burun", + "definition": "Nose" + }, + { + "id": 86, + "word": "Ağız", + "definition": "Mouth" + }, + { + "id": 87, + "word": "Diş", + "definition": "Tooth" + }, + { + "id": 88, + "word": "Saç", + "definition": "Hair" + }, + { + "id": 89, + "word": "El", + "definition": "Hand" + }, + { + "id": 90, + "word": "Ayak", + "definition": "Foot" + }, + { + "id": 91, + "word": "Bacak", + "definition": "Leg" + }, + { + "id": 92, + "word": "Kol", + "definition": "Arm" + }, + { + "id": 93, + "word": "Parmak", + "definition": "Finger" + }, + { + "id": 94, + "word": "Tırnak", + "definition": "Nail" + }, + { + "id": 95, + "word": "Kalp", + "definition": "Heart" + }, + { + "id": 96, + "word": "Beyin", + "definition": "Brain" + }, + { + "id": 97, + "word": "Akciğer", + "definition": "Lung" + }, + { + "id": 98, + "word": "Mide", + "definition": "Stomach" + }, + { + "id": 99, + "word": "Karaciğer", + "definition": "Liver" + }, + { + "id": 100, + "word": "Böbrek", + "definition": "Kidney" + }, + { + "id": 101, + "word": "Giysi", + "definition": "Clothing" + }, + { + "id": 102, + "word": "Gömlek", + "definition": "Shirt" + }, + { + "id": 103, + "word": "Pantolon", + "definition": "Pants" + }, + { + "id": 104, + "word": "Elbise", + "definition": "Dress" + }, + { + "id": 105, + "word": "Ceket", + "definition": "Jacket" + }, + { + "id": 106, + "word": "Ayakkabı", + "definition": "Shoe" + }, + { + "id": 107, + "word": "Çorap", + "definition": "Sock" + }, + { + "id": 108, + "word": "Şapka", + "definition": "Hat" + }, + { + "id": 109, + "word": "Eldiven", + "definition": "Glove" + }, + { + "id": 110, + "word": "Kemer", + "definition": "Belt" + }, + { + "id": 111, + "word": "Yiyecek", + "definition": "Food" + }, + { + "id": 112, + "word": "Ekmek", + "definition": "Bread" + }, + { + "id": 113, + "word": "Süt", + "definition": "Milk" + }, + { + "id": 114, + "word": "Peynir", + "definition": "Cheese" + }, + { + "id": 115, + "word": "Yumurta", + "definition": "Egg" + }, + { + "id": 116, + "word": "Et", + "definition": "Meat" + }, + { + "id": 117, + "word": "Tavuk", + "definition": "Chicken" + }, + { + "id": 118, + "word": "Balık", + "definition": "Fish" + }, + { + "id": 119, + "word": "Pirinç", + "definition": "Rice" + }, + { + "id": 120, + "word": "Makarna", + "definition": "Pasta" + }, + { + "id": 121, + "word": "Sebze", + "definition": "Vegetable" + }, + { + "id": 122, + "word": "Meyve", + "definition": "Fruit" + }, + { + "id": 123, + "word": "Elma", + "definition": "Apple" + }, + { + "id": 124, + "word": "Muz", + "definition": "Banana" + } +] + diff --git a/index.js b/index.js index 9c195d2..132101b 100644 --- a/index.js +++ b/index.js @@ -2,16 +2,14 @@ import express from "express"; const app = express(); import home from './routes/home.js'; -import en from './routes/en.js'; -import dutch from './routes/dutch.js'; -import pronounce from './routes/pronounce.js'; +import english from './routes/english.js'; +import language from './routes/language.js'; app.use('/', home); -app.use('/word/dutch', dutch); -app.use('/word', en); -app.use('/pronounce', pronounce); +app.use('/word', english); +app.use('/word', language); -app.use('/', function(req, res) { +app.use('/', function(_req, res) { res.status(404).json({ error: 1, message: 'Page or Data not Found' @@ -26,7 +24,7 @@ app.use((err, req, res, next) => { }); }); -const port = process.env.PORT || 3000; +const port = process.env.PORT || 3002; app.listen(port, function() { console.log('listening on port ' + port); -}); +}); \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..12e777c --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,2245 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + axios: + specifier: ^1.1.3 + version: 1.7.5 + cheerio: + specifier: ^1.0.0-rc.12 + version: 1.0.0 + express: + specifier: ^4.18.2 + version: 4.19.2 + node-pronounce: + specifier: ^0.0.4 + version: 0.0.4 + random-array-item: + specifier: ^0.0.2 + version: 0.0.2 + random-useragent: + specifier: ^0.5.0 + version: 0.5.0 + +devDependencies: + all-contributors-cli: + specifier: ^6.20.0 + version: 6.26.1 + gacp: + specifier: ^3.0.3 + version: 3.0.3 + nodemon: + specifier: ^2.0.19 + version: 2.0.22 + +packages: + + /@babel/code-frame@7.24.7: + resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.24.7 + picocolors: 1.0.1 + dev: true + + /@babel/helper-validator-identifier@7.24.7: + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/highlight@7.24.7: + resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.24.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.0.1 + dev: true + + /@babel/runtime@7.25.4: + resolution: {integrity: sha512-DSgLeL/FNcpXuzav5wfYvHCGvynXkJbn3Zvc3823AEe9nPwW9IK4UoCSS5yGymmQzN0pCPvivtgS6/8U2kkm1w==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.1 + dev: true + + /@commitlint/execute-rule@12.1.4: + resolution: {integrity: sha512-h2S1j8SXyNeABb27q2Ok2vD1WfxJiXvOttKuRA9Or7LN6OQoC/KtT3844CIhhWNteNMu/wE0gkTqGxDVAnJiHg==} + engines: {node: '>=v10'} + dev: true + + /@commitlint/load@12.1.4: + resolution: {integrity: sha512-Keszi0IOjRzKfxT+qES/n+KZyLrxy79RQz8wWgssCboYjKEp+wC+fLCgbiMCYjI5k31CIzIOq/16J7Ycr0C0EA==} + engines: {node: '>=v10'} + dependencies: + '@commitlint/execute-rule': 12.1.4 + '@commitlint/resolve-extends': 12.1.4 + '@commitlint/types': 12.1.4 + chalk: 4.1.2 + cosmiconfig: 7.1.0 + lodash: 4.17.21 + resolve-from: 5.0.0 + dev: true + + /@commitlint/resolve-extends@12.1.4: + resolution: {integrity: sha512-R9CoUtsXLd6KSCfsZly04grsH6JVnWFmVtWgWs1KdDpdV+G3TSs37tColMFqglpkx3dsWu8dsPD56+D9YnJfqg==} + engines: {node: '>=v10'} + dependencies: + import-fresh: 3.3.0 + lodash: 4.17.21 + resolve-from: 5.0.0 + resolve-global: 1.0.0 + dev: true + + /@commitlint/types@12.1.4: + resolution: {integrity: sha512-KRIjdnWNUx6ywz+SJvjmNCbQKcKP6KArhjZhY2l+CWKxak0d77SOjggkMwFTiSgLODOwmuLTbarR2ZfWPiPMlw==} + engines: {node: '>=v10'} + dependencies: + chalk: 4.1.2 + dev: true + + /@sindresorhus/is@0.14.0: + resolution: {integrity: sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==} + engines: {node: '>=6'} + dev: true + + /@szmarczak/http-timer@1.1.2: + resolution: {integrity: sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==} + engines: {node: '>=6'} + dependencies: + defer-to-connect: 1.1.3 + dev: true + + /@types/keyv@3.1.4: + resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} + dependencies: + '@types/node': 22.5.0 + dev: true + + /@types/node@22.5.0: + resolution: {integrity: sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg==} + dependencies: + undici-types: 6.19.8 + dev: true + + /@types/parse-json@4.0.2: + resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + dev: true + + /@types/responselike@1.0.3: + resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} + dependencies: + '@types/node': 22.5.0 + dev: true + + /@vivaxy/git@4.2.1: + resolution: {integrity: sha512-Gpnne7sk3oTd0fyw1J3clVX2ZBkJjNRduccDbOcgYv31M35nBzUHSzQ56eFiJsOTNfdVadL2bo0ICw5oilGfEA==} + dependencies: + execa: 5.1.1 + fs-extra: 10.1.0 + dev: true + + /accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + dev: false + + /all-contributors-cli@6.26.1: + resolution: {integrity: sha512-Ymgo3FJACRBEd1eE653FD1J/+uD0kqpUNYfr9zNC1Qby0LgbhDBzB3EF6uvkAbYpycStkk41J+0oo37Lc02yEw==} + engines: {node: '>=4'} + hasBin: true + dependencies: + '@babel/runtime': 7.25.4 + async: 3.2.6 + chalk: 4.1.2 + didyoumean: 1.2.2 + inquirer: 7.3.3 + json-fixer: 1.6.15 + lodash: 4.17.21 + node-fetch: 2.7.0 + pify: 5.0.0 + yargs: 15.4.1 + optionalDependencies: + prettier: 2.8.8 + transitivePeerDependencies: + - encoding + dev: true + + /ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + dependencies: + string-width: 4.2.3 + dev: true + + /ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + dev: false + + /async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + dev: true + + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: false + + /axios@1.7.5: + resolution: {integrity: sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==} + dependencies: + follow-redirects: 1.15.6 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: false + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + dev: true + + /body-parser@1.20.2: + resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + dev: false + + /boxen@5.1.2: + resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==} + engines: {node: '>=10'} + dependencies: + ansi-align: 3.0.1 + camelcase: 6.3.0 + chalk: 4.1.2 + cli-boxes: 2.2.1 + string-width: 4.2.3 + type-fest: 0.20.2 + widest-line: 3.1.0 + wrap-ansi: 7.0.0 + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.1.1 + dev: true + + /bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + dev: false + + /cacheable-request@6.1.0: + resolution: {integrity: sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==} + engines: {node: '>=8'} + dependencies: + clone-response: 1.0.3 + get-stream: 5.2.0 + http-cache-semantics: 4.1.1 + keyv: 3.1.0 + lowercase-keys: 2.0.0 + normalize-url: 4.5.1 + responselike: 1.0.2 + dev: true + + /call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + dev: false + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: true + + /camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + dev: true + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + dev: true + + /cheerio-select@2.1.0: + resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} + dependencies: + boolbase: 1.0.0 + css-select: 5.1.0 + css-what: 6.1.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.1.0 + dev: false + + /cheerio@1.0.0: + resolution: {integrity: sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==} + engines: {node: '>=18.17'} + dependencies: + cheerio-select: 2.1.0 + dom-serializer: 2.0.0 + domhandler: 5.0.3 + domutils: 3.1.0 + encoding-sniffer: 0.2.0 + htmlparser2: 9.1.0 + parse5: 7.1.2 + parse5-htmlparser2-tree-adapter: 7.0.0 + parse5-parser-stream: 7.1.2 + undici: 6.19.8 + whatwg-mimetype: 4.0.0 + dev: false + + /chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /ci-info@2.0.0: + resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} + dev: true + + /cli-boxes@2.2.1: + resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} + engines: {node: '>=6'} + dev: true + + /cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + dependencies: + restore-cursor: 3.1.0 + dev: true + + /cli-width@3.0.0: + resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} + engines: {node: '>= 10'} + dev: true + + /cliui@6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + dev: true + + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + + /clone-response@1.0.3: + resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} + dependencies: + mimic-response: 1.0.1 + dev: true + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: false + + /compromise-speech@0.1.0(compromise@14.14.0): + resolution: {integrity: sha512-+2KS/8T3SH5Hcd6tsCBVfxrkdi7sbJfKAeXGYimQdKGgweDMt0FT03wVCDZ6EgLYxReftkRKp1pxLx2pQLj4Kg==} + peerDependencies: + compromise: '>=14.0.0' + dependencies: + compromise: 14.14.0 + dev: false + + /compromise@14.14.0: + resolution: {integrity: sha512-0plNVaC0bGWZY3TeijP1xndyaAmjqBY1SSfsc/7ruVLTIfRCSHFLSd/uuK7ZTcaT/4y2u0lVn0et4tmmC98mRg==} + engines: {node: '>=12.0.0'} + dependencies: + efrt: 2.7.0 + grad-school: 0.0.5 + suffix-thumb: 5.0.2 + dev: false + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /configstore@5.0.1: + resolution: {integrity: sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==} + engines: {node: '>=8'} + dependencies: + dot-prop: 5.3.0 + graceful-fs: 4.2.11 + make-dir: 3.1.0 + unique-string: 2.0.0 + write-file-atomic: 3.0.3 + xdg-basedir: 4.0.0 + dev: true + + /content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + dev: false + + /conventional-commit-types@3.0.0: + resolution: {integrity: sha512-SmmCYnOniSsAa9GqWOeLqc179lfr5TRu5b4QFDkbsrJ5TZjPJx85wtOr3zn+1dbeNiXDKGPbZ72IKbPhLXh/Lg==} + dev: true + + /cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + dev: false + + /cookie@0.6.0: + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + engines: {node: '>= 0.6'} + dev: false + + /cosmiconfig@7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + dependencies: + '@types/parse-json': 4.0.2 + import-fresh: 3.3.0 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + dev: true + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /crypto-random-string@2.0.0: + resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} + engines: {node: '>=8'} + dev: true + + /css-select@5.1.0: + resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 5.0.3 + domutils: 3.1.0 + nth-check: 2.1.1 + dev: false + + /css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + dev: false + + /debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: false + + /debug@3.2.7(supports-color@5.5.0): + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + supports-color: 5.5.0 + dev: true + + /decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + dev: true + + /decompress-response@3.3.0: + resolution: {integrity: sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==} + engines: {node: '>=4'} + dependencies: + mimic-response: 1.0.1 + dev: true + + /deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + dev: true + + /defer-to-connect@1.1.3: + resolution: {integrity: sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==} + dev: true + + /define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + dev: false + + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: false + + /depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dev: false + + /destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dev: false + + /didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + dev: true + + /dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + dev: false + + /domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + dev: false + + /domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + dependencies: + domelementtype: 2.3.0 + dev: false + + /domutils@3.1.0: + resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + dev: false + + /dot-prop@5.3.0: + resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} + engines: {node: '>=8'} + dependencies: + is-obj: 2.0.0 + dev: true + + /duplexer3@0.1.5: + resolution: {integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==} + dev: true + + /ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + dev: false + + /efrt@2.7.0: + resolution: {integrity: sha512-/RInbCy1d4P6Zdfa+TMVsf/ufZVotat5hCw3QXmWtjU+3pFEOvOQ7ibo3aIxyCJw2leIeAMjmPj+1SLJiCpdrQ==} + engines: {node: '>=12.0.0'} + dev: false + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + dev: false + + /encoding-sniffer@0.2.0: + resolution: {integrity: sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==} + dependencies: + iconv-lite: 0.6.3 + whatwg-encoding: 3.1.1 + dev: false + + /end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + dependencies: + once: 1.4.0 + dev: true + + /entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + dev: false + + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.4 + dev: false + + /es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + dev: false + + /escalade@3.1.2: + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + engines: {node: '>=6'} + dev: true + + /escape-goat@2.1.1: + resolution: {integrity: sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==} + engines: {node: '>=8'} + dev: true + + /escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + dev: false + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + dev: false + + /execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + + /express@4.19.2: + resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} + engines: {node: '>= 0.10.0'} + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.2 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.6.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.7 + qs: 6.11.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: false + + /external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + dev: true + + /figures@3.2.0: + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /finalhandler@1.2.0: + resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + engines: {node: '>= 0.8'} + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: true + + /follow-redirects@1.15.6: + resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: false + + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + + /forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + dev: false + + /fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + dev: false + + /fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + dev: true + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: false + + /gacp@3.0.3: + resolution: {integrity: sha512-ncBb1MI/TRWhGVIRHJYl2MkLfVzrKHdy+9YlqzbdpAx0/yOktJQjrNeH0ublga49Jzk7VoSU8QdUfEexDJOd6g==} + hasBin: true + dependencies: + '@commitlint/load': 12.1.4 + '@commitlint/types': 12.1.4 + '@vivaxy/git': 4.2.1 + chalk: 4.1.2 + conventional-commit-types: 3.0.0 + cosmiconfig: 7.1.0 + execa: 5.1.1 + external-editor: 3.1.0 + figures: 3.2.0 + fs-extra: 10.1.0 + log-util: 2.3.0 + prompts: 2.4.2 + right-pad: 1.0.1 + update-notifier: 5.1.0 + word-wrap: 1.2.5 + yargs: 17.7.2 + dev: true + + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: true + + /get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + dev: false + + /get-stream@4.1.0: + resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==} + engines: {node: '>=6'} + dependencies: + pump: 3.0.0 + dev: true + + /get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + dependencies: + pump: 3.0.0 + dev: true + + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /global-dirs@0.1.1: + resolution: {integrity: sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==} + engines: {node: '>=4'} + dependencies: + ini: 1.3.8 + dev: true + + /global-dirs@3.0.1: + resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} + engines: {node: '>=10'} + dependencies: + ini: 2.0.0 + dev: true + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.4 + dev: false + + /got@9.6.0: + resolution: {integrity: sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==} + engines: {node: '>=8.6'} + dependencies: + '@sindresorhus/is': 0.14.0 + '@szmarczak/http-timer': 1.1.2 + '@types/keyv': 3.1.4 + '@types/responselike': 1.0.3 + cacheable-request: 6.1.0 + decompress-response: 3.3.0 + duplexer3: 0.1.5 + get-stream: 4.1.0 + lowercase-keys: 1.0.1 + mimic-response: 1.0.1 + p-cancelable: 1.1.0 + to-readable-stream: 1.0.0 + url-parse-lax: 3.0.0 + dev: true + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + + /grad-school@0.0.5: + resolution: {integrity: sha512-rXunEHF9M9EkMydTBux7+IryYXEZinRk6g8OBOGDBzo/qWJjhTxy86i5q7lQYpCLHN8Sqv1XX3OIOc7ka2gtvQ==} + engines: {node: '>=8.0.0'} + dev: false + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + dependencies: + es-define-property: 1.0.0 + dev: false + + /has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + dev: false + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: false + + /has-yarn@2.1.0: + resolution: {integrity: sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==} + engines: {node: '>=8'} + dev: true + + /hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: false + + /htmlparser2@9.1.0: + resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==} + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.1.0 + entities: 4.5.0 + dev: false + + /http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + dev: true + + /http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + dev: false + + /human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: true + + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + + /iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /ignore-by-default@1.0.1: + resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /import-lazy@2.1.0: + resolution: {integrity: sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==} + engines: {node: '>=4'} + dev: true + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false + + /ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: true + + /ini@2.0.0: + resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} + engines: {node: '>=10'} + dev: true + + /inquirer@7.3.3: + resolution: {integrity: sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==} + engines: {node: '>=8.0.0'} + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-width: 3.0.0 + external-editor: 3.1.0 + figures: 3.2.0 + lodash: 4.17.21 + mute-stream: 0.0.8 + run-async: 2.4.1 + rxjs: 6.6.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + through: 2.3.8 + dev: true + + /ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + dev: false + + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.3.0 + dev: true + + /is-ci@2.0.0: + resolution: {integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==} + hasBin: true + dependencies: + ci-info: 2.0.0 + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-installed-globally@0.4.0: + resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==} + engines: {node: '>=10'} + dependencies: + global-dirs: 3.0.1 + is-path-inside: 3.0.3 + dev: true + + /is-npm@5.0.0: + resolution: {integrity: sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==} + engines: {node: '>=10'} + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + dev: true + + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: true + + /is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + dev: true + + /is-yarn-global@0.3.0: + resolution: {integrity: sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + + /json-buffer@3.0.0: + resolution: {integrity: sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==} + dev: true + + /json-fixer@1.6.15: + resolution: {integrity: sha512-TuDuZ5KrgyjoCIppdPXBMqiGfota55+odM+j2cQ5rt/XKyKmqGB3Whz1F8SN8+60yYGy/Nu5lbRZ+rx8kBIvBw==} + engines: {node: '>=10'} + dependencies: + '@babel/runtime': 7.25.4 + chalk: 4.1.2 + pegjs: 0.10.0 + dev: true + + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + + /json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + dev: false + + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /keyv@3.1.0: + resolution: {integrity: sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==} + dependencies: + json-buffer: 3.0.0 + dev: true + + /kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + dev: true + + /latest-version@5.1.0: + resolution: {integrity: sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==} + engines: {node: '>=8'} + dependencies: + package-json: 6.5.0 + dev: true + + /lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true + + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: true + + /log-symbols@3.0.0: + resolution: {integrity: sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==} + engines: {node: '>=8'} + dependencies: + chalk: 2.4.2 + dev: true + + /log-util@2.3.0: + resolution: {integrity: sha512-ZFjjNKfCGicmPGUlcQX32TvOP/72qNpjgKha5MCsYPHj1rdQI4Cn6QSNGUpdzmG1KYAX3v/76oRG0df2M9nOKQ==} + dependencies: + chalk: 2.4.2 + figures: 3.2.0 + log-symbols: 3.0.0 + dev: true + + /lowercase-keys@1.0.1: + resolution: {integrity: sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==} + engines: {node: '>=0.10.0'} + dev: true + + /lowercase-keys@2.0.0: + resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} + engines: {node: '>=8'} + dev: true + + /make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + dependencies: + semver: 6.3.1 + dev: true + + /media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + dev: false + + /merge-descriptors@1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + dev: false + + /merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: true + + /methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + dev: false + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + + /mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: true + + /mimic-response@1.0.1: + resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} + engines: {node: '>=4'} + dev: true + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + + /ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: false + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + /mute-stream@0.0.8: + resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + dev: true + + /negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + dev: false + + /node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: true + + /node-pronounce@0.0.4: + resolution: {integrity: sha512-rX8YDCHU2uXMVklgaZ2OsuEzpp9Vg4ms1qnn6qTTA1wrU596N5rJv8Q+62xvLPj70jPJ8S+K24XiTTprecj0rQ==} + dependencies: + compromise: 14.14.0 + compromise-speech: 0.1.0(compromise@14.14.0) + dev: false + + /nodemon@2.0.22: + resolution: {integrity: sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==} + engines: {node: '>=8.10.0'} + hasBin: true + dependencies: + chokidar: 3.6.0 + debug: 3.2.7(supports-color@5.5.0) + ignore-by-default: 1.0.1 + minimatch: 3.1.2 + pstree.remy: 1.1.8 + semver: 5.7.2 + simple-update-notifier: 1.1.0 + supports-color: 5.5.0 + touch: 3.1.1 + undefsafe: 2.0.5 + dev: true + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /normalize-url@4.5.1: + resolution: {integrity: sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==} + engines: {node: '>=8'} + dev: true + + /npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + dev: true + + /nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + dependencies: + boolbase: 1.0.0 + dev: false + + /object-inspect@1.13.2: + resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} + engines: {node: '>= 0.4'} + dev: false + + /on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: false + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: true + + /os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + dev: true + + /p-cancelable@1.1.0: + resolution: {integrity: sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==} + engines: {node: '>=6'} + dev: true + + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /package-json@6.5.0: + resolution: {integrity: sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==} + engines: {node: '>=8'} + dependencies: + got: 9.6.0 + registry-auth-token: 4.2.2 + registry-url: 5.1.0 + semver: 6.3.1 + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.24.7 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /parse5-htmlparser2-tree-adapter@7.0.0: + resolution: {integrity: sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==} + dependencies: + domhandler: 5.0.3 + parse5: 7.1.2 + dev: false + + /parse5-parser-stream@7.1.2: + resolution: {integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==} + dependencies: + parse5: 7.1.2 + dev: false + + /parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + dependencies: + entities: 4.5.0 + dev: false + + /parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + dev: false + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-to-regexp@0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + dev: false + + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /pegjs@0.10.0: + resolution: {integrity: sha512-qI5+oFNEGi3L5HAxDwN2LA4Gg7irF70Zs25edhjld9QemOgp0CbvMtbFcMvFtEo1OityPrcCzkQFB8JP/hxgow==} + engines: {node: '>=0.10'} + hasBin: true + dev: true + + /picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + dev: true + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /pify@5.0.0: + resolution: {integrity: sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==} + engines: {node: '>=10'} + dev: true + + /prepend-http@2.0.0: + resolution: {integrity: sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==} + engines: {node: '>=4'} + dev: true + + /prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + requiresBuild: true + dev: true + optional: true + + /prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + dev: true + + /proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + dev: false + + /proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: false + + /pstree.remy@1.1.8: + resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} + dev: true + + /pump@3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: true + + /pupa@2.1.1: + resolution: {integrity: sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==} + engines: {node: '>=8'} + dependencies: + escape-goat: 2.1.1 + dev: true + + /qs@6.11.0: + resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.6 + dev: false + + /random-array-item@0.0.2: + resolution: {integrity: sha512-MF6cmiF8hApGJC/HcGdszIcwjhzNjVKsO7ytgqLgyMHpmiqF0keIvxi/2wvd7LraAnCM34khUZb0QhSh6NDIFA==} + dev: false + + /random-seed@0.3.0: + resolution: {integrity: sha512-y13xtn3kcTlLub3HKWXxJNeC2qK4mB59evwZ5EkeRlolx+Bp2ztF7LbcZmyCnOqlHQrLnfuNbi1sVmm9lPDlDA==} + engines: {node: '>= 0.6.0'} + dependencies: + json-stringify-safe: 5.0.1 + dev: false + + /random-useragent@0.5.0: + resolution: {integrity: sha512-FUMkqVdZeoSff5tErNL3FFGYXElDWZ1bEuedhm5u9MdCFwANriJWbHvDRYrLTOzp/fBsBGu5J1cWtDgifa97aQ==} + dependencies: + random-seed: 0.3.0 + dev: false + + /range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + dev: false + + /raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: false + + /rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + dev: true + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + + /regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + dev: true + + /registry-auth-token@4.2.2: + resolution: {integrity: sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==} + engines: {node: '>=6.0.0'} + dependencies: + rc: 1.2.8 + dev: true + + /registry-url@5.1.0: + resolution: {integrity: sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==} + engines: {node: '>=8'} + dependencies: + rc: 1.2.8 + dev: true + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: true + + /require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + dev: true + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + dev: true + + /resolve-global@1.0.0: + resolution: {integrity: sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==} + engines: {node: '>=8'} + dependencies: + global-dirs: 0.1.1 + dev: true + + /responselike@1.0.2: + resolution: {integrity: sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==} + dependencies: + lowercase-keys: 1.0.1 + dev: true + + /restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + dev: true + + /right-pad@1.0.1: + resolution: {integrity: sha512-bYBjgxmkvTAfgIYy328fmkwhp39v8lwVgWhhrzxPV3yHtcSqyYKe9/XOhvW48UFjATg3VuJbpsp5822ACNvkmw==} + engines: {node: '>= 0.10'} + deprecated: Please use String.prototype.padEnd() over this package. + dev: true + + /run-async@2.4.1: + resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} + engines: {node: '>=0.12.0'} + dev: true + + /rxjs@6.6.7: + resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==} + engines: {npm: '>=2.0.0'} + dependencies: + tslib: 1.14.1 + dev: true + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + /semver-diff@3.1.1: + resolution: {integrity: sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==} + engines: {node: '>=8'} + dependencies: + semver: 6.3.1 + dev: true + + /semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + dev: true + + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: true + + /semver@7.0.0: + resolution: {integrity: sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==} + hasBin: true + dev: true + + /semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + dev: true + + /send@0.18.0: + resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + engines: {node: '>= 0.8.0'} + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + dev: false + + /serve-static@1.15.0: + resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + engines: {node: '>= 0.8.0'} + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.18.0 + transitivePeerDependencies: + - supports-color + dev: false + + /set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + dev: true + + /set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + dev: false + + /setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + dev: false + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.2 + dev: false + + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true + + /simple-update-notifier@1.1.0: + resolution: {integrity: sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==} + engines: {node: '>=8.10.0'} + dependencies: + semver: 7.0.0 + dev: true + + /sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + dev: true + + /statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + dev: false + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: true + + /strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + dev: true + + /suffix-thumb@5.0.2: + resolution: {integrity: sha512-I5PWXAFKx3FYnI9a+dQMWNqTxoRt6vdBdb0O+BJ1sxXCWtSoQCusc13E58f+9p4MYx/qCnEMkD5jac6K2j3dgA==} + dev: false + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + dev: true + + /tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + dependencies: + os-tmpdir: 1.0.2 + dev: true + + /to-readable-stream@1.0.0: + resolution: {integrity: sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==} + engines: {node: '>=6'} + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + dev: false + + /touch@3.1.1: + resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==} + hasBin: true + dev: true + + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: true + + /tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: true + + /type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + dev: false + + /typedarray-to-buffer@3.1.5: + resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} + dependencies: + is-typedarray: 1.0.0 + dev: true + + /undefsafe@2.0.5: + resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} + dev: true + + /undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + dev: true + + /undici@6.19.8: + resolution: {integrity: sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==} + engines: {node: '>=18.17'} + dev: false + + /unique-string@2.0.0: + resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} + engines: {node: '>=8'} + dependencies: + crypto-random-string: 2.0.0 + dev: true + + /universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + dev: true + + /unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + dev: false + + /update-notifier@5.1.0: + resolution: {integrity: sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==} + engines: {node: '>=10'} + dependencies: + boxen: 5.1.2 + chalk: 4.1.2 + configstore: 5.0.1 + has-yarn: 2.1.0 + import-lazy: 2.1.0 + is-ci: 2.0.0 + is-installed-globally: 0.4.0 + is-npm: 5.0.0 + is-yarn-global: 0.3.0 + latest-version: 5.1.0 + pupa: 2.1.1 + semver: 7.6.3 + semver-diff: 3.1.1 + xdg-basedir: 4.0.0 + dev: true + + /url-parse-lax@3.0.0: + resolution: {integrity: sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==} + engines: {node: '>=4'} + dependencies: + prepend-http: 2.0.0 + dev: true + + /utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + dev: false + + /vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: false + + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: true + + /whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + dependencies: + iconv-lite: 0.6.3 + dev: false + + /whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + dev: false + + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: true + + /which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /widest-line@3.1.0: + resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} + engines: {node: '>=8'} + dependencies: + string-width: 4.2.3 + dev: true + + /word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + dev: true + + /wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /write-file-atomic@3.0.3: + resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} + dependencies: + imurmurhash: 0.1.4 + is-typedarray: 1.0.0 + signal-exit: 3.0.7 + typedarray-to-buffer: 3.1.5 + dev: true + + /xdg-basedir@4.0.0: + resolution: {integrity: sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==} + engines: {node: '>=8'} + dev: true + + /y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + dev: true + + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: true + + /yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + dev: true + + /yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + dev: true + + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: true + + /yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + dependencies: + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 4.2.3 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 18.1.3 + dev: true + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.1.2 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: true diff --git a/routes/dutch.js b/routes/dutch.js deleted file mode 100644 index 07b3cf2..0000000 --- a/routes/dutch.js +++ /dev/null @@ -1,35 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { pronounce } from "node-pronounce"; -import { readFileSync } from "fs"; -import { randomArrayItem } from "random-array-item"; -import { setDefaultHeaders } from "../utils/headers.js"; -var dutchRandomWord = []; -const dutchWordsData = JSON.parse(readFileSync(new URL("../data/dutch/words.json", import.meta.url))); - -router.get("/", function (req, res) { - setDefaultHeaders(res); - - if (dutchRandomWord.length > 0) { - dutchRandomWord = []; - } - - const fetchRandomWord = randomArrayItem(dutchWordsData); - - const word = fetchRandomWord.word; - const definition = fetchRandomWord.definition; - const pronunciation = pronounce(word); - - dutchRandomWord.push({ - word: decodeURI(word.charAt(0).toUpperCase() + word.slice(1)), - definition: decodeURI( - definition.charAt(0).toUpperCase() + definition.slice(1) - ), - pronunciation: decodeURI( - pronunciation.charAt(0).toUpperCase() + pronunciation.slice(1) - ), - }); - res.send(JSON.stringify(dutchRandomWord, null, 2)); -}); - -export default router; diff --git a/routes/en.js b/routes/en.js deleted file mode 100644 index cd553a6..0000000 --- a/routes/en.js +++ /dev/null @@ -1,122 +0,0 @@ -import express from "express"; -const router = express.Router(); -import axios from "axios"; -import * as cheerio from "cheerio"; -import { pronounce } from "node-pronounce"; -import randomUseragent from "random-useragent"; -import { setDefaultHeaders } from "../utils/headers.js"; -const rua = randomUseragent.getRandom(); -var wordOfDay = []; -const baseUrl = 'https://randomword.com'; - -router.get("/", function (req, res) { - setDefaultHeaders(res); - - axios({ - method: "GET", - url: baseUrl, - headers: { - "User-Agent": rua, - }, - }) - .then(function (response) { - const $ = cheerio.load(response.data); - if (wordOfDay.length > 0) { - wordOfDay = []; - } - - var post = $(".section #shared_section"); - var word = post - .find("#random_word") - .eq(0) - .text() - .replace("\r\n\t\t\t\t\t", "") - .replace("\r\n\t\t\t\t", "") - .replace("\n\t\t\t\t\t", "") - .replace("\n\t\t\t\t", ""); - var definition = post - .find("#random_word_definition") - .eq(0) - .text() - .replace("\n", ""); - var pronounceword = pronounce(word).replace(",", ""); - - wordOfDay.push({ - word: decodeURI(word.charAt(0).toUpperCase() + word.slice(1)), - definition: decodeURI( - definition.charAt(0).toUpperCase() + definition.slice(1) - ), - pronunciation: decodeURI( - pronounceword.charAt(0).toUpperCase() + pronounceword.slice(1) - ), - }); - res.send(JSON.stringify(wordOfDay, null, 2)); - }) - .catch(function (error) { - if (!error.response) { - console.log("API URL is Missing"); - res.json("API URL is Missing"); - } else { - console.log("Something Went Wrong - Enter the Correct API URL"); - res.json("Something Went Wrong - Enter the Correct API URL"); - } - }); -}); - -router.get("/:pos", function (req, res) { - setDefaultHeaders(res); - - const partOfSpeech = req.params.pos; - - axios({ - method: "GET", - url: `${baseUrl}/${partOfSpeech}`, - headers: { - "User-Agent": rua, - }, - }) - .then(function (response) { - const $ = cheerio.load(response.data); - if (wordOfDay.length > 0) { - wordOfDay = []; - } - - var post = $(".section #shared_section"); - var word = post - .find("#random_word") - .eq(0) - .text() - .replace("\r\n\t\t\t\t\t", "") - .replace("\r\n\t\t\t\t", "") - .replace("\n\t\t\t\t\t", "") - .replace("\n\t\t\t\t", ""); - var definition = post - .find("#random_word_definition") - .eq(0) - .text() - .replace("\n", ""); - var pronounceword = pronounce(word).replace(",", ""); - - wordOfDay.push({ - word: decodeURI(word.charAt(0).toUpperCase() + word.slice(1)), - definition: decodeURI( - definition.charAt(0).toUpperCase() + definition.slice(1) - ), - pronunciation: decodeURI( - pronounceword.charAt(0).toUpperCase() + pronounceword.slice(1) - ), - }); - res.send(JSON.stringify(wordOfDay, null, 2)); - }) - .catch(function (error) { - if (!error.response) { - console.log("API URL is Missing"); - res.json("API URL is Missing"); - } else { - console.log("Something Went Wrong - Enter the Correct API URL"); - res.json("Something Went Wrong - Enter the Correct API URL"); - } - }); -}); - -export default router; diff --git a/routes/english.js b/routes/english.js new file mode 100644 index 0000000..59cf128 --- /dev/null +++ b/routes/english.js @@ -0,0 +1,50 @@ +import express from "express"; +import { defaultHeaders } from "../utils/index.js"; +import { fetcher } from "../utils/index.js"; + +const router = express.Router(); +const baseUrl = "https://randomword.com"; + +const validPos = ['noun', 'verb', 'adjective', 'adverb', 'sentence', 'question', 'idiom', 'letter', 'paragraph', 'vocabulary', '1-word-quotes', '2-word-quotes', '3-word-quotes', 'affirmation']; + +router.get("/", async (req, res) => { + defaultHeaders(res); + try { + const word = await fetcher({ + url: baseUrl, + container: ".section", + containerId: "#shared_section", + wordId: "#random_word", + definitionId: "#random_word_definition", + }); + res.json(word); + } catch (error) { + console.error(error.message); + res.status(500).json({ error: error.message }); + } +}); + +router.get("/english/:pos", async (req, res, next) => { + const partOfSpeech = req.params.pos.toLowerCase(); + + if (!validPos.includes(partOfSpeech)) { + return next(); + } + + defaultHeaders(res); + try { + const word = await fetcher({ + url: `${baseUrl}/${partOfSpeech}`, + container: ".section", + containerId: "#shared_section", + wordId: "#random_word", + definitionId: "#random_word_definition", + }); + res.json(word); + } catch (error) { + console.error(error.message); + res.status(500).json({ error: error.message }); + } +}); + +export default router; \ No newline at end of file diff --git a/routes/home.js b/routes/home.js index 9bb5dd0..23a2058 100644 --- a/routes/home.js +++ b/routes/home.js @@ -9,7 +9,10 @@ router.get("/", function (req, res) { res.header("X-XSS-Protection", "1; mode=block"); res.header("X-Content-Type-Options", "nosniff"); res.header("Strict-Transport-Security", "max-age=63072000"); - res.json("Random Words API"); + res.json({ + message: "Welcome to the Random Words API", + docs: "https://github.com/mcnaveen/random-words-api" + }); }); export default router; \ No newline at end of file diff --git a/routes/language.js b/routes/language.js new file mode 100644 index 0000000..cdd155f --- /dev/null +++ b/routes/language.js @@ -0,0 +1,45 @@ +import express from "express"; +import fs from "fs/promises"; +import path from "path"; +import { fileURLToPath } from "url"; +import { randomArrayItem } from "random-array-item"; +import { defaultHeaders } from "../utils/index.js"; + +const router = express.Router(); +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +router.get("/:language", async function (req, res) { + defaultHeaders(res); + const language = req.params.language.toLowerCase(); + const wordsFilePath = path.join(__dirname, "..", "data", language, "words.json"); + + try { + await fs.access(wordsFilePath); + + const fileContent = await fs.readFile(wordsFilePath, "utf-8"); + + if (fileContent.trim()) { + const words = JSON.parse(fileContent); + const randomWord = randomArrayItem(words); + res.status(200).json([randomWord]); + } else { + throw new Error("Empty file"); + } + } catch (error) { + if (error.code === "ENOENT" || error.message === "Empty file") { + res.status(404).json({ + error: 1, + message: "Language not supported yet" + }); + } else { + console.error("Error reading words file:", error); + res.status(500).json({ + error: 1, + message: "Internal server error" + }); + } + } +}); + +export default router; \ No newline at end of file diff --git a/routes/pronounce.js b/routes/pronounce.js deleted file mode 100644 index f6b303e..0000000 --- a/routes/pronounce.js +++ /dev/null @@ -1,30 +0,0 @@ -import express from "express"; -import { pronounce } from "node-pronounce"; -const router = express.Router(); - -router.use(express.json()); - -router.post("/", function (req, res) { - res.header("Access-Control-Allow-Origin", "*"); - res.header( - "Access-Control-Allow-Headers", - "Access-Control-Allow-Headers,Content-Type,Access-Control-Allow-Methods, Authorization, X-Requested-With" - ); - res.header("Access-Control-Allow-Methods", "GET"); - res.header("X-Frame-Options", "DENY"); - res.header("X-XSS-Protection", "1; mode=block"); - res.header("X-Content-Type-Options", "nosniff"); - res.header("Strict-Transport-Security", "max-age=63072000"); - res.setHeader("Content-Type", "application/json"); - - var userWord = encodeURIComponent(req.body.word) || "Hello World"; - if (userWord == "undefined") { - res.status(400).json({ pronunciation: "Empty data" }); - } else { - let wordData = pronounce(userWord); - const pronouncedWord = decodeURIComponent(wordData); - res.status(200).json({ pronunciation: pronouncedWord }); - } -}); - -export default router; diff --git a/utils/headers.js b/utils/headers.js deleted file mode 100644 index 9224544..0000000 --- a/utils/headers.js +++ /dev/null @@ -1,10 +0,0 @@ -export const setDefaultHeaders = (response) => { - response.header("Access-Control-Allow-Origin", "*"); - response.header('Access-Control-Allow-Headers', 'Access-Control-Allow-Headers,Content-Type,Access-Control-Allow-Methods, Authorization, X-Requested-With'); - response.header("Access-Control-Allow-Methods", "GET"); - response.header("X-Frame-Options", "DENY"); - response.header("X-XSS-Protection", "1; mode=block"); - response.header("X-Content-Type-Options", "nosniff"); - response.header("Strict-Transport-Security", "max-age=63072000"); - response.setHeader("Content-Type", "application/json"); -} diff --git a/utils/index.js b/utils/index.js new file mode 100644 index 0000000..ebaa318 --- /dev/null +++ b/utils/index.js @@ -0,0 +1,50 @@ +import axios from "axios"; +import * as cheerio from "cheerio"; +import { pronounce } from "node-pronounce"; +import randomUseragent from "random-useragent"; + +const rua = randomUseragent.getRandom(); + +export const fetcher = async ({ + url, + container = ".section", + containerId = "#shared_section", + wordId = "#random_word", + definitionId = "#random_word_definition" +}) => { + try { + const response = await axios({ + method: "GET", + url, + headers: { "User-Agent": rua }, + }); + + const $ = cheerio.load(response.data); + const post = $(`${container} ${containerId}`); + const word = post.find(wordId).eq(0).text().replace(/[\r\n\t]+/g, ""); + const definition = post.find(definitionId).eq(0).text().replace("\n", ""); + const pronounceword = pronounce(word).replace(",", ""); + + return { + word: decodeURI(`${word.charAt(0).toUpperCase()}${word.slice(1)}`), + definition: decodeURI(`${definition.charAt(0).toUpperCase()}${definition.slice(1)}`), + pronunciation: decodeURI(`${pronounceword.charAt(0).toUpperCase()}${pronounceword.slice(1)}`), + }; + } catch (error) { + if (!error.response) { + throw new Error("API URL is Missing"); + } + throw new Error("Something Went Wrong - Enter the Correct API URL"); + } +} + +export const defaultHeaders = (response) => { + response.header("Access-Control-Allow-Origin", "*"); + response.header('Access-Control-Allow-Headers', 'Access-Control-Allow-Headers,Content-Type,Access-Control-Allow-Methods, Authorization, X-Requested-With'); + response.header("Access-Control-Allow-Methods", "GET"); + response.header("X-Frame-Options", "DENY"); + response.header("X-XSS-Protection", "1; mode=block"); + response.header("X-Content-Type-Options", "nosniff"); + response.header("Strict-Transport-Security", "max-age=63072000"); + response.setHeader("Content-Type", "application/json"); +} diff --git a/utils/randomNum.js b/utils/randomNum.js deleted file mode 100644 index 1ca8d73..0000000 --- a/utils/randomNum.js +++ /dev/null @@ -1,7 +0,0 @@ -function getRandomIntInclusive(min, max) { - min = Math.ceil(min); - max = Math.floor(max); - return Math.floor(Math.random() * (max - min + 1) + min); -} - -export const randNum = getRandomIntInclusive; From 0150fa290c1fdd21040ec1bde526ff6e4376072b Mon Sep 17 00:00:00 2001 From: Naveen MC <8493007+mcnaveen@users.noreply.github.com> Date: Sun, 25 Aug 2024 19:50:23 +0530 Subject: [PATCH 2/3] feat(docs): :sparkles: add swagger docs --- README.md | 8 ++ app.json | 6 +- index.js | 14 ++- package.json | 9 +- pnpm-lock.yaml | 208 +++++++++++++++++++++++++++++++++++++++++++-- routes/english.js | 53 ++++++++++++ routes/language.js | 33 +++++++ swagger-ui.js | 10 +++ swagger.js | 36 ++++++++ utils/index.js | 12 +++ 10 files changed, 375 insertions(+), 14 deletions(-) create mode 100644 swagger-ui.js create mode 100644 swagger.js diff --git a/README.md b/README.md index 9b0fffb..18a722c 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,14 @@ OR Project - Give Forked Repo URL - Go Live ``` +## 🔐 Rate Limit + +- To configure the rate limit, edit the `utils/index.js` file +- Look for `limiter` variable +- `max` is the maximum number of requests allowed in a given time window +- `windowMs` is the time window in milliseconds +- `message` is the message to be returned when the rate limit is exceeded + ## 😇 Add New Language - Create a new folder in `data` with the full language name `ex: english` - Add the words in the `words.json` file diff --git a/app.json b/app.json index 5c24a75..db4ad8d 100644 --- a/app.json +++ b/app.json @@ -1,6 +1,6 @@ { - "name": "wotd", - "description": "Word of the Day.", + "name": "random-words-api", + "description": "API for getting random words in different languages", "repository": "https://github.com/mcnaveen/Random-Words-API", - "keywords": ["expressjs", "nodejs", "json"] + "keywords": ["expressjs", "nodejs", "json", "random-words", "api"] } \ No newline at end of file diff --git a/index.js b/index.js index 132101b..a08a986 100644 --- a/index.js +++ b/index.js @@ -1,13 +1,23 @@ import express from "express"; const app = express(); -import home from './routes/home.js'; import english from './routes/english.js'; import language from './routes/language.js'; +import swaggerUi from './swagger-ui.js'; +import { limiter } from "./utils/index.js"; -app.use('/', home); +// Apply rate limiter to all routes except root +app.use((req, res, next) => { + if (req.path !== '/') { + return limiter(req, res, next); + } + next(); +}); + +app.use('/', swaggerUi); app.use('/word', english); app.use('/word', language); +app.use('/api-docs', swaggerUi); app.use('/', function(_req, res) { res.status(404).json({ diff --git a/package.json b/package.json index bebf5c9..23e5c32 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,19 @@ { - "name": "wotd", + "name": "random-words-api", "version": "1.0.0", - "description": "Word of the Day", + "description": "API for getting random words in different languages", "private": true, "main": "index.js", "dependencies": { "axios": "^1.1.3", "cheerio": "^1.0.0-rc.12", "express": "^4.18.2", + "express-rate-limit": "^7.4.0", "node-pronounce": "^0.0.4", "random-array-item": "^0.0.2", - "random-useragent": "^0.5.0" + "random-useragent": "^0.5.0", + "swagger-jsdoc": "^6.2.8", + "swagger-ui-express": "^5.0.1" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 12e777c..8afddac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ dependencies: express: specifier: ^4.18.2 version: 4.19.2 + express-rate-limit: + specifier: ^7.4.0 + version: 7.4.0(express@4.19.2) node-pronounce: specifier: ^0.0.4 version: 0.0.4 @@ -23,6 +26,12 @@ dependencies: random-useragent: specifier: ^0.5.0 version: 0.5.0 + swagger-jsdoc: + specifier: ^6.2.8 + version: 6.2.8(openapi-types@12.1.3) + swagger-ui-express: + specifier: ^5.0.1 + version: 5.0.1(express@4.19.2) devDependencies: all-contributors-cli: @@ -37,6 +46,38 @@ devDependencies: packages: + /@apidevtools/json-schema-ref-parser@9.1.2: + resolution: {integrity: sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==} + dependencies: + '@jsdevtools/ono': 7.1.3 + '@types/json-schema': 7.0.15 + call-me-maybe: 1.0.2 + js-yaml: 4.1.0 + dev: false + + /@apidevtools/openapi-schemas@2.1.0: + resolution: {integrity: sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==} + engines: {node: '>=10'} + dev: false + + /@apidevtools/swagger-methods@3.0.2: + resolution: {integrity: sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==} + dev: false + + /@apidevtools/swagger-parser@10.0.3(openapi-types@12.1.3): + resolution: {integrity: sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==} + peerDependencies: + openapi-types: '>=7' + dependencies: + '@apidevtools/json-schema-ref-parser': 9.1.2 + '@apidevtools/openapi-schemas': 2.1.0 + '@apidevtools/swagger-methods': 3.0.2 + '@jsdevtools/ono': 7.1.3 + call-me-maybe: 1.0.2 + openapi-types: 12.1.3 + z-schema: 5.0.5 + dev: false + /@babel/code-frame@7.24.7: resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} engines: {node: '>=6.9.0'} @@ -102,6 +143,10 @@ packages: chalk: 4.1.2 dev: true + /@jsdevtools/ono@7.1.3: + resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} + dev: false + /@sindresorhus/is@0.14.0: resolution: {integrity: sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==} engines: {node: '>=6'} @@ -114,6 +159,10 @@ packages: defer-to-connect: 1.1.3 dev: true + /@types/json-schema@7.0.15: + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + dev: false + /@types/keyv@3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: @@ -212,6 +261,10 @@ packages: picomatch: 2.3.1 dev: true + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: false + /array-flatten@1.1.1: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} dev: false @@ -236,7 +289,6 @@ packages: /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true /binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} @@ -286,7 +338,6 @@ packages: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - dev: true /braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} @@ -324,6 +375,10 @@ packages: set-function-length: 1.2.2 dev: false + /call-me-maybe@1.0.2: + resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==} + dev: false + /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -475,6 +530,18 @@ packages: delayed-stream: 1.0.0 dev: false + /commander@6.2.0: + resolution: {integrity: sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==} + engines: {node: '>= 6'} + dev: false + + /commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + requiresBuild: true + dev: false + optional: true + /compromise-speech@0.1.0(compromise@14.14.0): resolution: {integrity: sha512-+2KS/8T3SH5Hcd6tsCBVfxrkdi7sbJfKAeXGYimQdKGgweDMt0FT03wVCDZ6EgLYxReftkRKp1pxLx2pQLj4Kg==} peerDependencies: @@ -494,7 +561,6 @@ packages: /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true /configstore@5.0.1: resolution: {integrity: sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==} @@ -645,6 +711,13 @@ packages: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} dev: true + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: false + /dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} dependencies: @@ -756,6 +829,11 @@ packages: engines: {node: '>=0.8.0'} dev: true + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: false + /etag@1.8.1: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} @@ -776,6 +854,15 @@ packages: strip-final-newline: 2.0.0 dev: true + /express-rate-limit@7.4.0(express@4.19.2): + resolution: {integrity: sha512-v1204w3cXu5gCDmAvgvzI6qjzZzoMWKnyVDk3ACgfswTQLYiGen+r8w0VnXnGMmzEN/g8fwIQ4JrFFd4ZP6ssg==} + engines: {node: '>= 16'} + peerDependencies: + express: 4 || 5 || ^5.0.0-beta.1 + dependencies: + express: 4.19.2 + dev: false + /express@4.19.2: resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} engines: {node: '>= 0.10.0'} @@ -899,6 +986,10 @@ packages: universalify: 2.0.1 dev: true + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: false + /fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -975,6 +1066,18 @@ packages: is-glob: 4.0.3 dev: true + /glob@7.1.6: + resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} + deprecated: Glob versions prior to v9 are no longer supported + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: false + /global-dirs@0.1.1: resolution: {integrity: sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==} engines: {node: '>=4'} @@ -1125,6 +1228,14 @@ packages: engines: {node: '>=0.8.19'} dev: true + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: false + /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} dev: false @@ -1246,6 +1357,13 @@ packages: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} dev: true + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: false + /json-buffer@3.0.0: resolution: {integrity: sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==} dev: true @@ -1304,6 +1422,18 @@ packages: p-locate: 4.1.0 dev: true + /lodash.get@4.4.2: + resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + dev: false + + /lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + dev: false + + /lodash.mergewith@4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + dev: false + /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} dev: true @@ -1390,7 +1520,6 @@ packages: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: brace-expansion: 1.1.11 - dev: true /minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} @@ -1487,7 +1616,6 @@ packages: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: wrappy: 1.0.2 - dev: true /onetime@5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} @@ -1496,6 +1624,10 @@ packages: mimic-fn: 2.1.0 dev: true + /openapi-types@12.1.3: + resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} + dev: false + /os-tmpdir@1.0.2: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} engines: {node: '>=0.10.0'} @@ -1581,6 +1713,11 @@ packages: engines: {node: '>=8'} dev: true + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: false + /path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -1972,6 +2109,44 @@ packages: has-flag: 4.0.0 dev: true + /swagger-jsdoc@6.2.8(openapi-types@12.1.3): + resolution: {integrity: sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==} + engines: {node: '>=12.0.0'} + hasBin: true + dependencies: + commander: 6.2.0 + doctrine: 3.0.0 + glob: 7.1.6 + lodash.mergewith: 4.6.2 + swagger-parser: 10.0.3(openapi-types@12.1.3) + yaml: 2.0.0-1 + transitivePeerDependencies: + - openapi-types + dev: false + + /swagger-parser@10.0.3(openapi-types@12.1.3): + resolution: {integrity: sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==} + engines: {node: '>=10'} + dependencies: + '@apidevtools/swagger-parser': 10.0.3(openapi-types@12.1.3) + transitivePeerDependencies: + - openapi-types + dev: false + + /swagger-ui-dist@5.17.14: + resolution: {integrity: sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==} + dev: false + + /swagger-ui-express@5.0.1(express@4.19.2): + resolution: {integrity: sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==} + engines: {node: '>= v0.10.32'} + peerDependencies: + express: '>=4.0.0 || >=5.0.0-beta' + dependencies: + express: 4.19.2 + swagger-ui-dist: 5.17.14 + dev: false + /through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} dev: true @@ -2099,6 +2274,11 @@ packages: engines: {node: '>= 0.4.0'} dev: false + /validator@13.12.0: + resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==} + engines: {node: '>= 0.10'} + dev: false + /vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -2171,7 +2351,6 @@ packages: /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true /write-file-atomic@3.0.3: resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} @@ -2201,6 +2380,11 @@ packages: engines: {node: '>= 6'} dev: true + /yaml@2.0.0-1: + resolution: {integrity: sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==} + engines: {node: '>= 6'} + dev: false + /yargs-parser@18.1.3: resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} engines: {node: '>=6'} @@ -2243,3 +2427,15 @@ packages: y18n: 5.0.8 yargs-parser: 21.1.1 dev: true + + /z-schema@5.0.5: + resolution: {integrity: sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==} + engines: {node: '>=8.0.0'} + hasBin: true + dependencies: + lodash.get: 4.4.2 + lodash.isequal: 4.5.0 + validator: 13.12.0 + optionalDependencies: + commander: 9.5.0 + dev: false diff --git a/routes/english.js b/routes/english.js index 59cf128..f4245d1 100644 --- a/routes/english.js +++ b/routes/english.js @@ -7,6 +7,29 @@ const baseUrl = "https://randomword.com"; const validPos = ['noun', 'verb', 'adjective', 'adverb', 'sentence', 'question', 'idiom', 'letter', 'paragraph', 'vocabulary', '1-word-quotes', '2-word-quotes', '3-word-quotes', 'affirmation']; +/** + * @swagger + * /word: + * get: + * summary: Get a random English word + * description: Retrieve a random English word with its definition and pronunciation + * responses: + * 200: + * description: Successful response + * content: + * application/json: + * schema: + * type: object + * properties: + * word: + * type: string + * definition: + * type: string + * pronunciation: + * type: string + * 500: + * description: Server error + */ router.get("/", async (req, res) => { defaultHeaders(res); try { @@ -24,6 +47,36 @@ router.get("/", async (req, res) => { } }); +/** + * @swagger + * /word/english/{pos}: + * get: + * summary: Get a random English word by part of speech + * description: Retrieve a random English word with its definition and pronunciation for a specific part of speech + * parameters: + * - in: path + * name: pos + * required: true + * schema: + * type: string + * description: Part of speech (noun, verb, adjective, etc.) + * responses: + * 200: + * description: Successful response + * content: + * application/json: + * schema: + * type: object + * properties: + * word: + * type: string + * definition: + * type: string + * pronunciation: + * type: string + * 500: + * description: Server error + */ router.get("/english/:pos", async (req, res, next) => { const partOfSpeech = req.params.pos.toLowerCase(); diff --git a/routes/language.js b/routes/language.js index cdd155f..835c83d 100644 --- a/routes/language.js +++ b/routes/language.js @@ -9,6 +9,39 @@ const router = express.Router(); const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); +/** + * @swagger + * /word/{language}: + * get: + * summary: Get a random word in a specific language + * description: Retrieve a random word with its definition in a specified language + * parameters: + * - in: path + * name: language + * required: true + * schema: + * $ref: '#/components/schemas/Language' + * responses: + * 200: + * description: Successful response + * content: + * application/json: + * schema: + * type: array + * items: + * type: object + * properties: + * id: + * type: integer + * word: + * type: string + * definition: + * type: string + * 404: + * description: Language not supported + * 500: + * description: Server error + */ router.get("/:language", async function (req, res) { defaultHeaders(res); const language = req.params.language.toLowerCase(); diff --git a/swagger-ui.js b/swagger-ui.js new file mode 100644 index 0000000..4baac54 --- /dev/null +++ b/swagger-ui.js @@ -0,0 +1,10 @@ +import express from 'express'; +import swaggerUi from 'swagger-ui-express'; +import specs from './swagger.js'; + +const router = express.Router(); + +router.use('/', swaggerUi.serve); +router.get('/', swaggerUi.setup(specs, { explorer: true })); + +export default router; \ No newline at end of file diff --git a/swagger.js b/swagger.js new file mode 100644 index 0000000..5dae211 --- /dev/null +++ b/swagger.js @@ -0,0 +1,36 @@ +import swaggerJsdoc from 'swagger-jsdoc'; + +const options = { + definition: { + openapi: '3.0.0', + info: { + title: 'Random Words API', + version: '1.0.0', + description: 'API for getting random words in different languages', + contact: { + name: 'Source Code', + url: 'https://github.com/mcnaveen/random-words-api', + }, + }, + servers: [ + { + url: 'http://localhost:3000', + description: 'Development server', + }, + ], + components: { + schemas: { + Language: { + type: 'string', + enum: ['spanish', 'french', 'dutch', 'japanese', 'chinese', 'turkish'], + description: 'Available languages for random words', + }, + }, + }, + }, + apis: ['./routes/*.js'], +}; + +const specs = swaggerJsdoc(options); + +export default specs; \ No newline at end of file diff --git a/utils/index.js b/utils/index.js index ebaa318..61670d6 100644 --- a/utils/index.js +++ b/utils/index.js @@ -1,10 +1,22 @@ import axios from "axios"; import * as cheerio from "cheerio"; +import rateLimit from "express-rate-limit"; import { pronounce } from "node-pronounce"; import randomUseragent from "random-useragent"; const rua = randomUseragent.getRandom(); +export const limiter = rateLimit({ + windowMs: 15 * 60 * 1000, // 15 minutes + max: 5, // Limit each IP to 100 requests per windowMs + standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers + legacyHeaders: false, // Disable the `X-RateLimit-*` headers + message: { + error: 1, + message: 'Too many requests, please try again later.' + } +}); + export const fetcher = async ({ url, container = ".section", From 039ad1b226b7c31d6dccf88b1c3cd4072c0bb850 Mon Sep 17 00:00:00 2001 From: Naveen MC <8493007+mcnaveen@users.noreply.github.com> Date: Sun, 25 Aug 2024 19:52:21 +0530 Subject: [PATCH 3/3] bump rate limit --- utils/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/index.js b/utils/index.js index 61670d6..1fd7058 100644 --- a/utils/index.js +++ b/utils/index.js @@ -8,7 +8,7 @@ const rua = randomUseragent.getRandom(); export const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes - max: 5, // Limit each IP to 100 requests per windowMs + max: 30, // Limit each IP to 100 requests per windowMs standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers legacyHeaders: false, // Disable the `X-RateLimit-*` headers message: {