Evgeny Naumov commited on
Commit
8b7ba5a
·
1 Parent(s): 81869ed

Add API server and Hugging Face deployment configuration

Browse files
Files changed (13) hide show
  1. .huggingface/spaces/README.md +94 -0
  2. API.md +269 -0
  3. Dockerfile +22 -0
  4. README.md +126 -20
  5. app.py +132 -0
  6. package-lock.json +1353 -50
  7. package.json +11 -0
  8. requirements.txt +2 -0
  9. server/index.js +226 -0
  10. server/simple-server.js +271 -0
  11. server/transcriber.js +181 -0
  12. src/App.tsx +11 -0
  13. vite.config.ts +5 -0
.huggingface/spaces/README.md ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Настройка Hugging Face Spaces
2
+
3
+ ## Вариант 1: Gradio Space (Рекомендуется)
4
+
5
+ 1. Создайте новый Space на Hugging Face
6
+ 2. Выберите тип: **Gradio**
7
+ 3. Скопируйте все файлы проекта
8
+ 4. Убедитесь, что есть файлы:
9
+ - `app.py` - основной файл для Gradio
10
+ - `requirements.txt` - Python зависимости
11
+ - `package.json` - Node.js зависимости
12
+ - `server/simple-server.js` - API сервер
13
+
14
+ ## Вариант 2: Docker Space
15
+
16
+ 1. Создайте новый Space на Hugging Face
17
+ 2. Выберите тип: **Docker**
18
+ 3. Скопируйте все файлы проекта
19
+ 4. Убедитесь, что есть файл `Dockerfile`
20
+
21
+ ## Структура файлов
22
+
23
+ ```
24
+ whisper-web/
25
+ ├── app.py # Gradio интерфейс
26
+ ├── requirements.txt # Python зависимости
27
+ ├── package.json # Node.js зависимости
28
+ ├── server/
29
+ │ └── simple-server.js # API сервер
30
+ ├── src/ # React приложение
31
+ ├── dist/ # Собранное приложение
32
+ └── Dockerfile # Docker конфигурация
33
+ ```
34
+
35
+ ## Команды запуска
36
+
37
+ ### Для Gradio Space:
38
+ - **Команда запуска**: `python app.py`
39
+ - **Порт**: 7860 (Gradio) + 3001 (API)
40
+
41
+ ### Для Docker Space:
42
+ - **Команда запуска**: `npm start`
43
+ - **Порт**: 3001
44
+
45
+ ## API Endpoints
46
+
47
+ После запуска API будет доступен по адресу:
48
+ - **Локально**: `http://localhost:3001/api`
49
+ - **HF Space**: `https://your-space.hf.space/api`
50
+
51
+ ### Доступные endpoints:
52
+ - `GET /api/health` - проверка здоровья
53
+ - `GET /api/models` - список моделей
54
+ - `GET /api/languages` - список языков
55
+ - `POST /api/transcribe` - транскрипция файла
56
+ - `POST /api/transcribe/url` - транскрипция по URL
57
+
58
+ ## Примеры использования
59
+
60
+ ### Python
61
+ ```python
62
+ import requests
63
+
64
+ # Проверка API
65
+ response = requests.get('https://your-space.hf.space/api/health')
66
+ print(response.json())
67
+
68
+ # Транскрипция
69
+ with open('audio.mp3', 'rb') as f:
70
+ files = {'audio': f}
71
+ data = {'language': 'ru', 'model': 'base'}
72
+ response = requests.post('https://your-space.hf.space/api/transcribe',
73
+ files=files, data=data)
74
+ print(response.json()['transcription']['text'])
75
+ ```
76
+
77
+ ### JavaScript
78
+ ```javascript
79
+ // Проверка API
80
+ const health = await fetch('https://your-space.hf.space/api/health');
81
+ console.log(await health.json());
82
+
83
+ // Транскрипция по URL
84
+ const response = await fetch('https://your-space.hf.space/api/transcribe/url', {
85
+ method: 'POST',
86
+ headers: { 'Content-Type': 'application/json' },
87
+ body: JSON.stringify({
88
+ url: 'https://example.com/audio.mp3',
89
+ language: 'ru',
90
+ model: 'base'
91
+ })
92
+ });
93
+ const result = await response.json();
94
+ ```
API.md ADDED
@@ -0,0 +1,269 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Whisper API Документация
2
+
3
+ ## Обзор
4
+
5
+ Whisper API предоставляет REST API для транскрипции аудио файлов с использованием моделей Whisper. API работает на порту 3001.
6
+
7
+ **Базовый URL:** `http://localhost:3001/api`
8
+
9
+ ## Endpoints
10
+
11
+ ### 1. Проверка здоровья сервера
12
+
13
+ **GET** `/health`
14
+
15
+ Проверяет, что сервер работает.
16
+
17
+ **Ответ:**
18
+ ```json
19
+ {
20
+ "status": "ok",
21
+ "message": "Whisper API сервер работает",
22
+ "timestamp": "2024-01-01T12:00:00.000Z"
23
+ }
24
+ ```
25
+
26
+ ### 2. Транскрипция аудио файла
27
+
28
+ **POST** `/transcribe`
29
+
30
+ Загружает и транскрибирует аудио файл.
31
+
32
+ **Параметры:**
33
+ - `audio` (file) - аудио файл (обязательно)
34
+ - `language` (string) - язык аудио (по умолчанию: "auto")
35
+ - `model` (string) - модель Whisper (по умолчанию: "base")
36
+
37
+ **Поддерживаемые форматы:** mp3, wav, m4a, webm, ogg
38
+
39
+ **Максимальный размер файла:** 50MB
40
+
41
+ **Пример запроса (cURL):**
42
+ ```bash
43
+ curl -X POST http://localhost:3001/api/transcribe \
44
+ -F "audio=@/path/to/audio.mp3" \
45
+ -F "language=ru" \
46
+ -F "model=base"
47
+ ```
48
+
49
+ **Ответ:**
50
+ ```json
51
+ {
52
+ "success": true,
53
+ "transcription": {
54
+ "text": "Транскрибированный текст",
55
+ "language": "ru",
56
+ "model": "base",
57
+ "duration": 120.5,
58
+ "segments": [
59
+ {
60
+ "start": 0,
61
+ "end": 10,
62
+ "text": "Первая часть текста"
63
+ }
64
+ ],
65
+ "timestamp": "2024-01-01T12:00:00.000Z"
66
+ },
67
+ "timestamp": "2024-01-01T12:00:00.000Z"
68
+ }
69
+ ```
70
+
71
+ ### 3. Транскрипция по URL
72
+
73
+ **POST** `/transcribe/url`
74
+
75
+ Транскрибирует аудио файл по URL.
76
+
77
+ **Тело запроса:**
78
+ ```json
79
+ {
80
+ "url": "https://example.com/audio.mp3",
81
+ "language": "ru",
82
+ "model": "base"
83
+ }
84
+ ```
85
+
86
+ **Пример запроса (cURL):**
87
+ ```bash
88
+ curl -X POST http://localhost:3001/api/transcribe/url \
89
+ -H "Content-Type: application/json" \
90
+ -d '{
91
+ "url": "https://example.com/audio.mp3",
92
+ "language": "ru",
93
+ "model": "base"
94
+ }'
95
+ ```
96
+
97
+ ### 4. Список доступных моделей
98
+
99
+ **GET** `/models`
100
+
101
+ Возвращает список доступных моделей Whisper.
102
+
103
+ **Ответ:**
104
+ ```json
105
+ {
106
+ "models": [
107
+ {
108
+ "id": "tiny",
109
+ "name": "Tiny",
110
+ "size": "39 MB",
111
+ "languages": "multilingual"
112
+ },
113
+ {
114
+ "id": "base",
115
+ "name": "Base",
116
+ "size": "74 MB",
117
+ "languages": "multilingual"
118
+ },
119
+ {
120
+ "id": "small",
121
+ "name": "Small",
122
+ "size": "244 MB",
123
+ "languages": "multilingual"
124
+ },
125
+ {
126
+ "id": "medium",
127
+ "name": "Medium",
128
+ "size": "769 MB",
129
+ "languages": "multilingual"
130
+ },
131
+ {
132
+ "id": "large",
133
+ "name": "Large",
134
+ "size": "1550 MB",
135
+ "languages": "multilingual"
136
+ }
137
+ ],
138
+ "default": "base"
139
+ }
140
+ ```
141
+
142
+ ### 5. Список поддерживаемых языков
143
+
144
+ **GET** `/languages`
145
+
146
+ Возвращает список поддерживаемых языков.
147
+
148
+ **Ответ:**
149
+ ```json
150
+ {
151
+ "languages": [
152
+ {
153
+ "code": "auto",
154
+ "name": "Автоопределение"
155
+ },
156
+ {
157
+ "code": "ru",
158
+ "name": "Русский"
159
+ },
160
+ {
161
+ "code": "en",
162
+ "name": "English"
163
+ }
164
+ ],
165
+ "default": "auto"
166
+ }
167
+ ```
168
+
169
+ ## Коды ошибок
170
+
171
+ - **400** - Неверный запрос (отсутствует файл, неподдерживаемый формат)
172
+ - **404** - Endpoint не найден
173
+ - **500** - Внутренняя ошибка сервера
174
+
175
+ ## Примеры использования
176
+
177
+ ### Python
178
+
179
+ ```python
180
+ import requests
181
+
182
+ # Транскрипция файла
183
+ with open('audio.mp3', 'rb') as f:
184
+ files = {'audio': f}
185
+ data = {'language': 'ru', 'model': 'base'}
186
+ response = requests.post('http://localhost:3001/api/transcribe', files=files, data=data)
187
+ result = response.json()
188
+ print(result['transcription']['text'])
189
+
190
+ # Транскрипция по URL
191
+ data = {
192
+ 'url': 'https://example.com/audio.mp3',
193
+ 'language': 'ru',
194
+ 'model': 'base'
195
+ }
196
+ response = requests.post('http://localhost:3001/api/transcribe/url', json=data)
197
+ result = response.json()
198
+ print(result['transcription']['text'])
199
+ ```
200
+
201
+ ### JavaScript/Node.js
202
+
203
+ ```javascript
204
+ const FormData = require('form-data');
205
+ const fs = require('fs');
206
+ const axios = require('axios');
207
+
208
+ // Транскрипция файла
209
+ async function transcribeFile(filePath, language = 'ru', model = 'base') {
210
+ const form = new FormData();
211
+ form.append('audio', fs.createReadStream(filePath));
212
+ form.append('language', language);
213
+ form.append('model', model);
214
+
215
+ const response = await axios.post('http://localhost:3001/api/transcribe', form, {
216
+ headers: form.getHeaders()
217
+ });
218
+
219
+ return response.data.transcription.text;
220
+ }
221
+
222
+ // Транскрипция по URL
223
+ async function transcribeUrl(url, language = 'ru', model = 'base') {
224
+ const response = await axios.post('http://localhost:3001/api/transcribe/url', {
225
+ url,
226
+ language,
227
+ model
228
+ });
229
+
230
+ return response.data.transcription.text;
231
+ }
232
+ ```
233
+
234
+ ### C#
235
+
236
+ ```csharp
237
+ using System.Net.Http;
238
+
239
+ // Транскрипция файла
240
+ using var client = new HttpClient();
241
+ using var form = new MultipartFormDataContent();
242
+ using var fileStream = File.OpenRead("audio.mp3");
243
+ form.Add(new StreamContent(fileStream), "audio", "audio.mp3");
244
+ form.Add(new StringContent("ru"), "language");
245
+ form.Add(new StringContent("base"), "model");
246
+
247
+ var response = await client.PostAsync("http://localhost:3001/api/transcribe", form);
248
+ var result = await response.Content.ReadAsStringAsync();
249
+ ```
250
+
251
+ ## Запуск сервера
252
+
253
+ ```bash
254
+ # Только сервер API
255
+ npm run dev:server
256
+
257
+ # Фронтенд + API одновременно
258
+ npm run dev:full
259
+
260
+ # Продакшен режим
261
+ npm run start
262
+ ```
263
+
264
+ ## Примечания
265
+
266
+ - Первый запуск может занять время для загрузки модели Whisper
267
+ - Модели кэшируются в памяти для быстрого доступа
268
+ - Временные файлы автоматически удаляются после обработки
269
+ - API поддерживает CORS для кросс-доменных запросов
Dockerfile ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM node:18-alpine
2
+
3
+ # Устанавливаем рабочую директорию
4
+ WORKDIR /app
5
+
6
+ # Копируем файлы зависимостей
7
+ COPY package*.json ./
8
+
9
+ # Устанавливаем зависимости
10
+ RUN npm install
11
+
12
+ # Копируем исходный код
13
+ COPY . .
14
+
15
+ # Собираем проект
16
+ RUN npm run build
17
+
18
+ # Открываем порт
19
+ EXPOSE 3001
20
+
21
+ # Запускаем сервер
22
+ CMD ["npm", "start"]
README.md CHANGED
@@ -1,30 +1,136 @@
1
- # Whisper Web
2
 
3
- ML-powered speech recognition directly in your browser! Built with [🤗 Transformers.js](https://github.com/xenova/transformers.js).
4
 
5
- Check out the demo site [here](https://huggingface.co/spaces/Xenova/whisper-web).
6
 
7
- > [!IMPORTANT]
8
- > Experimental WebGPU support has been added to [this branch](https://github.com/xenova/whisper-web/tree/experimental-webgpu) ([demo](https://huggingface.co/spaces/Xenova/whisper-webgpu)), if you'd like to run with GPU acceleration!
9
 
10
- https://github.com/xenova/whisper-web/assets/26504141/fb170d84-9678-41b5-9248-a112ecc74c27
 
 
11
 
12
- ## Running locally
 
13
 
14
- 1. Clone the repo and install dependencies:
 
15
 
16
- ```bash
17
- git clone https://github.com/xenova/whisper-web.git
18
- cd whisper-web
19
- npm install
20
- ```
21
 
22
- 2. Run the development server:
 
 
23
 
24
- ```bash
25
- npm run dev
26
- ```
27
- > Firefox users need to change the `dom.workers.modules.enabled` setting in `about:config` to `true` to enable Web Workers.
28
- > Check out [this issue](https://github.com/xenova/whisper-web/issues/8) for more details.
29
 
30
- 3. Open the link (e.g., [http://localhost:5173/](http://localhost:5173/)) in your browser.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Whisper Web - Speech Recognition API
2
 
3
+ Веб-приложение для транскрипции аудио с использованием моделей Whisper, работающее прямо в браузере.
4
 
5
+ ## 🚀 Быстрый старт
6
 
7
+ ### Локальный запуск
 
8
 
9
+ ```bash
10
+ # Установка зависимостей
11
+ npm install
12
 
13
+ # Сборка проекта
14
+ npm run build
15
 
16
+ # Запуск API сервера (порт 3001)
17
+ npm run dev:server
18
 
19
+ # Запуск фронтенда (порт 3000)
20
+ npm run dev
 
 
 
21
 
22
+ # Запуск фронтенда + API одновременно
23
+ npm run dev:full
24
+ ```
25
 
26
+ ### Hugging Face Spaces
 
 
 
 
27
 
28
+ Для запуска на Hugging Face Spaces используйте:
29
+
30
+ ```bash
31
+ # Установка зависимостей
32
+ npm install
33
+
34
+ # Сборка проекта
35
+ npm run build
36
+
37
+ # Запуск сервера
38
+ npm start
39
+ ```
40
+
41
+ ## 📋 API Endpoints
42
+
43
+ ### Базовый URL: `https://your-space.hf.space/api`
44
+
45
+ - **GET** `/health` - проверка здоровья сервера
46
+ - **GET** `/models` - список доступных моделей
47
+ - **GET** `/languages` - список поддерживаемых языков
48
+ - **POST** `/transcribe` - транскрипция аудио файла
49
+ - **POST** `/transcribe/url` - транскрипция аудио по URL
50
+
51
+ ## 🔧 Конфигурация для Hugging Face
52
+
53
+ ### app.py (для Gradio Spaces)
54
+ ```python
55
+ import gradio as gr
56
+ import subprocess
57
+ import os
58
+
59
+ def launch_server():
60
+ subprocess.Popen(["npm", "start"], cwd="whisper-web")
61
+
62
+ # Запускаем сервер при старте
63
+ launch_server()
64
+
65
+ # Создаем Gradio интерфейс
66
+ with gr.Blocks() as demo:
67
+ gr.HTML("""
68
+ <iframe src="http://localhost:3001" width="100%" height="800px"></iframe>
69
+ """)
70
+
71
+ demo.launch()
72
+ ```
73
+
74
+ ### requirements.txt
75
+ ```
76
+ gradio
77
+ ```
78
+
79
+ ### Dockerfile (альтернатива)
80
+ ```dockerfile
81
+ FROM node:18-alpine
82
+
83
+ WORKDIR /app
84
+ COPY package*.json ./
85
+ RUN npm install
86
+
87
+ COPY . .
88
+ RUN npm run build
89
+
90
+ EXPOSE 3001
91
+ CMD ["npm", "start"]
92
+ ```
93
+
94
+ ## 📖 Примеры использования
95
+
96
+ ### Python
97
+ ```python
98
+ import requests
99
+
100
+ # Транскрипция файла
101
+ with open('audio.mp3', 'rb') as f:
102
+ files = {'audio': f}
103
+ data = {'language': 'ru', 'model': 'base'}
104
+ response = requests.post('http://localhost:3001/api/transcribe', files=files, data=data)
105
+ print(response.json()['transcription']['text'])
106
+ ```
107
+
108
+ ### JavaScript
109
+ ```javascript
110
+ // Транскрипция по URL
111
+ const response = await fetch('http://localhost:3001/api/transcribe/url', {
112
+ method: 'POST',
113
+ headers: { 'Content-Type': 'application/json' },
114
+ body: JSON.stringify({
115
+ url: 'https://example.com/audio.mp3',
116
+ language: 'ru',
117
+ model: 'base'
118
+ })
119
+ });
120
+ const result = await response.json();
121
+ ```
122
+
123
+ ## 🛠️ Технологии
124
+
125
+ - **Frontend**: React + TypeScript + Vite
126
+ - **Backend**: Node.js + HTTP Server
127
+ - **AI**: Whisper (OpenAI) via Transformers.js
128
+ - **Styling**: Tailwind CSS
129
+
130
+ ## 📝 Лицензия
131
+
132
+ MIT License
133
+
134
+ ## 👨‍💻 Автор
135
+
136
+ [@naumxv](https://t.me/naumxv)
app.py ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import subprocess
3
+ import os
4
+ import time
5
+ import threading
6
+
7
+ def launch_server():
8
+ """Запускает Node.js сервер в фоновом режиме"""
9
+ try:
10
+ # Устанавливаем зависимости
11
+ subprocess.run(["npm", "install"], cwd=".", check=True)
12
+
13
+ # Собираем проект
14
+ subprocess.run(["npm", "run", "build"], cwd=".", check=True)
15
+
16
+ # Запускаем сервер
17
+ subprocess.Popen(["npm", "start"], cwd=".")
18
+
19
+ print("🚀 Сервер запущен на порту 3001")
20
+ except Exception as e:
21
+ print(f"❌ Ошибка запуска сервера: {e}")
22
+
23
+ def create_interface():
24
+ """Создает Gradio интерфейс"""
25
+ with gr.Blocks(title="Whisper Web API", theme=gr.themes.Soft()) as demo:
26
+ gr.Markdown("""
27
+ # 🎤 Whisper Web API
28
+
29
+ Веб-приложение для транскрипции аудио с использованием моделей Whisper.
30
+
31
+ ## 📋 API Endpoints
32
+
33
+ - **GET** `/api/health` - проверка здоровья сервера
34
+ - **GET** `/api/models` - список доступных моделей
35
+ - **GET** `/api/languages` - список поддерживаемых языков
36
+ - **POST** `/api/transcribe` - транскрипция аудио файла
37
+ - **POST** `/api/transcribe/url` - транскрипция аудио по URL
38
+
39
+ ## 🔗 Ссылки
40
+
41
+ - **API Base URL**: `https://your-space.hf.space/api`
42
+ - **Веб-интерфейс**: `https://your-space.hf.space/`
43
+ """)
44
+
45
+ with gr.Row():
46
+ with gr.Column():
47
+ gr.HTML("""
48
+ <div style="text-align: center; padding: 20px;">
49
+ <h3>🌐 Веб-интерфейс</h3>
50
+ <p>Откройте веб-интерфейс для интерактивной транскрипции:</p>
51
+ <a href="/" target="_blank" style="
52
+ display: inline-block;
53
+ padding: 10px 20px;
54
+ background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);
55
+ color: white;
56
+ text-decoration: none;
57
+ border-radius: 5px;
58
+ font-weight: bold;
59
+ ">Открыть Whisper Web</a>
60
+ </div>
61
+ """)
62
+
63
+ with gr.Column():
64
+ gr.HTML("""
65
+ <div style="text-align: center; padding: 20px;">
66
+ <h3>🔧 API Тестирование</h3>
67
+ <p>Проверьте работу API:</p>
68
+ <a href="/api/health" target="_blank" style="
69
+ display: inline-block;
70
+ padding: 10px 20px;
71
+ background: linear-gradient(45deg, #f093fb 0%, #f5576c 100%);
72
+ color: white;
73
+ text-decoration: none;
74
+ border-radius: 5px;
75
+ font-weight: bold;
76
+ ">Проверить API</a>
77
+ </div>
78
+ """)
79
+
80
+ gr.Markdown("""
81
+ ## 📖 Примеры использования
82
+
83
+ ### Python
84
+ ```python
85
+ import requests
86
+
87
+ # Проверка здоровья
88
+ response = requests.get('https://your-space.hf.space/api/health')
89
+ print(response.json())
90
+
91
+ # Транскрипция файла
92
+ with open('audio.mp3', 'rb') as f:
93
+ files = {'audio': f}
94
+ data = {'language': 'ru', 'model': 'base'}
95
+ response = requests.post('https://your-space.hf.space/api/transcribe',
96
+ files=files, data=data)
97
+ print(response.json()['transcription']['text'])
98
+ ```
99
+
100
+ ### JavaScript
101
+ ```javascript
102
+ // Транскрипция по URL
103
+ const response = await fetch('https://your-space.hf.space/api/transcribe/url', {
104
+ method: 'POST',
105
+ headers: { 'Content-Type': 'application/json' },
106
+ body: JSON.stringify({
107
+ url: 'https://example.com/audio.mp3',
108
+ language: 'ru',
109
+ model: 'base'
110
+ })
111
+ });
112
+ const result = await response.json();
113
+ ```
114
+ """)
115
+
116
+ return demo
117
+
118
+ # Запускаем сервер в отдельном потоке
119
+ server_thread = threading.Thread(target=launch_server, daemon=True)
120
+ server_thread.start()
121
+
122
+ # Ждем немного, чтобы сервер успел запуститься
123
+ time.sleep(5)
124
+
125
+ # Создаем и запускаем Gradio интерфейс
126
+ demo = create_interface()
127
+ demo.launch(
128
+ server_name="0.0.0.0",
129
+ server_port=7860,
130
+ share=False,
131
+ show_error=True
132
+ )
package-lock.json CHANGED
@@ -9,8 +9,15 @@
9
  "version": "0.0.0",
10
  "dependencies": {
11
  "@headlessui/react": "^1.7.13",
 
 
 
12
  "@xenova/transformers": "^2.7.0",
13
  "axios": "^1.3.4",
 
 
 
 
14
  "react": "^18.2.0",
15
  "react-dom": "^18.2.0"
16
  },
@@ -21,6 +28,7 @@
21
  "@typescript-eslint/parser": "^5.57.0",
22
  "@vitejs/plugin-react": "^3.1.0",
23
  "autoprefixer": "^10.4.14",
 
24
  "eslint": "^8.37.0",
25
  "eslint-config-prettier": "^8.8.0",
26
  "eslint-config-standard-with-typescript": "^34.0.1",
@@ -679,6 +687,63 @@
679
  "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
680
  "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
681
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
682
  "node_modules/@types/json-schema": {
683
  "version": "7.0.11",
684
  "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
@@ -691,6 +756,21 @@
691
  "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
692
  "dev": true
693
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
694
  "node_modules/@types/node": {
695
  "version": "20.2.1",
696
  "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.1.tgz",
@@ -702,6 +782,18 @@
702
  "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
703
  "dev": true
704
  },
 
 
 
 
 
 
 
 
 
 
 
 
705
  "node_modules/@types/react": {
706
  "version": "18.2.6",
707
  "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.6.tgz",
@@ -734,6 +826,27 @@
734
  "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==",
735
  "dev": true
736
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
737
  "node_modules/@typescript-eslint/eslint-plugin": {
738
  "version": "5.59.6",
739
  "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.6.tgz",
@@ -953,6 +1066,40 @@
953
  "onnxruntime-node": "1.14.0"
954
  }
955
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
956
  "node_modules/acorn": {
957
  "version": "8.8.2",
958
  "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
@@ -1030,6 +1177,12 @@
1030
  "node": ">= 8"
1031
  }
1032
  },
 
 
 
 
 
 
1033
  "node_modules/arg": {
1034
  "version": "5.0.2",
1035
  "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
@@ -1236,6 +1389,26 @@
1236
  "readable-stream": "^3.4.0"
1237
  }
1238
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1239
  "node_modules/brace-expansion": {
1240
  "version": "1.1.11",
1241
  "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -1309,6 +1482,12 @@
1309
  "ieee754": "^1.1.13"
1310
  }
1311
  },
 
 
 
 
 
 
1312
  "node_modules/builtins": {
1313
  "version": "5.0.1",
1314
  "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
@@ -1318,6 +1497,26 @@
1318
  "semver": "^7.0.0"
1319
  }
1320
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1321
  "node_modules/call-bind": {
1322
  "version": "1.0.2",
1323
  "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
@@ -1331,6 +1530,35 @@
1331
  "url": "https://github.com/sponsors/ljharb"
1332
  }
1333
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1334
  "node_modules/callsites": {
1335
  "version": "3.1.0",
1336
  "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -1350,10 +1578,9 @@
1350
  }
1351
  },
1352
  "node_modules/caniuse-lite": {
1353
- "version": "1.0.30001488",
1354
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001488.tgz",
1355
- "integrity": "sha512-NORIQuuL4xGpIy6iCCQGN4iFjlBXtfKWIenlUuyZJumLRIindLb7wXM+GO8erEhb7vXfcnf4BAg2PrSDN5TNLQ==",
1356
- "dev": true,
1357
  "funding": [
1358
  {
1359
  "type": "opencollective",
@@ -1367,7 +1594,8 @@
1367
  "type": "github",
1368
  "url": "https://github.com/sponsors/ai"
1369
  }
1370
- ]
 
1371
  },
1372
  "node_modules/chalk": {
1373
  "version": "2.4.2",
@@ -1432,6 +1660,21 @@
1432
  "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
1433
  "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
1434
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1435
  "node_modules/color": {
1436
  "version": "4.2.3",
1437
  "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
@@ -1509,12 +1752,197 @@
1509
  "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
1510
  "dev": true
1511
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1512
  "node_modules/convert-source-map": {
1513
  "version": "1.9.0",
1514
  "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
1515
  "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
1516
  "dev": true
1517
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1518
  "node_modules/cross-spawn": {
1519
  "version": "7.0.3",
1520
  "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -1548,12 +1976,12 @@
1548
  "dev": true
1549
  },
1550
  "node_modules/debug": {
1551
- "version": "4.3.4",
1552
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
1553
- "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
1554
- "dev": true,
1555
  "dependencies": {
1556
- "ms": "2.1.2"
1557
  },
1558
  "engines": {
1559
  "node": ">=6.0"
@@ -1616,6 +2044,15 @@
1616
  "node": ">=0.4.0"
1617
  }
1618
  },
 
 
 
 
 
 
 
 
 
1619
  "node_modules/detect-libc": {
1620
  "version": "2.0.1",
1621
  "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
@@ -1660,12 +2097,48 @@
1660
  "node": ">=6.0.0"
1661
  }
1662
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1663
  "node_modules/electron-to-chromium": {
1664
  "version": "1.4.402",
1665
  "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.402.tgz",
1666
  "integrity": "sha512-gWYvJSkohOiBE6ecVYXkrDgNaUjo47QEKK0kQzmWyhkH+yoYiG44bwuicTGNSIQRG3WDMsWVZJLRnJnLNkbWvA==",
1667
  "dev": true
1668
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1669
  "node_modules/end-of-stream": {
1670
  "version": "1.4.4",
1671
  "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
@@ -1722,6 +2195,36 @@
1722
  "url": "https://github.com/sponsors/ljharb"
1723
  }
1724
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1725
  "node_modules/es-set-tostringtag": {
1726
  "version": "2.0.1",
1727
  "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
@@ -1808,6 +2311,12 @@
1808
  "node": ">=6"
1809
  }
1810
  },
 
 
 
 
 
 
1811
  "node_modules/escape-string-regexp": {
1812
  "version": "1.0.5",
1813
  "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
@@ -2429,7 +2938,16 @@
2429
  "node": ">=0.10.0"
2430
  }
2431
  },
2432
- "node_modules/expand-template": {
 
 
 
 
 
 
 
 
 
2433
  "version": "2.0.3",
2434
  "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
2435
  "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
@@ -2437,6 +2955,69 @@
2437
  "node": ">=6"
2438
  }
2439
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2440
  "node_modules/fast-deep-equal": {
2441
  "version": "3.1.3",
2442
  "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -2522,6 +3103,23 @@
2522
  "node": ">=8"
2523
  }
2524
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2525
  "node_modules/find-up": {
2526
  "version": "5.0.0",
2527
  "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@@ -2603,6 +3201,15 @@
2603
  "node": ">= 6"
2604
  }
2605
  },
 
 
 
 
 
 
 
 
 
2606
  "node_modules/fraction.js": {
2607
  "version": "4.2.0",
2608
  "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
@@ -2616,6 +3223,15 @@
2616
  "url": "https://www.patreon.com/infusion"
2617
  }
2618
  },
 
 
 
 
 
 
 
 
 
2619
  "node_modules/fs-constants": {
2620
  "version": "1.0.0",
2621
  "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
@@ -2642,10 +3258,13 @@
2642
  }
2643
  },
2644
  "node_modules/function-bind": {
2645
- "version": "1.1.1",
2646
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
2647
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
2648
- "dev": true
 
 
 
2649
  },
2650
  "node_modules/function.prototype.name": {
2651
  "version": "1.1.5",
@@ -2683,21 +3302,53 @@
2683
  "node": ">=6.9.0"
2684
  }
2685
  },
2686
- "node_modules/get-intrinsic": {
2687
- "version": "1.2.1",
2688
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
2689
- "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
2690
  "dev": true,
2691
- "dependencies": {
2692
- "function-bind": "^1.1.1",
2693
- "has": "^1.0.3",
2694
- "has-proto": "^1.0.1",
2695
- "has-symbols": "^1.0.3"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2696
  },
2697
  "funding": {
2698
  "url": "https://github.com/sponsors/ljharb"
2699
  }
2700
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
2701
  "node_modules/get-symbol-description": {
2702
  "version": "1.0.0",
2703
  "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
@@ -2776,12 +3427,12 @@
2776
  }
2777
  },
2778
  "node_modules/gopd": {
2779
- "version": "1.0.1",
2780
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
2781
- "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
2782
- "dev": true,
2783
- "dependencies": {
2784
- "get-intrinsic": "^1.1.3"
2785
  },
2786
  "funding": {
2787
  "url": "https://github.com/sponsors/ljharb"
@@ -2859,10 +3510,10 @@
2859
  }
2860
  },
2861
  "node_modules/has-symbols": {
2862
- "version": "1.0.3",
2863
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
2864
- "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
2865
- "dev": true,
2866
  "engines": {
2867
  "node": ">= 0.4"
2868
  },
@@ -2885,6 +3536,55 @@
2885
  "url": "https://github.com/sponsors/ljharb"
2886
  }
2887
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2888
  "node_modules/ieee754": {
2889
  "version": "1.2.1",
2890
  "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@@ -2972,6 +3672,15 @@
2972
  "node": ">= 0.4"
2973
  }
2974
  },
 
 
 
 
 
 
 
 
 
2975
  "node_modules/is-array-buffer": {
2976
  "version": "3.0.2",
2977
  "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
@@ -3079,6 +3788,16 @@
3079
  "node": ">=0.10.0"
3080
  }
3081
  },
 
 
 
 
 
 
 
 
 
 
3082
  "node_modules/is-glob": {
3083
  "version": "4.0.3",
3084
  "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@@ -3136,6 +3855,12 @@
3136
  "node": ">=8"
3137
  }
3138
  },
 
 
 
 
 
 
3139
  "node_modules/is-regex": {
3140
  "version": "1.1.4",
3141
  "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
@@ -3349,6 +4074,13 @@
3349
  "url": "https://github.com/sponsors/sindresorhus"
3350
  }
3351
  },
 
 
 
 
 
 
 
3352
  "node_modules/lodash.merge": {
3353
  "version": "4.6.2",
3354
  "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
@@ -3392,6 +4124,36 @@
3392
  "node": ">=12"
3393
  }
3394
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3395
  "node_modules/merge2": {
3396
  "version": "1.4.1",
3397
  "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -3464,16 +4226,68 @@
3464
  "url": "https://github.com/sponsors/ljharb"
3465
  }
3466
  },
 
 
 
 
 
 
 
 
 
 
 
 
3467
  "node_modules/mkdirp-classic": {
3468
  "version": "0.5.3",
3469
  "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
3470
  "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
3471
  },
3472
  "node_modules/ms": {
3473
- "version": "2.1.2",
3474
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
3475
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
3476
- "dev": true
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3477
  },
3478
  "node_modules/mz": {
3479
  "version": "2.7.0",
@@ -3521,6 +4335,15 @@
3521
  "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
3522
  "dev": true
3523
  },
 
 
 
 
 
 
 
 
 
3524
  "node_modules/node-abi": {
3525
  "version": "3.44.0",
3526
  "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.44.0.tgz",
@@ -3565,7 +4388,6 @@
3565
  "version": "4.1.1",
3566
  "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
3567
  "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
3568
- "dev": true,
3569
  "engines": {
3570
  "node": ">=0.10.0"
3571
  }
@@ -3580,10 +4402,13 @@
3580
  }
3581
  },
3582
  "node_modules/object-inspect": {
3583
- "version": "1.12.3",
3584
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
3585
- "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
3586
- "dev": true,
 
 
 
3587
  "funding": {
3588
  "url": "https://github.com/sponsors/ljharb"
3589
  }
@@ -3676,6 +4501,18 @@
3676
  "url": "https://github.com/sponsors/ljharb"
3677
  }
3678
  },
 
 
 
 
 
 
 
 
 
 
 
 
3679
  "node_modules/once": {
3680
  "version": "1.4.0",
3681
  "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -3783,6 +4620,15 @@
3783
  "node": ">=6"
3784
  }
3785
  },
 
 
 
 
 
 
 
 
 
3786
  "node_modules/path-exists": {
3787
  "version": "4.0.0",
3788
  "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -3816,6 +4662,15 @@
3816
  "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
3817
  "dev": true
3818
  },
 
 
 
 
 
 
 
 
 
3819
  "node_modules/path-type": {
3820
  "version": "4.0.0",
3821
  "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
@@ -4097,6 +4952,19 @@
4097
  "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
4098
  "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
4099
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
4100
  "node_modules/proxy-from-env": {
4101
  "version": "1.1.0",
4102
  "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
@@ -4120,6 +4988,21 @@
4120
  "node": ">=6"
4121
  }
4122
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4123
  "node_modules/queue-microtask": {
4124
  "version": "1.2.3",
4125
  "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -4140,6 +5023,30 @@
4140
  }
4141
  ]
4142
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4143
  "node_modules/rc": {
4144
  "version": "1.2.8",
4145
  "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
@@ -4263,6 +5170,16 @@
4263
  "url": "https://github.com/sponsors/mysticatea"
4264
  }
4265
  },
 
 
 
 
 
 
 
 
 
 
4266
  "node_modules/resolve": {
4267
  "version": "1.22.2",
4268
  "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
@@ -4350,6 +5267,22 @@
4350
  "fsevents": "~2.3.2"
4351
  }
4352
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4353
  "node_modules/run-parallel": {
4354
  "version": "1.2.0",
4355
  "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -4373,6 +5306,23 @@
4373
  "queue-microtask": "^1.2.2"
4374
  }
4375
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4376
  "node_modules/safe-buffer": {
4377
  "version": "5.2.1",
4378
  "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -4406,6 +5356,12 @@
4406
  "url": "https://github.com/sponsors/ljharb"
4407
  }
4408
  },
 
 
 
 
 
 
4409
  "node_modules/scheduler": {
4410
  "version": "0.23.0",
4411
  "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
@@ -4444,6 +5400,70 @@
4444
  "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
4445
  "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
4446
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4447
  "node_modules/sharp": {
4448
  "version": "0.32.1",
4449
  "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.1.tgz",
@@ -4487,15 +5507,86 @@
4487
  "node": ">=8"
4488
  }
4489
  },
4490
- "node_modules/side-channel": {
4491
- "version": "1.0.4",
4492
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
4493
- "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
4494
  "dev": true,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4495
  "dependencies": {
4496
- "call-bind": "^1.0.0",
4497
- "get-intrinsic": "^1.0.2",
4498
- "object-inspect": "^1.9.0"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4499
  },
4500
  "funding": {
4501
  "url": "https://github.com/sponsors/ljharb"
@@ -4570,6 +5661,23 @@
4570
  "node": ">=0.10.0"
4571
  }
4572
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4573
  "node_modules/string_decoder": {
4574
  "version": "1.3.0",
4575
  "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
@@ -4578,6 +5686,21 @@
4578
  "safe-buffer": "~5.2.0"
4579
  }
4580
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4581
  "node_modules/string.prototype.matchall": {
4582
  "version": "4.0.8",
4583
  "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz",
@@ -4853,6 +5976,25 @@
4853
  "node": ">=8.0"
4854
  }
4855
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4856
  "node_modules/ts-interface-checker": {
4857
  "version": "0.1.13",
4858
  "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
@@ -4939,6 +6081,41 @@
4939
  "url": "https://github.com/sponsors/sindresorhus"
4940
  }
4941
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4942
  "node_modules/typed-array-length": {
4943
  "version": "1.0.4",
4944
  "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
@@ -4953,6 +6130,12 @@
4953
  "url": "https://github.com/sponsors/ljharb"
4954
  }
4955
  },
 
 
 
 
 
 
4956
  "node_modules/typescript": {
4957
  "version": "4.9.5",
4958
  "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
@@ -4981,6 +6164,15 @@
4981
  "url": "https://github.com/sponsors/ljharb"
4982
  }
4983
  },
 
 
 
 
 
 
 
 
 
4984
  "node_modules/update-browserslist-db": {
4985
  "version": "1.0.11",
4986
  "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz",
@@ -5025,6 +6217,15 @@
5025
  "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
5026
  "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
5027
  },
 
 
 
 
 
 
 
 
 
5028
  "node_modules/vite": {
5029
  "version": "4.3.9",
5030
  "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz",
@@ -5124,11 +6325,84 @@
5124
  "url": "https://github.com/sponsors/ljharb"
5125
  }
5126
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5127
  "node_modules/wrappy": {
5128
  "version": "1.0.2",
5129
  "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
5130
  "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
5131
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5132
  "node_modules/yallist": {
5133
  "version": "3.1.1",
5134
  "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
@@ -5144,6 +6418,35 @@
5144
  "node": ">= 14"
5145
  }
5146
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5147
  "node_modules/yocto-queue": {
5148
  "version": "0.1.0",
5149
  "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
 
9
  "version": "0.0.0",
10
  "dependencies": {
11
  "@headlessui/react": "^1.7.13",
12
+ "@types/cors": "^2.8.19",
13
+ "@types/express": "^5.0.3",
14
+ "@types/multer": "^2.0.0",
15
  "@xenova/transformers": "^2.7.0",
16
  "axios": "^1.3.4",
17
+ "caniuse-lite": "^1.0.30001727",
18
+ "cors": "^2.8.5",
19
+ "express": "^5.1.0",
20
+ "multer": "^2.0.1",
21
  "react": "^18.2.0",
22
  "react-dom": "^18.2.0"
23
  },
 
28
  "@typescript-eslint/parser": "^5.57.0",
29
  "@vitejs/plugin-react": "^3.1.0",
30
  "autoprefixer": "^10.4.14",
31
+ "concurrently": "^9.2.0",
32
  "eslint": "^8.37.0",
33
  "eslint-config-prettier": "^8.8.0",
34
  "eslint-config-standard-with-typescript": "^34.0.1",
 
687
  "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
688
  "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
689
  },
690
+ "node_modules/@types/body-parser": {
691
+ "version": "1.19.6",
692
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
693
+ "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==",
694
+ "license": "MIT",
695
+ "dependencies": {
696
+ "@types/connect": "*",
697
+ "@types/node": "*"
698
+ }
699
+ },
700
+ "node_modules/@types/connect": {
701
+ "version": "3.4.38",
702
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
703
+ "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
704
+ "license": "MIT",
705
+ "dependencies": {
706
+ "@types/node": "*"
707
+ }
708
+ },
709
+ "node_modules/@types/cors": {
710
+ "version": "2.8.19",
711
+ "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz",
712
+ "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==",
713
+ "license": "MIT",
714
+ "dependencies": {
715
+ "@types/node": "*"
716
+ }
717
+ },
718
+ "node_modules/@types/express": {
719
+ "version": "5.0.3",
720
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz",
721
+ "integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==",
722
+ "license": "MIT",
723
+ "dependencies": {
724
+ "@types/body-parser": "*",
725
+ "@types/express-serve-static-core": "^5.0.0",
726
+ "@types/serve-static": "*"
727
+ }
728
+ },
729
+ "node_modules/@types/express-serve-static-core": {
730
+ "version": "5.0.7",
731
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz",
732
+ "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==",
733
+ "license": "MIT",
734
+ "dependencies": {
735
+ "@types/node": "*",
736
+ "@types/qs": "*",
737
+ "@types/range-parser": "*",
738
+ "@types/send": "*"
739
+ }
740
+ },
741
+ "node_modules/@types/http-errors": {
742
+ "version": "2.0.5",
743
+ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
744
+ "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
745
+ "license": "MIT"
746
+ },
747
  "node_modules/@types/json-schema": {
748
  "version": "7.0.11",
749
  "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
 
756
  "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
757
  "dev": true
758
  },
759
+ "node_modules/@types/mime": {
760
+ "version": "1.3.5",
761
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
762
+ "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
763
+ "license": "MIT"
764
+ },
765
+ "node_modules/@types/multer": {
766
+ "version": "2.0.0",
767
+ "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.0.0.tgz",
768
+ "integrity": "sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==",
769
+ "license": "MIT",
770
+ "dependencies": {
771
+ "@types/express": "*"
772
+ }
773
+ },
774
  "node_modules/@types/node": {
775
  "version": "20.2.1",
776
  "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.1.tgz",
 
782
  "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
783
  "dev": true
784
  },
785
+ "node_modules/@types/qs": {
786
+ "version": "6.14.0",
787
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz",
788
+ "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==",
789
+ "license": "MIT"
790
+ },
791
+ "node_modules/@types/range-parser": {
792
+ "version": "1.2.7",
793
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
794
+ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
795
+ "license": "MIT"
796
+ },
797
  "node_modules/@types/react": {
798
  "version": "18.2.6",
799
  "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.6.tgz",
 
826
  "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==",
827
  "dev": true
828
  },
829
+ "node_modules/@types/send": {
830
+ "version": "0.17.5",
831
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz",
832
+ "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==",
833
+ "license": "MIT",
834
+ "dependencies": {
835
+ "@types/mime": "^1",
836
+ "@types/node": "*"
837
+ }
838
+ },
839
+ "node_modules/@types/serve-static": {
840
+ "version": "1.15.8",
841
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz",
842
+ "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==",
843
+ "license": "MIT",
844
+ "dependencies": {
845
+ "@types/http-errors": "*",
846
+ "@types/node": "*",
847
+ "@types/send": "*"
848
+ }
849
+ },
850
  "node_modules/@typescript-eslint/eslint-plugin": {
851
  "version": "5.59.6",
852
  "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.6.tgz",
 
1066
  "onnxruntime-node": "1.14.0"
1067
  }
1068
  },
1069
+ "node_modules/accepts": {
1070
+ "version": "2.0.0",
1071
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
1072
+ "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
1073
+ "license": "MIT",
1074
+ "dependencies": {
1075
+ "mime-types": "^3.0.0",
1076
+ "negotiator": "^1.0.0"
1077
+ },
1078
+ "engines": {
1079
+ "node": ">= 0.6"
1080
+ }
1081
+ },
1082
+ "node_modules/accepts/node_modules/mime-db": {
1083
+ "version": "1.54.0",
1084
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
1085
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
1086
+ "license": "MIT",
1087
+ "engines": {
1088
+ "node": ">= 0.6"
1089
+ }
1090
+ },
1091
+ "node_modules/accepts/node_modules/mime-types": {
1092
+ "version": "3.0.1",
1093
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
1094
+ "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
1095
+ "license": "MIT",
1096
+ "dependencies": {
1097
+ "mime-db": "^1.54.0"
1098
+ },
1099
+ "engines": {
1100
+ "node": ">= 0.6"
1101
+ }
1102
+ },
1103
  "node_modules/acorn": {
1104
  "version": "8.8.2",
1105
  "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
 
1177
  "node": ">= 8"
1178
  }
1179
  },
1180
+ "node_modules/append-field": {
1181
+ "version": "1.0.0",
1182
+ "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
1183
+ "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==",
1184
+ "license": "MIT"
1185
+ },
1186
  "node_modules/arg": {
1187
  "version": "5.0.2",
1188
  "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
 
1389
  "readable-stream": "^3.4.0"
1390
  }
1391
  },
1392
+ "node_modules/body-parser": {
1393
+ "version": "2.2.0",
1394
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz",
1395
+ "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==",
1396
+ "license": "MIT",
1397
+ "dependencies": {
1398
+ "bytes": "^3.1.2",
1399
+ "content-type": "^1.0.5",
1400
+ "debug": "^4.4.0",
1401
+ "http-errors": "^2.0.0",
1402
+ "iconv-lite": "^0.6.3",
1403
+ "on-finished": "^2.4.1",
1404
+ "qs": "^6.14.0",
1405
+ "raw-body": "^3.0.0",
1406
+ "type-is": "^2.0.0"
1407
+ },
1408
+ "engines": {
1409
+ "node": ">=18"
1410
+ }
1411
+ },
1412
  "node_modules/brace-expansion": {
1413
  "version": "1.1.11",
1414
  "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
 
1482
  "ieee754": "^1.1.13"
1483
  }
1484
  },
1485
+ "node_modules/buffer-from": {
1486
+ "version": "1.1.2",
1487
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
1488
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
1489
+ "license": "MIT"
1490
+ },
1491
  "node_modules/builtins": {
1492
  "version": "5.0.1",
1493
  "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
 
1497
  "semver": "^7.0.0"
1498
  }
1499
  },
1500
+ "node_modules/busboy": {
1501
+ "version": "1.6.0",
1502
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
1503
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
1504
+ "dependencies": {
1505
+ "streamsearch": "^1.1.0"
1506
+ },
1507
+ "engines": {
1508
+ "node": ">=10.16.0"
1509
+ }
1510
+ },
1511
+ "node_modules/bytes": {
1512
+ "version": "3.1.2",
1513
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
1514
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
1515
+ "license": "MIT",
1516
+ "engines": {
1517
+ "node": ">= 0.8"
1518
+ }
1519
+ },
1520
  "node_modules/call-bind": {
1521
  "version": "1.0.2",
1522
  "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
 
1530
  "url": "https://github.com/sponsors/ljharb"
1531
  }
1532
  },
1533
+ "node_modules/call-bind-apply-helpers": {
1534
+ "version": "1.0.2",
1535
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
1536
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
1537
+ "license": "MIT",
1538
+ "dependencies": {
1539
+ "es-errors": "^1.3.0",
1540
+ "function-bind": "^1.1.2"
1541
+ },
1542
+ "engines": {
1543
+ "node": ">= 0.4"
1544
+ }
1545
+ },
1546
+ "node_modules/call-bound": {
1547
+ "version": "1.0.4",
1548
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
1549
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
1550
+ "license": "MIT",
1551
+ "dependencies": {
1552
+ "call-bind-apply-helpers": "^1.0.2",
1553
+ "get-intrinsic": "^1.3.0"
1554
+ },
1555
+ "engines": {
1556
+ "node": ">= 0.4"
1557
+ },
1558
+ "funding": {
1559
+ "url": "https://github.com/sponsors/ljharb"
1560
+ }
1561
+ },
1562
  "node_modules/callsites": {
1563
  "version": "3.1.0",
1564
  "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
 
1578
  }
1579
  },
1580
  "node_modules/caniuse-lite": {
1581
+ "version": "1.0.30001727",
1582
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz",
1583
+ "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==",
 
1584
  "funding": [
1585
  {
1586
  "type": "opencollective",
 
1594
  "type": "github",
1595
  "url": "https://github.com/sponsors/ai"
1596
  }
1597
+ ],
1598
+ "license": "CC-BY-4.0"
1599
  },
1600
  "node_modules/chalk": {
1601
  "version": "2.4.2",
 
1660
  "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
1661
  "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
1662
  },
1663
+ "node_modules/cliui": {
1664
+ "version": "8.0.1",
1665
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
1666
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
1667
+ "dev": true,
1668
+ "license": "ISC",
1669
+ "dependencies": {
1670
+ "string-width": "^4.2.0",
1671
+ "strip-ansi": "^6.0.1",
1672
+ "wrap-ansi": "^7.0.0"
1673
+ },
1674
+ "engines": {
1675
+ "node": ">=12"
1676
+ }
1677
+ },
1678
  "node_modules/color": {
1679
  "version": "4.2.3",
1680
  "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
 
1752
  "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
1753
  "dev": true
1754
  },
1755
+ "node_modules/concat-stream": {
1756
+ "version": "2.0.0",
1757
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
1758
+ "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
1759
+ "engines": [
1760
+ "node >= 6.0"
1761
+ ],
1762
+ "license": "MIT",
1763
+ "dependencies": {
1764
+ "buffer-from": "^1.0.0",
1765
+ "inherits": "^2.0.3",
1766
+ "readable-stream": "^3.0.2",
1767
+ "typedarray": "^0.0.6"
1768
+ }
1769
+ },
1770
+ "node_modules/concurrently": {
1771
+ "version": "9.2.0",
1772
+ "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.0.tgz",
1773
+ "integrity": "sha512-IsB/fiXTupmagMW4MNp2lx2cdSN2FfZq78vF90LBB+zZHArbIQZjQtzXCiXnvTxCZSvXanTqFLWBjw2UkLx1SQ==",
1774
+ "dev": true,
1775
+ "license": "MIT",
1776
+ "dependencies": {
1777
+ "chalk": "^4.1.2",
1778
+ "lodash": "^4.17.21",
1779
+ "rxjs": "^7.8.1",
1780
+ "shell-quote": "^1.8.1",
1781
+ "supports-color": "^8.1.1",
1782
+ "tree-kill": "^1.2.2",
1783
+ "yargs": "^17.7.2"
1784
+ },
1785
+ "bin": {
1786
+ "conc": "dist/bin/concurrently.js",
1787
+ "concurrently": "dist/bin/concurrently.js"
1788
+ },
1789
+ "engines": {
1790
+ "node": ">=18"
1791
+ },
1792
+ "funding": {
1793
+ "url": "https://github.com/open-cli-tools/concurrently?sponsor=1"
1794
+ }
1795
+ },
1796
+ "node_modules/concurrently/node_modules/ansi-styles": {
1797
+ "version": "4.3.0",
1798
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
1799
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
1800
+ "dev": true,
1801
+ "license": "MIT",
1802
+ "dependencies": {
1803
+ "color-convert": "^2.0.1"
1804
+ },
1805
+ "engines": {
1806
+ "node": ">=8"
1807
+ },
1808
+ "funding": {
1809
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
1810
+ }
1811
+ },
1812
+ "node_modules/concurrently/node_modules/chalk": {
1813
+ "version": "4.1.2",
1814
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
1815
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
1816
+ "dev": true,
1817
+ "license": "MIT",
1818
+ "dependencies": {
1819
+ "ansi-styles": "^4.1.0",
1820
+ "supports-color": "^7.1.0"
1821
+ },
1822
+ "engines": {
1823
+ "node": ">=10"
1824
+ },
1825
+ "funding": {
1826
+ "url": "https://github.com/chalk/chalk?sponsor=1"
1827
+ }
1828
+ },
1829
+ "node_modules/concurrently/node_modules/chalk/node_modules/supports-color": {
1830
+ "version": "7.2.0",
1831
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
1832
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
1833
+ "dev": true,
1834
+ "license": "MIT",
1835
+ "dependencies": {
1836
+ "has-flag": "^4.0.0"
1837
+ },
1838
+ "engines": {
1839
+ "node": ">=8"
1840
+ }
1841
+ },
1842
+ "node_modules/concurrently/node_modules/color-convert": {
1843
+ "version": "2.0.1",
1844
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
1845
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
1846
+ "dev": true,
1847
+ "license": "MIT",
1848
+ "dependencies": {
1849
+ "color-name": "~1.1.4"
1850
+ },
1851
+ "engines": {
1852
+ "node": ">=7.0.0"
1853
+ }
1854
+ },
1855
+ "node_modules/concurrently/node_modules/color-name": {
1856
+ "version": "1.1.4",
1857
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
1858
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
1859
+ "dev": true,
1860
+ "license": "MIT"
1861
+ },
1862
+ "node_modules/concurrently/node_modules/has-flag": {
1863
+ "version": "4.0.0",
1864
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
1865
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
1866
+ "dev": true,
1867
+ "license": "MIT",
1868
+ "engines": {
1869
+ "node": ">=8"
1870
+ }
1871
+ },
1872
+ "node_modules/concurrently/node_modules/supports-color": {
1873
+ "version": "8.1.1",
1874
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
1875
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
1876
+ "dev": true,
1877
+ "license": "MIT",
1878
+ "dependencies": {
1879
+ "has-flag": "^4.0.0"
1880
+ },
1881
+ "engines": {
1882
+ "node": ">=10"
1883
+ },
1884
+ "funding": {
1885
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
1886
+ }
1887
+ },
1888
+ "node_modules/content-disposition": {
1889
+ "version": "1.0.0",
1890
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz",
1891
+ "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==",
1892
+ "license": "MIT",
1893
+ "dependencies": {
1894
+ "safe-buffer": "5.2.1"
1895
+ },
1896
+ "engines": {
1897
+ "node": ">= 0.6"
1898
+ }
1899
+ },
1900
+ "node_modules/content-type": {
1901
+ "version": "1.0.5",
1902
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
1903
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
1904
+ "license": "MIT",
1905
+ "engines": {
1906
+ "node": ">= 0.6"
1907
+ }
1908
+ },
1909
  "node_modules/convert-source-map": {
1910
  "version": "1.9.0",
1911
  "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
1912
  "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
1913
  "dev": true
1914
  },
1915
+ "node_modules/cookie": {
1916
+ "version": "0.7.2",
1917
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
1918
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
1919
+ "license": "MIT",
1920
+ "engines": {
1921
+ "node": ">= 0.6"
1922
+ }
1923
+ },
1924
+ "node_modules/cookie-signature": {
1925
+ "version": "1.2.2",
1926
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
1927
+ "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
1928
+ "license": "MIT",
1929
+ "engines": {
1930
+ "node": ">=6.6.0"
1931
+ }
1932
+ },
1933
+ "node_modules/cors": {
1934
+ "version": "2.8.5",
1935
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
1936
+ "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
1937
+ "license": "MIT",
1938
+ "dependencies": {
1939
+ "object-assign": "^4",
1940
+ "vary": "^1"
1941
+ },
1942
+ "engines": {
1943
+ "node": ">= 0.10"
1944
+ }
1945
+ },
1946
  "node_modules/cross-spawn": {
1947
  "version": "7.0.3",
1948
  "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
 
1976
  "dev": true
1977
  },
1978
  "node_modules/debug": {
1979
+ "version": "4.4.1",
1980
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
1981
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
1982
+ "license": "MIT",
1983
  "dependencies": {
1984
+ "ms": "^2.1.3"
1985
  },
1986
  "engines": {
1987
  "node": ">=6.0"
 
2044
  "node": ">=0.4.0"
2045
  }
2046
  },
2047
+ "node_modules/depd": {
2048
+ "version": "2.0.0",
2049
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
2050
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
2051
+ "license": "MIT",
2052
+ "engines": {
2053
+ "node": ">= 0.8"
2054
+ }
2055
+ },
2056
  "node_modules/detect-libc": {
2057
  "version": "2.0.1",
2058
  "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
 
2097
  "node": ">=6.0.0"
2098
  }
2099
  },
2100
+ "node_modules/dunder-proto": {
2101
+ "version": "1.0.1",
2102
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
2103
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
2104
+ "license": "MIT",
2105
+ "dependencies": {
2106
+ "call-bind-apply-helpers": "^1.0.1",
2107
+ "es-errors": "^1.3.0",
2108
+ "gopd": "^1.2.0"
2109
+ },
2110
+ "engines": {
2111
+ "node": ">= 0.4"
2112
+ }
2113
+ },
2114
+ "node_modules/ee-first": {
2115
+ "version": "1.1.1",
2116
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
2117
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
2118
+ "license": "MIT"
2119
+ },
2120
  "node_modules/electron-to-chromium": {
2121
  "version": "1.4.402",
2122
  "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.402.tgz",
2123
  "integrity": "sha512-gWYvJSkohOiBE6ecVYXkrDgNaUjo47QEKK0kQzmWyhkH+yoYiG44bwuicTGNSIQRG3WDMsWVZJLRnJnLNkbWvA==",
2124
  "dev": true
2125
  },
2126
+ "node_modules/emoji-regex": {
2127
+ "version": "8.0.0",
2128
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
2129
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
2130
+ "dev": true,
2131
+ "license": "MIT"
2132
+ },
2133
+ "node_modules/encodeurl": {
2134
+ "version": "2.0.0",
2135
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
2136
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
2137
+ "license": "MIT",
2138
+ "engines": {
2139
+ "node": ">= 0.8"
2140
+ }
2141
+ },
2142
  "node_modules/end-of-stream": {
2143
  "version": "1.4.4",
2144
  "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
 
2195
  "url": "https://github.com/sponsors/ljharb"
2196
  }
2197
  },
2198
+ "node_modules/es-define-property": {
2199
+ "version": "1.0.1",
2200
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
2201
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
2202
+ "license": "MIT",
2203
+ "engines": {
2204
+ "node": ">= 0.4"
2205
+ }
2206
+ },
2207
+ "node_modules/es-errors": {
2208
+ "version": "1.3.0",
2209
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
2210
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
2211
+ "license": "MIT",
2212
+ "engines": {
2213
+ "node": ">= 0.4"
2214
+ }
2215
+ },
2216
+ "node_modules/es-object-atoms": {
2217
+ "version": "1.1.1",
2218
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
2219
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
2220
+ "license": "MIT",
2221
+ "dependencies": {
2222
+ "es-errors": "^1.3.0"
2223
+ },
2224
+ "engines": {
2225
+ "node": ">= 0.4"
2226
+ }
2227
+ },
2228
  "node_modules/es-set-tostringtag": {
2229
  "version": "2.0.1",
2230
  "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
 
2311
  "node": ">=6"
2312
  }
2313
  },
2314
+ "node_modules/escape-html": {
2315
+ "version": "1.0.3",
2316
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
2317
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
2318
+ "license": "MIT"
2319
+ },
2320
  "node_modules/escape-string-regexp": {
2321
  "version": "1.0.5",
2322
  "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
 
2938
  "node": ">=0.10.0"
2939
  }
2940
  },
2941
+ "node_modules/etag": {
2942
+ "version": "1.8.1",
2943
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
2944
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
2945
+ "license": "MIT",
2946
+ "engines": {
2947
+ "node": ">= 0.6"
2948
+ }
2949
+ },
2950
+ "node_modules/expand-template": {
2951
  "version": "2.0.3",
2952
  "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
2953
  "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
 
2955
  "node": ">=6"
2956
  }
2957
  },
2958
+ "node_modules/express": {
2959
+ "version": "5.1.0",
2960
+ "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz",
2961
+ "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==",
2962
+ "license": "MIT",
2963
+ "dependencies": {
2964
+ "accepts": "^2.0.0",
2965
+ "body-parser": "^2.2.0",
2966
+ "content-disposition": "^1.0.0",
2967
+ "content-type": "^1.0.5",
2968
+ "cookie": "^0.7.1",
2969
+ "cookie-signature": "^1.2.1",
2970
+ "debug": "^4.4.0",
2971
+ "encodeurl": "^2.0.0",
2972
+ "escape-html": "^1.0.3",
2973
+ "etag": "^1.8.1",
2974
+ "finalhandler": "^2.1.0",
2975
+ "fresh": "^2.0.0",
2976
+ "http-errors": "^2.0.0",
2977
+ "merge-descriptors": "^2.0.0",
2978
+ "mime-types": "^3.0.0",
2979
+ "on-finished": "^2.4.1",
2980
+ "once": "^1.4.0",
2981
+ "parseurl": "^1.3.3",
2982
+ "proxy-addr": "^2.0.7",
2983
+ "qs": "^6.14.0",
2984
+ "range-parser": "^1.2.1",
2985
+ "router": "^2.2.0",
2986
+ "send": "^1.1.0",
2987
+ "serve-static": "^2.2.0",
2988
+ "statuses": "^2.0.1",
2989
+ "type-is": "^2.0.1",
2990
+ "vary": "^1.1.2"
2991
+ },
2992
+ "engines": {
2993
+ "node": ">= 18"
2994
+ },
2995
+ "funding": {
2996
+ "type": "opencollective",
2997
+ "url": "https://opencollective.com/express"
2998
+ }
2999
+ },
3000
+ "node_modules/express/node_modules/mime-db": {
3001
+ "version": "1.54.0",
3002
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
3003
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
3004
+ "license": "MIT",
3005
+ "engines": {
3006
+ "node": ">= 0.6"
3007
+ }
3008
+ },
3009
+ "node_modules/express/node_modules/mime-types": {
3010
+ "version": "3.0.1",
3011
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
3012
+ "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
3013
+ "license": "MIT",
3014
+ "dependencies": {
3015
+ "mime-db": "^1.54.0"
3016
+ },
3017
+ "engines": {
3018
+ "node": ">= 0.6"
3019
+ }
3020
+ },
3021
  "node_modules/fast-deep-equal": {
3022
  "version": "3.1.3",
3023
  "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
 
3103
  "node": ">=8"
3104
  }
3105
  },
3106
+ "node_modules/finalhandler": {
3107
+ "version": "2.1.0",
3108
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz",
3109
+ "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==",
3110
+ "license": "MIT",
3111
+ "dependencies": {
3112
+ "debug": "^4.4.0",
3113
+ "encodeurl": "^2.0.0",
3114
+ "escape-html": "^1.0.3",
3115
+ "on-finished": "^2.4.1",
3116
+ "parseurl": "^1.3.3",
3117
+ "statuses": "^2.0.1"
3118
+ },
3119
+ "engines": {
3120
+ "node": ">= 0.8"
3121
+ }
3122
+ },
3123
  "node_modules/find-up": {
3124
  "version": "5.0.0",
3125
  "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
 
3201
  "node": ">= 6"
3202
  }
3203
  },
3204
+ "node_modules/forwarded": {
3205
+ "version": "0.2.0",
3206
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
3207
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
3208
+ "license": "MIT",
3209
+ "engines": {
3210
+ "node": ">= 0.6"
3211
+ }
3212
+ },
3213
  "node_modules/fraction.js": {
3214
  "version": "4.2.0",
3215
  "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
 
3223
  "url": "https://www.patreon.com/infusion"
3224
  }
3225
  },
3226
+ "node_modules/fresh": {
3227
+ "version": "2.0.0",
3228
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
3229
+ "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
3230
+ "license": "MIT",
3231
+ "engines": {
3232
+ "node": ">= 0.8"
3233
+ }
3234
+ },
3235
  "node_modules/fs-constants": {
3236
  "version": "1.0.0",
3237
  "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
 
3258
  }
3259
  },
3260
  "node_modules/function-bind": {
3261
+ "version": "1.1.2",
3262
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
3263
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
3264
+ "license": "MIT",
3265
+ "funding": {
3266
+ "url": "https://github.com/sponsors/ljharb"
3267
+ }
3268
  },
3269
  "node_modules/function.prototype.name": {
3270
  "version": "1.1.5",
 
3302
  "node": ">=6.9.0"
3303
  }
3304
  },
3305
+ "node_modules/get-caller-file": {
3306
+ "version": "2.0.5",
3307
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
3308
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
3309
  "dev": true,
3310
+ "license": "ISC",
3311
+ "engines": {
3312
+ "node": "6.* || 8.* || >= 10.*"
3313
+ }
3314
+ },
3315
+ "node_modules/get-intrinsic": {
3316
+ "version": "1.3.0",
3317
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
3318
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
3319
+ "license": "MIT",
3320
+ "dependencies": {
3321
+ "call-bind-apply-helpers": "^1.0.2",
3322
+ "es-define-property": "^1.0.1",
3323
+ "es-errors": "^1.3.0",
3324
+ "es-object-atoms": "^1.1.1",
3325
+ "function-bind": "^1.1.2",
3326
+ "get-proto": "^1.0.1",
3327
+ "gopd": "^1.2.0",
3328
+ "has-symbols": "^1.1.0",
3329
+ "hasown": "^2.0.2",
3330
+ "math-intrinsics": "^1.1.0"
3331
+ },
3332
+ "engines": {
3333
+ "node": ">= 0.4"
3334
  },
3335
  "funding": {
3336
  "url": "https://github.com/sponsors/ljharb"
3337
  }
3338
  },
3339
+ "node_modules/get-proto": {
3340
+ "version": "1.0.1",
3341
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
3342
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
3343
+ "license": "MIT",
3344
+ "dependencies": {
3345
+ "dunder-proto": "^1.0.1",
3346
+ "es-object-atoms": "^1.0.0"
3347
+ },
3348
+ "engines": {
3349
+ "node": ">= 0.4"
3350
+ }
3351
+ },
3352
  "node_modules/get-symbol-description": {
3353
  "version": "1.0.0",
3354
  "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
 
3427
  }
3428
  },
3429
  "node_modules/gopd": {
3430
+ "version": "1.2.0",
3431
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
3432
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
3433
+ "license": "MIT",
3434
+ "engines": {
3435
+ "node": ">= 0.4"
3436
  },
3437
  "funding": {
3438
  "url": "https://github.com/sponsors/ljharb"
 
3510
  }
3511
  },
3512
  "node_modules/has-symbols": {
3513
+ "version": "1.1.0",
3514
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
3515
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
3516
+ "license": "MIT",
3517
  "engines": {
3518
  "node": ">= 0.4"
3519
  },
 
3536
  "url": "https://github.com/sponsors/ljharb"
3537
  }
3538
  },
3539
+ "node_modules/hasown": {
3540
+ "version": "2.0.2",
3541
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
3542
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
3543
+ "license": "MIT",
3544
+ "dependencies": {
3545
+ "function-bind": "^1.1.2"
3546
+ },
3547
+ "engines": {
3548
+ "node": ">= 0.4"
3549
+ }
3550
+ },
3551
+ "node_modules/http-errors": {
3552
+ "version": "2.0.0",
3553
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
3554
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
3555
+ "license": "MIT",
3556
+ "dependencies": {
3557
+ "depd": "2.0.0",
3558
+ "inherits": "2.0.4",
3559
+ "setprototypeof": "1.2.0",
3560
+ "statuses": "2.0.1",
3561
+ "toidentifier": "1.0.1"
3562
+ },
3563
+ "engines": {
3564
+ "node": ">= 0.8"
3565
+ }
3566
+ },
3567
+ "node_modules/http-errors/node_modules/statuses": {
3568
+ "version": "2.0.1",
3569
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
3570
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
3571
+ "license": "MIT",
3572
+ "engines": {
3573
+ "node": ">= 0.8"
3574
+ }
3575
+ },
3576
+ "node_modules/iconv-lite": {
3577
+ "version": "0.6.3",
3578
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
3579
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
3580
+ "license": "MIT",
3581
+ "dependencies": {
3582
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
3583
+ },
3584
+ "engines": {
3585
+ "node": ">=0.10.0"
3586
+ }
3587
+ },
3588
  "node_modules/ieee754": {
3589
  "version": "1.2.1",
3590
  "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
 
3672
  "node": ">= 0.4"
3673
  }
3674
  },
3675
+ "node_modules/ipaddr.js": {
3676
+ "version": "1.9.1",
3677
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
3678
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
3679
+ "license": "MIT",
3680
+ "engines": {
3681
+ "node": ">= 0.10"
3682
+ }
3683
+ },
3684
  "node_modules/is-array-buffer": {
3685
  "version": "3.0.2",
3686
  "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
 
3788
  "node": ">=0.10.0"
3789
  }
3790
  },
3791
+ "node_modules/is-fullwidth-code-point": {
3792
+ "version": "3.0.0",
3793
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
3794
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
3795
+ "dev": true,
3796
+ "license": "MIT",
3797
+ "engines": {
3798
+ "node": ">=8"
3799
+ }
3800
+ },
3801
  "node_modules/is-glob": {
3802
  "version": "4.0.3",
3803
  "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
 
3855
  "node": ">=8"
3856
  }
3857
  },
3858
+ "node_modules/is-promise": {
3859
+ "version": "4.0.0",
3860
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
3861
+ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
3862
+ "license": "MIT"
3863
+ },
3864
  "node_modules/is-regex": {
3865
  "version": "1.1.4",
3866
  "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
 
4074
  "url": "https://github.com/sponsors/sindresorhus"
4075
  }
4076
  },
4077
+ "node_modules/lodash": {
4078
+ "version": "4.17.21",
4079
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
4080
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
4081
+ "dev": true,
4082
+ "license": "MIT"
4083
+ },
4084
  "node_modules/lodash.merge": {
4085
  "version": "4.6.2",
4086
  "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
 
4124
  "node": ">=12"
4125
  }
4126
  },
4127
+ "node_modules/math-intrinsics": {
4128
+ "version": "1.1.0",
4129
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
4130
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
4131
+ "license": "MIT",
4132
+ "engines": {
4133
+ "node": ">= 0.4"
4134
+ }
4135
+ },
4136
+ "node_modules/media-typer": {
4137
+ "version": "1.1.0",
4138
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
4139
+ "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
4140
+ "license": "MIT",
4141
+ "engines": {
4142
+ "node": ">= 0.8"
4143
+ }
4144
+ },
4145
+ "node_modules/merge-descriptors": {
4146
+ "version": "2.0.0",
4147
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
4148
+ "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
4149
+ "license": "MIT",
4150
+ "engines": {
4151
+ "node": ">=18"
4152
+ },
4153
+ "funding": {
4154
+ "url": "https://github.com/sponsors/sindresorhus"
4155
+ }
4156
+ },
4157
  "node_modules/merge2": {
4158
  "version": "1.4.1",
4159
  "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
 
4226
  "url": "https://github.com/sponsors/ljharb"
4227
  }
4228
  },
4229
+ "node_modules/mkdirp": {
4230
+ "version": "0.5.6",
4231
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
4232
+ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
4233
+ "license": "MIT",
4234
+ "dependencies": {
4235
+ "minimist": "^1.2.6"
4236
+ },
4237
+ "bin": {
4238
+ "mkdirp": "bin/cmd.js"
4239
+ }
4240
+ },
4241
  "node_modules/mkdirp-classic": {
4242
  "version": "0.5.3",
4243
  "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
4244
  "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
4245
  },
4246
  "node_modules/ms": {
4247
+ "version": "2.1.3",
4248
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
4249
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
4250
+ "license": "MIT"
4251
+ },
4252
+ "node_modules/multer": {
4253
+ "version": "2.0.1",
4254
+ "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.1.tgz",
4255
+ "integrity": "sha512-Ug8bXeTIUlxurg8xLTEskKShvcKDZALo1THEX5E41pYCD2sCVub5/kIRIGqWNoqV6szyLyQKV6mD4QUrWE5GCQ==",
4256
+ "license": "MIT",
4257
+ "dependencies": {
4258
+ "append-field": "^1.0.0",
4259
+ "busboy": "^1.6.0",
4260
+ "concat-stream": "^2.0.0",
4261
+ "mkdirp": "^0.5.6",
4262
+ "object-assign": "^4.1.1",
4263
+ "type-is": "^1.6.18",
4264
+ "xtend": "^4.0.2"
4265
+ },
4266
+ "engines": {
4267
+ "node": ">= 10.16.0"
4268
+ }
4269
+ },
4270
+ "node_modules/multer/node_modules/media-typer": {
4271
+ "version": "0.3.0",
4272
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
4273
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
4274
+ "license": "MIT",
4275
+ "engines": {
4276
+ "node": ">= 0.6"
4277
+ }
4278
+ },
4279
+ "node_modules/multer/node_modules/type-is": {
4280
+ "version": "1.6.18",
4281
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
4282
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
4283
+ "license": "MIT",
4284
+ "dependencies": {
4285
+ "media-typer": "0.3.0",
4286
+ "mime-types": "~2.1.24"
4287
+ },
4288
+ "engines": {
4289
+ "node": ">= 0.6"
4290
+ }
4291
  },
4292
  "node_modules/mz": {
4293
  "version": "2.7.0",
 
4335
  "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
4336
  "dev": true
4337
  },
4338
+ "node_modules/negotiator": {
4339
+ "version": "1.0.0",
4340
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
4341
+ "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
4342
+ "license": "MIT",
4343
+ "engines": {
4344
+ "node": ">= 0.6"
4345
+ }
4346
+ },
4347
  "node_modules/node-abi": {
4348
  "version": "3.44.0",
4349
  "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.44.0.tgz",
 
4388
  "version": "4.1.1",
4389
  "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
4390
  "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
 
4391
  "engines": {
4392
  "node": ">=0.10.0"
4393
  }
 
4402
  }
4403
  },
4404
  "node_modules/object-inspect": {
4405
+ "version": "1.13.4",
4406
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
4407
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
4408
+ "license": "MIT",
4409
+ "engines": {
4410
+ "node": ">= 0.4"
4411
+ },
4412
  "funding": {
4413
  "url": "https://github.com/sponsors/ljharb"
4414
  }
 
4501
  "url": "https://github.com/sponsors/ljharb"
4502
  }
4503
  },
4504
+ "node_modules/on-finished": {
4505
+ "version": "2.4.1",
4506
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
4507
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
4508
+ "license": "MIT",
4509
+ "dependencies": {
4510
+ "ee-first": "1.1.1"
4511
+ },
4512
+ "engines": {
4513
+ "node": ">= 0.8"
4514
+ }
4515
+ },
4516
  "node_modules/once": {
4517
  "version": "1.4.0",
4518
  "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
 
4620
  "node": ">=6"
4621
  }
4622
  },
4623
+ "node_modules/parseurl": {
4624
+ "version": "1.3.3",
4625
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
4626
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
4627
+ "license": "MIT",
4628
+ "engines": {
4629
+ "node": ">= 0.8"
4630
+ }
4631
+ },
4632
  "node_modules/path-exists": {
4633
  "version": "4.0.0",
4634
  "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
 
4662
  "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
4663
  "dev": true
4664
  },
4665
+ "node_modules/path-to-regexp": {
4666
+ "version": "8.2.0",
4667
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz",
4668
+ "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==",
4669
+ "license": "MIT",
4670
+ "engines": {
4671
+ "node": ">=16"
4672
+ }
4673
+ },
4674
  "node_modules/path-type": {
4675
  "version": "4.0.0",
4676
  "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
 
4952
  "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
4953
  "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
4954
  },
4955
+ "node_modules/proxy-addr": {
4956
+ "version": "2.0.7",
4957
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
4958
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
4959
+ "license": "MIT",
4960
+ "dependencies": {
4961
+ "forwarded": "0.2.0",
4962
+ "ipaddr.js": "1.9.1"
4963
+ },
4964
+ "engines": {
4965
+ "node": ">= 0.10"
4966
+ }
4967
+ },
4968
  "node_modules/proxy-from-env": {
4969
  "version": "1.1.0",
4970
  "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
 
4988
  "node": ">=6"
4989
  }
4990
  },
4991
+ "node_modules/qs": {
4992
+ "version": "6.14.0",
4993
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
4994
+ "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
4995
+ "license": "BSD-3-Clause",
4996
+ "dependencies": {
4997
+ "side-channel": "^1.1.0"
4998
+ },
4999
+ "engines": {
5000
+ "node": ">=0.6"
5001
+ },
5002
+ "funding": {
5003
+ "url": "https://github.com/sponsors/ljharb"
5004
+ }
5005
+ },
5006
  "node_modules/queue-microtask": {
5007
  "version": "1.2.3",
5008
  "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
 
5023
  }
5024
  ]
5025
  },
5026
+ "node_modules/range-parser": {
5027
+ "version": "1.2.1",
5028
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
5029
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
5030
+ "license": "MIT",
5031
+ "engines": {
5032
+ "node": ">= 0.6"
5033
+ }
5034
+ },
5035
+ "node_modules/raw-body": {
5036
+ "version": "3.0.0",
5037
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz",
5038
+ "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==",
5039
+ "license": "MIT",
5040
+ "dependencies": {
5041
+ "bytes": "3.1.2",
5042
+ "http-errors": "2.0.0",
5043
+ "iconv-lite": "0.6.3",
5044
+ "unpipe": "1.0.0"
5045
+ },
5046
+ "engines": {
5047
+ "node": ">= 0.8"
5048
+ }
5049
+ },
5050
  "node_modules/rc": {
5051
  "version": "1.2.8",
5052
  "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
 
5170
  "url": "https://github.com/sponsors/mysticatea"
5171
  }
5172
  },
5173
+ "node_modules/require-directory": {
5174
+ "version": "2.1.1",
5175
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
5176
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
5177
+ "dev": true,
5178
+ "license": "MIT",
5179
+ "engines": {
5180
+ "node": ">=0.10.0"
5181
+ }
5182
+ },
5183
  "node_modules/resolve": {
5184
  "version": "1.22.2",
5185
  "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
 
5267
  "fsevents": "~2.3.2"
5268
  }
5269
  },
5270
+ "node_modules/router": {
5271
+ "version": "2.2.0",
5272
+ "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
5273
+ "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
5274
+ "license": "MIT",
5275
+ "dependencies": {
5276
+ "debug": "^4.4.0",
5277
+ "depd": "^2.0.0",
5278
+ "is-promise": "^4.0.0",
5279
+ "parseurl": "^1.3.3",
5280
+ "path-to-regexp": "^8.0.0"
5281
+ },
5282
+ "engines": {
5283
+ "node": ">= 18"
5284
+ }
5285
+ },
5286
  "node_modules/run-parallel": {
5287
  "version": "1.2.0",
5288
  "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
 
5306
  "queue-microtask": "^1.2.2"
5307
  }
5308
  },
5309
+ "node_modules/rxjs": {
5310
+ "version": "7.8.2",
5311
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
5312
+ "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
5313
+ "dev": true,
5314
+ "license": "Apache-2.0",
5315
+ "dependencies": {
5316
+ "tslib": "^2.1.0"
5317
+ }
5318
+ },
5319
+ "node_modules/rxjs/node_modules/tslib": {
5320
+ "version": "2.8.1",
5321
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
5322
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
5323
+ "dev": true,
5324
+ "license": "0BSD"
5325
+ },
5326
  "node_modules/safe-buffer": {
5327
  "version": "5.2.1",
5328
  "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
 
5356
  "url": "https://github.com/sponsors/ljharb"
5357
  }
5358
  },
5359
+ "node_modules/safer-buffer": {
5360
+ "version": "2.1.2",
5361
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
5362
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
5363
+ "license": "MIT"
5364
+ },
5365
  "node_modules/scheduler": {
5366
  "version": "0.23.0",
5367
  "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
 
5400
  "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
5401
  "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
5402
  },
5403
+ "node_modules/send": {
5404
+ "version": "1.2.0",
5405
+ "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz",
5406
+ "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==",
5407
+ "license": "MIT",
5408
+ "dependencies": {
5409
+ "debug": "^4.3.5",
5410
+ "encodeurl": "^2.0.0",
5411
+ "escape-html": "^1.0.3",
5412
+ "etag": "^1.8.1",
5413
+ "fresh": "^2.0.0",
5414
+ "http-errors": "^2.0.0",
5415
+ "mime-types": "^3.0.1",
5416
+ "ms": "^2.1.3",
5417
+ "on-finished": "^2.4.1",
5418
+ "range-parser": "^1.2.1",
5419
+ "statuses": "^2.0.1"
5420
+ },
5421
+ "engines": {
5422
+ "node": ">= 18"
5423
+ }
5424
+ },
5425
+ "node_modules/send/node_modules/mime-db": {
5426
+ "version": "1.54.0",
5427
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
5428
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
5429
+ "license": "MIT",
5430
+ "engines": {
5431
+ "node": ">= 0.6"
5432
+ }
5433
+ },
5434
+ "node_modules/send/node_modules/mime-types": {
5435
+ "version": "3.0.1",
5436
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
5437
+ "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
5438
+ "license": "MIT",
5439
+ "dependencies": {
5440
+ "mime-db": "^1.54.0"
5441
+ },
5442
+ "engines": {
5443
+ "node": ">= 0.6"
5444
+ }
5445
+ },
5446
+ "node_modules/serve-static": {
5447
+ "version": "2.2.0",
5448
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz",
5449
+ "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==",
5450
+ "license": "MIT",
5451
+ "dependencies": {
5452
+ "encodeurl": "^2.0.0",
5453
+ "escape-html": "^1.0.3",
5454
+ "parseurl": "^1.3.3",
5455
+ "send": "^1.2.0"
5456
+ },
5457
+ "engines": {
5458
+ "node": ">= 18"
5459
+ }
5460
+ },
5461
+ "node_modules/setprototypeof": {
5462
+ "version": "1.2.0",
5463
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
5464
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
5465
+ "license": "ISC"
5466
+ },
5467
  "node_modules/sharp": {
5468
  "version": "0.32.1",
5469
  "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.1.tgz",
 
5507
  "node": ">=8"
5508
  }
5509
  },
5510
+ "node_modules/shell-quote": {
5511
+ "version": "1.8.3",
5512
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz",
5513
+ "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==",
5514
  "dev": true,
5515
+ "license": "MIT",
5516
+ "engines": {
5517
+ "node": ">= 0.4"
5518
+ },
5519
+ "funding": {
5520
+ "url": "https://github.com/sponsors/ljharb"
5521
+ }
5522
+ },
5523
+ "node_modules/side-channel": {
5524
+ "version": "1.1.0",
5525
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
5526
+ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
5527
+ "license": "MIT",
5528
+ "dependencies": {
5529
+ "es-errors": "^1.3.0",
5530
+ "object-inspect": "^1.13.3",
5531
+ "side-channel-list": "^1.0.0",
5532
+ "side-channel-map": "^1.0.1",
5533
+ "side-channel-weakmap": "^1.0.2"
5534
+ },
5535
+ "engines": {
5536
+ "node": ">= 0.4"
5537
+ },
5538
+ "funding": {
5539
+ "url": "https://github.com/sponsors/ljharb"
5540
+ }
5541
+ },
5542
+ "node_modules/side-channel-list": {
5543
+ "version": "1.0.0",
5544
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
5545
+ "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
5546
+ "license": "MIT",
5547
  "dependencies": {
5548
+ "es-errors": "^1.3.0",
5549
+ "object-inspect": "^1.13.3"
5550
+ },
5551
+ "engines": {
5552
+ "node": ">= 0.4"
5553
+ },
5554
+ "funding": {
5555
+ "url": "https://github.com/sponsors/ljharb"
5556
+ }
5557
+ },
5558
+ "node_modules/side-channel-map": {
5559
+ "version": "1.0.1",
5560
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
5561
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
5562
+ "license": "MIT",
5563
+ "dependencies": {
5564
+ "call-bound": "^1.0.2",
5565
+ "es-errors": "^1.3.0",
5566
+ "get-intrinsic": "^1.2.5",
5567
+ "object-inspect": "^1.13.3"
5568
+ },
5569
+ "engines": {
5570
+ "node": ">= 0.4"
5571
+ },
5572
+ "funding": {
5573
+ "url": "https://github.com/sponsors/ljharb"
5574
+ }
5575
+ },
5576
+ "node_modules/side-channel-weakmap": {
5577
+ "version": "1.0.2",
5578
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
5579
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
5580
+ "license": "MIT",
5581
+ "dependencies": {
5582
+ "call-bound": "^1.0.2",
5583
+ "es-errors": "^1.3.0",
5584
+ "get-intrinsic": "^1.2.5",
5585
+ "object-inspect": "^1.13.3",
5586
+ "side-channel-map": "^1.0.1"
5587
+ },
5588
+ "engines": {
5589
+ "node": ">= 0.4"
5590
  },
5591
  "funding": {
5592
  "url": "https://github.com/sponsors/ljharb"
 
5661
  "node": ">=0.10.0"
5662
  }
5663
  },
5664
+ "node_modules/statuses": {
5665
+ "version": "2.0.2",
5666
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
5667
+ "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
5668
+ "license": "MIT",
5669
+ "engines": {
5670
+ "node": ">= 0.8"
5671
+ }
5672
+ },
5673
+ "node_modules/streamsearch": {
5674
+ "version": "1.1.0",
5675
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
5676
+ "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
5677
+ "engines": {
5678
+ "node": ">=10.0.0"
5679
+ }
5680
+ },
5681
  "node_modules/string_decoder": {
5682
  "version": "1.3.0",
5683
  "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
 
5686
  "safe-buffer": "~5.2.0"
5687
  }
5688
  },
5689
+ "node_modules/string-width": {
5690
+ "version": "4.2.3",
5691
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
5692
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
5693
+ "dev": true,
5694
+ "license": "MIT",
5695
+ "dependencies": {
5696
+ "emoji-regex": "^8.0.0",
5697
+ "is-fullwidth-code-point": "^3.0.0",
5698
+ "strip-ansi": "^6.0.1"
5699
+ },
5700
+ "engines": {
5701
+ "node": ">=8"
5702
+ }
5703
+ },
5704
  "node_modules/string.prototype.matchall": {
5705
  "version": "4.0.8",
5706
  "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz",
 
5976
  "node": ">=8.0"
5977
  }
5978
  },
5979
+ "node_modules/toidentifier": {
5980
+ "version": "1.0.1",
5981
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
5982
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
5983
+ "license": "MIT",
5984
+ "engines": {
5985
+ "node": ">=0.6"
5986
+ }
5987
+ },
5988
+ "node_modules/tree-kill": {
5989
+ "version": "1.2.2",
5990
+ "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
5991
+ "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
5992
+ "dev": true,
5993
+ "license": "MIT",
5994
+ "bin": {
5995
+ "tree-kill": "cli.js"
5996
+ }
5997
+ },
5998
  "node_modules/ts-interface-checker": {
5999
  "version": "0.1.13",
6000
  "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
 
6081
  "url": "https://github.com/sponsors/sindresorhus"
6082
  }
6083
  },
6084
+ "node_modules/type-is": {
6085
+ "version": "2.0.1",
6086
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
6087
+ "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
6088
+ "license": "MIT",
6089
+ "dependencies": {
6090
+ "content-type": "^1.0.5",
6091
+ "media-typer": "^1.1.0",
6092
+ "mime-types": "^3.0.0"
6093
+ },
6094
+ "engines": {
6095
+ "node": ">= 0.6"
6096
+ }
6097
+ },
6098
+ "node_modules/type-is/node_modules/mime-db": {
6099
+ "version": "1.54.0",
6100
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
6101
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
6102
+ "license": "MIT",
6103
+ "engines": {
6104
+ "node": ">= 0.6"
6105
+ }
6106
+ },
6107
+ "node_modules/type-is/node_modules/mime-types": {
6108
+ "version": "3.0.1",
6109
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
6110
+ "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
6111
+ "license": "MIT",
6112
+ "dependencies": {
6113
+ "mime-db": "^1.54.0"
6114
+ },
6115
+ "engines": {
6116
+ "node": ">= 0.6"
6117
+ }
6118
+ },
6119
  "node_modules/typed-array-length": {
6120
  "version": "1.0.4",
6121
  "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
 
6130
  "url": "https://github.com/sponsors/ljharb"
6131
  }
6132
  },
6133
+ "node_modules/typedarray": {
6134
+ "version": "0.0.6",
6135
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
6136
+ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
6137
+ "license": "MIT"
6138
+ },
6139
  "node_modules/typescript": {
6140
  "version": "4.9.5",
6141
  "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
 
6164
  "url": "https://github.com/sponsors/ljharb"
6165
  }
6166
  },
6167
+ "node_modules/unpipe": {
6168
+ "version": "1.0.0",
6169
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
6170
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
6171
+ "license": "MIT",
6172
+ "engines": {
6173
+ "node": ">= 0.8"
6174
+ }
6175
+ },
6176
  "node_modules/update-browserslist-db": {
6177
  "version": "1.0.11",
6178
  "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz",
 
6217
  "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
6218
  "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
6219
  },
6220
+ "node_modules/vary": {
6221
+ "version": "1.1.2",
6222
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
6223
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
6224
+ "license": "MIT",
6225
+ "engines": {
6226
+ "node": ">= 0.8"
6227
+ }
6228
+ },
6229
  "node_modules/vite": {
6230
  "version": "4.3.9",
6231
  "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz",
 
6325
  "url": "https://github.com/sponsors/ljharb"
6326
  }
6327
  },
6328
+ "node_modules/wrap-ansi": {
6329
+ "version": "7.0.0",
6330
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
6331
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
6332
+ "dev": true,
6333
+ "license": "MIT",
6334
+ "dependencies": {
6335
+ "ansi-styles": "^4.0.0",
6336
+ "string-width": "^4.1.0",
6337
+ "strip-ansi": "^6.0.0"
6338
+ },
6339
+ "engines": {
6340
+ "node": ">=10"
6341
+ },
6342
+ "funding": {
6343
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
6344
+ }
6345
+ },
6346
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
6347
+ "version": "4.3.0",
6348
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
6349
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
6350
+ "dev": true,
6351
+ "license": "MIT",
6352
+ "dependencies": {
6353
+ "color-convert": "^2.0.1"
6354
+ },
6355
+ "engines": {
6356
+ "node": ">=8"
6357
+ },
6358
+ "funding": {
6359
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
6360
+ }
6361
+ },
6362
+ "node_modules/wrap-ansi/node_modules/color-convert": {
6363
+ "version": "2.0.1",
6364
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
6365
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
6366
+ "dev": true,
6367
+ "license": "MIT",
6368
+ "dependencies": {
6369
+ "color-name": "~1.1.4"
6370
+ },
6371
+ "engines": {
6372
+ "node": ">=7.0.0"
6373
+ }
6374
+ },
6375
+ "node_modules/wrap-ansi/node_modules/color-name": {
6376
+ "version": "1.1.4",
6377
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
6378
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
6379
+ "dev": true,
6380
+ "license": "MIT"
6381
+ },
6382
  "node_modules/wrappy": {
6383
  "version": "1.0.2",
6384
  "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
6385
  "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
6386
  },
6387
+ "node_modules/xtend": {
6388
+ "version": "4.0.2",
6389
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
6390
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
6391
+ "license": "MIT",
6392
+ "engines": {
6393
+ "node": ">=0.4"
6394
+ }
6395
+ },
6396
+ "node_modules/y18n": {
6397
+ "version": "5.0.8",
6398
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
6399
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
6400
+ "dev": true,
6401
+ "license": "ISC",
6402
+ "engines": {
6403
+ "node": ">=10"
6404
+ }
6405
+ },
6406
  "node_modules/yallist": {
6407
  "version": "3.1.1",
6408
  "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
 
6418
  "node": ">= 14"
6419
  }
6420
  },
6421
+ "node_modules/yargs": {
6422
+ "version": "17.7.2",
6423
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
6424
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
6425
+ "dev": true,
6426
+ "license": "MIT",
6427
+ "dependencies": {
6428
+ "cliui": "^8.0.1",
6429
+ "escalade": "^3.1.1",
6430
+ "get-caller-file": "^2.0.5",
6431
+ "require-directory": "^2.1.1",
6432
+ "string-width": "^4.2.3",
6433
+ "y18n": "^5.0.5",
6434
+ "yargs-parser": "^21.1.1"
6435
+ },
6436
+ "engines": {
6437
+ "node": ">=12"
6438
+ }
6439
+ },
6440
+ "node_modules/yargs-parser": {
6441
+ "version": "21.1.1",
6442
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
6443
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
6444
+ "dev": true,
6445
+ "license": "ISC",
6446
+ "engines": {
6447
+ "node": ">=12"
6448
+ }
6449
+ },
6450
  "node_modules/yocto-queue": {
6451
  "version": "0.1.0",
6452
  "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
package.json CHANGED
@@ -5,9 +5,12 @@
5
  "type": "module",
6
  "scripts": {
7
  "dev": "vite",
 
 
8
  "clean": "rm -rf node_modules/ dist/",
9
  "build": "tsc && vite build",
10
  "preview": "vite preview",
 
11
  "lint": "eslint src/**/*.{js,jsx,ts,tsx,json}",
12
  "lint:fix": "eslint --fix src/**/*.{js,jsx,ts,tsx,json}",
13
  "format": "prettier --write src/**/*.{js,jsx,ts,tsx,css,md,json} --config ./.prettierrc",
@@ -15,8 +18,15 @@
15
  },
16
  "dependencies": {
17
  "@headlessui/react": "^1.7.13",
 
 
 
18
  "@xenova/transformers": "^2.7.0",
19
  "axios": "^1.3.4",
 
 
 
 
20
  "react": "^18.2.0",
21
  "react-dom": "^18.2.0"
22
  },
@@ -27,6 +37,7 @@
27
  "@typescript-eslint/parser": "^5.57.0",
28
  "@vitejs/plugin-react": "^3.1.0",
29
  "autoprefixer": "^10.4.14",
 
30
  "eslint": "^8.37.0",
31
  "eslint-config-prettier": "^8.8.0",
32
  "eslint-config-standard-with-typescript": "^34.0.1",
 
5
  "type": "module",
6
  "scripts": {
7
  "dev": "vite",
8
+ "dev:server": "node server/simple-server.js",
9
+ "dev:full": "concurrently \"npm run dev\" \"npm run dev:server\"",
10
  "clean": "rm -rf node_modules/ dist/",
11
  "build": "tsc && vite build",
12
  "preview": "vite preview",
13
+ "start": "node server/simple-server.js",
14
  "lint": "eslint src/**/*.{js,jsx,ts,tsx,json}",
15
  "lint:fix": "eslint --fix src/**/*.{js,jsx,ts,tsx,json}",
16
  "format": "prettier --write src/**/*.{js,jsx,ts,tsx,css,md,json} --config ./.prettierrc",
 
18
  },
19
  "dependencies": {
20
  "@headlessui/react": "^1.7.13",
21
+ "@types/cors": "^2.8.19",
22
+ "@types/express": "^5.0.3",
23
+ "@types/multer": "^2.0.0",
24
  "@xenova/transformers": "^2.7.0",
25
  "axios": "^1.3.4",
26
+ "caniuse-lite": "^1.0.30001727",
27
+ "cors": "^2.8.5",
28
+ "express": "^5.1.0",
29
+ "multer": "^2.0.1",
30
  "react": "^18.2.0",
31
  "react-dom": "^18.2.0"
32
  },
 
37
  "@typescript-eslint/parser": "^5.57.0",
38
  "@vitejs/plugin-react": "^3.1.0",
39
  "autoprefixer": "^10.4.14",
40
+ "concurrently": "^9.2.0",
41
  "eslint": "^8.37.0",
42
  "eslint-config-prettier": "^8.8.0",
43
  "eslint-config-standard-with-typescript": "^34.0.1",
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ gradio>=4.0.0
2
+ requests>=2.31.0
server/index.js ADDED
@@ -0,0 +1,226 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import express from 'express';
2
+ import cors from 'cors';
3
+ import multer from 'multer';
4
+ import path from 'path';
5
+ import fs from 'fs';
6
+ import { fileURLToPath } from 'url';
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = path.dirname(__filename);
10
+
11
+ const app = express();
12
+ const PORT = process.env.PORT || 3001;
13
+
14
+ // Middleware
15
+ app.use(cors());
16
+ app.use(express.json());
17
+ app.use(express.static(path.join(__dirname, '../dist')));
18
+
19
+ // Настройка multer для загрузки файлов
20
+ const storage = multer.diskStorage({
21
+ destination: function (req, file, cb) {
22
+ const uploadDir = path.join(__dirname, 'uploads');
23
+ if (!fs.existsSync(uploadDir)) {
24
+ fs.mkdirSync(uploadDir, { recursive: true });
25
+ }
26
+ cb(null, uploadDir);
27
+ },
28
+ filename: function (req, file, cb) {
29
+ const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
30
+ cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname));
31
+ }
32
+ });
33
+
34
+ const upload = multer({
35
+ storage: storage,
36
+ fileFilter: (req, file, cb) => {
37
+ // Разрешаем только аудио файлы
38
+ if (file.mimetype.startsWith('audio/') || file.mimetype === 'video/webm') {
39
+ cb(null, true);
40
+ } else {
41
+ cb(new Error('Только аудио файлы разрешены!'), false);
42
+ }
43
+ },
44
+ limits: {
45
+ fileSize: 50 * 1024 * 1024 // 50MB максимум
46
+ }
47
+ });
48
+
49
+ // API Routes
50
+
51
+ // GET /api/health - проверка здоровья сервера
52
+ app.get('/api/health', (req, res) => {
53
+ res.json({
54
+ status: 'ok',
55
+ message: 'Whisper API сервер работает',
56
+ timestamp: new Date().toISOString()
57
+ });
58
+ });
59
+
60
+ // POST /api/transcribe - транскрипция аудио файла
61
+ app.post('/api/transcribe', upload.single('audio'), async (req, res) => {
62
+ try {
63
+ if (!req.file) {
64
+ return res.status(400).json({
65
+ error: 'Аудио файл не предоставлен'
66
+ });
67
+ }
68
+
69
+ const audioFile = req.file;
70
+ const language = req.body.language || 'auto';
71
+ const model = req.body.model || 'base';
72
+
73
+ console.log(`Получен файл: ${audioFile.originalname}`);
74
+ console.log(`Размер: ${audioFile.size} байт`);
75
+ console.log(`Язык: ${language}, Модель: ${model}`);
76
+
77
+ // Пока возвращаем заглушку (реальная транскрипция будет добавлена позже)
78
+ const transcription = {
79
+ text: `[Транскрипция файла: ${audioFile.originalname}]`,
80
+ language: language,
81
+ model: model,
82
+ duration: 0,
83
+ segments: []
84
+ };
85
+
86
+ // Удаляем временный файл
87
+ fs.unlinkSync(audioFile.path);
88
+
89
+ res.json({
90
+ success: true,
91
+ transcription: transcription,
92
+ timestamp: new Date().toISOString()
93
+ });
94
+
95
+ } catch (error) {
96
+ console.error('Ошибка транскрипции:', error);
97
+
98
+ // Удаляем файл в случае ошибки
99
+ if (req.file && fs.existsSync(req.file.path)) {
100
+ fs.unlinkSync(req.file.path);
101
+ }
102
+
103
+ res.status(500).json({
104
+ error: 'Ошибка при обработке аудио файла',
105
+ details: error.message
106
+ });
107
+ }
108
+ });
109
+
110
+ // POST /api/transcribe/url - транскрипция аудио по URL
111
+ app.post('/api/transcribe/url', async (req, res) => {
112
+ try {
113
+ const { url, language = 'auto', model = 'base' } = req.body;
114
+
115
+ if (!url) {
116
+ return res.status(400).json({
117
+ error: 'URL не предоставлен'
118
+ });
119
+ }
120
+
121
+ console.log(`Получен URL: ${url}`);
122
+ console.log(`Язык: ${language}, Модель: ${model}`);
123
+
124
+ // Пока возвращаем заглушку
125
+ const transcription = {
126
+ text: `[Транскрипция URL: ${url}]`,
127
+ language: language,
128
+ model: model,
129
+ duration: 0,
130
+ segments: []
131
+ };
132
+
133
+ res.json({
134
+ success: true,
135
+ transcription: transcription,
136
+ timestamp: new Date().toISOString()
137
+ });
138
+
139
+ } catch (error) {
140
+ console.error('Ошибка транскрипции по URL:', error);
141
+ res.status(500).json({
142
+ error: 'Ошибка при обработке URL',
143
+ details: error.message
144
+ });
145
+ }
146
+ });
147
+
148
+ // GET /api/models - список доступных моделей
149
+ app.get('/api/models', (req, res) => {
150
+ const models = [
151
+ { id: 'tiny', name: 'Tiny', size: '39 MB', languages: 'multilingual' },
152
+ { id: 'base', name: 'Base', size: '74 MB', languages: 'multilingual' },
153
+ { id: 'small', name: 'Small', size: '244 MB', languages: 'multilingual' },
154
+ { id: 'medium', name: 'Medium', size: '769 MB', languages: 'multilingual' },
155
+ { id: 'large', name: 'Large', size: '1550 MB', languages: 'multilingual' }
156
+ ];
157
+
158
+ res.json({
159
+ models: models,
160
+ default: 'base'
161
+ });
162
+ });
163
+
164
+ // GET /api/languages - список поддерживаемых языков
165
+ app.get('/api/languages', (req, res) => {
166
+ const languages = [
167
+ { code: 'auto', name: 'Автоопределение' },
168
+ { code: 'ru', name: 'Русский' },
169
+ { code: 'en', name: 'English' },
170
+ { code: 'es', name: 'Español' },
171
+ { code: 'fr', name: 'Français' },
172
+ { code: 'de', name: 'Deutsch' },
173
+ { code: 'it', name: 'Italiano' },
174
+ { code: 'pt', name: 'Português' },
175
+ { code: 'pl', name: 'Polski' },
176
+ { code: 'tr', name: 'Türkçe' },
177
+ { code: 'ja', name: '日本語' },
178
+ { code: 'ko', name: '한국어' },
179
+ { code: 'zh', name: '中文' }
180
+ ];
181
+
182
+ res.json({
183
+ languages: languages,
184
+ default: 'auto'
185
+ });
186
+ });
187
+
188
+ // Обработка ошибок multer
189
+ app.use((error, req, res, next) => {
190
+ if (error instanceof multer.MulterError) {
191
+ if (error.code === 'LIMIT_FILE_SIZE') {
192
+ return res.status(400).json({
193
+ error: 'Файл слишком большой. Максимальный размер: 50MB'
194
+ });
195
+ }
196
+ }
197
+
198
+ if (error.message === 'Только аудио файлы разрешены!') {
199
+ return res.status(400).json({
200
+ error: error.message
201
+ });
202
+ }
203
+
204
+ next(error);
205
+ });
206
+
207
+ // Обработка 404 для API
208
+ app.use('/api/*', (req, res) => {
209
+ res.status(404).json({
210
+ error: 'API endpoint не найден'
211
+ });
212
+ });
213
+
214
+ // Serve React app
215
+ app.get('*', (req, res) => {
216
+ res.sendFile(path.join(__dirname, '../dist/index.html'));
217
+ });
218
+
219
+ // Запуск сервера
220
+ app.listen(PORT, () => {
221
+ console.log(`🚀 Whisper API сервер запущен на порту ${PORT}`);
222
+ console.log(`📝 API документация: http://localhost:${PORT}/api/health`);
223
+ console.log(`🌐 Веб-приложение: http://localhost:${PORT}`);
224
+ });
225
+
226
+ export default app;
server/simple-server.js ADDED
@@ -0,0 +1,271 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import http from 'http';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import { fileURLToPath } from 'url';
5
+ import { pipeline } from 'stream/promises';
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+
10
+ const PORT = process.env.PORT || 3001;
11
+
12
+ // Создаем папку для загрузок
13
+ const uploadDir = path.join(__dirname, 'uploads');
14
+ if (!fs.existsSync(uploadDir)) {
15
+ fs.mkdirSync(uploadDir, { recursive: true });
16
+ }
17
+
18
+ // Функция для парсинга multipart/form-data
19
+ function parseMultipartData(body, boundary) {
20
+ const parts = body.split('--' + boundary);
21
+ const result = {};
22
+
23
+ for (const part of parts) {
24
+ if (part.includes('Content-Disposition: form-data')) {
25
+ const lines = part.split('\r\n');
26
+ let name = '';
27
+ let value = '';
28
+ let isFile = false;
29
+ let filename = '';
30
+
31
+ for (const line of lines) {
32
+ if (line.startsWith('Content-Disposition: form-data; name=')) {
33
+ name = line.split('name=')[1].replace(/"/g, '');
34
+ }
35
+ if (line.includes('filename=')) {
36
+ isFile = true;
37
+ filename = line.split('filename=')[1].replace(/"/g, '');
38
+ }
39
+ if (line === '' && !isFile) {
40
+ const valueIndex = lines.indexOf(line) + 1;
41
+ value = lines[valueIndex];
42
+ }
43
+ }
44
+
45
+ if (isFile) {
46
+ result[name] = { filename, isFile: true };
47
+ } else {
48
+ result[name] = value;
49
+ }
50
+ }
51
+ }
52
+
53
+ return result;
54
+ }
55
+
56
+ // Функция для отправки JSON ответа
57
+ function sendJsonResponse(res, statusCode, data) {
58
+ res.writeHead(statusCode, { 'Content-Type': 'application/json' });
59
+ res.end(JSON.stringify(data));
60
+ }
61
+
62
+ // Функция для отправки CORS заголовков
63
+ function setCorsHeaders(res) {
64
+ res.setHeader('Access-Control-Allow-Origin', '*');
65
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
66
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
67
+ }
68
+
69
+ // Создаем HTTP сервер
70
+ const server = http.createServer(async (req, res) => {
71
+ setCorsHeaders(res);
72
+
73
+ // Обработка preflight запросов
74
+ if (req.method === 'OPTIONS') {
75
+ res.writeHead(200);
76
+ res.end();
77
+ return;
78
+ }
79
+
80
+ const url = new URL(req.url, `http://${req.headers.host}`);
81
+ const pathname = url.pathname;
82
+
83
+ try {
84
+ // API endpoints
85
+ if (pathname === '/api/health' && req.method === 'GET') {
86
+ sendJsonResponse(res, 200, {
87
+ status: 'ok',
88
+ message: 'Whisper API сервер работает',
89
+ timestamp: new Date().toISOString()
90
+ });
91
+ return;
92
+ }
93
+
94
+ if (pathname === '/api/models' && req.method === 'GET') {
95
+ const models = [
96
+ { id: 'tiny', name: 'Tiny', size: '39 MB', languages: 'multilingual' },
97
+ { id: 'base', name: 'Base', size: '74 MB', languages: 'multilingual' },
98
+ { id: 'small', name: 'Small', size: '244 MB', languages: 'multilingual' },
99
+ { id: 'medium', name: 'Medium', size: '769 MB', languages: 'multilingual' },
100
+ { id: 'large', name: 'Large', size: '1550 MB', languages: 'multilingual' }
101
+ ];
102
+
103
+ sendJsonResponse(res, 200, {
104
+ models: models,
105
+ default: 'base'
106
+ });
107
+ return;
108
+ }
109
+
110
+ if (pathname === '/api/languages' && req.method === 'GET') {
111
+ const languages = [
112
+ { code: 'auto', name: 'Автоопределение' },
113
+ { code: 'ru', name: 'Русский' },
114
+ { code: 'en', name: 'English' },
115
+ { code: 'es', name: 'Español' },
116
+ { code: 'fr', name: 'Français' },
117
+ { code: 'de', name: 'Deutsch' },
118
+ { code: 'it', name: 'Italiano' },
119
+ { code: 'pt', name: 'Português' },
120
+ { code: 'pl', name: 'Polski' },
121
+ { code: 'tr', name: 'Türkçe' },
122
+ { code: 'ja', name: '日本語' },
123
+ { code: 'ko', name: '한국어' },
124
+ { code: 'zh', name: '中文' }
125
+ ];
126
+
127
+ sendJsonResponse(res, 200, {
128
+ languages: languages,
129
+ default: 'auto'
130
+ });
131
+ return;
132
+ }
133
+
134
+ if (pathname === '/api/transcribe' && req.method === 'POST') {
135
+ let body = '';
136
+ req.on('data', chunk => {
137
+ body += chunk.toString();
138
+ });
139
+
140
+ req.on('end', () => {
141
+ try {
142
+ const contentType = req.headers['content-type'] || '';
143
+
144
+ if (contentType.includes('multipart/form-data')) {
145
+ const boundary = contentType.split('boundary=')[1];
146
+ const formData = parseMultipartData(body, boundary);
147
+
148
+ console.log('Получены данные формы:', formData);
149
+
150
+ // Пока возвращаем заглушку
151
+ const transcription = {
152
+ text: `[Транскрипция файла: ${formData.audio?.filename || 'unknown'}]`,
153
+ language: formData.language || 'auto',
154
+ model: formData.model || 'base',
155
+ duration: 0,
156
+ segments: []
157
+ };
158
+
159
+ sendJsonResponse(res, 200, {
160
+ success: true,
161
+ transcription: transcription,
162
+ timestamp: new Date().toISOString()
163
+ });
164
+ } else {
165
+ sendJsonResponse(res, 400, {
166
+ error: 'Неверный Content-Type. Ожидается multipart/form-data'
167
+ });
168
+ }
169
+ } catch (error) {
170
+ console.error('Ошибка обработки запроса:', error);
171
+ sendJsonResponse(res, 500, {
172
+ error: 'Внутренняя ошибка сервера',
173
+ details: error.message
174
+ });
175
+ }
176
+ });
177
+ return;
178
+ }
179
+
180
+ if (pathname === '/api/transcribe/url' && req.method === 'POST') {
181
+ let body = '';
182
+ req.on('data', chunk => {
183
+ body += chunk.toString();
184
+ });
185
+
186
+ req.on('end', () => {
187
+ try {
188
+ const data = JSON.parse(body);
189
+ const { url, language = 'auto', model = 'base' } = data;
190
+
191
+ if (!url) {
192
+ sendJsonResponse(res, 400, {
193
+ error: 'URL не предоставлен'
194
+ });
195
+ return;
196
+ }
197
+
198
+ console.log(`Получен URL: ${url}`);
199
+ console.log(`Язык: ${language}, Модель: ${model}`);
200
+
201
+ // Пока возвращаем заглушку
202
+ const transcription = {
203
+ text: `[Транскрипция URL: ${url}]`,
204
+ language: language,
205
+ model: model,
206
+ duration: 0,
207
+ segments: []
208
+ };
209
+
210
+ sendJsonResponse(res, 200, {
211
+ success: true,
212
+ transcription: transcription,
213
+ timestamp: new Date().toISOString()
214
+ });
215
+ } catch (error) {
216
+ console.error('Ошибка обработки JSON:', error);
217
+ sendJsonResponse(res, 400, {
218
+ error: 'Неверный JSON формат'
219
+ });
220
+ }
221
+ });
222
+ return;
223
+ }
224
+
225
+ // API 404
226
+ if (pathname.startsWith('/api/')) {
227
+ sendJsonResponse(res, 404, {
228
+ error: 'API endpoint не найден'
229
+ });
230
+ return;
231
+ }
232
+
233
+ // Serve static files
234
+ let filePath = path.join(__dirname, '../dist', pathname === '/' ? 'index.html' : pathname);
235
+
236
+ if (!fs.existsSync(filePath)) {
237
+ filePath = path.join(__dirname, '../dist/index.html');
238
+ }
239
+
240
+ const ext = path.extname(filePath);
241
+ const contentType = {
242
+ '.html': 'text/html',
243
+ '.js': 'text/javascript',
244
+ '.css': 'text/css',
245
+ '.json': 'application/json',
246
+ '.png': 'image/png',
247
+ '.jpg': 'image/jpg',
248
+ '.gif': 'image/gif',
249
+ '.svg': 'image/svg+xml'
250
+ }[ext] || 'text/plain';
251
+
252
+ res.writeHead(200, { 'Content-Type': contentType });
253
+ fs.createReadStream(filePath).pipe(res);
254
+
255
+ } catch (error) {
256
+ console.error('Ошибка сервера:', error);
257
+ sendJsonResponse(res, 500, {
258
+ error: 'Внутренняя ошибка сервера',
259
+ details: error.message
260
+ });
261
+ }
262
+ });
263
+
264
+ // Запускаем сервер
265
+ server.listen(PORT, () => {
266
+ console.log(`🚀 Whisper API сервер запущен на порту ${PORT}`);
267
+ console.log(`📝 API документация: http://localhost:${PORT}/api/health`);
268
+ console.log(`🌐 Веб-приложение: http://localhost:${PORT}`);
269
+ });
270
+
271
+ export default server;
server/transcriber.js ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { pipeline } from '@xenova/transformers';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import { fileURLToPath } from 'url';
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = path.dirname(__filename);
8
+
9
+ class Transcriber {
10
+ constructor() {
11
+ this.pipeline = null;
12
+ this.isLoading = false;
13
+ this.modelCache = new Map();
14
+ }
15
+
16
+ async loadModel(modelName = 'base') {
17
+ const cacheKey = modelName;
18
+
19
+ if (this.modelCache.has(cacheKey)) {
20
+ return this.modelCache.get(cacheKey);
21
+ }
22
+
23
+ if (this.isLoading) {
24
+ // Ждем, пока модель загружается
25
+ while (this.isLoading) {
26
+ await new Promise(resolve => setTimeout(resolve, 100));
27
+ }
28
+ return this.modelCache.get(cacheKey);
29
+ }
30
+
31
+ try {
32
+ this.isLoading = true;
33
+ console.log(`Загрузка модели: ${modelName}...`);
34
+
35
+ const model = await pipeline('automatic-speech-recognition', `Xenova/whisper-${modelName}`);
36
+
37
+ this.modelCache.set(cacheKey, model);
38
+ console.log(`Модель ${modelName} загружена успешно`);
39
+
40
+ return model;
41
+ } catch (error) {
42
+ console.error(`Ошибка загрузки модели ${modelName}:`, error);
43
+ throw error;
44
+ } finally {
45
+ this.isLoading = false;
46
+ }
47
+ }
48
+
49
+ async transcribeAudio(audioPath, options = {}) {
50
+ try {
51
+ const {
52
+ language = 'auto',
53
+ model = 'base',
54
+ task = 'transcribe',
55
+ chunk_length_s = 30,
56
+ stride_length_s = 5
57
+ } = options;
58
+
59
+ console.log(`Начинаем транскрипцию: ${audioPath}`);
60
+ console.log(`Параметры: язык=${language}, модель=${model}, задача=${task}`);
61
+
62
+ // Загружаем модель
63
+ const whisperModel = await this.loadModel(model);
64
+
65
+ // Читаем аудио файл
66
+ const audioBuffer = fs.readFileSync(audioPath);
67
+
68
+ // Транскрибируем
69
+ const result = await whisperModel(audioBuffer, {
70
+ language: language === 'auto' ? undefined : language,
71
+ task: task,
72
+ chunk_length_s: chunk_length_s,
73
+ stride_length_s: stride_length_s,
74
+ return_timestamps: true
75
+ });
76
+
77
+ console.log('Транскрипция завершена');
78
+
79
+ return {
80
+ text: result.text,
81
+ language: result.language || language,
82
+ model: model,
83
+ duration: result.duration || 0,
84
+ segments: result.chunks || [],
85
+ timestamp: new Date().toISOString()
86
+ };
87
+
88
+ } catch (error) {
89
+ console.error('Ошибка транскрипции:', error);
90
+ throw error;
91
+ }
92
+ }
93
+
94
+ async transcribeFromUrl(url, options = {}) {
95
+ try {
96
+ const https = await import('https');
97
+ const http = await import('http');
98
+
99
+ console.log(`Загружаем аудио с URL: ${url}`);
100
+
101
+ // Определяем протокол
102
+ const protocol = url.startsWith('https:') ? https.default : http.default;
103
+
104
+ // Создаем временный файл
105
+ const tempPath = path.join(__dirname, 'uploads', `temp-${Date.now()}.webm`);
106
+
107
+ return new Promise((resolve, reject) => {
108
+ const file = fs.createWriteStream(tempPath);
109
+
110
+ protocol.get(url, (response) => {
111
+ if (response.statusCode !== 200) {
112
+ reject(new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`));
113
+ return;
114
+ }
115
+
116
+ response.pipe(file);
117
+
118
+ file.on('finish', async () => {
119
+ file.close();
120
+ try {
121
+ const result = await this.transcribeAudio(tempPath, options);
122
+
123
+ // Удаляем временный файл
124
+ fs.unlinkSync(tempPath);
125
+
126
+ resolve(result);
127
+ } catch (error) {
128
+ // Удаляем временный файл в случае ошибки
129
+ if (fs.existsSync(tempPath)) {
130
+ fs.unlinkSync(tempPath);
131
+ }
132
+ reject(error);
133
+ }
134
+ });
135
+ }).on('error', (error) => {
136
+ // Удаляем временный файл в случае ошибки
137
+ if (fs.existsSync(tempPath)) {
138
+ fs.unlinkSync(tempPath);
139
+ }
140
+ reject(error);
141
+ });
142
+ });
143
+
144
+ } catch (error) {
145
+ console.error('Ошибка загрузки с URL:', error);
146
+ throw error;
147
+ }
148
+ }
149
+
150
+ // Получить информацию о доступных моделях
151
+ getAvailableModels() {
152
+ return [
153
+ { id: 'tiny', name: 'Tiny', size: '39 MB', languages: 'multilingual' },
154
+ { id: 'base', name: 'Base', size: '74 MB', languages: 'multilingual' },
155
+ { id: 'small', name: 'Small', size: '244 MB', languages: 'multilingual' },
156
+ { id: 'medium', name: 'Medium', size: '769 MB', languages: 'multilingual' },
157
+ { id: 'large', name: 'Large', size: '1550 MB', languages: 'multilingual' }
158
+ ];
159
+ }
160
+
161
+ // Получить информацию о поддерживаемых языках
162
+ getSupportedLanguages() {
163
+ return [
164
+ { code: 'auto', name: 'Автоопределение' },
165
+ { code: 'ru', name: 'Русский' },
166
+ { code: 'en', name: 'English' },
167
+ { code: 'es', name: 'Español' },
168
+ { code: 'fr', name: 'Français' },
169
+ { code: 'de', name: 'Deutsch' },
170
+ { code: 'it', name: 'Italiano' },
171
+ { code: 'pt', name: 'Português' },
172
+ { code: 'pl', name: 'Polski' },
173
+ { code: 'tr', name: 'Türkçe' },
174
+ { code: 'ja', name: '日本語' },
175
+ { code: 'ko', name: '한국어' },
176
+ { code: 'zh', name: '中文' }
177
+ ];
178
+ }
179
+ }
180
+
181
+ export default Transcriber;
src/App.tsx CHANGED
@@ -23,9 +23,20 @@ function App() {
23
  <a
24
  className='underline'
25
  href='https://github.com/xenova/transformers.js'
 
 
26
  >
27
  🤗 Transformers.js
28
  </a>
 
 
 
 
 
 
 
 
 
29
  </div>
30
  </div>
31
  );
 
23
  <a
24
  className='underline'
25
  href='https://github.com/xenova/transformers.js'
26
+ target="_blank"
27
+ rel="noopener noreferrer"
28
  >
29
  🤗 Transformers.js
30
  </a>
31
+ {" "}by{" "}
32
+ <a
33
+ className='underline'
34
+ href='https://t.me/naumxv'
35
+ target="_blank"
36
+ rel="noopener noreferrer"
37
+ >
38
+ @naumxv
39
+ </a>
40
  </div>
41
  </div>
42
  );
vite.config.ts CHANGED
@@ -7,4 +7,9 @@ export default defineConfig({
7
  plugins: [
8
  react()
9
  ],
 
 
 
 
 
10
  })
 
7
  plugins: [
8
  react()
9
  ],
10
+ server: {
11
+ port: 3000,
12
+ host: true, // Позволяет доступ с других устройств в сети
13
+ open: true // Автоматически открывает браузер при запуске
14
+ }
15
  })