Один репозиторий, три клиента и общие контракты

Один язык и один репозиторий ещё не означают общий протокол.

В ZionVox рядом живут backend, браузерный клиент, mobile и публичный web-контур. Но у приложений отдельные package.json и lock-файлы, а npm workspaces в корне нет. Общие библиотеки подключаются через file-зависимости. Значит, порядок установки и сборки — реальная часть архитектуры.

Я разделяю три вида общей логики: сетевые структуры и подписи в p2p-protocol, wire-форматы ошибок в api-contract, клиентские механизмы Bot API в bot-api-client. Это не повод переносить в shared каждую удобную функцию: зависимости от браузера или мобильного runtime быстро лишат пакет переносимости.

Особенно важна граница между TypeScript и сетью. Тип исчезает при исполнении. Входящий JSON всё ещё может оказаться старым форматом или страницей ошибки посредника.

Поэтому общий apiErrorBodySchema проверяет данные через Zod: error должен быть true, code — непустой строкой до 128 символов, details — не длиннее 2000. Разбор возвращает null, если формат не совпал. Машинное решение строится на code, а не на поиске подстроки в человеческом message.

Для подписанных данных этого мало. Нужна согласованная последовательность байтов: canonicalJson задаёт представление, на котором строится подпись. Похожие объекты без одинаковой канонизации не гарантируют успешной проверки.

На сервере есть ещё одна полезная граница: API и signaling запускаются разными runtime из одного образа. При этом база и код общие. Я называю это разделением выполнения, а не независимыми микросервисами. Масштабирование процесса не равно независимости модели данных.

Сборка отражает тот же подход: сначала shared packages, потом backend и клиенты. В истории есть отдельное исправление установки api-contract перед backend npm ci. Оставшийся на рабочей машине dist способен скрыть такую ошибку; чистый CI — нет.

Что взять себе: рисовать граф сборки, валидировать сеть во время исполнения, отделять границу процесса от границы данных и не считать соседство папок доказательством совместимости.

В полной статье — карта зависимостей, пример runtime-схемы и разбор компромиссов. Я проектирую такие архитектуры и для клиентских проектов.

https://arhellist.ru/blog/odin-repozitoriy-tri-klienta-i-obschie-kontrakty/

Один репозиторий, три клиента и общие контракты | Сетка — социальная сеть от hh.ru