Files
xboct-flow/docs/PLAN.md
T
2026-07-13 16:42:26 +05:00

6.9 KiB
Raw Blame History

project-tasks — VS Code Extension

Хранение

Формат: Markdown + YAML frontmatter (один .task.md файл на задачу)

---
id: "..."
title: "Пофиксить баг логина"
status: todo # todo | in-progress | done | cancelled
priority: high # low | medium | high | critical
tags: [bug, frontend]
assignee: ""
created: 2026-07-12T10:00:00Z
updated: 2026-07-12T10:00:00Z
---

Описание задачи в markdown...

Структура папок:

  • .vscode/tasks/ — проектные задачи
  • глобальная папка — настраивается (projectTasks.globalPath)

Оба пути настраиваются через VS Code settings.

UI в основном окне (Split-редактор)

Через Custom Editor + WebView:

  1. Activity Bar — вкладка Project Tasks
  2. Task Dashboard — WebView в editor area со split layout:
    • Левая панель — список задач с фильтрацией/группировкой
    • Правая панель — содержимое выбранной задачи (редактируемый markdown)
  3. TreeView — быстрый просмотр по статусу

Архитектура кода

Актуальная раскладка (после рефакторинга портов/адаптеров):

src/
├── extension.ts                 # composition root (DI, register)
├── ports.ts                     # IFileSystem, ITaskRepository, IConfigProvider
├── error.ts                     # AppErrorVariant + AppError { variant, message }
├── model/task.ts
├── storage/
│   ├── FsTaskRepository.ts
│   ├── NodeFileSystem.ts
│   └── VscodeConfigProvider.ts
├── commands/                    # use-cases без vscode UI
│   ├── createTask.ts
│   ├── openTask.ts
│   ├── deleteTask.ts
│   └── changeStatus.ts
├── views/
│   └── taskTreeProvider.ts      # (+ dashboard later)
└── utils/
    ├── uuid.ts
    └── markdown.ts              # parse/serialize frontmatter

tests/helpers/InMemoryFileSystem.ts

UI (input box, quick pick, open editor) — тонкие адаптеры; бизнес-логика в use-cases + ITaskRepository. Ошибки — AppError из error.ts.

План реализации

Фаза Что делаем
1. Scaffold Extension, TypeScript, сборка, package.json
2. Storage CRUD .task.md, парсинг frontmatter, unit-тесты storage
3. TreeView sidebar по статусу, file watcher
4. Команды createTask, deleteTask, changeStatus, openTask (use-cases → wiring UI)
5. Task Dashboard WebView split layout
6. Глобальные задачи использование globalPath
7. Kanban drag-n-drop
8. Публикация vsce publish

Фаза 4 — команды (use-cases)

Команда Поведение
createTask title + folder → defaults todo/medium; empty title / no folder
deleteTask folder + id → delete; not found
changeStatus folder + id + status → update; not found
openTask folder + id → path + task для editor; not found

Зависимости

  • front-matter — разбор YAML frontmatter (body + attributes)
  • js-yaml — сериализация frontmatter обратно в YAML (dump)
  • uuid — генерация ID
  • neverthrowResult / ResultAsync для use-cases
  • vitest / eslint — dev

История изменений (решения, не чеклист)

Краткая летопись смен относительно изначального наброска плана. Детали рефакторинга storage/тестов — в архиве docs/REFACTOR-AND-TEST.md (документ закрыт, не ведём).

Изначальный набросок (v0)

  • Парсинг: gray-matter
  • Storage: taskStore.ts (CRUD), configStore.ts (settings)
  • Сборка/скелет: yo code-ориентированный scaffold
  • Дерево модулей: storage + views (tree/list/dashboard) + commands + utils

Рефакторинг storage / чистая архитектура

  • taskStore / configStoreпорты (IFileSystem, ITaskRepository, IConfigProvider) и адаптеры:
    • FsTaskRepository, NodeFileSystem, VscodeConfigProvider
  • extension.ts — composition root (DI), tree зависит от портов
  • Unit-тесты: Vitest, colocation, InMemoryFileSystem в tests/helpers/

gray-matterfront-matter + js-yaml

  • Было в плане: один пакет gray-matter на parse (+ stringify при необходимости).
  • Стало: front-matter для чтения attributes/body; js-yaml (dump) для записи frontmatter в serializeTask.
  • Зачем: gray-matter даёт лишние возможности парсинга (eval для JS и прочая «магия»), которые для задач не нужны; Vite на eval ругается, с точки зрения безопасности это нежелательно. Поэтому parse через front-matter, serialize через js-yaml (dump). Формат файла тот же: Markdown + YAML frontmatter.

neverthrow + AppError

  • Use-cases возвращают ResultAsync<T, AppError>.
  • AppErrorVariant — const-object кодов (NOT_FOUND: "not-found").
  • AppError{ variant, message }; message из шаблона с {placeholders} через appError(variant, params?).

Прочее относительно v0

  • Сборка: Vite (extension bundle), не классический tsc-only из yo code
  • В модели/файле задачи зафиксирован id в frontmatter (нужен для list/get/update/delete)
  • Фаза 4: use-cases в src/commands/* тестируются без vscode; UI — отдельные адаптеры