├── .gitignore ├── README.md ├── db-llm ├── .ipynb ├── db-llm.pdf └── db.sqlite3 ├── docs ├── docker.pdf ├── imgs │ ├── intro-2.png │ └── intro.png └── roadmap │ ├── dj-react.md │ ├── encore-nextjs.md │ ├── index.md │ ├── py-beginer.md │ └── react-nextjs.md ├── fastapi ├── Dockerfile ├── app.py ├── data_chat.sqlite3 ├── db.py ├── requirements.txt └── utils.py ├── nextjs-app ├── .gitignore ├── README.md ├── app │ ├── favicon.ico │ ├── fonts │ │ ├── GeistMonoVF.woff │ │ └── GeistVF.woff │ ├── globals.css │ ├── layout.tsx │ └── page.tsx ├── next.config.ts ├── package-lock.json ├── package.json ├── postcss.config.mjs ├── public │ ├── file.svg │ ├── globe.svg │ ├── next.svg │ ├── vercel.svg │ └── window.svg ├── tailwind.config.ts └── tsconfig.json └── ollama ├── Dockerfile └── pull-qwen.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # FastAPI 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | *.so 6 | .Python 7 | env/ 8 | .venv/ 9 | venv/ 10 | ENV/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # Next.js 27 | .next/ 28 | out/ 29 | build/ 30 | .DS_Store 31 | *.pem 32 | npm-debug.log* 33 | yarn-debug.log* 34 | yarn-error.log* 35 | .env*.local 36 | .vercel 37 | node_modules/ 38 | .env 39 | .env.local 40 | .env.development.local 41 | .env.test.local 42 | .env.production.local 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8syncdev/ollama-docker-web-application/29061ad0001200732fe7bd8df35aee47fb180f19/README.md -------------------------------------------------------------------------------- /db-llm/.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "# LangChain components\n", 10 | "from langchain_ollama import OllamaLLM # Tích hợp mô hình Ollama\n", 11 | "from langchain.chains.sql_database.query import create_sql_query_chain # Tạo chuỗi truy vấn SQL\n", 12 | "from langchain.prompts import PromptTemplate # Template cho prompt\n", 13 | "from langchain_community.tools import QuerySQLDataBaseTool # Tool truy vấn DB\n", 14 | "from langchain.sql_database import SQLDatabase # Wrapper cho DB\n", 15 | "from langchain_core.output_parsers import StrOutputParser # Parser output\n", 16 | "from langchain_core.runnables import RunnablePassthrough # Pipeline processing\n", 17 | "\n", 18 | "# SQLModel for ORM\n", 19 | "from sqlmodel import Field, SQLModel, create_engine, Session, select\n", 20 | "\n", 21 | "# Caching\n", 22 | "from langchain.cache import InMemoryCache\n", 23 | "from langchain.globals import set_llm_cache\n" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": 2, 29 | "metadata": {}, 30 | "outputs": [ 31 | { 32 | "name": "stdout", 33 | "output_type": "stream", 34 | "text": [ 35 | "NAME ID SIZE MODIFIED \n", 36 | "qwen2.5-coder:1.5b 6d3abb8d2d53 986 MB 3 weeks ago \n", 37 | "llama3.2:3b a80c4f17acd5 2.0 GB 5 weeks ago \n" 38 | ] 39 | } 40 | ], 41 | "source": [ 42 | "!ollama list" 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": 3, 48 | "metadata": {}, 49 | "outputs": [], 50 | "source": [ 51 | "llm = OllamaLLM(\n", 52 | " model=\"llama3.2:3b\"\n", 53 | ")" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 4, 59 | "metadata": {}, 60 | "outputs": [], 61 | "source": [ 62 | "\n", 63 | "class Blog(SQLModel, table=True):\n", 64 | " id: int = Field(primary_key=True, index=True)\n", 65 | " title: str\n", 66 | " content: str\n", 67 | "\n", 68 | "file_path = \"./db.sqlite3\"\n", 69 | "engine = create_engine(f\"sqlite:///{file_path}\")\n", 70 | "\n", 71 | "def create_all_tables():\n", 72 | " SQLModel.metadata.create_all(engine)" 73 | ] 74 | }, 75 | { 76 | "cell_type": "code", 77 | "execution_count": 5, 78 | "metadata": {}, 79 | "outputs": [], 80 | "source": [ 81 | "create_all_tables()" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": 6, 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [ 90 | "db = SQLDatabase(engine=engine)" 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "execution_count": 7, 96 | "metadata": {}, 97 | "outputs": [ 98 | { 99 | "name": "stdout", 100 | "output_type": "stream", 101 | "text": [ 102 | "\n", 103 | "CREATE TABLE blog (\n", 104 | "\tid INTEGER NOT NULL, \n", 105 | "\ttitle VARCHAR NOT NULL, \n", 106 | "\tcontent VARCHAR NOT NULL, \n", 107 | "\tPRIMARY KEY (id)\n", 108 | ")\n", 109 | "\n", 110 | "/*\n", 111 | "3 rows from blog table:\n", 112 | "id\ttitle\tcontent\n", 113 | "1\tNew Post\tThis is a new post.\n", 114 | "2\tTên của bài viết có thể là: \"Làm quen với TypeScript: Tìm hiểu về các loại và đặc điểm của ngôn ngữ \t**Tiêu đề:** Những Mẹo Sử Dụng TypeScript Để Tối化 Kỹ Năng Cập Nhật Cập Nhật của Bạn\n", 115 | "\n", 116 | "**Nội dung:**\n", 117 | "\n", 118 | "\n", 119 | "*/\n" 120 | ] 121 | } 122 | ], 123 | "source": [ 124 | "print(db.get_table_info(db.get_usable_table_names()))" 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": 8, 130 | "metadata": {}, 131 | "outputs": [], 132 | "source": [ 133 | "def standardize_query(query: str):\n", 134 | " if \"SQLQuery: \" in query:\n", 135 | " query = query.split(\"SQLQuery: \")[1]\n", 136 | " elif \"```sql\" in query:\n", 137 | " query = query.split(\"```sql\")[1].split(\"```\")[0].strip()\n", 138 | " return query.split(\";\")[0]\n", 139 | "\n" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 9, 145 | "metadata": {}, 146 | "outputs": [], 147 | "source": [ 148 | "sql_chain = create_sql_query_chain(\n", 149 | " llm=llm,\n", 150 | " db=db\n", 151 | ")" 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "execution_count": 26, 157 | "metadata": {}, 158 | "outputs": [], 159 | "source": [ 160 | "llm_chain = (\n", 161 | " RunnablePassthrough.assign(\n", 162 | " question = lambda x: x[\"question\"]\n", 163 | " ).assign(\n", 164 | " title = lambda x: llm.invoke(\"Tạo ra title từ question: {}\".format(x[\"question\"]))\n", 165 | " ).assign(\n", 166 | " content = lambda x: llm.invoke(\"Tạo content cho question: {}\".format(x[\"question\"]))\n", 167 | " ).assign(\n", 168 | " db_exec = lambda x: db.run('''INSERT INTO \"blog\" (\"title\", \"content\") VALUES ('{}', '{}')'''.format(\n", 169 | " x[\"title\"].replace(\"'\", \"''\"),\n", 170 | " x[\"content\"].replace(\"'\", \"''\"),\n", 171 | " ))\n", 172 | " )\n", 173 | ")" 174 | ] 175 | }, 176 | { 177 | "cell_type": "code", 178 | "execution_count": 11, 179 | "metadata": {}, 180 | "outputs": [], 181 | "source": [ 182 | "cache = InMemoryCache()\n", 183 | "set_llm_cache(cache)" 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": 12, 189 | "metadata": {}, 190 | "outputs": [], 191 | "source": [ 192 | "generation_params = {\n", 193 | " \"temperature\": 0.7, # Điều chỉnh độ ngẫu nhiên (0-1)\n", 194 | " \"top_k\": 10, # Giới hạn từ vựng top K tokens\n", 195 | " \"top_p\": 0.95, # Ngưỡng nucleus sampling\n", 196 | " \"num_ctx\": 2048, # Kích thước cửa sổ ngữ cảnh\n", 197 | " \"num_thread\": 1, # Số luồng sử dụng\n", 198 | " \"num_predict\": 200, # Số tokens tối đa dự đoán\n", 199 | " \"repeat_last_n\": 64, # Số tokens cuối cùng xem xét lặp lại\n", 200 | " \"repeat_penalty\": 1.15 # Hệ số phạt lặp lại\n", 201 | "}\n" 202 | ] 203 | }, 204 | { 205 | "cell_type": "code", 206 | "execution_count": 27, 207 | "metadata": {}, 208 | "outputs": [], 209 | "source": [ 210 | "run_llm = (llm_chain.with_config({\n", 211 | " **generation_params\n", 212 | "}).invoke({\n", 213 | " \"question\": \"Thêm bài viết về Typescript\"\n", 214 | "}))\n", 215 | "\n" 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": 28, 221 | "metadata": {}, 222 | "outputs": [ 223 | { 224 | "name": "stdout", 225 | "output_type": "stream", 226 | "text": [ 227 | "\n", 228 | "hello\n", 229 | "hello\n", 230 | "hello\n", 231 | "hello\n", 232 | "hello\n", 233 | "hello\n", 234 | "\n", 235 | "\n" 236 | ] 237 | } 238 | ], 239 | "source": [ 240 | "print('''\n", 241 | "hello\n", 242 | "hello\n", 243 | "hello\n", 244 | "hello\n", 245 | "hello\n", 246 | "hello\n", 247 | "\n", 248 | "''')" 249 | ] 250 | } 251 | ], 252 | "metadata": { 253 | "kernelspec": { 254 | "display_name": "venv", 255 | "language": "python", 256 | "name": "python3" 257 | }, 258 | "language_info": { 259 | "codemirror_mode": { 260 | "name": "ipython", 261 | "version": 3 262 | }, 263 | "file_extension": ".py", 264 | "mimetype": "text/x-python", 265 | "name": "python", 266 | "nbconvert_exporter": "python", 267 | "pygments_lexer": "ipython3", 268 | "version": "3.11.9" 269 | } 270 | }, 271 | "nbformat": 4, 272 | "nbformat_minor": 2 273 | } 274 | -------------------------------------------------------------------------------- /db-llm/db-llm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8syncdev/ollama-docker-web-application/29061ad0001200732fe7bd8df35aee47fb180f19/db-llm/db-llm.pdf -------------------------------------------------------------------------------- /db-llm/db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8syncdev/ollama-docker-web-application/29061ad0001200732fe7bd8df35aee47fb180f19/db-llm/db.sqlite3 -------------------------------------------------------------------------------- /docs/docker.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8syncdev/ollama-docker-web-application/29061ad0001200732fe7bd8df35aee47fb180f19/docs/docker.pdf -------------------------------------------------------------------------------- /docs/imgs/intro-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8syncdev/ollama-docker-web-application/29061ad0001200732fe7bd8df35aee47fb180f19/docs/imgs/intro-2.png -------------------------------------------------------------------------------- /docs/imgs/intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8syncdev/ollama-docker-web-application/29061ad0001200732fe7bd8df35aee47fb180f19/docs/imgs/intro.png -------------------------------------------------------------------------------- /docs/roadmap/dj-react.md: -------------------------------------------------------------------------------- 1 | ### **Lộ trình học Django Ninja + ReactJS + HTML, CSS, JS, TS + Python Foundation (45 buổi)** 2 | 3 | --- 4 | 5 | ### **Mục tiêu khóa học:** 6 | - **Python Foundation**: Hiểu và làm chủ các khái niệm lập trình Python cơ bản, tạo nền tảng vững chắc cho việc phát triển backend. 7 | - **Frontend Development**: Thành thạo HTML, CSS, JavaScript (JS) và TypeScript (TS), kết hợp chúng để xây dựng giao diện người dùng hiện đại. 8 | - **Backend Development**: Làm chủ Django Ninja để phát triển API mạnh mẽ và bảo mật. 9 | - **Fullstack Project**: Tích hợp ReactJS với Django Ninja để phát triển một dự án thực tế từ đầu đến cuối. 10 | - **Triển khai và bảo mật**: Đưa dự án lên môi trường thực tế, tối ưu hóa hiệu năng và bảo mật. 11 | 12 | --- 13 | 14 | ### **Tổng quan lộ trình:** 15 | 1. **Giai đoạn 1 (Buổi 1–10)**: Python Foundation. 16 | 2. **Giai đoạn 2 (Buổi 11–20)**: HTML, CSS, JS, TS cơ bản. 17 | 3. **Giai đoạn 3 (Buổi 21–30)**: Django Ninja cơ bản và xây dựng API Backend. 18 | 4. **Giai đoạn 4 (Buổi 31–40)**: ReactJS cơ bản và phát triển giao diện người dùng. 19 | 5. **Giai đoạn 5 (Buổi 41–45)**: Triển khai, bảo mật và tối ưu hóa dự án. 20 | 21 | --- 22 | 23 | ### **Chi tiết lộ trình:** 24 | 25 | --- 26 | 27 | #### **Giai đoạn 1: Python Foundation (Buổi 1–10)** 28 | **Buổi 1: Làm quen với Python và cài đặt môi trường** 29 | - Cài đặt Python, IDE (Visual Studio Code, PyCharm). 30 | - Viết chương trình Python đầu tiên: "Hello, World!". 31 | - Hiểu cơ bản về biến, kiểu dữ liệu, và toán tử. 32 | - Thực hành: Tính tổng, hiệu, tích, thương hai số. 33 | 34 | **Buổi 2: Cấu trúc điều khiển** 35 | - Câu lệnh điều kiện: `if`, `elif`, `else`. 36 | - Vòng lặp: `for`, `while`. 37 | - Thực hành: Tính dãy Fibonacci và kiểm tra số nguyên tố. 38 | 39 | **Buổi 3: Hàm và cấu trúc dữ liệu cơ bản** 40 | - Tạo hàm với `def`. 41 | - Làm việc với danh sách, tuple, dictionary, và set. 42 | - Thực hành: Viết chương trình quản lý danh sách sinh viên. 43 | 44 | **Buổi 4: File I/O và xử lý ngoại lệ** 45 | - Đọc và ghi file với Python. 46 | - Xử lý ngoại lệ bằng `try`, `except`. 47 | - Thực hành: Lưu trữ dữ liệu sinh viên vào file CSV. 48 | 49 | **Buổi 5: Lập trình hướng đối tượng (OOP)** 50 | - Giới thiệu lớp, đối tượng, thuộc tính và phương thức. 51 | - Kế thừa và đa hình. 52 | - Thực hành: Xây dựng lớp quản lý sách (Book). 53 | 54 | **Buổi 6: Module và thư viện Python** 55 | - Sử dụng các thư viện tích hợp như `math`, `datetime`, `os`. 56 | - Cách tổ chức và tái sử dụng code với module. 57 | - Thực hành: Xây dựng module tính diện tích hình học. 58 | 59 | **Buổi 7: Giới thiệu Flask và REST API cơ bản** 60 | - Cài đặt Flask, tạo ứng dụng API cơ bản. 61 | - Thực hành: Tạo API "Hello, World!". 62 | 63 | **Buổi 8: Làm việc với cơ sở dữ liệu SQLite** 64 | - Kết nối Python với SQLite. 65 | - Thực hành: Tạo cơ sở dữ liệu quản lý sách với CRUD. 66 | 67 | **Buổi 9: Sử dụng thư viện bên ngoài (pip)** 68 | - Tìm hiểu pip và cách quản lý môi trường với `venv`. 69 | - Cài đặt và sử dụng thư viện `requests` để gọi API. 70 | 71 | **Buổi 10: Tổng kết Python Foundation** 72 | - Tổng hợp kiến thức và xây dựng ứng dụng mini quản lý thư viện sách. 73 | 74 | --- 75 | 76 | #### **Giai đoạn 2: HTML, CSS, JS, TS cơ bản (Buổi 11–20)** 77 | 78 | **Buổi 11: HTML cơ bản** 79 | - Hiểu cấu trúc HTML: các thẻ cơ bản như `div`, `span`, `p`, `h1`–`h6`, `img`, `a`. 80 | - Thực hành: Tạo trang web giới thiệu bản thân. 81 | 82 | **Buổi 12: CSS cơ bản** 83 | - Sử dụng các thuộc tính CSS: màu sắc, bố cục, định dạng text. 84 | - Thực hành: Thiết kế giao diện web đơn giản. 85 | 86 | **Buổi 13: JavaScript cơ bản** 87 | - Làm quen với cú pháp JavaScript. 88 | - Các khái niệm cơ bản như biến, hàm, và vòng lặp. 89 | - Thực hành: Viết chương trình đổi màu nền trang web khi nhấn nút. 90 | 91 | **Buổi 14: DOM Manipulation** 92 | - Hiểu và thay đổi DOM bằng JavaScript. 93 | - Thực hành: Thêm và xóa phần tử danh sách động. 94 | 95 | **Buổi 15: Event Handling trong JavaScript** 96 | - Lắng nghe và xử lý sự kiện như click, submit, hover. 97 | - Thực hành: Xây dựng form đăng ký người dùng với xác thực. 98 | 99 | **Buổi 16: Giới thiệu TypeScript (TS)** 100 | - Hiểu TypeScript là gì và tại sao nên dùng. 101 | - Cú pháp cơ bản của TS. 102 | 103 | **Buổi 17: Làm việc với kiểu dữ liệu và interface trong TS** 104 | - Sử dụng kiểu dữ liệu tĩnh và khai báo interface. 105 | - Thực hành: Tạo ứng dụng quản lý sách với TS. 106 | 107 | **Buổi 18: Sử dụng Fetch API** 108 | - Gọi API Django Ninja từ frontend với Fetch hoặc Axios. 109 | - Thực hành: Hiển thị danh sách sách từ API. 110 | 111 | **Buổi 19: Responsive Design với CSS** 112 | - Thiết kế web thân thiện với mọi thiết bị bằng Flexbox và Grid. 113 | - Thực hành: Tạo giao diện mobile-first. 114 | 115 | **Buổi 20: Tổng kết HTML, CSS, JS, TS** 116 | - Tổng hợp kiến thức qua bài tập thiết kế giao diện quản lý thư viện sách. 117 | 118 | --- 119 | 120 | #### **Giai đoạn 3: Django Ninja cơ bản và xây dựng API Backend (Buổi 21–30)** 121 | 122 | **Buổi 21: Giới thiệu về Django Ninja và cài đặt môi trường** 123 | - Django và Django Ninja là gì? 124 | - Cài đặt Python, Django, Django Ninja, và các công cụ cần thiết. 125 | - Tạo dự án Django đầu tiên. 126 | - Viết API đơn giản: Hello World. 127 | 128 | **Buổi 22: Làm việc với Models và ORM** 129 | - Giới thiệu Django ORM và cách quản lý cơ sở dữ liệu. 130 | - Tạo các model đầu tiên (e.g., User, Book, Category). 131 | - Sử dụng `makemigrations` và `migrate`. 132 | - Thực hành: Tạo model quản lý sách. 133 | 134 | **Buổi 23: Tạo CRUD API cơ bản với Django Ninja** 135 | - GET, POST, PUT, DELETE APIs. 136 | - Quản lý đường dẫn với `path` và `query parameters`. 137 | - Thực hành: API CRUD cho quản lý danh mục sách. 138 | 139 | **Buổi 24: Quản lý xác thực và bảo mật cơ bản** 140 | - Giới thiệu OAuth2 và JWT (JSON Web Tokens). 141 | - Tạo hệ thống đăng nhập, đăng ký với Django Ninja. 142 | - Thực hành: Bảo mật API với JWT. 143 | 144 | **Buổi 25: Middleware và xử lý lỗi** 145 | - Xây dựng và sử dụng middleware trong Django Ninja. 146 | - Xử lý lỗi tuỳ chỉnh (custom exceptions). 147 | - Thực hành: Log hoạt động API. 148 | 149 | **Buổi 26: Upload và quản lý file trong Django Ninja** 150 | - Tạo API upload file (e.g., ảnh bìa sách). 151 | - Quản lý file tĩnh (static files) và thư viện `Pillow`. 152 | - Thực hành: API upload ảnh và hiển thị URL ảnh. 153 | 154 | **Buổi 27: Pagination, Filters, và Search API** 155 | - Phân trang dữ liệu với `paginator`. 156 | - Lọc và tìm kiếm dữ liệu nâng cao. 157 | - Thực hành: API phân trang danh sách sách. 158 | 159 | **Buổi 28: Testing và kiểm tra API với Postman** 160 | - Cách viết test case cho API. 161 | - Kiểm tra API với Postman. 162 | - Thực hành: Test API sách và người dùng. 163 | 164 | **Buổi 29: Tích hợp cơ sở dữ liệu nâng cao (PostgreSQL)** 165 | - Kết nối PostgreSQL thay vì SQLite. 166 | - Indexing, query optimization. 167 | - Thực hành: Xây dựng API tối ưu hóa hiệu suất. 168 | 169 | **Buổi 30: Xây dựng API cho dự án thực tế** 170 | - Tổng hợp các kiến thức để xây dựng API hoàn chỉnh. 171 | - Thực hành: API cho hệ thống quản lý thư viện. 172 | 173 | --- 174 | 175 | #### **Giai đoạn 4: ReactJS cơ bản và phát triển giao diện người dùng (Buổi 31–40)** 176 | 177 | **Buổi 31: Giới thiệu ReactJS và cài đặt môi trường** 178 | - React là gì? Cách sử dụng Node.js và npm/yarn. 179 | - Tạo ứng dụng React đầu tiên với `create-react-app`. 180 | - Thực hành: Tạo giao diện "Hello, React!". 181 | 182 | **Buổi 32: JSX và Components** 183 | - Hiểu về JSX (JavaScript XML). 184 | - Tạo và quản lý components. 185 | - Thực hành: Tạo các component đơn giản (Header, Footer). 186 | 187 | **Buổi 33: Props và State trong ReactJS** 188 | - Truyền dữ liệu giữa các component bằng Props. 189 | - Quản lý trạng thái với State. 190 | - Thực hành: Xây dựng giao diện quản lý danh sách sách. 191 | 192 | **Buổi 34: Sự kiện và Form Handling** 193 | - Xử lý sự kiện trong ReactJS. 194 | - Quản lý form và input người dùng. 195 | - Thực hành: Tạo form đăng ký sách. 196 | 197 | **Buổi 35: Sử dụng React Router** 198 | - Tạo các route với `react-router-dom`. 199 | - Quản lý navigation (đa trang). 200 | - Thực hành: Xây dựng hệ thống menu với các trang (Home, Sách, Người dùng). 201 | 202 | **Buổi 36: Gọi API từ React (Axios hoặc Fetch)** 203 | - Sử dụng `axios` hoặc `fetch` để gọi API Django Ninja. 204 | - Hiển thị dữ liệu từ backend lên giao diện. 205 | - Thực hành: Tích hợp API danh sách sách với giao diện. 206 | 207 | **Buổi 37: Quản lý trạng thái với Context API** 208 | - Giới thiệu Context API. 209 | - Quản lý dữ liệu toàn cục. 210 | - Thực hành: Hệ thống quản lý đăng nhập trên toàn ứng dụng. 211 | 212 | **Buổi 38: Sử dụng Redux (Quản lý trạng thái nâng cao)** 213 | - Giới thiệu Redux và cách tích hợp. 214 | - Thực hành: Quản lý danh sách sách với Redux. 215 | 216 | **Buổi 39: UI nâng cao với Ant Design hoặc Material-UI** 217 | - Giới thiệu Ant Design hoặc Material-UI. 218 | - Thực hành: Thiết kế giao diện thư viện đẹp mắt. 219 | 220 | **Buổi 40: Testing React Components** 221 | - Viết test với Jest và React Testing Library. 222 | - Thực hành: Test các components giao diện. 223 | 224 | --- 225 | 226 | #### **Giai đoạn 5: Triển khai, bảo mật và tối ưu hóa (Buổi 41–45)** 227 | 228 | **Buổi 41: Triển khai dự án (Phần 1)** 229 | - Sử dụng Docker để đóng gói ứng dụng. 230 | - Chuẩn bị môi trường production. 231 | 232 | **Buổi 42: Triển khai dự án (Phần 2)** 233 | - Deploy Django Ninja và ReactJS lên Heroku hoặc AWS. 234 | - Cấu hình domain và SSL. 235 | 236 | **Buổi 43: Bảo mật và tối ưu hóa** 237 | - Sử dụng HTTPS và bảo mật JWT. 238 | - Caching và tối ưu hóa database queries. 239 | - Tối ưu hiệu năng frontend. 240 | 241 | **Buổi 44: Monitoring và logging** 242 | - Cài đặt hệ thống giám sát. 243 | - Quản lý logs và debug trong production. 244 | 245 | **Buổi 45: Tổng kết và trình bày dự án** 246 | - Review dự án hoàn chỉnh. 247 | - Gợi ý các bước phát triển nâng cao. 248 | 249 | --- 250 | -------------------------------------------------------------------------------- /docs/roadmap/encore-nextjs.md: -------------------------------------------------------------------------------- 1 | ### **Lộ trình học Microservices với Encore và Next.js (35–45 buổi)** 2 | 3 | --- 4 | 5 | **Mục tiêu khóa học:** 6 | - Nắm vững kiến trúc Microservices và cách áp dụng **Encore** để xây dựng backend hiện đại. 7 | - Thành thạo **Next.js** để phát triển giao diện người dùng tối ưu, kết hợp frontend với backend. 8 | - Hoàn thiện một dự án thực tế, từ thiết kế đến triển khai hệ thống hoàn chỉnh. 9 | 10 | --- 11 | 12 | ### **Tổng quan lộ trình:** 13 | 1. **Giai đoạn 1 (Buổi 1–10):** Làm quen với Microservices và Encore Backend. 14 | 2. **Giai đoạn 2 (Buổi 11–20):** Next.js cơ bản và phát triển giao diện người dùng. 15 | 3. **Giai đoạn 3 (Buổi 21–30):** Tích hợp Microservices (Encore) và Next.js. 16 | 4. **Giai đoạn 4 (Buổi 31–40):** Dự án thực tế và triển khai toàn hệ thống. 17 | 5. **Giai đoạn 5 (Buổi 41–45):** Tối ưu hóa, bảo mật và đánh giá dự án. 18 | 19 | --- 20 | 21 | ### **Chi tiết lộ trình học:** 22 | 23 | --- 24 | 25 | #### **Giai đoạn 1: Làm quen với Microservices và Encore Backend (Buổi 1–10)** 26 | 27 | **Buổi 1: Giới thiệu Microservices và Encore** 28 | - Tổng quan về kiến trúc Microservices: 29 | - Ưu điểm và nhược điểm. 30 | - Sự khác biệt so với kiến trúc Monolithic. 31 | - Giới thiệu framework **Encore**: 32 | - Các tính năng nổi bật (API, DB, Pub/Sub, Background Tasks). 33 | - Cài đặt môi trường Encore: 34 | - Thiết lập Node.js, Docker. 35 | - Tạo ứng dụng đầu tiên: "Hello, World!". 36 | 37 | **Buổi 2: Xây dựng RESTful API với Encore** 38 | - RESTful API và cách hoạt động trong Microservices. 39 | - Tạo endpoint cơ bản: GET, POST, PUT, DELETE. 40 | - Thực hành: 41 | - API CRUD cho hệ thống quản lý sản phẩm. 42 | - Test API bằng Postman. 43 | 44 | **Buổi 3: Sử dụng Database với Encore** 45 | - Kết nối với cơ sở dữ liệu PostgreSQL. 46 | - Tạo và quản lý bảng dữ liệu trong Encore. 47 | - Thực hành: 48 | - Tích hợp cơ sở dữ liệu cho API quản lý sản phẩm. 49 | - Viết truy vấn cơ bản: SELECT, INSERT, UPDATE, DELETE. 50 | 51 | **Buổi 4: Xử lý sự kiện với Pub/Sub trong Encore** 52 | - Giới thiệu Publish/Subscribe (Pub/Sub): 53 | - Cách hoạt động và ứng dụng. 54 | - Thực hành: 55 | - Tạo dịch vụ gửi email khi thêm sản phẩm mới. 56 | 57 | **Buổi 5: Authentication và Authorization trong Encore** 58 | - Giới thiệu hệ thống bảo mật: 59 | - OAuth2 và JWT trong Microservices. 60 | - Tích hợp hệ thống đăng nhập và phân quyền người dùng. 61 | - Thực hành: 62 | - API login/logout và phân quyền dựa trên role. 63 | 64 | **Buổi 6: Làm việc với Background Tasks** 65 | - Giới thiệu background tasks và cách sử dụng. 66 | - Thực hành: 67 | - Xử lý tác vụ gửi email báo cáo định kỳ. 68 | 69 | **Buổi 7: Tích hợp nhiều Microservices** 70 | - Tạo và giao tiếp giữa các dịch vụ (Service Communication). 71 | - Thực hành: 72 | - Tích hợp dịch vụ quản lý sản phẩm và đơn hàng. 73 | 74 | **Buổi 8: Testing dịch vụ Backend** 75 | - Viết Unit Test và Integration Test cho API. 76 | - Công cụ hỗ trợ: Jest hoặc Mocha. 77 | - Thực hành: 78 | - Test dịch vụ quản lý sản phẩm. 79 | 80 | **Buổi 9: Logging và Monitoring** 81 | - Hệ thống log và giám sát trong Microservices: 82 | - Tích hợp Prometheus/Grafana. 83 | - Thực hành: 84 | - Theo dõi log và hiệu suất của API. 85 | 86 | **Buổi 10: Xây dựng API Gateway** 87 | - Giới thiệu API Gateway: 88 | - Mục đích và vai trò trong hệ thống Microservices. 89 | - Thực hành: 90 | - Xây dựng API Gateway quản lý truy cập đến các dịch vụ. 91 | 92 | --- 93 | 94 | #### **Giai đoạn 2: Next.js cơ bản và phát triển giao diện người dùng (Buổi 11–20)** 95 | 96 | **Buổi 11: Giới thiệu Next.js và cài đặt môi trường** 97 | - Tổng quan về Next.js và lợi ích so với ReactJS thuần. 98 | - Cài đặt môi trường làm việc (Node.js, npm/yarn). 99 | - Tạo ứng dụng đầu tiên với Next.js: "Hello, World!". 100 | 101 | **Buổi 12: Routing trong Next.js** 102 | - Routing cơ bản và dynamic routing. 103 | - Thực hành: 104 | - Tạo hệ thống route cho trang sản phẩm (Danh sách, Chi tiết). 105 | 106 | **Buổi 13: Static Site Generation (SSG) và Server-Side Rendering (SSR)** 107 | - Giới thiệu SSG và SSR: 108 | - Khi nào sử dụng? 109 | - Thực hành: 110 | - Tích hợp SSR cho trang danh sách sản phẩm. 111 | 112 | **Buổi 14: Gọi API từ Next.js** 113 | - Gọi API bằng `fetch` hoặc `axios`. 114 | - Thực hành: 115 | - Hiển thị dữ liệu từ dịch vụ Encore trên giao diện. 116 | 117 | **Buổi 15: Xử lý Form và sự kiện trong Next.js** 118 | - Quản lý form nhập liệu và sự kiện người dùng. 119 | - Thực hành: 120 | - Form thêm mới sản phẩm. 121 | 122 | **Buổi 16: Context API trong Next.js** 123 | - Quản lý trạng thái toàn cục bằng Context API. 124 | - Thực hành: 125 | - Quản lý trạng thái người dùng đăng nhập. 126 | 127 | **Buổi 17: Redux Toolkit với Next.js** 128 | - Giới thiệu Redux và cách tích hợp với Next.js. 129 | - Thực hành: 130 | - Quản lý giỏ hàng với Redux Toolkit. 131 | 132 | **Buổi 18: Tối ưu giao diện với Material-UI hoặc TailwindCSS** 133 | - Tích hợp thư viện giao diện: 134 | - Material-UI hoặc TailwindCSS. 135 | - Thực hành: 136 | - Thiết kế giao diện đẹp mắt cho trang sản phẩm. 137 | 138 | **Buổi 19: Internationalization (i18n) trong Next.js** 139 | - Hỗ trợ đa ngôn ngữ. 140 | - Thực hành: 141 | - Thêm tiếng Anh và tiếng Việt vào ứng dụng. 142 | 143 | **Buổi 20: Testing giao diện** 144 | - Testing component bằng Jest và React Testing Library. 145 | - Thực hành: 146 | - Viết test cho trang sản phẩm. 147 | 148 | --- 149 | 150 | #### **Giai đoạn 3: Tích hợp Microservices và Next.js (Buổi 21–30)** 151 | 152 | **Buổi 21: Tích hợp API vào giao diện** 153 | - Kết nối backend Encore với frontend Next.js. 154 | - Thực hành: 155 | - Tích hợp API CRUD cho sản phẩm. 156 | 157 | **Buổi 22–25: Xây dựng các tính năng nâng cao** 158 | - Hoàn thiện giao diện quản lý sản phẩm: 159 | - Danh sách, thêm mới, sửa, xóa. 160 | - Quản lý đơn hàng: 161 | - Tích hợp hệ thống đặt hàng. 162 | 163 | **Buổi 26–28: Authentication và Authorization trên frontend** 164 | - Sử dụng JWT cho bảo mật frontend. 165 | - Thực hành: 166 | - Giao diện đăng nhập, phân quyền. 167 | 168 | **Buổi 29: Quản lý thanh toán** 169 | - Tích hợp Stripe/PayPal vào hệ thống thanh toán. 170 | - Thực hành: 171 | - Tạo giao diện thanh toán cho người dùng. 172 | 173 | **Buổi 30: Tối ưu hóa hiệu suất** 174 | - Lazy Loading và Code Splitting. 175 | - Thực hành: 176 | - Tăng tốc độ tải trang với Next.js. 177 | 178 | --- 179 | 180 | #### **Giai đoạn 4: Dự án thực tế (Buổi 31–40)** 181 | 182 | **Dự án: Hệ thống quản lý bán hàng** 183 | - **Backend (Encore):** 184 | - Microservices quản lý sản phẩm, đơn hàng, người dùng. 185 | - Quản lý thông báo và kho. 186 | - **Frontend (Next.js):** 187 | - Dashboard quản lý. 188 | - Trang khách hàng. 189 | 190 | --- 191 | 192 | #### **Giai đoạn 5: Triển khai và bảo mật (Buổi 41–45)** 193 | 194 | **Buổi 41–43: Triển khai toàn hệ thống** 195 | - Đóng gói dịch vụ bằng Docker. 196 | - Deploy lên AWS/GCP. 197 | 198 | **Buổi 44: Bảo mật và giám sát** 199 | - Thêm HTTPS, bảo mật API. 200 | - Giám sát hệ thống với Prometheus. 201 | 202 | **Buổi 45: Tổng kết và đánh giá** 203 | - Demo dự án hoàn chỉnh. 204 | - Nhận phản hồi, định hướng tương lai. -------------------------------------------------------------------------------- /docs/roadmap/index.md: -------------------------------------------------------------------------------- 1 | # Xem chi tiết khóa học 2 | 3 | ## 1. Django React [Xem chi tiết](./dj-react.md) 4 | ## 2. Encore NextJS [Xem chi tiết](./encore-nextjs.md) 5 | ## 3. Python Beginner [Xem chi tiết](./py-beginer.md) 6 | ## 4. React NextJS [Xem chi tiết](./react-nextjs.md) 7 | -------------------------------------------------------------------------------- /docs/roadmap/py-beginer.md: -------------------------------------------------------------------------------- 1 | ### **Lộ trình Python cho người mới bắt đầu (25 buổi)** 2 | **Chủ đề chính:** Python cơ bản đến nâng cao, ứng dụng các công nghệ hot như **FastAPI**, **Taipy (UI)**, và **Large Language Models (LLM) với Ollama** để thực hiện dự án cuối khóa. 3 | 4 | --- 5 | 6 | ### **Phần 1: Python Cơ Bản (Buổi 1-5)** 7 | 8 | **Buổi 1: Giới thiệu Python và cài đặt môi trường** 9 | - Python là gì? 10 | - Cài đặt Python, VSCode, và pip. 11 | - Làm quen với Jupyter Notebook và Terminal. 12 | - Viết chương trình "Hello, World!". 13 | 14 | **Buổi 2: Kiểu dữ liệu, Biến và Toán tử** 15 | - Các kiểu dữ liệu cơ bản: số, chuỗi, boolean. 16 | - Toán tử: số học, so sánh, logic. 17 | - Thực hành: Tính toán cơ bản, quản lý chuỗi. 18 | 19 | **Buổi 3: Cấu trúc điều kiện và Vòng lặp** 20 | - If-else, While, For loops. 21 | - Break và Continue trong vòng lặp. 22 | - Thực hành: Kiểm tra số nguyên tố, in bảng cửu chương. 23 | 24 | **Buổi 4: Hàm và Quản lý lỗi** 25 | - Viết và gọi hàm. 26 | - Tham số, giá trị trả về. 27 | - Xử lý lỗi với `try`, `except`. 28 | - Thực hành: Viết hàm kiểm tra số chẵn lẻ. 29 | 30 | **Buổi 5: Cấu trúc dữ liệu Python (List, Tuple, Dictionary, Set)** 31 | - Khai báo, truy cập và sửa đổi dữ liệu. 32 | - Các phương thức phổ biến. 33 | - Thực hành: Quản lý danh sách sinh viên. 34 | 35 | --- 36 | 37 | ### **Phần 2: FastAPI và Cơ bản Web Development (Buổi 6-10)** 38 | 39 | **Buổi 6: Làm quen với FastAPI** 40 | - Cài đặt FastAPI và Uvicorn. 41 | - Viết ứng dụng đầu tiên: API "Hello, World!". 42 | - Kiến thức cơ bản: Path, Query Parameters. 43 | 44 | **Buổi 7: Routes và CRUD Operations** 45 | - GET, POST, PUT, DELETE. 46 | - Xây dựng API CRUD cho hệ thống quản lý sách. 47 | 48 | **Buổi 8: Middleware và Xử lý lỗi** 49 | - Middleware trong FastAPI. 50 | - Xử lý lỗi tuỳ chỉnh với `HTTPException`. 51 | - Thực hành: Tích hợp middleware log request/response. 52 | 53 | **Buổi 9: Kết nối Database với FastAPI** 54 | - Cài đặt và sử dụng SQLAlchemy. 55 | - Tích hợp SQLite/PostgreSQL. 56 | - Thực hành: API CRUD với cơ sở dữ liệu. 57 | 58 | **Buổi 10: Bảo mật cơ bản và Authentication** 59 | - Cơ bản về OAuth2 và JWT. 60 | - Tạo hệ thống đăng nhập và quản lý người dùng. 61 | - Thực hành: API bảo mật với JWT Token. 62 | 63 | --- 64 | 65 | ### **Phần 3: Xây dựng giao diện người dùng với Taipy (Buổi 11-15)** 66 | 67 | **Buổi 11: Giới thiệu Taipy và UI cơ bản** 68 | - Cài đặt Taipy. 69 | - Xây dựng giao diện "Hello, World!" với Taipy. 70 | - Cách tổ chức các thành phần giao diện. 71 | 72 | **Buổi 12: Tích hợp giao diện với FastAPI** 73 | - Kết nối FastAPI với Taipy. 74 | - Hiển thị dữ liệu từ API lên giao diện. 75 | - Thực hành: Giao diện hiển thị danh sách sách. 76 | 77 | **Buổi 13: Tạo biểu đồ và tương tác dữ liệu** 78 | - Sử dụng Taipy để tạo biểu đồ động. 79 | - Thực hành: Dashboard thống kê số liệu bán hàng. 80 | 81 | **Buổi 14: Xây dựng form nhập liệu** 82 | - Tạo form để thêm, sửa, xóa dữ liệu. 83 | - Thực hành: Giao diện CRUD với Taipy. 84 | 85 | **Buổi 15: Tích hợp biểu đồ nâng cao với Taipy** 86 | - Sử dụng biểu đồ nâng cao và tương tác trực tiếp. 87 | - Thực hành: Dashboard doanh thu theo tháng. 88 | 89 | --- 90 | 91 | ### **Phần 4: Làm việc với LLM Ollama (Buổi 16-20)** 92 | 93 | **Buổi 16: Giới thiệu Large Language Models (LLM)** 94 | - LLM là gì và cách hoạt động. 95 | - Cài đặt và sử dụng Ollama. 96 | - Viết ứng dụng hỏi đáp cơ bản với LLM. 97 | 98 | **Buổi 17: Tích hợp LLM Ollama vào FastAPI** 99 | - Gọi LLM từ FastAPI. 100 | - Thực hành: API hỏi đáp sử dụng Ollama. 101 | 102 | **Buổi 18: Xử lý văn bản với Ollama** 103 | - Sử dụng Ollama để phân tích văn bản. 104 | - Thực hành: API phân tích cảm xúc bài viết. 105 | 106 | **Buổi 19: Huấn luyện và tuỳ chỉnh mô hình LLM Ollama** 107 | - Cách tùy chỉnh mô hình LLM. 108 | - Thực hành: Huấn luyện mô hình trên dữ liệu riêng. 109 | 110 | **Buổi 20: Tích hợp LLM vào giao diện người dùng** 111 | - Giao diện tương tác với LLM qua Taipy. 112 | - Thực hành: Chatbot trả lời câu hỏi trên giao diện. 113 | 114 | --- 115 | 116 | ### **Phần 5: Dự án Cuối Khóa (Buổi 21-25)** 117 | 118 | **Buổi 21: Lập kế hoạch dự án** 119 | - Đề bài: "Xây dựng hệ thống Quản lý kiến thức AI" với FastAPI, Taipy, và Ollama. 120 | - Phân chia công việc: 121 | - API backend (FastAPI). 122 | - Giao diện người dùng (Taipy). 123 | - Tích hợp LLM (Ollama). 124 | 125 | **Buổi 22: Xây dựng backend (FastAPI)** 126 | - Xây dựng API CRUD quản lý tài liệu. 127 | - API tìm kiếm và phân loại tài liệu. 128 | 129 | **Buổi 23: Xây dựng giao diện người dùng (Taipy)** 130 | - Form nhập liệu và hiển thị danh sách tài liệu. 131 | - Dashboard hiển thị thống kê. 132 | 133 | **Buổi 24: Tích hợp LLM và triển khai hệ thống** 134 | - Chatbot tìm kiếm tài liệu bằng LLM Ollama. 135 | - Kết nối giao diện với backend. 136 | 137 | **Buổi 25: Kiểm tra và trình bày dự án** 138 | - Kiểm tra hệ thống hoàn chỉnh. 139 | - Thuyết trình dự án và nhận phản hồi. 140 | 141 | --- 142 | 143 | ### **Kết quả đạt được:** 144 | - Thành thạo Python cơ bản và nâng cao. 145 | - Hiểu cách xây dựng API backend với FastAPI. 146 | - Làm chủ UI với Taipy để tạo giao diện hiện đại. 147 | - Ứng dụng LLM Ollama vào các giải pháp thực tế. 148 | - Hoàn thiện dự án cuối khóa mang tính ứng dụng cao. 149 | 150 | -------------------------------------------------------------------------------- /docs/roadmap/react-nextjs.md: -------------------------------------------------------------------------------- 1 | ### **Lộ trình học React + Next.js (35 buổi)** 2 | **Bao gồm: HTML, CSS, JavaScript, TypeScript** 3 | 4 | **Mục tiêu khóa học:** 5 | - Hiểu cơ bản về HTML, CSS, và JavaScript. 6 | - Làm chủ React và Next.js để xây dựng ứng dụng web mạnh mẽ. 7 | - Học TypeScript để tăng độ ổn định và khả năng bảo trì mã nguồn. 8 | - Hoàn thành một dự án thực tế từ đầu đến cuối. 9 | 10 | --- 11 | 12 | ### **Giai đoạn 1 (Buổi 1–10): HTML, CSS, JavaScript cơ bản** 13 | **Mục tiêu:** Xây dựng nền tảng vững chắc cho lập trình frontend. 14 | 15 | #### **Buổi 1: Giới thiệu và nền tảng web cơ bản** 16 | - Tổng quan về phát triển web: HTML, CSS, JS, và TypeScript. 17 | - Cấu trúc cơ bản của một file HTML. 18 | - Thực hành: Tạo trang "Hello, World!" với HTML và CSS. 19 | 20 | #### **Buổi 2: HTML nâng cao** 21 | - Các thẻ HTML quan trọng (form, table, semantic tags). 22 | - Thực hành: Tạo trang thông tin cá nhân cơ bản. 23 | 24 | #### **Buổi 3: CSS cơ bản** 25 | - Styling cơ bản với CSS: selectors, properties, và box model. 26 | - Thực hành: Thiết kế trang giới thiệu với CSS. 27 | 28 | #### **Buổi 4: CSS nâng cao** 29 | - Flexbox và Grid layout. 30 | - Responsive design (Media Queries). 31 | - Thực hành: Trang web responsive hiển thị sản phẩm. 32 | 33 | #### **Buổi 5: JavaScript cơ bản** 34 | - Biến, kiểu dữ liệu, và hàm trong JavaScript. 35 | - Thao tác với DOM (Document Object Model). 36 | - Thực hành: Hiển thị thông báo (alert) khi người dùng nhấn nút. 37 | 38 | #### **Buổi 6: JavaScript nâng cao** 39 | - Vòng lặp, điều kiện, và sự kiện. 40 | - Thao tác với mảng và object. 41 | - Thực hành: Danh sách sản phẩm có thể thêm/xóa bằng JS. 42 | 43 | #### **Buổi 7: JavaScript bất đồng bộ (Async JS)** 44 | - Giới thiệu `Promise` và `async/await`. 45 | - Gọi API giả lập với `fetch`. 46 | - Thực hành: Hiển thị danh sách người dùng từ API giả lập. 47 | 48 | #### **Buổi 8: TypeScript cơ bản** 49 | - TypeScript là gì? Tại sao sử dụng TypeScript? 50 | - Cài đặt TypeScript và các kiểu dữ liệu cơ bản. 51 | - Thực hành: Chuyển một ứng dụng JS nhỏ sang TypeScript. 52 | 53 | #### **Buổi 9: TypeScript nâng cao** 54 | - Interface, Type Aliases, và Generics. 55 | - Thực hành: Xây dựng cấu trúc dữ liệu sản phẩm với TypeScript. 56 | 57 | #### **Buổi 10: Tổng hợp kiến thức nền tảng** 58 | - Kết hợp HTML, CSS, JS, và TS trong một dự án nhỏ. 59 | - Thực hành: Xây dựng trang web danh sách sản phẩm có chức năng tìm kiếm. 60 | 61 | --- 62 | 63 | ### **Giai đoạn 2 (Buổi 11–20): React + Next.js cơ bản** 64 | **Mục tiêu:** Làm chủ React và Next.js để xây dựng giao diện hiện đại. 65 | 66 | #### **Buổi 11: Giới thiệu React** 67 | - React là gì? So sánh React với các framework khác. 68 | - Tạo ứng dụng đầu tiên với `create-react-app`. 69 | - Thực hành: Tạo giao diện "Hello, React!". 70 | 71 | #### **Buổi 12: JSX và Components cơ bản** 72 | - Giới thiệu JSX và cách sử dụng components. 73 | - Thực hành: Tạo Header, Footer, và Main Content components. 74 | 75 | #### **Buổi 13: Props và State trong React** 76 | - Sử dụng Props để truyền dữ liệu giữa các components. 77 | - Quản lý State trong functional components. 78 | - Thực hành: Danh sách sản phẩm với chức năng thêm sản phẩm mới. 79 | 80 | #### **Buổi 14: Event Handling và Form** 81 | - Xử lý sự kiện trong React. 82 | - Quản lý form và validation. 83 | - Thực hành: Tạo form đăng ký sản phẩm mới. 84 | 85 | #### **Buổi 15: React Router** 86 | - Tạo ứng dụng đa trang với `react-router-dom`. 87 | - Thực hành: Tạo menu điều hướng (Home, About, Products). 88 | 89 | #### **Buổi 16: Giới thiệu Next.js** 90 | - Next.js là gì? So sánh với React.js thuần. 91 | - Tạo dự án Next.js đầu tiên. 92 | - Thực hành: Tạo trang "Hello, Next.js!". 93 | 94 | #### **Buổi 17: Routing trong Next.js** 95 | - Routing cơ bản và động trong Next.js. 96 | - Thực hành: Xây dựng hệ thống route cho quản lý sản phẩm. 97 | 98 | #### **Buổi 18: SSG và SSR trong Next.js** 99 | - Sự khác biệt giữa Static Site Generation (SSG) và Server-Side Rendering (SSR). 100 | - Thực hành: Hiển thị danh sách sản phẩm với SSG. 101 | 102 | #### **Buổi 19: API Routes trong Next.js** 103 | - Tạo API backend ngay trong Next.js. 104 | - Thực hành: API CRUD sản phẩm đơn giản. 105 | 106 | #### **Buổi 20: Tích hợp React + Next.js** 107 | - Sử dụng React để quản lý trạng thái trong Next.js. 108 | - Thực hành: Hoàn thiện giao diện quản lý sản phẩm. 109 | 110 | --- 111 | 112 | ### **Giai đoạn 3 (Buổi 21–30): Tích hợp API, quản lý trạng thái, và tối ưu hóa** 113 | 114 | #### **Buổi 21: Tích hợp API thực tế với Next.js** 115 | - Sử dụng `axios` hoặc `fetch` để gọi API từ server thực tế. 116 | - Thực hành: Tích hợp API sản phẩm từ backend giả lập. 117 | 118 | #### **Buổi 22: Quản lý trạng thái với Context API** 119 | - Sử dụng Context API trong ứng dụng Next.js. 120 | - Thực hành: Quản lý giỏ hàng với Context API. 121 | 122 | #### **Buổi 23: Quản lý trạng thái nâng cao với Redux** 123 | - Giới thiệu Redux và cách tích hợp với Next.js. 124 | - Thực hành: Sử dụng Redux để quản lý danh sách sản phẩm. 125 | 126 | #### **Buổi 24: Tối ưu hóa giao diện với TailwindCSS hoặc Material-UI** 127 | - Tích hợp TailwindCSS hoặc Material-UI vào Next.js. 128 | - Thực hành: Thiết kế trang sản phẩm hiện đại. 129 | 130 | #### **Buổi 25–27: Authentication và bảo mật** 131 | - Xây dựng hệ thống đăng nhập và đăng ký người dùng. 132 | - Quản lý quyền truy cập vào các trang. 133 | - Thực hành: Tích hợp hệ thống xác thực với JWT. 134 | 135 | #### **Buổi 28–30: Tối ưu hóa hiệu suất ứng dụng** 136 | - Tối ưu hóa SEO với Head trong Next.js. 137 | - Lazy loading, Image Optimization. 138 | - Thực hành: Cải thiện tốc độ tải trang và hiệu suất. 139 | 140 | --- 141 | 142 | ### **Giai đoạn 4 (Buổi 31–35): Dự án thực tế và triển khai** 143 | 144 | **Dự án: Hệ thống quản lý sản phẩm thương mại điện tử** 145 | - **Backend:** API quản lý sản phẩm và người dùng. 146 | - **Frontend:** Giao diện danh sách sản phẩm, chi tiết sản phẩm, giỏ hàng, và thanh toán. 147 | 148 | **Buổi 31–33: Xây dựng dự án thực tế** 149 | - Tích hợp toàn bộ kiến thức đã học vào dự án. 150 | - Phát triển các chức năng chính như CRUD sản phẩm, giỏ hàng, và thanh toán. 151 | 152 | **Buổi 34: Kiểm tra và kiểm thử dự án** 153 | - Viết test cho các tính năng chính. 154 | - Fix bug và cải thiện giao diện người dùng. 155 | 156 | **Buổi 35: Triển khai dự án** 157 | - Deploy ứng dụng lên Vercel hoặc AWS. 158 | - Tổng kết và định hướng phát triển nâng cao. 159 | 160 | --- -------------------------------------------------------------------------------- /fastapi/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.11-slim 2 | 3 | WORKDIR /app 4 | 5 | COPY ./requirements.txt /app/requirements.txt 6 | RUN pip3 install -r /app/requirements.txt 7 | 8 | CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000", "--reload"] -------------------------------------------------------------------------------- /fastapi/app.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from fastapi import FastAPI, Response 3 | 4 | # Database 5 | from db import ( 6 | create_chat, 7 | get_all_chats, 8 | get_chat_by_id, 9 | delete_chat, 10 | DataChat, 11 | path_db 12 | ) 13 | 14 | # Langchain 15 | from langchain_ollama import OllamaLLM # Ollama model 16 | from langchain_ollama.llms import BaseLLM # Lớp cơ sở của LLM 17 | from langchain.chains.llm import LLMChain # xử lí chuỗi các LLM 18 | from langchain.chains.sql_database.query import create_sql_query_chain # tạo câu truy vấn cơ sở dữ liệu từ llm 19 | from langchain.prompts import PromptTemplate # tạo câu truy vấn từ mẫu 20 | from langchain_community.tools import QuerySQLDataBaseTool # công cụ truy vấn cơ sở dữ liệu 21 | from langchain.sql_database import SQLDatabase # cơ sở dữ liệu 22 | from langchain_core.output_parsers import StrOutputParser, PydanticOutputParser # xử lí kết quả trả về là kiểu dữ liệu chuỗi 23 | from langchain_core.runnables import RunnablePassthrough # truyền đa dạng đối số 24 | from operator import itemgetter # lấy giá trị từ dict 25 | # Cache 26 | from langchain.cache import InMemoryCache 27 | from langchain.globals import set_llm_cache 28 | #-------------------------------------------------- 29 | 30 | # Utility 31 | from utils import get_sql_from_answer_llm 32 | 33 | #test on docker 34 | url_docker = "http://ollama-server:11434" 35 | #test on local 36 | url_local = "http://localhost:11434" 37 | model = "qwen2.5-coder:0.5b" 38 | 39 | llm = OllamaLLM( 40 | base_url=url_local, 41 | model=model 42 | ) 43 | 44 | cache = InMemoryCache() 45 | set_llm_cache(cache) 46 | 47 | 48 | template = PromptTemplate.from_template( 49 | """ 50 | Từ các bảng cơ sở dữ đã có: {tables} 51 | Tạo câu truy vấn cơ sở dữ liệu từ câu hỏi sau: 52 | {question} 53 | 54 | Trả lời ở đây: 55 | """ 56 | ) 57 | 58 | # nếu câu hỏi không liên quan đến các bảng cơ sở dữ liệu đã có thì trả lời là "Không liên quan đến các bảng cơ sở dữ liệu đã có", và nếu câu hỏi gây nguy hiểm đến cơ sở dữ liệu thì trả lời là "Không thể trả lời câu hỏi này" 59 | 60 | llm_chain = ( 61 | template | 62 | llm | 63 | StrOutputParser() 64 | ) 65 | 66 | db = SQLDatabase.from_uri(f"sqlite:///{path_db}") 67 | 68 | 69 | app = FastAPI() 70 | 71 | 72 | 73 | 74 | @app.get('/') 75 | def home(): 76 | return {"hello" : "World"} 77 | 78 | @app.get('/ask') 79 | def ask(prompt :str): 80 | # name of the service is ollama-server, is hostname by bridge to connect same network 81 | # res = requests.post('http://ollama-server:11434/api/generate', json={ 82 | # "prompt": prompt, 83 | # "stream" : False, 84 | # "model" : "qwen2.5-coder:0.5b" 85 | # }) 86 | 87 | res = llm_chain.invoke({ 88 | "tables": f'''{db.get_table_info(db.get_usable_table_names())}''', 89 | "question": prompt 90 | }) 91 | 92 | response = "" 93 | if isinstance(res, str): 94 | response = res 95 | else: 96 | response = res.text 97 | 98 | # Store chat in database 99 | chat = create_chat(message=prompt, response=response) 100 | 101 | try: 102 | data_db = db.run(get_sql_from_answer_llm(response)) 103 | except Exception as e: 104 | data_db = str(e) 105 | 106 | return { 107 | "answer": response, 108 | "data_db": data_db 109 | } 110 | -------------------------------------------------------------------------------- /fastapi/data_chat.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8syncdev/ollama-docker-web-application/29061ad0001200732fe7bd8df35aee47fb180f19/fastapi/data_chat.sqlite3 -------------------------------------------------------------------------------- /fastapi/db.py: -------------------------------------------------------------------------------- 1 | from sqlmodel import ( 2 | SQLModel, 3 | create_engine, 4 | Session, 5 | select, 6 | Field 7 | ) 8 | 9 | 10 | class DataChat(SQLModel, table=True): 11 | """Model for storing chat messages and responses in database 12 | 13 | Attributes: 14 | id (int): Primary key ID for the chat entry 15 | message (str): The user's input message 16 | response (str): The response generated for the message 17 | """ 18 | id: int | None = Field(default=None, primary_key=True, index=True) 19 | message: str 20 | response: str 21 | 22 | 23 | 24 | 25 | path_db = "data_chat.sqlite3" 26 | 27 | # Create SQLite database engine 28 | engine = create_engine(f"sqlite:///{path_db}") 29 | 30 | # Create all database tables 31 | SQLModel.metadata.create_all(engine) 32 | 33 | def get_session(): 34 | """Get a database session 35 | 36 | Yields: 37 | Session: Database session for executing queries 38 | """ 39 | with Session(engine) as session: 40 | yield session 41 | 42 | def create_chat(message: str, response: str): 43 | """Create a new chat entry in the database 44 | 45 | Args: 46 | message (str): The user's input message 47 | response (str): The generated response 48 | 49 | Returns: 50 | DataChat: The created chat entry 51 | """ 52 | chat = DataChat(message=message, response=response) 53 | with Session(engine) as session: 54 | session.add(chat) 55 | session.commit() 56 | session.refresh(chat) 57 | return chat 58 | 59 | def get_all_chats(): 60 | """Get all chat entries from the database 61 | 62 | Returns: 63 | list[DataChat]: List of all chat entries 64 | """ 65 | with Session(engine) as session: 66 | statement = select(DataChat) 67 | chats = session.exec(statement).all() 68 | return chats 69 | 70 | def get_chat_by_id(chat_id: int): 71 | """Get a specific chat entry by ID 72 | 73 | Args: 74 | chat_id (int): ID of the chat to retrieve 75 | 76 | Returns: 77 | DataChat | None: The chat entry if found, None otherwise 78 | """ 79 | with Session(engine) as session: 80 | statement = select(DataChat).where(DataChat.id == chat_id) 81 | chat = session.exec(statement).first() 82 | return chat 83 | 84 | def delete_chat(chat_id: int): 85 | """Delete a chat entry from the database 86 | 87 | Args: 88 | chat_id (int): ID of the chat to delete 89 | 90 | Returns: 91 | bool: True if chat was deleted, False if not found 92 | """ 93 | with Session(engine) as session: 94 | chat = get_chat_by_id(chat_id) 95 | if chat: 96 | session.delete(chat) 97 | session.commit() 98 | return True 99 | return False 100 | -------------------------------------------------------------------------------- /fastapi/requirements.txt: -------------------------------------------------------------------------------- 1 | # Backend 2 | fastapi 3 | requests 4 | 5 | # Server 6 | uvicorn 7 | 8 | # Database 9 | sqlmodel 10 | 11 | # Langchain libraries for LLM integration and experimentation 12 | langchain # LLM 13 | langchain-ollama # LLM 14 | langchain-community # Runnable 15 | langchain-experimental # Runnable -------------------------------------------------------------------------------- /fastapi/utils.py: -------------------------------------------------------------------------------- 1 | from sqlmodel import SQLModel 2 | 3 | def get_sql_from_answer_llm(answer: str): 4 | return answer.split("```sql")[1].split("```")[0].strip() 5 | 6 | 7 | -------------------------------------------------------------------------------- /nextjs-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.* 7 | .yarn/* 8 | !.yarn/patches 9 | !.yarn/plugins 10 | !.yarn/releases 11 | !.yarn/versions 12 | 13 | # testing 14 | /coverage 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | *.pem 26 | 27 | # debug 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | 32 | # env files (can opt-in for committing if needed) 33 | .env* 34 | 35 | # vercel 36 | .vercel 37 | 38 | # typescript 39 | *.tsbuildinfo 40 | next-env.d.ts 41 | -------------------------------------------------------------------------------- /nextjs-app/README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | # or 14 | bun dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 20 | 21 | This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. 22 | 23 | ## Learn More 24 | 25 | To learn more about Next.js, take a look at the following resources: 26 | 27 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 28 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 29 | 30 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! 31 | 32 | ## Deploy on Vercel 33 | 34 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 35 | 36 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. 37 | -------------------------------------------------------------------------------- /nextjs-app/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8syncdev/ollama-docker-web-application/29061ad0001200732fe7bd8df35aee47fb180f19/nextjs-app/app/favicon.ico -------------------------------------------------------------------------------- /nextjs-app/app/fonts/GeistMonoVF.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8syncdev/ollama-docker-web-application/29061ad0001200732fe7bd8df35aee47fb180f19/nextjs-app/app/fonts/GeistMonoVF.woff -------------------------------------------------------------------------------- /nextjs-app/app/fonts/GeistVF.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8syncdev/ollama-docker-web-application/29061ad0001200732fe7bd8df35aee47fb180f19/nextjs-app/app/fonts/GeistVF.woff -------------------------------------------------------------------------------- /nextjs-app/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --background: #ffffff; 7 | --foreground: #171717; 8 | } 9 | 10 | @media (prefers-color-scheme: dark) { 11 | :root { 12 | --background: #0a0a0a; 13 | --foreground: #ededed; 14 | } 15 | } 16 | 17 | body { 18 | color: var(--foreground); 19 | background: var(--background); 20 | font-family: Arial, Helvetica, sans-serif; 21 | } 22 | -------------------------------------------------------------------------------- /nextjs-app/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import localFont from "next/font/local"; 3 | import "./globals.css"; 4 | 5 | const geistSans = localFont({ 6 | src: "./fonts/GeistVF.woff", 7 | variable: "--font-geist-sans", 8 | weight: "100 900", 9 | }); 10 | const geistMono = localFont({ 11 | src: "./fonts/GeistMonoVF.woff", 12 | variable: "--font-geist-mono", 13 | weight: "100 900", 14 | }); 15 | 16 | export const metadata: Metadata = { 17 | title: "Create Next App", 18 | description: "Generated by create next app", 19 | }; 20 | 21 | export default function RootLayout({ 22 | children, 23 | }: Readonly<{ 24 | children: React.ReactNode; 25 | }>) { 26 | return ( 27 | 28 | 31 | {children} 32 | 33 | 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /nextjs-app/app/page.tsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | 3 | export default function Home() { 4 | return ( 5 |
6 |
7 | Next.js logo 15 |
    16 |
  1. 17 | Get started by editing{" "} 18 | 19 | app/page.tsx 20 | 21 | . 22 |
  2. 23 |
  3. Save and see your changes instantly.
  4. 24 |
25 | 26 |
27 | 33 | Vercel logomark 40 | Deploy now 41 | 42 | 48 | Read our docs 49 | 50 |
51 |
52 | 99 |
100 | ); 101 | } 102 | -------------------------------------------------------------------------------- /nextjs-app/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | 3 | const nextConfig: NextConfig = { 4 | /* config options here */ 5 | }; 6 | 7 | export default nextConfig; 8 | -------------------------------------------------------------------------------- /nextjs-app/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextjs-app", 3 | "version": "0.1.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "nextjs-app", 9 | "version": "0.1.0", 10 | "dependencies": { 11 | "next": "15.0.3", 12 | "react": "19.0.0-rc-66855b96-20241106", 13 | "react-dom": "19.0.0-rc-66855b96-20241106" 14 | }, 15 | "devDependencies": { 16 | "@types/node": "^20", 17 | "@types/react": "^18", 18 | "@types/react-dom": "^18", 19 | "postcss": "^8", 20 | "tailwindcss": "^3.4.1", 21 | "typescript": "^5" 22 | } 23 | }, 24 | "node_modules/@alloc/quick-lru": { 25 | "version": "5.2.0", 26 | "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", 27 | "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", 28 | "dev": true, 29 | "engines": { 30 | "node": ">=10" 31 | }, 32 | "funding": { 33 | "url": "https://github.com/sponsors/sindresorhus" 34 | } 35 | }, 36 | "node_modules/@emnapi/runtime": { 37 | "version": "1.3.1", 38 | "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz", 39 | "integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==", 40 | "optional": true, 41 | "dependencies": { 42 | "tslib": "^2.4.0" 43 | } 44 | }, 45 | "node_modules/@img/sharp-darwin-arm64": { 46 | "version": "0.33.5", 47 | "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", 48 | "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", 49 | "cpu": [ 50 | "arm64" 51 | ], 52 | "optional": true, 53 | "os": [ 54 | "darwin" 55 | ], 56 | "engines": { 57 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 58 | }, 59 | "funding": { 60 | "url": "https://opencollective.com/libvips" 61 | }, 62 | "optionalDependencies": { 63 | "@img/sharp-libvips-darwin-arm64": "1.0.4" 64 | } 65 | }, 66 | "node_modules/@img/sharp-darwin-x64": { 67 | "version": "0.33.5", 68 | "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", 69 | "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", 70 | "cpu": [ 71 | "x64" 72 | ], 73 | "optional": true, 74 | "os": [ 75 | "darwin" 76 | ], 77 | "engines": { 78 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 79 | }, 80 | "funding": { 81 | "url": "https://opencollective.com/libvips" 82 | }, 83 | "optionalDependencies": { 84 | "@img/sharp-libvips-darwin-x64": "1.0.4" 85 | } 86 | }, 87 | "node_modules/@img/sharp-libvips-darwin-arm64": { 88 | "version": "1.0.4", 89 | "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", 90 | "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", 91 | "cpu": [ 92 | "arm64" 93 | ], 94 | "optional": true, 95 | "os": [ 96 | "darwin" 97 | ], 98 | "funding": { 99 | "url": "https://opencollective.com/libvips" 100 | } 101 | }, 102 | "node_modules/@img/sharp-libvips-darwin-x64": { 103 | "version": "1.0.4", 104 | "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", 105 | "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", 106 | "cpu": [ 107 | "x64" 108 | ], 109 | "optional": true, 110 | "os": [ 111 | "darwin" 112 | ], 113 | "funding": { 114 | "url": "https://opencollective.com/libvips" 115 | } 116 | }, 117 | "node_modules/@img/sharp-libvips-linux-arm": { 118 | "version": "1.0.5", 119 | "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", 120 | "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", 121 | "cpu": [ 122 | "arm" 123 | ], 124 | "optional": true, 125 | "os": [ 126 | "linux" 127 | ], 128 | "funding": { 129 | "url": "https://opencollective.com/libvips" 130 | } 131 | }, 132 | "node_modules/@img/sharp-libvips-linux-arm64": { 133 | "version": "1.0.4", 134 | "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", 135 | "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", 136 | "cpu": [ 137 | "arm64" 138 | ], 139 | "optional": true, 140 | "os": [ 141 | "linux" 142 | ], 143 | "funding": { 144 | "url": "https://opencollective.com/libvips" 145 | } 146 | }, 147 | "node_modules/@img/sharp-libvips-linux-s390x": { 148 | "version": "1.0.4", 149 | "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", 150 | "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", 151 | "cpu": [ 152 | "s390x" 153 | ], 154 | "optional": true, 155 | "os": [ 156 | "linux" 157 | ], 158 | "funding": { 159 | "url": "https://opencollective.com/libvips" 160 | } 161 | }, 162 | "node_modules/@img/sharp-libvips-linux-x64": { 163 | "version": "1.0.4", 164 | "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", 165 | "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", 166 | "cpu": [ 167 | "x64" 168 | ], 169 | "optional": true, 170 | "os": [ 171 | "linux" 172 | ], 173 | "funding": { 174 | "url": "https://opencollective.com/libvips" 175 | } 176 | }, 177 | "node_modules/@img/sharp-libvips-linuxmusl-arm64": { 178 | "version": "1.0.4", 179 | "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", 180 | "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", 181 | "cpu": [ 182 | "arm64" 183 | ], 184 | "optional": true, 185 | "os": [ 186 | "linux" 187 | ], 188 | "funding": { 189 | "url": "https://opencollective.com/libvips" 190 | } 191 | }, 192 | "node_modules/@img/sharp-libvips-linuxmusl-x64": { 193 | "version": "1.0.4", 194 | "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", 195 | "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", 196 | "cpu": [ 197 | "x64" 198 | ], 199 | "optional": true, 200 | "os": [ 201 | "linux" 202 | ], 203 | "funding": { 204 | "url": "https://opencollective.com/libvips" 205 | } 206 | }, 207 | "node_modules/@img/sharp-linux-arm": { 208 | "version": "0.33.5", 209 | "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", 210 | "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", 211 | "cpu": [ 212 | "arm" 213 | ], 214 | "optional": true, 215 | "os": [ 216 | "linux" 217 | ], 218 | "engines": { 219 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 220 | }, 221 | "funding": { 222 | "url": "https://opencollective.com/libvips" 223 | }, 224 | "optionalDependencies": { 225 | "@img/sharp-libvips-linux-arm": "1.0.5" 226 | } 227 | }, 228 | "node_modules/@img/sharp-linux-arm64": { 229 | "version": "0.33.5", 230 | "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", 231 | "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", 232 | "cpu": [ 233 | "arm64" 234 | ], 235 | "optional": true, 236 | "os": [ 237 | "linux" 238 | ], 239 | "engines": { 240 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 241 | }, 242 | "funding": { 243 | "url": "https://opencollective.com/libvips" 244 | }, 245 | "optionalDependencies": { 246 | "@img/sharp-libvips-linux-arm64": "1.0.4" 247 | } 248 | }, 249 | "node_modules/@img/sharp-linux-s390x": { 250 | "version": "0.33.5", 251 | "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", 252 | "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", 253 | "cpu": [ 254 | "s390x" 255 | ], 256 | "optional": true, 257 | "os": [ 258 | "linux" 259 | ], 260 | "engines": { 261 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 262 | }, 263 | "funding": { 264 | "url": "https://opencollective.com/libvips" 265 | }, 266 | "optionalDependencies": { 267 | "@img/sharp-libvips-linux-s390x": "1.0.4" 268 | } 269 | }, 270 | "node_modules/@img/sharp-linux-x64": { 271 | "version": "0.33.5", 272 | "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", 273 | "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", 274 | "cpu": [ 275 | "x64" 276 | ], 277 | "optional": true, 278 | "os": [ 279 | "linux" 280 | ], 281 | "engines": { 282 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 283 | }, 284 | "funding": { 285 | "url": "https://opencollective.com/libvips" 286 | }, 287 | "optionalDependencies": { 288 | "@img/sharp-libvips-linux-x64": "1.0.4" 289 | } 290 | }, 291 | "node_modules/@img/sharp-linuxmusl-arm64": { 292 | "version": "0.33.5", 293 | "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", 294 | "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", 295 | "cpu": [ 296 | "arm64" 297 | ], 298 | "optional": true, 299 | "os": [ 300 | "linux" 301 | ], 302 | "engines": { 303 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 304 | }, 305 | "funding": { 306 | "url": "https://opencollective.com/libvips" 307 | }, 308 | "optionalDependencies": { 309 | "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" 310 | } 311 | }, 312 | "node_modules/@img/sharp-linuxmusl-x64": { 313 | "version": "0.33.5", 314 | "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", 315 | "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", 316 | "cpu": [ 317 | "x64" 318 | ], 319 | "optional": true, 320 | "os": [ 321 | "linux" 322 | ], 323 | "engines": { 324 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 325 | }, 326 | "funding": { 327 | "url": "https://opencollective.com/libvips" 328 | }, 329 | "optionalDependencies": { 330 | "@img/sharp-libvips-linuxmusl-x64": "1.0.4" 331 | } 332 | }, 333 | "node_modules/@img/sharp-wasm32": { 334 | "version": "0.33.5", 335 | "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", 336 | "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", 337 | "cpu": [ 338 | "wasm32" 339 | ], 340 | "optional": true, 341 | "dependencies": { 342 | "@emnapi/runtime": "^1.2.0" 343 | }, 344 | "engines": { 345 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 346 | }, 347 | "funding": { 348 | "url": "https://opencollective.com/libvips" 349 | } 350 | }, 351 | "node_modules/@img/sharp-win32-ia32": { 352 | "version": "0.33.5", 353 | "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", 354 | "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", 355 | "cpu": [ 356 | "ia32" 357 | ], 358 | "optional": true, 359 | "os": [ 360 | "win32" 361 | ], 362 | "engines": { 363 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 364 | }, 365 | "funding": { 366 | "url": "https://opencollective.com/libvips" 367 | } 368 | }, 369 | "node_modules/@img/sharp-win32-x64": { 370 | "version": "0.33.5", 371 | "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", 372 | "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", 373 | "cpu": [ 374 | "x64" 375 | ], 376 | "optional": true, 377 | "os": [ 378 | "win32" 379 | ], 380 | "engines": { 381 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 382 | }, 383 | "funding": { 384 | "url": "https://opencollective.com/libvips" 385 | } 386 | }, 387 | "node_modules/@isaacs/cliui": { 388 | "version": "8.0.2", 389 | "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", 390 | "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", 391 | "dev": true, 392 | "dependencies": { 393 | "string-width": "^5.1.2", 394 | "string-width-cjs": "npm:string-width@^4.2.0", 395 | "strip-ansi": "^7.0.1", 396 | "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", 397 | "wrap-ansi": "^8.1.0", 398 | "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" 399 | }, 400 | "engines": { 401 | "node": ">=12" 402 | } 403 | }, 404 | "node_modules/@jridgewell/gen-mapping": { 405 | "version": "0.3.5", 406 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", 407 | "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", 408 | "dev": true, 409 | "dependencies": { 410 | "@jridgewell/set-array": "^1.2.1", 411 | "@jridgewell/sourcemap-codec": "^1.4.10", 412 | "@jridgewell/trace-mapping": "^0.3.24" 413 | }, 414 | "engines": { 415 | "node": ">=6.0.0" 416 | } 417 | }, 418 | "node_modules/@jridgewell/resolve-uri": { 419 | "version": "3.1.2", 420 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 421 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 422 | "dev": true, 423 | "engines": { 424 | "node": ">=6.0.0" 425 | } 426 | }, 427 | "node_modules/@jridgewell/set-array": { 428 | "version": "1.2.1", 429 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", 430 | "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", 431 | "dev": true, 432 | "engines": { 433 | "node": ">=6.0.0" 434 | } 435 | }, 436 | "node_modules/@jridgewell/sourcemap-codec": { 437 | "version": "1.5.0", 438 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 439 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", 440 | "dev": true 441 | }, 442 | "node_modules/@jridgewell/trace-mapping": { 443 | "version": "0.3.25", 444 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", 445 | "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", 446 | "dev": true, 447 | "dependencies": { 448 | "@jridgewell/resolve-uri": "^3.1.0", 449 | "@jridgewell/sourcemap-codec": "^1.4.14" 450 | } 451 | }, 452 | "node_modules/@next/env": { 453 | "version": "15.0.3", 454 | "resolved": "https://registry.npmjs.org/@next/env/-/env-15.0.3.tgz", 455 | "integrity": "sha512-t9Xy32pjNOvVn2AS+Utt6VmyrshbpfUMhIjFO60gI58deSo/KgLOp31XZ4O+kY/Is8WAGYwA5gR7kOb1eORDBA==" 456 | }, 457 | "node_modules/@next/swc-darwin-arm64": { 458 | "version": "15.0.3", 459 | "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.0.3.tgz", 460 | "integrity": "sha512-s3Q/NOorCsLYdCKvQlWU+a+GeAd3C8Rb3L1YnetsgwXzhc3UTWrtQpB/3eCjFOdGUj5QmXfRak12uocd1ZiiQw==", 461 | "cpu": [ 462 | "arm64" 463 | ], 464 | "optional": true, 465 | "os": [ 466 | "darwin" 467 | ], 468 | "engines": { 469 | "node": ">= 10" 470 | } 471 | }, 472 | "node_modules/@next/swc-darwin-x64": { 473 | "version": "15.0.3", 474 | "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.0.3.tgz", 475 | "integrity": "sha512-Zxl/TwyXVZPCFSf0u2BNj5sE0F2uR6iSKxWpq4Wlk/Sv9Ob6YCKByQTkV2y6BCic+fkabp9190hyrDdPA/dNrw==", 476 | "cpu": [ 477 | "x64" 478 | ], 479 | "optional": true, 480 | "os": [ 481 | "darwin" 482 | ], 483 | "engines": { 484 | "node": ">= 10" 485 | } 486 | }, 487 | "node_modules/@next/swc-linux-arm64-gnu": { 488 | "version": "15.0.3", 489 | "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.0.3.tgz", 490 | "integrity": "sha512-T5+gg2EwpsY3OoaLxUIofmMb7ohAUlcNZW0fPQ6YAutaWJaxt1Z1h+8zdl4FRIOr5ABAAhXtBcpkZNwUcKI2fw==", 491 | "cpu": [ 492 | "arm64" 493 | ], 494 | "optional": true, 495 | "os": [ 496 | "linux" 497 | ], 498 | "engines": { 499 | "node": ">= 10" 500 | } 501 | }, 502 | "node_modules/@next/swc-linux-arm64-musl": { 503 | "version": "15.0.3", 504 | "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.0.3.tgz", 505 | "integrity": "sha512-WkAk6R60mwDjH4lG/JBpb2xHl2/0Vj0ZRu1TIzWuOYfQ9tt9NFsIinI1Epma77JVgy81F32X/AeD+B2cBu/YQA==", 506 | "cpu": [ 507 | "arm64" 508 | ], 509 | "optional": true, 510 | "os": [ 511 | "linux" 512 | ], 513 | "engines": { 514 | "node": ">= 10" 515 | } 516 | }, 517 | "node_modules/@next/swc-linux-x64-gnu": { 518 | "version": "15.0.3", 519 | "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.0.3.tgz", 520 | "integrity": "sha512-gWL/Cta1aPVqIGgDb6nxkqy06DkwJ9gAnKORdHWX1QBbSZZB+biFYPFti8aKIQL7otCE1pjyPaXpFzGeG2OS2w==", 521 | "cpu": [ 522 | "x64" 523 | ], 524 | "optional": true, 525 | "os": [ 526 | "linux" 527 | ], 528 | "engines": { 529 | "node": ">= 10" 530 | } 531 | }, 532 | "node_modules/@next/swc-linux-x64-musl": { 533 | "version": "15.0.3", 534 | "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.0.3.tgz", 535 | "integrity": "sha512-QQEMwFd8r7C0GxQS62Zcdy6GKx999I/rTO2ubdXEe+MlZk9ZiinsrjwoiBL5/57tfyjikgh6GOU2WRQVUej3UA==", 536 | "cpu": [ 537 | "x64" 538 | ], 539 | "optional": true, 540 | "os": [ 541 | "linux" 542 | ], 543 | "engines": { 544 | "node": ">= 10" 545 | } 546 | }, 547 | "node_modules/@next/swc-win32-arm64-msvc": { 548 | "version": "15.0.3", 549 | "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.0.3.tgz", 550 | "integrity": "sha512-9TEp47AAd/ms9fPNgtgnT7F3M1Hf7koIYYWCMQ9neOwjbVWJsHZxrFbI3iEDJ8rf1TDGpmHbKxXf2IFpAvheIQ==", 551 | "cpu": [ 552 | "arm64" 553 | ], 554 | "optional": true, 555 | "os": [ 556 | "win32" 557 | ], 558 | "engines": { 559 | "node": ">= 10" 560 | } 561 | }, 562 | "node_modules/@next/swc-win32-x64-msvc": { 563 | "version": "15.0.3", 564 | "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.0.3.tgz", 565 | "integrity": "sha512-VNAz+HN4OGgvZs6MOoVfnn41kBzT+M+tB+OK4cww6DNyWS6wKaDpaAm/qLeOUbnMh0oVx1+mg0uoYARF69dJyA==", 566 | "cpu": [ 567 | "x64" 568 | ], 569 | "optional": true, 570 | "os": [ 571 | "win32" 572 | ], 573 | "engines": { 574 | "node": ">= 10" 575 | } 576 | }, 577 | "node_modules/@nodelib/fs.scandir": { 578 | "version": "2.1.5", 579 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 580 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 581 | "dev": true, 582 | "dependencies": { 583 | "@nodelib/fs.stat": "2.0.5", 584 | "run-parallel": "^1.1.9" 585 | }, 586 | "engines": { 587 | "node": ">= 8" 588 | } 589 | }, 590 | "node_modules/@nodelib/fs.stat": { 591 | "version": "2.0.5", 592 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 593 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 594 | "dev": true, 595 | "engines": { 596 | "node": ">= 8" 597 | } 598 | }, 599 | "node_modules/@nodelib/fs.walk": { 600 | "version": "1.2.8", 601 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 602 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 603 | "dev": true, 604 | "dependencies": { 605 | "@nodelib/fs.scandir": "2.1.5", 606 | "fastq": "^1.6.0" 607 | }, 608 | "engines": { 609 | "node": ">= 8" 610 | } 611 | }, 612 | "node_modules/@pkgjs/parseargs": { 613 | "version": "0.11.0", 614 | "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", 615 | "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", 616 | "dev": true, 617 | "optional": true, 618 | "engines": { 619 | "node": ">=14" 620 | } 621 | }, 622 | "node_modules/@swc/counter": { 623 | "version": "0.1.3", 624 | "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", 625 | "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" 626 | }, 627 | "node_modules/@swc/helpers": { 628 | "version": "0.5.13", 629 | "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.13.tgz", 630 | "integrity": "sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==", 631 | "dependencies": { 632 | "tslib": "^2.4.0" 633 | } 634 | }, 635 | "node_modules/@types/node": { 636 | "version": "20.17.6", 637 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.6.tgz", 638 | "integrity": "sha512-VEI7OdvK2wP7XHnsuXbAJnEpEkF6NjSN45QJlL4VGqZSXsnicpesdTWsg9RISeSdYd3yeRj/y3k5KGjUXYnFwQ==", 639 | "dev": true, 640 | "dependencies": { 641 | "undici-types": "~6.19.2" 642 | } 643 | }, 644 | "node_modules/@types/prop-types": { 645 | "version": "15.7.13", 646 | "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", 647 | "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", 648 | "dev": true 649 | }, 650 | "node_modules/@types/react": { 651 | "version": "18.3.12", 652 | "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", 653 | "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", 654 | "dev": true, 655 | "dependencies": { 656 | "@types/prop-types": "*", 657 | "csstype": "^3.0.2" 658 | } 659 | }, 660 | "node_modules/@types/react-dom": { 661 | "version": "18.3.1", 662 | "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", 663 | "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==", 664 | "dev": true, 665 | "dependencies": { 666 | "@types/react": "*" 667 | } 668 | }, 669 | "node_modules/ansi-regex": { 670 | "version": "6.1.0", 671 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", 672 | "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", 673 | "dev": true, 674 | "engines": { 675 | "node": ">=12" 676 | }, 677 | "funding": { 678 | "url": "https://github.com/chalk/ansi-regex?sponsor=1" 679 | } 680 | }, 681 | "node_modules/ansi-styles": { 682 | "version": "6.2.1", 683 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", 684 | "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", 685 | "dev": true, 686 | "engines": { 687 | "node": ">=12" 688 | }, 689 | "funding": { 690 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 691 | } 692 | }, 693 | "node_modules/any-promise": { 694 | "version": "1.3.0", 695 | "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", 696 | "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", 697 | "dev": true 698 | }, 699 | "node_modules/anymatch": { 700 | "version": "3.1.3", 701 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 702 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 703 | "dev": true, 704 | "dependencies": { 705 | "normalize-path": "^3.0.0", 706 | "picomatch": "^2.0.4" 707 | }, 708 | "engines": { 709 | "node": ">= 8" 710 | } 711 | }, 712 | "node_modules/arg": { 713 | "version": "5.0.2", 714 | "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", 715 | "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", 716 | "dev": true 717 | }, 718 | "node_modules/balanced-match": { 719 | "version": "1.0.2", 720 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 721 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 722 | "dev": true 723 | }, 724 | "node_modules/binary-extensions": { 725 | "version": "2.3.0", 726 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", 727 | "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", 728 | "dev": true, 729 | "engines": { 730 | "node": ">=8" 731 | }, 732 | "funding": { 733 | "url": "https://github.com/sponsors/sindresorhus" 734 | } 735 | }, 736 | "node_modules/brace-expansion": { 737 | "version": "2.0.1", 738 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 739 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 740 | "dev": true, 741 | "dependencies": { 742 | "balanced-match": "^1.0.0" 743 | } 744 | }, 745 | "node_modules/braces": { 746 | "version": "3.0.3", 747 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 748 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 749 | "dev": true, 750 | "dependencies": { 751 | "fill-range": "^7.1.1" 752 | }, 753 | "engines": { 754 | "node": ">=8" 755 | } 756 | }, 757 | "node_modules/busboy": { 758 | "version": "1.6.0", 759 | "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", 760 | "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", 761 | "dependencies": { 762 | "streamsearch": "^1.1.0" 763 | }, 764 | "engines": { 765 | "node": ">=10.16.0" 766 | } 767 | }, 768 | "node_modules/camelcase-css": { 769 | "version": "2.0.1", 770 | "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", 771 | "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", 772 | "dev": true, 773 | "engines": { 774 | "node": ">= 6" 775 | } 776 | }, 777 | "node_modules/caniuse-lite": { 778 | "version": "1.0.30001680", 779 | "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001680.tgz", 780 | "integrity": "sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==", 781 | "funding": [ 782 | { 783 | "type": "opencollective", 784 | "url": "https://opencollective.com/browserslist" 785 | }, 786 | { 787 | "type": "tidelift", 788 | "url": "https://tidelift.com/funding/github/npm/caniuse-lite" 789 | }, 790 | { 791 | "type": "github", 792 | "url": "https://github.com/sponsors/ai" 793 | } 794 | ] 795 | }, 796 | "node_modules/chokidar": { 797 | "version": "3.6.0", 798 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", 799 | "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", 800 | "dev": true, 801 | "dependencies": { 802 | "anymatch": "~3.1.2", 803 | "braces": "~3.0.2", 804 | "glob-parent": "~5.1.2", 805 | "is-binary-path": "~2.1.0", 806 | "is-glob": "~4.0.1", 807 | "normalize-path": "~3.0.0", 808 | "readdirp": "~3.6.0" 809 | }, 810 | "engines": { 811 | "node": ">= 8.10.0" 812 | }, 813 | "funding": { 814 | "url": "https://paulmillr.com/funding/" 815 | }, 816 | "optionalDependencies": { 817 | "fsevents": "~2.3.2" 818 | } 819 | }, 820 | "node_modules/chokidar/node_modules/glob-parent": { 821 | "version": "5.1.2", 822 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 823 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 824 | "dev": true, 825 | "dependencies": { 826 | "is-glob": "^4.0.1" 827 | }, 828 | "engines": { 829 | "node": ">= 6" 830 | } 831 | }, 832 | "node_modules/client-only": { 833 | "version": "0.0.1", 834 | "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", 835 | "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" 836 | }, 837 | "node_modules/color": { 838 | "version": "4.2.3", 839 | "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", 840 | "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", 841 | "optional": true, 842 | "dependencies": { 843 | "color-convert": "^2.0.1", 844 | "color-string": "^1.9.0" 845 | }, 846 | "engines": { 847 | "node": ">=12.5.0" 848 | } 849 | }, 850 | "node_modules/color-convert": { 851 | "version": "2.0.1", 852 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 853 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 854 | "devOptional": true, 855 | "dependencies": { 856 | "color-name": "~1.1.4" 857 | }, 858 | "engines": { 859 | "node": ">=7.0.0" 860 | } 861 | }, 862 | "node_modules/color-name": { 863 | "version": "1.1.4", 864 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 865 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 866 | "devOptional": true 867 | }, 868 | "node_modules/color-string": { 869 | "version": "1.9.1", 870 | "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", 871 | "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", 872 | "optional": true, 873 | "dependencies": { 874 | "color-name": "^1.0.0", 875 | "simple-swizzle": "^0.2.2" 876 | } 877 | }, 878 | "node_modules/commander": { 879 | "version": "4.1.1", 880 | "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", 881 | "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", 882 | "dev": true, 883 | "engines": { 884 | "node": ">= 6" 885 | } 886 | }, 887 | "node_modules/cross-spawn": { 888 | "version": "7.0.6", 889 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", 890 | "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", 891 | "dev": true, 892 | "dependencies": { 893 | "path-key": "^3.1.0", 894 | "shebang-command": "^2.0.0", 895 | "which": "^2.0.1" 896 | }, 897 | "engines": { 898 | "node": ">= 8" 899 | } 900 | }, 901 | "node_modules/cssesc": { 902 | "version": "3.0.0", 903 | "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", 904 | "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", 905 | "dev": true, 906 | "bin": { 907 | "cssesc": "bin/cssesc" 908 | }, 909 | "engines": { 910 | "node": ">=4" 911 | } 912 | }, 913 | "node_modules/csstype": { 914 | "version": "3.1.3", 915 | "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", 916 | "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", 917 | "dev": true 918 | }, 919 | "node_modules/detect-libc": { 920 | "version": "2.0.3", 921 | "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", 922 | "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", 923 | "optional": true, 924 | "engines": { 925 | "node": ">=8" 926 | } 927 | }, 928 | "node_modules/didyoumean": { 929 | "version": "1.2.2", 930 | "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", 931 | "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", 932 | "dev": true 933 | }, 934 | "node_modules/dlv": { 935 | "version": "1.1.3", 936 | "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", 937 | "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", 938 | "dev": true 939 | }, 940 | "node_modules/eastasianwidth": { 941 | "version": "0.2.0", 942 | "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", 943 | "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", 944 | "dev": true 945 | }, 946 | "node_modules/emoji-regex": { 947 | "version": "9.2.2", 948 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", 949 | "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", 950 | "dev": true 951 | }, 952 | "node_modules/fast-glob": { 953 | "version": "3.3.2", 954 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", 955 | "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", 956 | "dev": true, 957 | "dependencies": { 958 | "@nodelib/fs.stat": "^2.0.2", 959 | "@nodelib/fs.walk": "^1.2.3", 960 | "glob-parent": "^5.1.2", 961 | "merge2": "^1.3.0", 962 | "micromatch": "^4.0.4" 963 | }, 964 | "engines": { 965 | "node": ">=8.6.0" 966 | } 967 | }, 968 | "node_modules/fast-glob/node_modules/glob-parent": { 969 | "version": "5.1.2", 970 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 971 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 972 | "dev": true, 973 | "dependencies": { 974 | "is-glob": "^4.0.1" 975 | }, 976 | "engines": { 977 | "node": ">= 6" 978 | } 979 | }, 980 | "node_modules/fastq": { 981 | "version": "1.17.1", 982 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", 983 | "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", 984 | "dev": true, 985 | "dependencies": { 986 | "reusify": "^1.0.4" 987 | } 988 | }, 989 | "node_modules/fill-range": { 990 | "version": "7.1.1", 991 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 992 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 993 | "dev": true, 994 | "dependencies": { 995 | "to-regex-range": "^5.0.1" 996 | }, 997 | "engines": { 998 | "node": ">=8" 999 | } 1000 | }, 1001 | "node_modules/foreground-child": { 1002 | "version": "3.3.0", 1003 | "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", 1004 | "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", 1005 | "dev": true, 1006 | "dependencies": { 1007 | "cross-spawn": "^7.0.0", 1008 | "signal-exit": "^4.0.1" 1009 | }, 1010 | "engines": { 1011 | "node": ">=14" 1012 | }, 1013 | "funding": { 1014 | "url": "https://github.com/sponsors/isaacs" 1015 | } 1016 | }, 1017 | "node_modules/fsevents": { 1018 | "version": "2.3.3", 1019 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1020 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1021 | "dev": true, 1022 | "hasInstallScript": true, 1023 | "optional": true, 1024 | "os": [ 1025 | "darwin" 1026 | ], 1027 | "engines": { 1028 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1029 | } 1030 | }, 1031 | "node_modules/function-bind": { 1032 | "version": "1.1.2", 1033 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 1034 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 1035 | "dev": true, 1036 | "funding": { 1037 | "url": "https://github.com/sponsors/ljharb" 1038 | } 1039 | }, 1040 | "node_modules/glob": { 1041 | "version": "10.4.5", 1042 | "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", 1043 | "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", 1044 | "dev": true, 1045 | "dependencies": { 1046 | "foreground-child": "^3.1.0", 1047 | "jackspeak": "^3.1.2", 1048 | "minimatch": "^9.0.4", 1049 | "minipass": "^7.1.2", 1050 | "package-json-from-dist": "^1.0.0", 1051 | "path-scurry": "^1.11.1" 1052 | }, 1053 | "bin": { 1054 | "glob": "dist/esm/bin.mjs" 1055 | }, 1056 | "funding": { 1057 | "url": "https://github.com/sponsors/isaacs" 1058 | } 1059 | }, 1060 | "node_modules/glob-parent": { 1061 | "version": "6.0.2", 1062 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", 1063 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", 1064 | "dev": true, 1065 | "dependencies": { 1066 | "is-glob": "^4.0.3" 1067 | }, 1068 | "engines": { 1069 | "node": ">=10.13.0" 1070 | } 1071 | }, 1072 | "node_modules/hasown": { 1073 | "version": "2.0.2", 1074 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 1075 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 1076 | "dev": true, 1077 | "dependencies": { 1078 | "function-bind": "^1.1.2" 1079 | }, 1080 | "engines": { 1081 | "node": ">= 0.4" 1082 | } 1083 | }, 1084 | "node_modules/is-arrayish": { 1085 | "version": "0.3.2", 1086 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", 1087 | "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", 1088 | "optional": true 1089 | }, 1090 | "node_modules/is-binary-path": { 1091 | "version": "2.1.0", 1092 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 1093 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 1094 | "dev": true, 1095 | "dependencies": { 1096 | "binary-extensions": "^2.0.0" 1097 | }, 1098 | "engines": { 1099 | "node": ">=8" 1100 | } 1101 | }, 1102 | "node_modules/is-core-module": { 1103 | "version": "2.15.1", 1104 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", 1105 | "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", 1106 | "dev": true, 1107 | "dependencies": { 1108 | "hasown": "^2.0.2" 1109 | }, 1110 | "engines": { 1111 | "node": ">= 0.4" 1112 | }, 1113 | "funding": { 1114 | "url": "https://github.com/sponsors/ljharb" 1115 | } 1116 | }, 1117 | "node_modules/is-extglob": { 1118 | "version": "2.1.1", 1119 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1120 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 1121 | "dev": true, 1122 | "engines": { 1123 | "node": ">=0.10.0" 1124 | } 1125 | }, 1126 | "node_modules/is-fullwidth-code-point": { 1127 | "version": "3.0.0", 1128 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1129 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 1130 | "dev": true, 1131 | "engines": { 1132 | "node": ">=8" 1133 | } 1134 | }, 1135 | "node_modules/is-glob": { 1136 | "version": "4.0.3", 1137 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 1138 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 1139 | "dev": true, 1140 | "dependencies": { 1141 | "is-extglob": "^2.1.1" 1142 | }, 1143 | "engines": { 1144 | "node": ">=0.10.0" 1145 | } 1146 | }, 1147 | "node_modules/is-number": { 1148 | "version": "7.0.0", 1149 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1150 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1151 | "dev": true, 1152 | "engines": { 1153 | "node": ">=0.12.0" 1154 | } 1155 | }, 1156 | "node_modules/isexe": { 1157 | "version": "2.0.0", 1158 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1159 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 1160 | "dev": true 1161 | }, 1162 | "node_modules/jackspeak": { 1163 | "version": "3.4.3", 1164 | "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", 1165 | "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", 1166 | "dev": true, 1167 | "dependencies": { 1168 | "@isaacs/cliui": "^8.0.2" 1169 | }, 1170 | "funding": { 1171 | "url": "https://github.com/sponsors/isaacs" 1172 | }, 1173 | "optionalDependencies": { 1174 | "@pkgjs/parseargs": "^0.11.0" 1175 | } 1176 | }, 1177 | "node_modules/jiti": { 1178 | "version": "1.21.6", 1179 | "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", 1180 | "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", 1181 | "dev": true, 1182 | "bin": { 1183 | "jiti": "bin/jiti.js" 1184 | } 1185 | }, 1186 | "node_modules/lilconfig": { 1187 | "version": "2.1.0", 1188 | "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", 1189 | "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", 1190 | "dev": true, 1191 | "engines": { 1192 | "node": ">=10" 1193 | } 1194 | }, 1195 | "node_modules/lines-and-columns": { 1196 | "version": "1.2.4", 1197 | "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", 1198 | "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", 1199 | "dev": true 1200 | }, 1201 | "node_modules/lru-cache": { 1202 | "version": "10.4.3", 1203 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", 1204 | "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", 1205 | "dev": true 1206 | }, 1207 | "node_modules/merge2": { 1208 | "version": "1.4.1", 1209 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 1210 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 1211 | "dev": true, 1212 | "engines": { 1213 | "node": ">= 8" 1214 | } 1215 | }, 1216 | "node_modules/micromatch": { 1217 | "version": "4.0.8", 1218 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", 1219 | "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", 1220 | "dev": true, 1221 | "dependencies": { 1222 | "braces": "^3.0.3", 1223 | "picomatch": "^2.3.1" 1224 | }, 1225 | "engines": { 1226 | "node": ">=8.6" 1227 | } 1228 | }, 1229 | "node_modules/minimatch": { 1230 | "version": "9.0.5", 1231 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", 1232 | "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", 1233 | "dev": true, 1234 | "dependencies": { 1235 | "brace-expansion": "^2.0.1" 1236 | }, 1237 | "engines": { 1238 | "node": ">=16 || 14 >=14.17" 1239 | }, 1240 | "funding": { 1241 | "url": "https://github.com/sponsors/isaacs" 1242 | } 1243 | }, 1244 | "node_modules/minipass": { 1245 | "version": "7.1.2", 1246 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", 1247 | "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", 1248 | "dev": true, 1249 | "engines": { 1250 | "node": ">=16 || 14 >=14.17" 1251 | } 1252 | }, 1253 | "node_modules/mz": { 1254 | "version": "2.7.0", 1255 | "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", 1256 | "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", 1257 | "dev": true, 1258 | "dependencies": { 1259 | "any-promise": "^1.0.0", 1260 | "object-assign": "^4.0.1", 1261 | "thenify-all": "^1.0.0" 1262 | } 1263 | }, 1264 | "node_modules/nanoid": { 1265 | "version": "3.3.7", 1266 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", 1267 | "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", 1268 | "funding": [ 1269 | { 1270 | "type": "github", 1271 | "url": "https://github.com/sponsors/ai" 1272 | } 1273 | ], 1274 | "bin": { 1275 | "nanoid": "bin/nanoid.cjs" 1276 | }, 1277 | "engines": { 1278 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1279 | } 1280 | }, 1281 | "node_modules/next": { 1282 | "version": "15.0.3", 1283 | "resolved": "https://registry.npmjs.org/next/-/next-15.0.3.tgz", 1284 | "integrity": "sha512-ontCbCRKJUIoivAdGB34yCaOcPgYXr9AAkV/IwqFfWWTXEPUgLYkSkqBhIk9KK7gGmgjc64B+RdoeIDM13Irnw==", 1285 | "dependencies": { 1286 | "@next/env": "15.0.3", 1287 | "@swc/counter": "0.1.3", 1288 | "@swc/helpers": "0.5.13", 1289 | "busboy": "1.6.0", 1290 | "caniuse-lite": "^1.0.30001579", 1291 | "postcss": "8.4.31", 1292 | "styled-jsx": "5.1.6" 1293 | }, 1294 | "bin": { 1295 | "next": "dist/bin/next" 1296 | }, 1297 | "engines": { 1298 | "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" 1299 | }, 1300 | "optionalDependencies": { 1301 | "@next/swc-darwin-arm64": "15.0.3", 1302 | "@next/swc-darwin-x64": "15.0.3", 1303 | "@next/swc-linux-arm64-gnu": "15.0.3", 1304 | "@next/swc-linux-arm64-musl": "15.0.3", 1305 | "@next/swc-linux-x64-gnu": "15.0.3", 1306 | "@next/swc-linux-x64-musl": "15.0.3", 1307 | "@next/swc-win32-arm64-msvc": "15.0.3", 1308 | "@next/swc-win32-x64-msvc": "15.0.3", 1309 | "sharp": "^0.33.5" 1310 | }, 1311 | "peerDependencies": { 1312 | "@opentelemetry/api": "^1.1.0", 1313 | "@playwright/test": "^1.41.2", 1314 | "babel-plugin-react-compiler": "*", 1315 | "react": "^18.2.0 || 19.0.0-rc-66855b96-20241106", 1316 | "react-dom": "^18.2.0 || 19.0.0-rc-66855b96-20241106", 1317 | "sass": "^1.3.0" 1318 | }, 1319 | "peerDependenciesMeta": { 1320 | "@opentelemetry/api": { 1321 | "optional": true 1322 | }, 1323 | "@playwright/test": { 1324 | "optional": true 1325 | }, 1326 | "babel-plugin-react-compiler": { 1327 | "optional": true 1328 | }, 1329 | "sass": { 1330 | "optional": true 1331 | } 1332 | } 1333 | }, 1334 | "node_modules/next/node_modules/postcss": { 1335 | "version": "8.4.31", 1336 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", 1337 | "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", 1338 | "funding": [ 1339 | { 1340 | "type": "opencollective", 1341 | "url": "https://opencollective.com/postcss/" 1342 | }, 1343 | { 1344 | "type": "tidelift", 1345 | "url": "https://tidelift.com/funding/github/npm/postcss" 1346 | }, 1347 | { 1348 | "type": "github", 1349 | "url": "https://github.com/sponsors/ai" 1350 | } 1351 | ], 1352 | "dependencies": { 1353 | "nanoid": "^3.3.6", 1354 | "picocolors": "^1.0.0", 1355 | "source-map-js": "^1.0.2" 1356 | }, 1357 | "engines": { 1358 | "node": "^10 || ^12 || >=14" 1359 | } 1360 | }, 1361 | "node_modules/normalize-path": { 1362 | "version": "3.0.0", 1363 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1364 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1365 | "dev": true, 1366 | "engines": { 1367 | "node": ">=0.10.0" 1368 | } 1369 | }, 1370 | "node_modules/object-assign": { 1371 | "version": "4.1.1", 1372 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1373 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 1374 | "dev": true, 1375 | "engines": { 1376 | "node": ">=0.10.0" 1377 | } 1378 | }, 1379 | "node_modules/object-hash": { 1380 | "version": "3.0.0", 1381 | "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", 1382 | "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", 1383 | "dev": true, 1384 | "engines": { 1385 | "node": ">= 6" 1386 | } 1387 | }, 1388 | "node_modules/package-json-from-dist": { 1389 | "version": "1.0.1", 1390 | "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", 1391 | "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", 1392 | "dev": true 1393 | }, 1394 | "node_modules/path-key": { 1395 | "version": "3.1.1", 1396 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1397 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1398 | "dev": true, 1399 | "engines": { 1400 | "node": ">=8" 1401 | } 1402 | }, 1403 | "node_modules/path-parse": { 1404 | "version": "1.0.7", 1405 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 1406 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 1407 | "dev": true 1408 | }, 1409 | "node_modules/path-scurry": { 1410 | "version": "1.11.1", 1411 | "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", 1412 | "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", 1413 | "dev": true, 1414 | "dependencies": { 1415 | "lru-cache": "^10.2.0", 1416 | "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" 1417 | }, 1418 | "engines": { 1419 | "node": ">=16 || 14 >=14.18" 1420 | }, 1421 | "funding": { 1422 | "url": "https://github.com/sponsors/isaacs" 1423 | } 1424 | }, 1425 | "node_modules/picocolors": { 1426 | "version": "1.1.1", 1427 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", 1428 | "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" 1429 | }, 1430 | "node_modules/picomatch": { 1431 | "version": "2.3.1", 1432 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1433 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1434 | "dev": true, 1435 | "engines": { 1436 | "node": ">=8.6" 1437 | }, 1438 | "funding": { 1439 | "url": "https://github.com/sponsors/jonschlinkert" 1440 | } 1441 | }, 1442 | "node_modules/pify": { 1443 | "version": "2.3.0", 1444 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 1445 | "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", 1446 | "dev": true, 1447 | "engines": { 1448 | "node": ">=0.10.0" 1449 | } 1450 | }, 1451 | "node_modules/pirates": { 1452 | "version": "4.0.6", 1453 | "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", 1454 | "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", 1455 | "dev": true, 1456 | "engines": { 1457 | "node": ">= 6" 1458 | } 1459 | }, 1460 | "node_modules/postcss": { 1461 | "version": "8.4.49", 1462 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", 1463 | "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", 1464 | "dev": true, 1465 | "funding": [ 1466 | { 1467 | "type": "opencollective", 1468 | "url": "https://opencollective.com/postcss/" 1469 | }, 1470 | { 1471 | "type": "tidelift", 1472 | "url": "https://tidelift.com/funding/github/npm/postcss" 1473 | }, 1474 | { 1475 | "type": "github", 1476 | "url": "https://github.com/sponsors/ai" 1477 | } 1478 | ], 1479 | "dependencies": { 1480 | "nanoid": "^3.3.7", 1481 | "picocolors": "^1.1.1", 1482 | "source-map-js": "^1.2.1" 1483 | }, 1484 | "engines": { 1485 | "node": "^10 || ^12 || >=14" 1486 | } 1487 | }, 1488 | "node_modules/postcss-import": { 1489 | "version": "15.1.0", 1490 | "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", 1491 | "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", 1492 | "dev": true, 1493 | "dependencies": { 1494 | "postcss-value-parser": "^4.0.0", 1495 | "read-cache": "^1.0.0", 1496 | "resolve": "^1.1.7" 1497 | }, 1498 | "engines": { 1499 | "node": ">=14.0.0" 1500 | }, 1501 | "peerDependencies": { 1502 | "postcss": "^8.0.0" 1503 | } 1504 | }, 1505 | "node_modules/postcss-js": { 1506 | "version": "4.0.1", 1507 | "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", 1508 | "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", 1509 | "dev": true, 1510 | "dependencies": { 1511 | "camelcase-css": "^2.0.1" 1512 | }, 1513 | "engines": { 1514 | "node": "^12 || ^14 || >= 16" 1515 | }, 1516 | "funding": { 1517 | "type": "opencollective", 1518 | "url": "https://opencollective.com/postcss/" 1519 | }, 1520 | "peerDependencies": { 1521 | "postcss": "^8.4.21" 1522 | } 1523 | }, 1524 | "node_modules/postcss-load-config": { 1525 | "version": "4.0.2", 1526 | "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", 1527 | "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", 1528 | "dev": true, 1529 | "funding": [ 1530 | { 1531 | "type": "opencollective", 1532 | "url": "https://opencollective.com/postcss/" 1533 | }, 1534 | { 1535 | "type": "github", 1536 | "url": "https://github.com/sponsors/ai" 1537 | } 1538 | ], 1539 | "dependencies": { 1540 | "lilconfig": "^3.0.0", 1541 | "yaml": "^2.3.4" 1542 | }, 1543 | "engines": { 1544 | "node": ">= 14" 1545 | }, 1546 | "peerDependencies": { 1547 | "postcss": ">=8.0.9", 1548 | "ts-node": ">=9.0.0" 1549 | }, 1550 | "peerDependenciesMeta": { 1551 | "postcss": { 1552 | "optional": true 1553 | }, 1554 | "ts-node": { 1555 | "optional": true 1556 | } 1557 | } 1558 | }, 1559 | "node_modules/postcss-load-config/node_modules/lilconfig": { 1560 | "version": "3.1.2", 1561 | "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", 1562 | "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", 1563 | "dev": true, 1564 | "engines": { 1565 | "node": ">=14" 1566 | }, 1567 | "funding": { 1568 | "url": "https://github.com/sponsors/antonk52" 1569 | } 1570 | }, 1571 | "node_modules/postcss-nested": { 1572 | "version": "6.2.0", 1573 | "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", 1574 | "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", 1575 | "dev": true, 1576 | "funding": [ 1577 | { 1578 | "type": "opencollective", 1579 | "url": "https://opencollective.com/postcss/" 1580 | }, 1581 | { 1582 | "type": "github", 1583 | "url": "https://github.com/sponsors/ai" 1584 | } 1585 | ], 1586 | "dependencies": { 1587 | "postcss-selector-parser": "^6.1.1" 1588 | }, 1589 | "engines": { 1590 | "node": ">=12.0" 1591 | }, 1592 | "peerDependencies": { 1593 | "postcss": "^8.2.14" 1594 | } 1595 | }, 1596 | "node_modules/postcss-selector-parser": { 1597 | "version": "6.1.2", 1598 | "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", 1599 | "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", 1600 | "dev": true, 1601 | "dependencies": { 1602 | "cssesc": "^3.0.0", 1603 | "util-deprecate": "^1.0.2" 1604 | }, 1605 | "engines": { 1606 | "node": ">=4" 1607 | } 1608 | }, 1609 | "node_modules/postcss-value-parser": { 1610 | "version": "4.2.0", 1611 | "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", 1612 | "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", 1613 | "dev": true 1614 | }, 1615 | "node_modules/queue-microtask": { 1616 | "version": "1.2.3", 1617 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 1618 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 1619 | "dev": true, 1620 | "funding": [ 1621 | { 1622 | "type": "github", 1623 | "url": "https://github.com/sponsors/feross" 1624 | }, 1625 | { 1626 | "type": "patreon", 1627 | "url": "https://www.patreon.com/feross" 1628 | }, 1629 | { 1630 | "type": "consulting", 1631 | "url": "https://feross.org/support" 1632 | } 1633 | ] 1634 | }, 1635 | "node_modules/react": { 1636 | "version": "19.0.0-rc-66855b96-20241106", 1637 | "resolved": "https://registry.npmjs.org/react/-/react-19.0.0-rc-66855b96-20241106.tgz", 1638 | "integrity": "sha512-klH7xkT71SxRCx4hb1hly5FJB21Hz0ACyxbXYAECEqssUjtJeFUAaI2U1DgJAzkGEnvEm3DkxuBchMC/9K4ipg==", 1639 | "engines": { 1640 | "node": ">=0.10.0" 1641 | } 1642 | }, 1643 | "node_modules/react-dom": { 1644 | "version": "19.0.0-rc-66855b96-20241106", 1645 | "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0-rc-66855b96-20241106.tgz", 1646 | "integrity": "sha512-D25vdaytZ1wFIRiwNU98NPQ/upS2P8Co4/oNoa02PzHbh8deWdepjm5qwZM/46OdSiGv4WSWwxP55RO9obqJEQ==", 1647 | "dependencies": { 1648 | "scheduler": "0.25.0-rc-66855b96-20241106" 1649 | }, 1650 | "peerDependencies": { 1651 | "react": "19.0.0-rc-66855b96-20241106" 1652 | } 1653 | }, 1654 | "node_modules/read-cache": { 1655 | "version": "1.0.0", 1656 | "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", 1657 | "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", 1658 | "dev": true, 1659 | "dependencies": { 1660 | "pify": "^2.3.0" 1661 | } 1662 | }, 1663 | "node_modules/readdirp": { 1664 | "version": "3.6.0", 1665 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 1666 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 1667 | "dev": true, 1668 | "dependencies": { 1669 | "picomatch": "^2.2.1" 1670 | }, 1671 | "engines": { 1672 | "node": ">=8.10.0" 1673 | } 1674 | }, 1675 | "node_modules/resolve": { 1676 | "version": "1.22.8", 1677 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", 1678 | "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", 1679 | "dev": true, 1680 | "dependencies": { 1681 | "is-core-module": "^2.13.0", 1682 | "path-parse": "^1.0.7", 1683 | "supports-preserve-symlinks-flag": "^1.0.0" 1684 | }, 1685 | "bin": { 1686 | "resolve": "bin/resolve" 1687 | }, 1688 | "funding": { 1689 | "url": "https://github.com/sponsors/ljharb" 1690 | } 1691 | }, 1692 | "node_modules/reusify": { 1693 | "version": "1.0.4", 1694 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 1695 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 1696 | "dev": true, 1697 | "engines": { 1698 | "iojs": ">=1.0.0", 1699 | "node": ">=0.10.0" 1700 | } 1701 | }, 1702 | "node_modules/run-parallel": { 1703 | "version": "1.2.0", 1704 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 1705 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 1706 | "dev": true, 1707 | "funding": [ 1708 | { 1709 | "type": "github", 1710 | "url": "https://github.com/sponsors/feross" 1711 | }, 1712 | { 1713 | "type": "patreon", 1714 | "url": "https://www.patreon.com/feross" 1715 | }, 1716 | { 1717 | "type": "consulting", 1718 | "url": "https://feross.org/support" 1719 | } 1720 | ], 1721 | "dependencies": { 1722 | "queue-microtask": "^1.2.2" 1723 | } 1724 | }, 1725 | "node_modules/scheduler": { 1726 | "version": "0.25.0-rc-66855b96-20241106", 1727 | "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0-rc-66855b96-20241106.tgz", 1728 | "integrity": "sha512-HQXp/Mnp/MMRSXMQF7urNFla+gmtXW/Gr1KliuR0iboTit4KvZRY8KYaq5ccCTAOJiUqQh2rE2F3wgUekmgdlA==" 1729 | }, 1730 | "node_modules/semver": { 1731 | "version": "7.6.3", 1732 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", 1733 | "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", 1734 | "optional": true, 1735 | "bin": { 1736 | "semver": "bin/semver.js" 1737 | }, 1738 | "engines": { 1739 | "node": ">=10" 1740 | } 1741 | }, 1742 | "node_modules/sharp": { 1743 | "version": "0.33.5", 1744 | "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", 1745 | "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", 1746 | "hasInstallScript": true, 1747 | "optional": true, 1748 | "dependencies": { 1749 | "color": "^4.2.3", 1750 | "detect-libc": "^2.0.3", 1751 | "semver": "^7.6.3" 1752 | }, 1753 | "engines": { 1754 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1755 | }, 1756 | "funding": { 1757 | "url": "https://opencollective.com/libvips" 1758 | }, 1759 | "optionalDependencies": { 1760 | "@img/sharp-darwin-arm64": "0.33.5", 1761 | "@img/sharp-darwin-x64": "0.33.5", 1762 | "@img/sharp-libvips-darwin-arm64": "1.0.4", 1763 | "@img/sharp-libvips-darwin-x64": "1.0.4", 1764 | "@img/sharp-libvips-linux-arm": "1.0.5", 1765 | "@img/sharp-libvips-linux-arm64": "1.0.4", 1766 | "@img/sharp-libvips-linux-s390x": "1.0.4", 1767 | "@img/sharp-libvips-linux-x64": "1.0.4", 1768 | "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", 1769 | "@img/sharp-libvips-linuxmusl-x64": "1.0.4", 1770 | "@img/sharp-linux-arm": "0.33.5", 1771 | "@img/sharp-linux-arm64": "0.33.5", 1772 | "@img/sharp-linux-s390x": "0.33.5", 1773 | "@img/sharp-linux-x64": "0.33.5", 1774 | "@img/sharp-linuxmusl-arm64": "0.33.5", 1775 | "@img/sharp-linuxmusl-x64": "0.33.5", 1776 | "@img/sharp-wasm32": "0.33.5", 1777 | "@img/sharp-win32-ia32": "0.33.5", 1778 | "@img/sharp-win32-x64": "0.33.5" 1779 | } 1780 | }, 1781 | "node_modules/shebang-command": { 1782 | "version": "2.0.0", 1783 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1784 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1785 | "dev": true, 1786 | "dependencies": { 1787 | "shebang-regex": "^3.0.0" 1788 | }, 1789 | "engines": { 1790 | "node": ">=8" 1791 | } 1792 | }, 1793 | "node_modules/shebang-regex": { 1794 | "version": "3.0.0", 1795 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1796 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1797 | "dev": true, 1798 | "engines": { 1799 | "node": ">=8" 1800 | } 1801 | }, 1802 | "node_modules/signal-exit": { 1803 | "version": "4.1.0", 1804 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", 1805 | "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", 1806 | "dev": true, 1807 | "engines": { 1808 | "node": ">=14" 1809 | }, 1810 | "funding": { 1811 | "url": "https://github.com/sponsors/isaacs" 1812 | } 1813 | }, 1814 | "node_modules/simple-swizzle": { 1815 | "version": "0.2.2", 1816 | "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", 1817 | "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", 1818 | "optional": true, 1819 | "dependencies": { 1820 | "is-arrayish": "^0.3.1" 1821 | } 1822 | }, 1823 | "node_modules/source-map-js": { 1824 | "version": "1.2.1", 1825 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", 1826 | "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", 1827 | "engines": { 1828 | "node": ">=0.10.0" 1829 | } 1830 | }, 1831 | "node_modules/streamsearch": { 1832 | "version": "1.1.0", 1833 | "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", 1834 | "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", 1835 | "engines": { 1836 | "node": ">=10.0.0" 1837 | } 1838 | }, 1839 | "node_modules/string-width": { 1840 | "version": "5.1.2", 1841 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", 1842 | "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", 1843 | "dev": true, 1844 | "dependencies": { 1845 | "eastasianwidth": "^0.2.0", 1846 | "emoji-regex": "^9.2.2", 1847 | "strip-ansi": "^7.0.1" 1848 | }, 1849 | "engines": { 1850 | "node": ">=12" 1851 | }, 1852 | "funding": { 1853 | "url": "https://github.com/sponsors/sindresorhus" 1854 | } 1855 | }, 1856 | "node_modules/string-width-cjs": { 1857 | "name": "string-width", 1858 | "version": "4.2.3", 1859 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1860 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1861 | "dev": true, 1862 | "dependencies": { 1863 | "emoji-regex": "^8.0.0", 1864 | "is-fullwidth-code-point": "^3.0.0", 1865 | "strip-ansi": "^6.0.1" 1866 | }, 1867 | "engines": { 1868 | "node": ">=8" 1869 | } 1870 | }, 1871 | "node_modules/string-width-cjs/node_modules/ansi-regex": { 1872 | "version": "5.0.1", 1873 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1874 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 1875 | "dev": true, 1876 | "engines": { 1877 | "node": ">=8" 1878 | } 1879 | }, 1880 | "node_modules/string-width-cjs/node_modules/emoji-regex": { 1881 | "version": "8.0.0", 1882 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1883 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 1884 | "dev": true 1885 | }, 1886 | "node_modules/string-width-cjs/node_modules/strip-ansi": { 1887 | "version": "6.0.1", 1888 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1889 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1890 | "dev": true, 1891 | "dependencies": { 1892 | "ansi-regex": "^5.0.1" 1893 | }, 1894 | "engines": { 1895 | "node": ">=8" 1896 | } 1897 | }, 1898 | "node_modules/strip-ansi": { 1899 | "version": "7.1.0", 1900 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", 1901 | "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", 1902 | "dev": true, 1903 | "dependencies": { 1904 | "ansi-regex": "^6.0.1" 1905 | }, 1906 | "engines": { 1907 | "node": ">=12" 1908 | }, 1909 | "funding": { 1910 | "url": "https://github.com/chalk/strip-ansi?sponsor=1" 1911 | } 1912 | }, 1913 | "node_modules/strip-ansi-cjs": { 1914 | "name": "strip-ansi", 1915 | "version": "6.0.1", 1916 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1917 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1918 | "dev": true, 1919 | "dependencies": { 1920 | "ansi-regex": "^5.0.1" 1921 | }, 1922 | "engines": { 1923 | "node": ">=8" 1924 | } 1925 | }, 1926 | "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { 1927 | "version": "5.0.1", 1928 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1929 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 1930 | "dev": true, 1931 | "engines": { 1932 | "node": ">=8" 1933 | } 1934 | }, 1935 | "node_modules/styled-jsx": { 1936 | "version": "5.1.6", 1937 | "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", 1938 | "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", 1939 | "dependencies": { 1940 | "client-only": "0.0.1" 1941 | }, 1942 | "engines": { 1943 | "node": ">= 12.0.0" 1944 | }, 1945 | "peerDependencies": { 1946 | "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" 1947 | }, 1948 | "peerDependenciesMeta": { 1949 | "@babel/core": { 1950 | "optional": true 1951 | }, 1952 | "babel-plugin-macros": { 1953 | "optional": true 1954 | } 1955 | } 1956 | }, 1957 | "node_modules/sucrase": { 1958 | "version": "3.35.0", 1959 | "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", 1960 | "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", 1961 | "dev": true, 1962 | "dependencies": { 1963 | "@jridgewell/gen-mapping": "^0.3.2", 1964 | "commander": "^4.0.0", 1965 | "glob": "^10.3.10", 1966 | "lines-and-columns": "^1.1.6", 1967 | "mz": "^2.7.0", 1968 | "pirates": "^4.0.1", 1969 | "ts-interface-checker": "^0.1.9" 1970 | }, 1971 | "bin": { 1972 | "sucrase": "bin/sucrase", 1973 | "sucrase-node": "bin/sucrase-node" 1974 | }, 1975 | "engines": { 1976 | "node": ">=16 || 14 >=14.17" 1977 | } 1978 | }, 1979 | "node_modules/supports-preserve-symlinks-flag": { 1980 | "version": "1.0.0", 1981 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 1982 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 1983 | "dev": true, 1984 | "engines": { 1985 | "node": ">= 0.4" 1986 | }, 1987 | "funding": { 1988 | "url": "https://github.com/sponsors/ljharb" 1989 | } 1990 | }, 1991 | "node_modules/tailwindcss": { 1992 | "version": "3.4.15", 1993 | "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.15.tgz", 1994 | "integrity": "sha512-r4MeXnfBmSOuKUWmXe6h2CcyfzJCEk4F0pptO5jlnYSIViUkVmsawj80N5h2lO3gwcmSb4n3PuN+e+GC1Guylw==", 1995 | "dev": true, 1996 | "dependencies": { 1997 | "@alloc/quick-lru": "^5.2.0", 1998 | "arg": "^5.0.2", 1999 | "chokidar": "^3.6.0", 2000 | "didyoumean": "^1.2.2", 2001 | "dlv": "^1.1.3", 2002 | "fast-glob": "^3.3.2", 2003 | "glob-parent": "^6.0.2", 2004 | "is-glob": "^4.0.3", 2005 | "jiti": "^1.21.6", 2006 | "lilconfig": "^2.1.0", 2007 | "micromatch": "^4.0.8", 2008 | "normalize-path": "^3.0.0", 2009 | "object-hash": "^3.0.0", 2010 | "picocolors": "^1.1.1", 2011 | "postcss": "^8.4.47", 2012 | "postcss-import": "^15.1.0", 2013 | "postcss-js": "^4.0.1", 2014 | "postcss-load-config": "^4.0.2", 2015 | "postcss-nested": "^6.2.0", 2016 | "postcss-selector-parser": "^6.1.2", 2017 | "resolve": "^1.22.8", 2018 | "sucrase": "^3.35.0" 2019 | }, 2020 | "bin": { 2021 | "tailwind": "lib/cli.js", 2022 | "tailwindcss": "lib/cli.js" 2023 | }, 2024 | "engines": { 2025 | "node": ">=14.0.0" 2026 | } 2027 | }, 2028 | "node_modules/thenify": { 2029 | "version": "3.3.1", 2030 | "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", 2031 | "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", 2032 | "dev": true, 2033 | "dependencies": { 2034 | "any-promise": "^1.0.0" 2035 | } 2036 | }, 2037 | "node_modules/thenify-all": { 2038 | "version": "1.6.0", 2039 | "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", 2040 | "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", 2041 | "dev": true, 2042 | "dependencies": { 2043 | "thenify": ">= 3.1.0 < 4" 2044 | }, 2045 | "engines": { 2046 | "node": ">=0.8" 2047 | } 2048 | }, 2049 | "node_modules/to-regex-range": { 2050 | "version": "5.0.1", 2051 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2052 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2053 | "dev": true, 2054 | "dependencies": { 2055 | "is-number": "^7.0.0" 2056 | }, 2057 | "engines": { 2058 | "node": ">=8.0" 2059 | } 2060 | }, 2061 | "node_modules/ts-interface-checker": { 2062 | "version": "0.1.13", 2063 | "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", 2064 | "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", 2065 | "dev": true 2066 | }, 2067 | "node_modules/tslib": { 2068 | "version": "2.8.1", 2069 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", 2070 | "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" 2071 | }, 2072 | "node_modules/typescript": { 2073 | "version": "5.6.3", 2074 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", 2075 | "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", 2076 | "dev": true, 2077 | "bin": { 2078 | "tsc": "bin/tsc", 2079 | "tsserver": "bin/tsserver" 2080 | }, 2081 | "engines": { 2082 | "node": ">=14.17" 2083 | } 2084 | }, 2085 | "node_modules/undici-types": { 2086 | "version": "6.19.8", 2087 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", 2088 | "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", 2089 | "dev": true 2090 | }, 2091 | "node_modules/util-deprecate": { 2092 | "version": "1.0.2", 2093 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 2094 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", 2095 | "dev": true 2096 | }, 2097 | "node_modules/which": { 2098 | "version": "2.0.2", 2099 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2100 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2101 | "dev": true, 2102 | "dependencies": { 2103 | "isexe": "^2.0.0" 2104 | }, 2105 | "bin": { 2106 | "node-which": "bin/node-which" 2107 | }, 2108 | "engines": { 2109 | "node": ">= 8" 2110 | } 2111 | }, 2112 | "node_modules/wrap-ansi": { 2113 | "version": "8.1.0", 2114 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", 2115 | "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", 2116 | "dev": true, 2117 | "dependencies": { 2118 | "ansi-styles": "^6.1.0", 2119 | "string-width": "^5.0.1", 2120 | "strip-ansi": "^7.0.1" 2121 | }, 2122 | "engines": { 2123 | "node": ">=12" 2124 | }, 2125 | "funding": { 2126 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 2127 | } 2128 | }, 2129 | "node_modules/wrap-ansi-cjs": { 2130 | "name": "wrap-ansi", 2131 | "version": "7.0.0", 2132 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 2133 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 2134 | "dev": true, 2135 | "dependencies": { 2136 | "ansi-styles": "^4.0.0", 2137 | "string-width": "^4.1.0", 2138 | "strip-ansi": "^6.0.0" 2139 | }, 2140 | "engines": { 2141 | "node": ">=10" 2142 | }, 2143 | "funding": { 2144 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 2145 | } 2146 | }, 2147 | "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { 2148 | "version": "5.0.1", 2149 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 2150 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 2151 | "dev": true, 2152 | "engines": { 2153 | "node": ">=8" 2154 | } 2155 | }, 2156 | "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { 2157 | "version": "4.3.0", 2158 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 2159 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 2160 | "dev": true, 2161 | "dependencies": { 2162 | "color-convert": "^2.0.1" 2163 | }, 2164 | "engines": { 2165 | "node": ">=8" 2166 | }, 2167 | "funding": { 2168 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 2169 | } 2170 | }, 2171 | "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { 2172 | "version": "8.0.0", 2173 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 2174 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 2175 | "dev": true 2176 | }, 2177 | "node_modules/wrap-ansi-cjs/node_modules/string-width": { 2178 | "version": "4.2.3", 2179 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 2180 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 2181 | "dev": true, 2182 | "dependencies": { 2183 | "emoji-regex": "^8.0.0", 2184 | "is-fullwidth-code-point": "^3.0.0", 2185 | "strip-ansi": "^6.0.1" 2186 | }, 2187 | "engines": { 2188 | "node": ">=8" 2189 | } 2190 | }, 2191 | "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { 2192 | "version": "6.0.1", 2193 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2194 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2195 | "dev": true, 2196 | "dependencies": { 2197 | "ansi-regex": "^5.0.1" 2198 | }, 2199 | "engines": { 2200 | "node": ">=8" 2201 | } 2202 | }, 2203 | "node_modules/yaml": { 2204 | "version": "2.6.0", 2205 | "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", 2206 | "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", 2207 | "dev": true, 2208 | "bin": { 2209 | "yaml": "bin.mjs" 2210 | }, 2211 | "engines": { 2212 | "node": ">= 14" 2213 | } 2214 | } 2215 | } 2216 | } 2217 | -------------------------------------------------------------------------------- /nextjs-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextjs-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev --turbopack", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "react": "19.0.0-rc-66855b96-20241106", 13 | "react-dom": "19.0.0-rc-66855b96-20241106", 14 | "next": "15.0.3" 15 | }, 16 | "devDependencies": { 17 | "typescript": "^5", 18 | "@types/node": "^20", 19 | "@types/react": "^18", 20 | "@types/react-dom": "^18", 21 | "postcss": "^8", 22 | "tailwindcss": "^3.4.1" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /nextjs-app/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /nextjs-app/public/file.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nextjs-app/public/globe.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nextjs-app/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nextjs-app/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nextjs-app/public/window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nextjs-app/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | export default { 4 | content: [ 5 | "./pages/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./components/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./app/**/*.{js,ts,jsx,tsx,mdx}", 8 | ], 9 | theme: { 10 | extend: { 11 | colors: { 12 | background: "var(--background)", 13 | foreground: "var(--foreground)", 14 | }, 15 | }, 16 | }, 17 | plugins: [], 18 | } satisfies Config; 19 | -------------------------------------------------------------------------------- /nextjs-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /ollama/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ollama/ollama 2 | 3 | COPY ./pull-qwen.sh /pull-qwen.sh 4 | -------------------------------------------------------------------------------- /ollama/pull-qwen.sh: -------------------------------------------------------------------------------- 1 | 2 | ./bin/ollama serve & 3 | 4 | pid=$! 5 | 6 | sleep 5 7 | 8 | 9 | echo "Pulling qwen2.5-coder model" 10 | ollama pull qwen2.5-coder:0.5b 11 | 12 | 13 | wait $pid 14 | --------------------------------------------------------------------------------