@iwonz/ywtc 4.1.1 → 4.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/README.md +189 -232
- package/dist/clients/confluence-cloud.js +45 -38
- package/dist/clients/confluence-cloud.js.map +1 -1
- package/dist/clients/confluence-response.d.ts +226 -0
- package/dist/clients/confluence-response.js +205 -0
- package/dist/clients/confluence-response.js.map +1 -0
- package/dist/clients/confluence.js +51 -40
- package/dist/clients/confluence.js.map +1 -1
- package/dist/connection-verifier.js +6 -1
- package/dist/connection-verifier.js.map +1 -1
- package/dist/doctor.js +3 -1
- package/dist/doctor.js.map +1 -1
- package/dist/http.js +28 -2
- package/dist/http.js.map +1 -1
- package/dist/migrator.js +4 -2
- package/dist/migrator.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
Notable changes to `ywtc` are documented in this file. Versions follow [Semantic Versioning](https://semver.org/).
|
|
4
4
|
|
|
5
|
+
## [4.1.2](https://github.com/iwonz/ywtc/compare/v4.1.1...v4.1.2) (2026-10-16)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **confluence:** validate provider readiness responses ([1a6b32e](https://github.com/iwonz/ywtc/commit/1a6b32ed25c32bd13eca5ad78ab209e02f07ffbf))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Documentation
|
|
14
|
+
|
|
15
|
+
* **readme:** simplify operator documentation ([cd745e7](https://github.com/iwonz/ywtc/commit/cd745e74662cd2bd4a5edc592994e39559fab81c))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Maintenance
|
|
19
|
+
|
|
20
|
+
* **ci:** re-run documentation checks ([92d2504](https://github.com/iwonz/ywtc/commit/92d2504912123828429794913edc3b9703cb403e))
|
|
21
|
+
* **homebrew:** update formula to v4.1.1 ([6ef4a77](https://github.com/iwonz/ywtc/commit/6ef4a77b01f2730775b0e5a0ed6e22e8fe638e31))
|
|
22
|
+
|
|
5
23
|
## [4.1.1](https://github.com/iwonz/ywtc/compare/v4.1.0...v4.1.1) (2026-10-16)
|
|
6
24
|
|
|
7
25
|
|
package/README.md
CHANGED
|
@@ -4,44 +4,24 @@
|
|
|
4
4
|
|
|
5
5
|
# ywtc
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
`ywtc` — CLI для переноса страниц между Yandex Wiki и Confluence и экспорта в Markdown или автономный HTML. Он сохраняет структуру и содержимое, продолжает операции по state-файлу и не удаляет source или destination автоматически.
|
|
7
|
+
`ywtc` — CLI для переноса страниц между Yandex Wiki и Confluence и экспорта в Markdown или автономный HTML. Он сохраняет иерархию и доступное содержимое, проверяет результат, продолжает прерванные операции и ничего не удаляет автоматически.
|
|
10
8
|
|
|
11
9
|
Требуются Node.js `>=24` и npm `>=11.5.1`. Лицензия — [MIT](LICENSE).
|
|
12
10
|
|
|
13
|
-
##
|
|
14
|
-
|
|
15
|
-
| Исходный материал | Как переносится |
|
|
16
|
-
| --- | --- |
|
|
17
|
-
| Страницы и структура | Одна страница, полное структурное поддерево или граф связанных страниц. Иерархия восстанавливается, циклы обрабатываются без повторного переноса. Пустая страница-раздел переносится как корректная пустая страница, а не как fallback. |
|
|
18
|
-
| Текст и оформление | Заголовки, абзацы, жирное/курсивное/зачёркнутое и цветное начертание, списки и задачи, цитаты, разделители, inline/preformatted code с языком и обычные таблицы преобразуются в нативную или семантически эквивалентную разметку destination. |
|
|
19
|
-
| Секции и колонки | YFM `layout/block` и Confluence page layouts сохраняются нативными секциями и колонками в Yandex Wiki и Confluence. HTML использует адаптивную сетку; Markdown сохраняет все ячейки по порядку и отмечает линеаризацию как adaptation без ухудшения статуса. |
|
|
20
|
-
| Ссылки и якоря | Ссылки между выбранными страницами переписываются на destination, якоря сохраняются. Внешние ссылки и ссылки за пределы выбранного набора остаются исходными. |
|
|
21
|
-
| Вложения | Переносятся все доступные через API для скачивания файлы, включая PNG/JPEG/GIF/WebP/SVG, PDF, ZIP, DOC/DOCX, XLS/XLSX и PPT/PPTX. Файлы передаются потоково, совпадения имён разрешаются стабильно, размер и SHA-256 проверяются. |
|
|
22
|
-
| Изображения | Прикреплённые изображения становятся attachments destination или локальными файлами экспорта. Внешние изображения остаются внешними; подписи и размеры сохраняются, если destination это поддерживает. |
|
|
23
|
-
| Специальная разметка | В обе стороны сопоставляются notes ↔ `info`/`tip`/`warning`/`note`, cuts ↔ `expand`, tree ↔ `children`, задачи, code, anchors, page/attachment links и изображения. Tabs становятся статическими секциями, Grid — проверяемой статической таблицей. Такие полные эквивалентные представления считаются adaptation и остаются `complete`. Безопасный Storage Format и YFM сохраняются нативно при переносе внутри одного провайдера. |
|
|
24
|
-
| Комментарии | По умолчанию все доступные комментарии страницы собираются в один архивный комментарий: отдельные раскрываемые ветки сохраняют участников, авторов, даты, статусы, inline-контекст, удалённые записи и вложенность ответов. Вложения, на которые есть ссылки в тексте комментариев, складываются в один проверяемый ZIP с hash-prefixed именами и manifest. Для Markdown/HTML создаются локальные секции и ZIP. |
|
|
25
|
-
| Конструкции без точного эквивалента | Создаётся читаемый fallback и при необходимости raw snapshot. Если весь payload представлен и проверен, это adaptation со статусом `complete`; только потеря данных, значимой структуры или невозможность проверки дают degradation и `partial`. |
|
|
26
|
-
|
|
27
|
-
### Не переносится
|
|
28
|
-
|
|
29
|
-
| Ограничение | Поведение ywtc |
|
|
30
|
-
| --- | --- |
|
|
31
|
-
| История версий | Переносится только актуальное содержимое страницы. |
|
|
32
|
-
| Реакции и комментарии не к странице | Реакции не копируются. Комментарии к attachments, blog posts и custom content не входят в архив: читаются только footer/inline page comments. |
|
|
33
|
-
| Пользовательские сущности, watchers, права и ограничения доступа | Не создаются; исходное авторство комментариев сохраняется в архивном тексте, а destination-объекты создаются пользователем текущего токена и наследуют права destination. |
|
|
34
|
-
| Удалённые, недоступные или не возвращённые source API страницы | Не восстанавливаются; недоступность и пропуски фиксируются в state и отчёте. |
|
|
35
|
-
| Точная геометрия, произвольный CSS, скрипты и неизвестные widgets/macros | Не исполняются и не подменяются недоказанным эквивалентом. Содержимое сохраняется статически, через fallback или raw snapshot; неполнота отмечается как degradation. |
|
|
36
|
-
| Внешние файлы и изображения, не принадлежащие source | Не копируются; абсолютный URL, подпись и доступные размеры сохраняются как external reference без ухудшения статуса. Недоступный source-managed ресурс считается неполным переносом. |
|
|
37
|
-
|
|
38
|
-
## Установка
|
|
11
|
+
## Быстрый старт
|
|
39
12
|
|
|
40
13
|
```bash
|
|
41
|
-
# npm
|
|
42
14
|
npm install -g @iwonz/ywtc
|
|
15
|
+
ywtc init --interactive
|
|
16
|
+
ywtc migrate --interactive
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Первый мастер создаёт рабочий каталог, настраивает Yandex Wiki и Confluence и проверяет соединения. Второй собирает параметры переноса и по умолчанию выполняет dry-run; live-запуск начинается только после подтверждения.
|
|
20
|
+
|
|
21
|
+
Другие способы запуска:
|
|
43
22
|
|
|
44
|
-
|
|
23
|
+
```bash
|
|
24
|
+
# Без глобальной установки
|
|
45
25
|
npx @iwonz/ywtc@latest --version
|
|
46
26
|
|
|
47
27
|
# Homebrew
|
|
@@ -50,253 +30,230 @@ brew trust --tap iwonz/ywtc
|
|
|
50
30
|
brew install ywtc
|
|
51
31
|
```
|
|
52
32
|
|
|
53
|
-
|
|
33
|
+
Обновление: `ywtc update` проверяет версию, `ywtc update --install` обновляет через обнаруженный канал, `--via npm|brew` выбирает канал явно.
|
|
34
|
+
|
|
35
|
+
## Возможности
|
|
54
36
|
|
|
55
|
-
|
|
37
|
+
| Материал | Результат |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| Страницы и структура | `page`, полное `subtree` или рекурсивный граф `linked`. Иерархия восстанавливается, циклы не создают повторов, пустая страница-раздел остаётся корректной пустой страницей. |
|
|
40
|
+
| Текст и таблицы | Сохраняются заголовки, начертания и цвет, списки и задачи, цитаты, разделители, inline/preformatted code с языком и обычные таблицы. Destination получает нативную или семантически эквивалентную разметку. |
|
|
41
|
+
| Секции и колонки | YFM `layout/block` и Confluence layouts преобразуются в нативные секции и колонки. HTML использует адаптивную сетку; Markdown сохраняет содержимое ячеек в исходном порядке. |
|
|
42
|
+
| Ссылки и якоря | Ссылки внутри выбранного набора переписываются на destination; якоря сохраняются. Внешние ссылки и переходы за границу набора остаются исходными. |
|
|
43
|
+
| Файлы и изображения | Доступные через API вложения передаются потоково с проверкой размера и SHA-256. Поддерживаются любые скачиваемые файлы, включая PNG/JPEG/GIF/WebP/SVG, PDF, ZIP, DOCX, XLSX и PPTX. Коллизии имён разрешаются стабильно. |
|
|
44
|
+
| Специальная разметка | Notes ↔ callout macros, cuts ↔ expand, tree ↔ children, задачи, code, anchors, page/attachment links и изображения получают ближайший эквивалент. Tabs становятся секциями, Grid — проверяемой статической таблицей. |
|
|
45
|
+
| Комментарии | По умолчанию footer/inline page comments архивируются с авторами, датами, статусами и иерархией ответов. Явно упомянутые вложения собираются в проверяемый ZIP с hash-prefixed именами и manifest. |
|
|
46
|
+
| Надёжность содержимого | Новая страница сразу создаётся с полным source-derived body, а не placeholder. Ошибка отдельного ресурса не блокирует текст: остаётся source-ссылка и повторяемый outcome. После записи destination перечитывается и проверяется. |
|
|
47
|
+
| Различия платформ | Безопасная normalization и полная adaptation считаются `complete`. Если эквивалента нет, ywtc сохраняет читаемый fallback и при необходимости raw snapshot; недоказанная полнота становится degradation. |
|
|
48
|
+
|
|
49
|
+
### Ограничения
|
|
50
|
+
|
|
51
|
+
| Не переносится как исходная сущность | Что сохраняется |
|
|
52
|
+
| --- | --- |
|
|
53
|
+
| История версий | Текущее содержимое; последующие обновления destination образуют его обычную историю версий. |
|
|
54
|
+
| Реакции; комментарии к attachments, blog posts и custom content | Только footer/inline comments страницы. |
|
|
55
|
+
| Пользователи, watchers, права и ограничения доступа | Авторство комментариев остаётся в архивном тексте; новые объекты создаёт владелец токена и они наследуют права destination. |
|
|
56
|
+
| Недоступные или не возвращённые API страницы | Причина и незавершённая ветка фиксируются в state и отчёте. |
|
|
57
|
+
| Произвольный CSS, scripts и неизвестные интерактивные widgets/macros | Безопасное статическое представление, fallback или raw snapshot; тихой потери быть не должно. |
|
|
58
|
+
| Внешние файлы и изображения | Исходный абсолютный URL, alt и доступные размеры; внешние данные не скачиваются. Недоступный source-managed ресурс считается неполным переносом. |
|
|
56
59
|
|
|
57
|
-
|
|
58
|
-
ywtc update # только проверка
|
|
59
|
-
ywtc update --install # канал текущей установки
|
|
60
|
-
ywtc update --install --via brew # явно через Homebrew
|
|
61
|
-
```
|
|
60
|
+
## Совместимость
|
|
62
61
|
|
|
63
|
-
|
|
62
|
+
| Source | Destination |
|
|
63
|
+
| --- | --- |
|
|
64
|
+
| Yandex Wiki | Confluence, Yandex Wiki, Markdown, HTML |
|
|
65
|
+
| Confluence | Yandex Wiki, Confluence, Markdown, HTML |
|
|
64
66
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
| Система | Поддерживаемый контракт | Авторизация |
|
|
68
|
+
| --- | --- | --- |
|
|
69
|
+
| Yandex Wiki | Public API v1; новые необязательные поля допускаются | OAuth или пользовательский IAM; `X-Org-Id`/`X-Cloud-Org-Id` |
|
|
70
|
+
| Confluence Data Center | 7.9+ без искусственной верхней границы | Bearer PAT |
|
|
71
|
+
| Confluence Cloud | REST v2 для страниц, REST v1 для attachments | Email + API token |
|
|
72
|
+
|
|
73
|
+
Confluence Server, Data Center Basic Auth и OAuth app-flow не поддерживаются. Перед чтением страниц и записью `doctor`/`migrate` проверяет готовность REST API: startup/maintenance HTML и неполный JSON останавливают операцию без создания state или destination-объектов. После восстановления Confluence повторите команду; если сервер исправен, проверьте `baseUrl` и `deployment`. Контрактные тесты не заменяют live-сертификацию каждой patch-версии.
|
|
68
74
|
|
|
69
75
|
## Конфигурация
|
|
70
76
|
|
|
71
|
-
Рабочий каталог выбирается
|
|
77
|
+
Рабочий каталог выбирается в порядке `--workdir` → `ywtc.config.yaml` непосредственно в текущем каталоге → `~/.ywtc`. Родительские каталоги не просматриваются.
|
|
72
78
|
|
|
73
79
|
```text
|
|
74
80
|
~/.ywtc/
|
|
75
|
-
├── ywtc.config.yaml
|
|
76
|
-
└── .states/
|
|
81
|
+
├── ywtc.config.yaml # подключения, настройки и токены
|
|
82
|
+
└── .states/ # state, cache, backups и отчёты
|
|
77
83
|
```
|
|
78
84
|
|
|
79
|
-
`ywtc init --interactive`
|
|
85
|
+
`ywtc init --interactive` настраивает и проверяет оба провайдера; `ywtc init` создаёт пустой шаблон для автоматизации. `migrate` создаёт отсутствующий workspace, но до API-запросов требует заполнить обязательные поля. Проверка мастера подтверждает API и авторизацию, но не права конкретных страниц: их проверяют `doctor` или `migrate`. Конфигурация строгая, неизвестные поля отклоняются; process environment её не переопределяет. Локальный файл игнорируется Git, новый создаётся с mode `0600`, секреты маскируются в выводе. Полный шаблон: [`ywtc.config.example.yaml`](ywtc.config.example.yaml).
|
|
80
86
|
|
|
81
|
-
### Поля
|
|
87
|
+
### Поля `ywtc.config.yaml`
|
|
82
88
|
|
|
83
|
-
| Поле |
|
|
89
|
+
| Поле | Профиль | Значения / default | Назначение |
|
|
84
90
|
| --- | --- | --- | --- |
|
|
85
|
-
| `defaults.timeoutMs` |
|
|
86
|
-
| `defaults.concurrency` |
|
|
87
|
-
| `connections.<name>` |
|
|
88
|
-
| `type` |
|
|
89
|
-
| `token` |
|
|
90
|
-
| `apiUrl` | Yandex Wiki | URL
|
|
91
|
-
| `
|
|
92
|
-
| `
|
|
93
|
-
| `organization.
|
|
94
|
-
| `
|
|
95
|
-
| `
|
|
96
|
-
| `
|
|
97
|
-
| `
|
|
98
|
-
| `
|
|
99
|
-
| `limits.
|
|
100
|
-
| `limits.
|
|
101
|
-
| `limits.
|
|
102
|
-
| `limits.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
Confluence Server, Data Center Basic Auth и OAuth app-flow не поддерживаются. Совместимость определяется preflight-проверкой необходимых API/capabilities, а не сертификацией каждой patch-версии.
|
|
126
|
-
|
|
127
|
-
## Как получить токены
|
|
128
|
-
|
|
129
|
-
### Yandex Wiki
|
|
130
|
-
|
|
131
|
-
- [ ] Создайте приложение в [Яндекс OAuth](https://oauth.yandex.ru/).
|
|
132
|
-
- [ ] Выдайте права Wiki на чтение; для destination также нужны права записи.
|
|
133
|
-
- [ ] Получите OAuth-токен пользователя с доступом к страницам. Для федеративного пользователя Yandex Cloud допустим IAM-токен и `authType: iam`.
|
|
134
|
-
- [ ] Найдите ID организации в **Yandex Tracker → Администрирование → Организации**.
|
|
135
|
-
- [ ] Укажите `organization.type: yandex360` для Яндекс 360 или `cloud` для Cloud Organization.
|
|
136
|
-
- [ ] Запишите токен в `connections.<name>.token` выбранного профиля.
|
|
137
|
-
|
|
138
|
-
### Confluence Data Center
|
|
139
|
-
|
|
140
|
-
- [ ] Откройте **Avatar → Settings → Personal access tokens → Create token**.
|
|
141
|
-
- [ ] Создайте PAT и запишите его в `connections.<name>.token`.
|
|
142
|
-
- [ ] Используйте `deployment: data-center` и `authType: pat`.
|
|
143
|
-
- [ ] Проверьте права на чтение source и создание/изменение страниц и вложений destination.
|
|
144
|
-
|
|
145
|
-
### Confluence Cloud
|
|
146
|
-
|
|
147
|
-
- [ ] Создайте [Atlassian API token](https://id.atlassian.com/manage-profile/security/api-tokens).
|
|
148
|
-
- [ ] Используйте `deployment: cloud`, `authType: api-token`, `token` и `email`.
|
|
149
|
-
- [ ] Запишите API token и email аккаунта непосредственно в выбранный профиль.
|
|
150
|
-
- [ ] Проверьте доступ аккаунта к source и destination spaces.
|
|
151
|
-
|
|
152
|
-
## Параметры
|
|
91
|
+
| `defaults.timeoutMs` | общий | `1000..300000`; `30000` | Таймаут HTTP-запроса |
|
|
92
|
+
| `defaults.concurrency` | общий | `1..64`; `4` | Общая параллельность операции |
|
|
93
|
+
| `connections.<name>` | общий | имя `[a-z0-9._-]+` | Именованное подключение |
|
|
94
|
+
| `type` | любой | `yandex-wiki` или `confluence` | Провайдер |
|
|
95
|
+
| `token` | любой | непустой | OAuth, IAM, PAT или API token |
|
|
96
|
+
| `apiUrl` / `webUrl` | Yandex Wiki | URL API v1 / базовый web URL | API-запросы, ссылки и выбор профиля |
|
|
97
|
+
| `authType` | Yandex Wiki | `oauth` или `iam`; `oauth` | Схема авторизации; IAM допустим только с Cloud Organization |
|
|
98
|
+
| `organization.type` | Yandex Wiki | `yandex360` или `cloud`; `yandex360` | Выбирает `X-Org-Id` или `X-Cloud-Org-Id` |
|
|
99
|
+
| `organization.id` | Yandex Wiki | непустой | ID организации |
|
|
100
|
+
| `deployment` | Confluence | `data-center` или `cloud` | Тип инстанса |
|
|
101
|
+
| `baseUrl` | Confluence | URL, включая context path | Базовый адрес API и web |
|
|
102
|
+
| `authType` | Confluence | `pat` или `api-token` | PAT для Data Center; API token для Cloud |
|
|
103
|
+
| `email` | Confluence Cloud | непустой | Atlassian account email для Basic Auth |
|
|
104
|
+
| `limits.readConcurrency` | любой | `1..64`; `4` | Параллельные чтения |
|
|
105
|
+
| `limits.writeConcurrency` | любой | `1..32`; `2` | Параллельные записи |
|
|
106
|
+
| `limits.downloadConcurrency` / `uploadConcurrency` | любой | `1..32`; `2` | Параллельные передачи файлов |
|
|
107
|
+
| `limits.requestsPerSecond` | любой | `1..1000`; `8` | Устойчивая частота запросов |
|
|
108
|
+
| `limits.burst` | любой | `1..1000`; Yandex `8`, Confluence `10` | Кратковременный burst |
|
|
109
|
+
|
|
110
|
+
### Токены
|
|
111
|
+
|
|
112
|
+
#### Yandex Wiki
|
|
113
|
+
|
|
114
|
+
1. Создайте приложение в [Яндекс OAuth](https://oauth.yandex.ru/) и выдайте ему [права Wiki](https://yandex.ru/support/wiki/ru/api-ref/access) на чтение, а для destination — на запись.
|
|
115
|
+
2. Получите OAuth-токен пользователя с доступом к нужным страницам. Для федеративного пользователя Yandex Cloud допустим IAM-токен.
|
|
116
|
+
3. Найдите ID в **Yandex Tracker → Администрирование → Организации** и выберите `organization.type: yandex360` либо `cloud`.
|
|
117
|
+
4. Запишите значения в Yandex-профиль; для IAM используйте `authType: iam` и Cloud Organization.
|
|
118
|
+
|
|
119
|
+
#### Confluence Data Center
|
|
120
|
+
|
|
121
|
+
1. Откройте **Avatar → Settings → Personal access tokens → Create token**; порядок действий описан в [документации Atlassian](https://confluence.atlassian.com/enterprise/using-personal-access-tokens-1026032365.html).
|
|
122
|
+
2. Запишите PAT в профиль с `deployment: data-center` и `authType: pat`.
|
|
123
|
+
3. Убедитесь, что пользователь может читать source и создавать страницы и attachments в destination.
|
|
124
|
+
|
|
125
|
+
#### Confluence Cloud
|
|
126
|
+
|
|
127
|
+
1. Создайте [Atlassian API token](https://id.atlassian.com/manage-profile/security/api-tokens).
|
|
128
|
+
2. Используйте `deployment: cloud`, `authType: api-token`, `email` и `token`; аккаунту нужен доступ к исходному и целевому spaces.
|
|
129
|
+
|
|
130
|
+
## CLI
|
|
153
131
|
|
|
154
132
|
### Команды
|
|
155
133
|
|
|
156
134
|
| Команда | Назначение |
|
|
157
135
|
| --- | --- |
|
|
158
|
-
| `ywtc init [
|
|
159
|
-
| `ywtc doctor [options]` | Проверить workspace; с source и destination выполнить read-only preflight |
|
|
160
|
-
| `ywtc migrate
|
|
161
|
-
| `ywtc migrate
|
|
162
|
-
| `ywtc reports list [
|
|
163
|
-
| `ywtc reports open [run-id\|last] [
|
|
164
|
-
| `ywtc update [
|
|
165
|
-
| `ywtc --help`, `ywtc <command> --help` | Показать общую или командную справку |
|
|
166
|
-
| `ywtc --version` | Показать версию |
|
|
136
|
+
| `ywtc init [-i] [-w <path>]` | Создать workspace или настроить оба подключения в TTY-мастере |
|
|
137
|
+
| `ywtc doctor [options]` | Проверить workspace; с source и destination — выполнить read-only preflight |
|
|
138
|
+
| `ywtc migrate -i` | Выбрать параметры, выполнить dry-run и при допустимом результате явно перейти к live |
|
|
139
|
+
| `ywtc migrate -s <locator> -d <locator\|directory> [options]` | Неинтерактивный перенос или экспорт |
|
|
140
|
+
| `ywtc reports list [-w <path>]` | Показать локальные отчёты от новых к старым |
|
|
141
|
+
| `ywtc reports open [run-id\|last] [-w <path>]` | Открыть выбранный или последний корректный отчёт |
|
|
142
|
+
| `ywtc update [-i] [-c npm\|brew]` | Проверить или установить обновление безопасным для текущего канала способом |
|
|
167
143
|
|
|
168
144
|
### Опции
|
|
169
145
|
|
|
170
|
-
| Полная
|
|
171
|
-
| --- | --- | --- |
|
|
172
|
-
| `--interactive
|
|
173
|
-
| `--workdir
|
|
174
|
-
| `--source
|
|
175
|
-
| `--destination
|
|
176
|
-
| `--source-profile
|
|
177
|
-
| `--destination-profile
|
|
178
|
-
| `--scope
|
|
179
|
-
| `--source-status
|
|
180
|
-
| `--comments` / `--no-comments
|
|
181
|
-
| `--format
|
|
182
|
-
| `--archive
|
|
183
|
-
| `--dry-run
|
|
184
|
-
| `--fresh
|
|
185
|
-
| `--open-report
|
|
186
|
-
| `--concurrency
|
|
187
|
-
| `--state
|
|
188
|
-
| `--install
|
|
189
|
-
| `--via
|
|
190
|
-
| `--help
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
-
|
|
198
|
-
-
|
|
199
|
-
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
- `
|
|
208
|
-
|
|
209
|
-
|
|
146
|
+
| Полная / short | Команды | Значения и назначение |
|
|
147
|
+
| --- | --- | --- |
|
|
148
|
+
| `--interactive`, `-i` | `init`, `migrate` | TTY-мастер; в `migrate` переданные опции становятся редактируемыми defaults |
|
|
149
|
+
| `--workdir`, `-w` | `init`, `doctor`, `migrate`, `reports` | Явный workspace; поддерживается `~/...` |
|
|
150
|
+
| `--source`, `-s` | `doctor`, `migrate` | URL, page ID или Yandex slug; обязателен в неинтерактивном `migrate` |
|
|
151
|
+
| `--destination`, `-d` | `doctor`, `migrate` | Родительская страница или каталог; обязателен в неинтерактивном `migrate` |
|
|
152
|
+
| `--source-profile`, `-S` | `doctor`, `migrate` | Имя source-профиля при неоднозначном коротком locator |
|
|
153
|
+
| `--destination-profile`, `-D` | `doctor`, `migrate` | Имя remote destination-профиля; запрещён для файлового экспорта |
|
|
154
|
+
| `--scope`, `-m` | `doctor`, `migrate` | `page`, `subtree` (default), `linked` |
|
|
155
|
+
| `--source-status`, `-t` | `doctor`, `migrate` | `all` (default) или `current`; root включается всегда |
|
|
156
|
+
| `--comments`, `-C` / `--no-comments`, `-N` | `doctor`, `migrate` | Комментарии включены по умолчанию; `-N` исключает все comment API calls |
|
|
157
|
+
| `--format`, `-f` | `doctor`, `migrate` | `markdown` или `html`; делает destination файловым |
|
|
158
|
+
| `--archive`, `-a` | `migrate` | Дополнительный ZIP для файлового экспорта |
|
|
159
|
+
| `--dry-run`, `-n` | `migrate` | Полный discovery/render без destination writes |
|
|
160
|
+
| `--fresh`, `-F` | `migrate` | Игнорировать mappings; существующий live-state сохранить как backup |
|
|
161
|
+
| `--open-report`, `-o` | `migrate` | Открыть итоговый HTML; ошибка opener не меняет outcome переноса |
|
|
162
|
+
| `--concurrency`, `-j` | `migrate` | `1..64`; иначе `defaults.concurrency` |
|
|
163
|
+
| `--state`, `-r` | `migrate` | Явный state path внутри workspace |
|
|
164
|
+
| `--install`, `-i` | `update` | Установить найденное обновление |
|
|
165
|
+
| `--via`, `-c` | `update` | `npm` или `brew` |
|
|
166
|
+
| `--help`, `-h` / `--version`, `-v` | CLI | Справка / версия |
|
|
167
|
+
|
|
168
|
+
Short-алиасы локальны для команды: `migrate -i` запускает мастер, `update -i` устанавливает обновление.
|
|
169
|
+
|
|
170
|
+
### Locators и выбор страниц
|
|
171
|
+
|
|
172
|
+
- Yandex Wiki: полный URL, числовой page ID или slug вида `team/start`.
|
|
173
|
+
- Confluence: числовой page ID, URL с `pageId=<id>`, `/pages/<id>` или `/content/<id>`.
|
|
174
|
+
- Полный URL выбирает профиль по нормализованному base URL. Для неоднозначного ID/slug укажите профиль явно.
|
|
175
|
+
- Каталог считается destination только с `--format`.
|
|
176
|
+
|
|
177
|
+
| Scope | Выбор |
|
|
178
|
+
| --- | --- |
|
|
179
|
+
| `page` | Только root |
|
|
180
|
+
| `subtree` | Root и все доступные структурные descendants до последнего уровня; default |
|
|
181
|
+
| `linked` | Детерминированный BFS по внутренним ссылкам и page/include references; циклы завершаются безопасно |
|
|
182
|
+
|
|
183
|
+
`--source-status all` включает все доступные descendants: в Yandex Wiki — `actual` и `obsolete`; `current` оставляет только `actual/current`. Confluence зависит от hierarchy API и может не возвращать archived, trashed и historical versions.
|
|
184
|
+
|
|
185
|
+
### Примеры
|
|
210
186
|
|
|
211
187
|
```bash
|
|
212
|
-
# Перенести
|
|
213
|
-
ywtc migrate
|
|
214
|
-
|
|
188
|
+
# Перенести структурное поддерево
|
|
189
|
+
ywtc migrate -s https://wiki.example.com/team/start \
|
|
190
|
+
-d https://confluence.example.com/confluence/pages/viewpage.action?pageId=123
|
|
215
191
|
|
|
216
|
-
# Перенести
|
|
217
|
-
ywtc migrate
|
|
218
|
-
|
|
219
|
-
|
|
192
|
+
# Перенести рекурсивно связанные страницы
|
|
193
|
+
ywtc migrate -s https://wiki.example.com/team/start \
|
|
194
|
+
-d https://confluence.example.com/confluence/pages/viewpage.action?pageId=123 \
|
|
195
|
+
-m linked
|
|
220
196
|
|
|
221
|
-
# Создать автономный HTML
|
|
222
|
-
ywtc migrate
|
|
223
|
-
|
|
224
|
-
--format html --archive
|
|
197
|
+
# Создать автономный HTML и ZIP
|
|
198
|
+
ywtc migrate -s https://wiki.example.com/team/start \
|
|
199
|
+
-d ./exports/knowledge-base -f html -a
|
|
225
200
|
|
|
226
201
|
# Открыть последний корректный отчёт
|
|
227
202
|
ywtc reports open last
|
|
228
203
|
```
|
|
229
204
|
|
|
230
|
-
`doctor` без endpoints проверяет workspace и конфигурацию, а с source и destination выполняет page-specific read-only capability-preflight.
|
|
231
|
-
|
|
232
205
|
## Файловый экспорт
|
|
233
206
|
|
|
234
|
-
Markdown создаёт `index.md`, `pages/`, `attachments
|
|
235
|
-
|
|
236
|
-
При включённых комментариях каждая страница получает секцию `Комментарии` с раскрываемыми ветками. Связанные из комментариев файлы находятся в одном ZIP рядом с attachments страницы; `manifest.json` внутри ZIP связывает source comment ID, исходную ссылку, исходное и архивное имя, размер и SHA-256.
|
|
237
|
-
|
|
238
|
-
Экспорт сначала строится в staging-каталоге. Существующий каталог заменяется только при строгом актуальном manifest с `tool: ywtc` и той же canonical identity, а прежний каталог сохраняется как timestamped backup. `--archive` оставляет каталог и создаёт новый ZIP, не перезаписывая существующий архив.
|
|
239
|
-
|
|
240
|
-
## State
|
|
207
|
+
Markdown создаёт `index.md`, `pages/`, `attachments/` и `.ywtc-export.json`. HTML создаёт автономный адаптивный сайт с локальным CSS, который работает через `file://` и на static hosting без CDN или внешнего runtime. `_source/` появляется только для страниц, которым нужен raw snapshot.
|
|
241
208
|
|
|
242
|
-
|
|
209
|
+
Внутренние ссылки и resources становятся относительными. Комментарии входят в страницу раскрываемыми ветками; явно связанные с ними файлы находятся в одном ZIP с `manifest.json`.
|
|
243
210
|
|
|
244
|
-
|
|
211
|
+
Экспорт строится в соседнем staging-каталоге. Существующий каталог заменяется только при актуальном manifest с `tool: ywtc` и той же canonical identity; предыдущая версия сохраняется как timestamped backup. `--archive` оставляет каталог и создаёт новый ZIP, не перезаписывая существующий.
|
|
245
212
|
|
|
246
|
-
|
|
247
|
-
- Переключение `current → all` расширяет тот же state новыми страницами без дубликатов; обратное переключение не удаляет mappings вне текущего выбора.
|
|
248
|
-
- Подтверждённая state-mapping означает, что source авторитетен: отличающийся body, title или parent mapped-страницы обновляется поверх актуальной destination-версии, а прежнее содержимое остаётся в истории провайдера.
|
|
249
|
-
- Неверный parent исправляется до потомков. Временный `404` повторяется с backoff; устойчиво пропавшая mapping восстанавливается под ожидаемым родителем с сохранением прежнего ID.
|
|
250
|
-
- Страницы и файлы сверяются по ID, размеру и SHA-256. Cache переиспользуется; неудачные вложения получают стабильные уникальные имена и повторяются без `--fresh`.
|
|
251
|
-
- Прежний неизменённый placeholder заменяется source-derived контентом. Ошибка файла оставляет полный текст и source-ссылку, даёт `partial` и повторяется позже.
|
|
252
|
-
- Архивы комментариев и ZIP проверяются и переиспользуются. Confluence-архив обновляется версией, Yandex Wiki получает новую ревизию; удалённый mapped-комментарий создаётся заново, исчезнувший source-архив помечается `stale`.
|
|
253
|
-
- Запуск с `--no-comments` не обращается к comment API и не удаляет ранее созданные архивы; следующий обычный запуск дополнит тот же state.
|
|
254
|
-
- `conflict` используется только при доказанной неоднозначности immutable ownership/identity: несколько source mappings на один destination ID, несовпадение возвращённого immutable ID или несколько равноправных ownership-кандидатов. Версия, title, URL, slug, parent, fingerprint, HTTP `409`, слово `conflict` в сообщении и коллизия имени сами по себе конфликтом не являются.
|
|
255
|
-
- `--fresh` игнорирует mappings; перед live-run прежний state сохраняется как backup, а destination может получить новые объекты.
|
|
256
|
-
- Удалённые из source объекты автоматически не удаляются из destination.
|
|
213
|
+
## State и повторные запуски
|
|
257
214
|
|
|
258
|
-
|
|
215
|
+
State находится в `<workdir>/.states/<automatic-id>.json`. ID зависит от канонических профилей и page IDs, а для экспорта — ещё от формата; URL/ID/slug, `scope` и `source-status` его не меняют. Относительный `--state` разрешается только внутри workspace.
|
|
259
216
|
|
|
260
|
-
|
|
217
|
+
- Повтор одинакового направления подхватывает mappings, cache и незавершённые операции без дубликатов.
|
|
218
|
+
- Для доказанной mapping source авторитетен: body, title и parent обновляются поверх текущей destination-версии, а прежнее содержимое остаётся в истории. Unmapped и неоднозначно принадлежащие объекты не перезаписываются.
|
|
219
|
+
- Неверная иерархия исправляется сверху вниз; временные `404` повторяются, пропавшая mapped-страница восстанавливается под ожидаемым родителем без удаления старого объекта.
|
|
220
|
+
- Файлы согласуются по immutable ID, размеру и SHA-256; проверенный cache переиспользуется, занятые имена получают стабильный суффикс.
|
|
221
|
+
- Комментарии и их ZIP проверяются и переиспользуются. Confluence-архив обновляется версией, Yandex Wiki получает новую ревизию; исчезнувший source-архив сохраняется как stale.
|
|
222
|
+
- `current → all` расширяет тот же state; обратное переключение не удаляет прежние mappings. Удаление в source также не удаляет destination.
|
|
223
|
+
- `--fresh` игнорирует mappings и сохраняет прежний state как backup; destination при этом может получить новые объекты.
|
|
261
224
|
|
|
262
|
-
|
|
225
|
+
Live-run использует exclusive lock; stale lock восстанавливается. При SIGINT/SIGTERM новые задачи не запускаются, безопасные активные операции завершаются, state и отчёт сохраняются. Коды выхода: `0` — completed, `1` — partial/verification failure, `2` — usage/config/preflight, `130`/`143` — сигнал.
|
|
263
226
|
|
|
264
|
-
|
|
227
|
+
## Отчёты и статусы
|
|
265
228
|
|
|
266
|
-
|
|
229
|
+
Каждый запуск создаёт `<workdir>/.states/reports/<run-id>/index.html` и очищенный `report.json`, затем печатает URL и команду открытия. Используйте `--open-report`, `ywtc reports list` или `ywtc reports open [run-id|last]`; без selector `open` также выбирает последний корректный отчёт.
|
|
267
230
|
|
|
268
|
-
|
|
231
|
+
Автономный отчёт показывает только ненулевые показатели, канонические source/destination, исходную иерархию, исключённые страницы и проблемы. Дерево поддерживает поиск и фильтры; детали страницы содержат доступные files, comments, side-by-side comparison и диагностику. RU/EN и system/light/dark переключаются иконками. `report.json` не содержит body страниц, тексты комментариев или preview HTML.
|
|
269
232
|
|
|
270
|
-
|
|
233
|
+
### Outcomes объектов
|
|
271
234
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
|
277
|
-
|
|
278
|
-
| `
|
|
279
|
-
| `
|
|
280
|
-
| `
|
|
281
|
-
| `blocked` | Страница не запускалась из-за недоступного failed/conflict родителя или другой зависимости | Нет в этом запуске | Исправить указанную upstream-ошибку и повторить запуск |
|
|
282
|
-
| `conflict` | Immutable ownership/identity destination доказанно неоднозначна, в отчёте перечислены кандидаты | Нет автоматической перезаписи | Проверить candidate IDs и устранить неоднозначное сопоставление |
|
|
283
|
-
| `planned` | Объект рассчитан в `--dry-run`; запись не выполнялась | Нет | Убрать `--dry-run` для переноса |
|
|
284
|
-
| `not-started` | Live-run остановился до начала независимой операции | Нет | Повторить ту же миграцию |
|
|
285
|
-
|
|
286
|
-
Статусы файлов:
|
|
235
|
+
| Outcome | Объекты | Значение и действие |
|
|
236
|
+
| --- | --- | --- |
|
|
237
|
+
| `complete` | страницы, файлы, comment archives | Записано и проверено; действий не требуется |
|
|
238
|
+
| `partial` | страницы, файлы, comment archives | Основное представление доступно, но часть данных отсутствует или не проверена; изучить degradation и повторить retryable-операцию |
|
|
239
|
+
| `failed` | все | Операция началась, но корректная запись или проверка не получилась; исправить root error и повторить запуск |
|
|
240
|
+
| `blocked` | страницы, файлы, comment archives | Операция не начиналась из-за недоступного parent/dependency; сначала исправить upstream failure/conflict |
|
|
241
|
+
| `conflict` | mapped-объекты | Immutable ownership/identity неоднозначна; проверить candidate IDs. Обычная новая версия, ручное изменение, title collision или HTTP `409` конфликтом не считаются |
|
|
242
|
+
| `planned` | все | Объект рассчитан в dry-run, записи не было; запустить live |
|
|
243
|
+
| `not-started` | все | Live-run остановился до независимой операции; повторить запуск |
|
|
287
244
|
|
|
288
|
-
|
|
289
|
-
|---|---|---:|---|
|
|
290
|
-
| `complete` | Файл загружен и проверен | Да | Ничего |
|
|
291
|
-
| `partial` | Файл доступен через сохранённый fallback, но нативная передача неполна | Частично | Проверить fallback и повторить retryable-операцию |
|
|
292
|
-
| `failed` | Download, upload или verification файла выполнялся и завершился ошибкой | Возможно частично | Проверить причину и повторить запуск |
|
|
293
|
-
| `blocked` | Файл не обрабатывался, потому что destination-страница недоступна | Нет в этом запуске | Сначала устранить указанную ошибку страницы |
|
|
294
|
-
| `planned` | Файл только запланирован в `--dry-run` | Нет | Запустить без `--dry-run` |
|
|
295
|
-
| `not-started` | Live-run прерван до начала обработки файла | Нет | Повторить ту же миграцию |
|
|
245
|
+
### Качество преобразования
|
|
296
246
|
|
|
297
|
-
|
|
247
|
+
| Категория | Влияние |
|
|
248
|
+
| --- | --- |
|
|
249
|
+
| Normalization | Безопасная разница сериализации или нативный эквивалент; остаётся `complete` |
|
|
250
|
+
| Adaptation | Другое представление с проверенной полнотой, например Grid → static table; остаётся `complete` |
|
|
251
|
+
| Preserved external reference | Внешний URL сохранён как внешний и не требует копирования; остаётся `complete` |
|
|
252
|
+
| Degradation | Данные или значимая структура отсутствуют либо полнота не доказана; даёт `partial` |
|
|
253
|
+
| Warning | Требует внимания, но сам по себе не доказывает потерю |
|
|
254
|
+
| Error | Неудавшаяся API/record/verification операция; итог зависит от сохранности полного body и объекта |
|
|
298
255
|
|
|
299
|
-
|
|
256
|
+
Итог запуска: `completed`, `completed-with-warnings`, `partial`, `failed`, `cancelled` или `interrupted`. HTML, JSON, terminal summary и `reports list` используют одинаковые totals; зависимые `blocked` объекты не считаются отдельными root errors.
|
|
300
257
|
|
|
301
258
|
## Разработка
|
|
302
259
|
|
|
@@ -308,6 +265,6 @@ npm run workspace:init
|
|
|
308
265
|
npm run check
|
|
309
266
|
```
|
|
310
267
|
|
|
311
|
-
`npm run check` запускает
|
|
268
|
+
`npm run check` запускает release hygiene и security audit, TypeScript, Biome, Knip, Vitest, Playwright, сборку, package smoke-test и строгую OpenSpec-валидацию. Любое изменение проходит цикл из [`AGENTS.md`](AGENTS.md).
|
|
312
269
|
|
|
313
|
-
Release Please рассчитывает SemVer из Conventional Commits. После merge release PR GitHub Actions
|
|
270
|
+
Release Please рассчитывает SemVer из Conventional Commits. После merge release PR GitHub Actions публикует GitHub Release и npm-пакет с OIDC provenance, затем генерирует, устанавливает и тестирует Homebrew-формулу.
|