Metadata-Version: 2.4
Name: s-adapterkit
Version: 0.1.2
Summary: Переиспользуемый SDK сетевых адаптеров: Transport/Auth/RetryPolicy/HttpClient, ErrorMap, пагинация, браузер/антибот-транспорты, SessionStore, BaseAdapter + контракт плагинов. Тонкий коннектор поверх librarykit.
Author: Dmitry
License: MIT
License-File: LICENSE
Requires-Python: >=3.11
Requires-Dist: s-clikit
Requires-Dist: s-librarykit
Provides-Extra: antibot
Requires-Dist: curl-cffi>=0.7; extra == 'antibot'
Provides-Extra: browser
Requires-Dist: playwright>=1.40; extra == 'browser'
Provides-Extra: dev
Requires-Dist: hypothesis>=6; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest>=8.3; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Requires-Dist: ruff>=0.8; extra == 'dev'
Provides-Extra: oauth
Requires-Dist: authlib>=1.3; extra == 'oauth'
Description-Content-Type: text/markdown

# adapterkit

**Тонкий коннектор сетевых адаптеров поверх [librarykit](https://gitlab.com/S-kits/librarykit).**
adapterkit отвечает на один вопрос: «как подключить сетевой адаптер к приложению».
Он даёт декларативный контракт плагина, реестр с автодискавери через entry-points и
базовый фасад адаптера — а весь сетевой движок (transport/auth/retry/errmap/
pagination/sessions/antibot/browser) **реэкспортирует из librarykit**, не дублируя
его. Пишется один раз, переиспользуется любым доменным пакетом.

```
librarykit   ← КОРЕНЬ: весь сетевой движок (transport/auth/retry/errmap/
                        pagination/sessions/antibot/browser)
   ▲
adapterkit   ← ЭТОТ КИТ: контракт NetworkAdapter + registry (entry-points) +
                        BaseAdapter + orchestration_api.
                        Остальное — тонкий реэкспорт-шим из librarykit.
   ▲
домен        ← конкретные адаптеры (endpoint-таблица + мапперы на сеть)
```

Зависимости направлены **только внутрь**: adapterkit зависит от `librarykit`
(и от `clikit` для CLI-примитивов), но НЕ от домена. Адаптеры кодируются против
стабильных `typing.Protocol` из `adapterkit.contract` (структурный контракт, а не
наследование от домена). Композиция конкретных реализаций — единственный
composition root на приложение.

## Установка

```bash
uv add s-adapterkit
```

Имя дистрибутива — `s-adapterkit`, имя для импорта — `adapterkit`. Граф китов
(`librarykit`, `clikit`) подтянется автоматически как транзитивные зависимости.

Опциональные extra:

```bash
uv add "s-adapterkit[browser]"   # Playwright — browser-login
uv add "s-adapterkit[antibot]"   # curl-cffi — JA3-impersonate
uv add "s-adapterkit[oauth]"     # authlib — OAuth2-flows
```

## Быстрый старт

Описать адаптер декларативно и зарегистрировать его в реестре:

```python
from adapterkit import BaseAdapter, Endpoint, register_adapter

class TwitterAdapter(BaseAdapter):
    api_version = 1
    endpoints = {
        "search": Endpoint(name="search", method="GET", path="/2/tweets/search/recent"),
    }

register_adapter("twitter", TwitterAdapter)
```

Либо отдать адаптер на автодискавери — объявить entry-point в своём `pyproject.toml`,
и любой потребитель adapterkit подхватит его без явного импорта:

```toml
[project.entry-points."adapterkit.adapters"]
twitter = "my_package.adapter:TwitterAdapter"
```

```python
from adapterkit import discover_adapters, get_adapter_class

discover_adapters()                       # загрузить все плагины из entry-points
cls = get_adapter_class("twitter")        # получить класс по имени сервиса
```

## Карта модулей

| Модуль | Назначение | Реализация |
|--------|-----------|------------|
| `contract.py` | граничные `Protocol` (`NetworkAdapter`/`Transport`/`Auth`/`ErrorMapper`/`Paginator`/`SessionStoreProtocol`) + DTO (`Endpoint`/`SessionRef`/`Creds`) + `ADAPTER_API_VERSION`/`MIN_SUPPORTED_API_VERSION` | контракт коннектора |
| `registry.py` | `AdapterRegistry` + автодискавери через entry-points `adapterkit.adapters`, ленивая загрузка, ручная регистрация | код коннектора |
| `base.py` | `BaseAdapter` + ресурс-под-сервисы (`ContentResource`/`CommentsResource`/`MetricsResource`/`SearchResource`) — Stripe-стиль фасад | код коннектора |
| `orchestration_api.py` | тонкий registry-driven API: `onboard_all` / `health_check_all` (без импортов домена) | код коннектора |
| `onboarding_contract.py` | онбординг/health-контракты (`LoginMode`/`OnboardingProtocol`/`HealthProtocol`, api_version 2) | реэкспорт `librarykit.protocols` |
| `errors.py` | единая иерархия ошибок | реэкспорт `librarykit.errors` |
| `retry.py` | header-driven `RetryPolicy` | реэкспорт `librarykit.retry` |
| `transport.py` / `client.py` | `HttpxTransport` + choke-point `HttpClient` | реэкспорт `librarykit.transport` |
| `auth.py` | `TokenAuth`/`OAuth2Auth`/`CookieSessionAuth`/`BrowserLoginAuth` | реэкспорт `librarykit.auth` |
| `errmap.py` | декларативная карта ответ → доменная ошибка | реэкспорт `librarykit.errmap` |
| `pagination.py` | `CursorPaginator` (offset/cursor/page) | реэкспорт `librarykit.pagination` |
| `sessions.py` | envelope-шифрованный `SessionStore` | реэкспорт `librarykit.sessions` |
| `antibot.py` | выбор транспорта Tier 0-4 (curl-cffi JA3 / CDP) | реэкспорт `librarykit.antibot` |
| `browser.py` | warm/cold-login (требует extra `browser`) | реэкспорт `librarykit.browser` |

Всё, что помечено «реэкспорт», — тонкий shim: единая реализация живёт в `librarykit`,
adapterkit лишь предоставляет её под привычным именем. Собственный код коннектора —
только `contract`/`registry`/`base`/`orchestration_api`.

## Разработка

```bash
uv sync --extra dev
uv run --extra dev pytest -q
uv run --extra dev ruff check adapterkit
```

Граф китов (`librarykit`/`clikit`) тянется из публичной группы
[gitlab.com/S-kits](https://gitlab.com/S-kits) как git-зависимости. Для локальной
правки кита временно укажите path-источник в `[tool.uv.sources]` (см. комментарий
в `pyproject.toml`) и выполните `uv lock --upgrade`.

## Лицензия

MIT © 2026 Dmitry.
