fix: harden browser file picker and remove legacy

This commit is contained in:
“Naeel”
2026-09-05 20:50:36 +03:00
parent f6b2f6d1b3
commit 017bd8c354
20 changed files with 499 additions and 216 deletions
+76 -34
View File
@@ -1,40 +1,68 @@
# Upload Platform
Переиспользуемый browser-only file-picker. Модуль выбирает отдельные файлы,
папки и ZIP, строит сворачиваемое дерево и возвращает исходные browser `File`
objects с полными путями. Файлы не отправляются на VM и не загружаются через
backend.
Переиспользуемый browser-only file-picker версии `0.1.12`. Он выбирает файлы,
папки и ZIP, строит дерево и возвращает интегрирующему приложению browser
`File` objects. Содержимое файлов остаётся в браузере: текущий проект не
загружает его на VM, в Flask или в другое хранилище.
## Слои
## Карта файлов
| Слой | Ответственность |
### Корень проекта
| Путь | Назначение | Статус |
|---|---|---|
| `package.json` | Версия пакета и команда `npm run build`. | Используется |
| `package-lock.json` | Зафиксированные npm-зависимости. | Используется |
| `build.mjs` | esbuild-сборка ESM и IIFE bundle. | Используется |
| `requirements.txt` | Python-зависимости demo-сервера. | Используется demo |
| `config.json` | Конфигурация demo: разрешённые расширения. | Используется demo |
| `dist/file-picker.esm.js` | Готовый ESM bundle для интеграции. | Используется |
| `dist/file-picker.iife.js` | Готовый IIFE bundle `FilePicker`. | Используется |
| `upload/` | Исходники переиспользуемого picker-модуля. | Используется |
| `site/` | Flask demo, который раздаёт страницу и bundle. | Используется только demo |
| `docs/` | Справочная и историческая документация. | См. раздел LEGACY |
| `HISTORY/` | Архив решений, ревью и результатов проверок. | Только история |
### `upload/` — исходники picker-а
| Путь | Назначение |
|---|---|
| Конфиг | `allowedExt`, `labels`, `layout`, `limits` |
| Picker | таблица, дедупликация, ZIP, рекурсивный обход папки |
| Интегрирующее приложение | получает leaf-файлы через `getFiles()` |
| `upload/README.md` | Краткая инструкция интеграции готового bundle. |
| `upload/config.example.json` | Пример конфигурации разрешённых расширений. |
| `upload/frontend/index.js` | Единственная актуальная точка входа `initFilePicker(config)`, DOM, lifecycle API. |
| `upload/frontend/table/add_file_with_dedup.js` | Дедупликация файлов и слияние одинаковых корней. |
| `upload/frontend/table/esc.js` | HTML-экранирование имён, путей и атрибутов. |
| `upload/frontend/table/fs.js` | Форматирование размеров файлов. |
| `upload/frontend/table/on_files_change.js` | Выбор файлов, фильтрация, ZIP-разбор и fallback ошибок. |
| `upload/frontend/table/on_folder_change.js` | Выбор папки через `webkitdirectory` и построение дерева. |
| `upload/frontend/table/rebase_tree.js` | Добавление префикса пути без изменения базового `File.name`. |
| `upload/frontend/table/render.js` | Рендер дерева, счётчик, поиск узлов и `flattenFiles()`. |
| `upload/frontend/zip/list_zip_files.js` | Безопасный рекурсивный разбор ZIP через встроенный `fflate`. |
## Структура
### `site/` — demo-обёртка
```
upload-platform/
├── requirements.txt
├── config.json # слой 0 (рабочий конфиг этого демо)
├── package.json # сборка browser bundle
├── build.mjs # esbuild: ESM + IIFE
├── dist/ # готовые bundle для встраивания
├── upload/ # ← переиспользуемый модуль (копируется в любой проект)
│ ├── README.md # инструкция интеграции
│ ├── config.example.json
│ ├── frontend/ # picker (vanilla JS, ES-модули)
│ │ ├── zip/
│ │ ├── table/
│ └── backend/ # LEGACY: VM upload/session remnants
└── site/ # демо-обёртка (не переиспользуется)
├── app.py
├── routes/
├── templates/
└── static/
```
| Путь | Назначение |
|---|---|
| `site/app.py` | Flask entrypoint, `/`, `/health`, раздача bundle и совместимый маршрут исходников. |
| `site/templates/index.html` | Demo-страница и вызов `FilePicker.initFilePicker()`. |
| `site/static/style.css` | Стили demo-страницы. |
| `site/routes/` | Текущий каталог маршрутов; прикладного upload backend в нём нет. |
### `docs/`
| Путь | Назначение | Статус |
|---|---|---|
| `docs/CODE-REFERENCE.md` | Справочник актуального picker-кода и API. | Использовать |
| `docs/PLAN-componentization.md` | Исторический план перехода к bundle API. | LEGACY, не использовать как план |
| `docs/sonnet-architecture-review-prompt.md` | Исторический prompt ревью старой архитектуры. | LEGACY, не использовать |
| `docs/*-architecture-review-response.md` | Ответы на исторические ревью. | История, не спецификация |
### `HISTORY/`
Файлы `HISTORY/` фиксируют состояние проекта на даты ревью, тестов и решений.
Они могут описывать удалённые файлы, VM-upload или старые версии. Это архив,
а не инструкция: при расхождении с кодом руководствоваться только исходниками,
`README.md`, `upload/README.md` и `docs/CODE-REFERENCE.md`.
## Локальный запуск
@@ -76,10 +104,24 @@ ZIP-файлы используются как контейнеры и раск
## Legacy
`upload/backend/` и старые VM-upload упоминания сохранены только для истории и
совместимости с предыдущими этапами проекта. Текущая picker-only интеграция их
не импортирует и не требует Flask API для обработки файлов.
Переиспользуемая инструкция находится в `upload/README.md`.
### Удалено и не должно восстанавливаться
- `upload/backend/` — старый backend VM-upload, sessions и pull API;
- `upload/frontend/table/init_upload_table.js` — старый entry point с готовыми DOM-узлами;
- `upload/frontend/table/set_status.js` — неиспользуемый legacy helper;
- `upload/frontend/upload/` — старый frontend VM-upload layer.
Эти части не входят в сборку `build.mjs`, не импортируются текущим picker-ом и
не являются частью API. Не добавлять их обратно при интеграции.
### Исторические документы
`PLAN.md`, `docs/PLAN-componentization.md`, review prompts и записи `HISTORY/`
могут содержать описания старой VM/backend-архитектуры. Они нужны для аудита
решений, но не являются актуальной спецификацией и не должны использоваться
как план разработки.
Актуальная инструкция интеграции находится в `upload/README.md`.
Полный справочник функций, состояния, DOM-контрактов и ограничений находится в
[`docs/CODE-REFERENCE.md`](docs/CODE-REFERENCE.md).