docs: rewrite JsonRpcBundle docs, add SDK docs, move them under docs/api
uk/docs/api/json-rpc-bundle/documentation.md
новий файл +134
−0
1
+
# Документація API
2
+
3
+
Документацію не треба писати окремо: бандл будує її з коду — типів PHP, PHPDoc, DTO, enum, обмежень валідації та атрибутів.
4
+
5
+
| Запит | Відповідь |
6
+
| --- | --- |
7
+
| `GET /rpc` | Документ [OpenRPC](https://spec.open-rpc.org/) |
8
+
| `GET /rpc?info` | Лише заголовок документа (`info`, `servers`) без методів і схем |
9
+
| `GET /rpc/postman` | Колекція Postman |
10
+
| `GET /rpc/v2`, `GET /rpc/v2/postman` | Те саме для [версії API](/docs/api/json-rpc-bundle/functionality/versions) |
11
+
| `GET /rpc/internal`, … | Те саме для [групи API](/docs/api/json-rpc-bundle/functionality/groups) |
12
+
13
+
Якщо в [налаштуваннях](/docs/api/json-rpc-bundle/config) `protected_doc: true`, ці запити теж потребують токена.
14
+
15
+
## Що потрапляє в OpenRPC
16
+
17
+
* **Методи** згруповані тегами за псевдонімом класу з [`#[RPC\Info]`](/docs/api/json-rpc-bundle/add_rpc_service/info); повна назва класу — в описі тегу.
18
+
* **Параметри й результат** — JSON Schema з нативних типів і PHPDoc: union, nullable, `Dto[]`, `array<string, Dto>`; значення за замовчуванням і обов'язковість.
19
+
* **DTO та enum** винесені в `#/components/schemas` і підключаються через `$ref`, тож кожен описаний один раз.
20
+
* **Обмеження** з [`#[RPC\Assertions]`](/docs/api/json-rpc-bundle/add_rpc_service/assertions) перетворюються на правила схеми.
21
+
* **Помилки** методу — з тегів `@throws` у докблоці (код і повідомлення кожного винятку).
22
+
* **Застарілі методи** (`@deprecated`, `#[\Deprecated]`) позначаються `"deprecated": true`.
23
+
* **Версії** — перелік у `info.x-versions`; службова інформація UFO — у розширеннях `x-ufo`.
24
+
25
+
```php
26
+
/**
27
+
* Returns a user by id
28
+
* @param int $id User identifier
29
+
* @return UserDto
30
+
* @throws UserNotFoundException
31
+
*/
32
+
public function get(int $id): UserDto
33
+
```
34
+
35
+
## Колекція Postman
36
+
37
+
`GET /rpc/postman` повертає колекцію з усіма методами й прикладами параметрів. Назва колекції: `RPC: <project_name> <версія>`, для групи — з суфіксом `[група]`. Адреса сервера — у змінній `base_url`, токен — у заголовку з назвою `token_name`.
38
+
39
+
## Переклад назв і описів методів
40
+
41
+
Назву (`summary` в OpenRPC) і опис методу можна задати й перекласти без зміни коду. Переклади кладуться в `translations/rpc.<locale>.yaml` (або `.yml`), ключ — назва RPC-методу:
42
+
43
+
```yaml
44
+
# translations/rpc.uk.yaml
45
+
catalog.list:
46
+
title: Каталог
47
+
description: Список товарів
48
+
```
49
+
50
+
```yaml
51
+
# translations/rpc.en.yaml
52
+
catalog.list:
53
+
title: Catalog
54
+
description: List of products
55
+
```
56
+
57
+
Мова вибирається з заголовка `Accept-Language` серед мов, для яких є файли перекладів (`uk-UA` дає `uk`); без збігу — `kernel.default_locale`. Відповідь отримує `Content-Language` і `Vary: Accept-Language`.
58
+
59
+
### Переклади для групи API
60
+
61
+
Перевизначення для однієї [групи](/docs/api/json-rpc-bundle/functionality/groups) — у підтеці `rpc/`:
62
+
63
+
```
64
+
translations/rpc.uk.yaml # база, для всіх груп
65
+
translations/rpc/bfa.uk.yaml # лише для групи bfa
66
+
```
67
+
68
+
```yaml
69
+
# translations/rpc/bfa.uk.yaml
70
+
catalog.list:
71
+
title: Каталог для партнерів # description береться з базового перекладу
72
+
```
73
+
74
+
Кожне поле шукається в такому порядку (група важливіша за мову):
75
+
76
+
| Крок | Джерело |
77
+
| --- | --- |
78
+
| 1 | група, мова клієнта |
79
+
| 2 | група, `kernel.default_locale` |
80
+
| 3 | база, мова клієнта |
81
+
| 4 | база, `kernel.default_locale` |
82
+
| 5 | `#[RPC\Info]` / PHPDoc |
83
+
84
+
Мова — останній сегмент імені файлу, група — усе перед ним: `rpc/partner.v2.en.yaml` належить групі `partner.v2`.
85
+
86
+
:::warning
87
+
Не називайте групу як домен Symfony Translator (`messages`, `validators`, `security` або власний): Translator сканує `translations/` рекурсивно і вважатиме `rpc/messages.uk.yaml` частиною домену `messages`.
88
+
:::
89
+
90
+
:::info subtitle="Відома проблема 10.4"
91
+
Список мов спільний для всіх груп — див. [Актуальні помилки](/docs/api/json-rpc-bundle/developers/known_issues/open).
92
+
:::
93
+
94
+
### Переклади з розширень
95
+
96
+
Бандл, що додає RPC-методи, може постачати їхні переклади. Додаткові теки з тією самою структурою (`rpc.<locale>.yaml`, `rpc/<group>.<locale>.yaml`) підключаються через `translations.paths`:
97
+
98
+
```yaml
99
+
ufo_json_rpc:
100
+
translations:
101
+
paths:
102
+
- '%kernel.project_dir%/vendor/acme/rpc-extension/translations'
103
+
```
104
+
105
+
або з самого розширення в `prepend()`:
106
+
107
+
```php
108
+
public function prepend(ContainerBuilder $container): void
109
+
{
110
+
$container->prependExtensionConfig('ufo_json_rpc', [
111
+
'translations' => ['paths' => [__DIR__.'/../../translations']],
112
+
]);
113
+
}
114
+
```
115
+
116
+
Теки зводяться поле за полем, пізніша перекриває попередню; `translations/` застосунку завжди остання. Переклади збираються під час компіляції контейнера; у debug контейнер перебудовується при змінах файлів.
117
+
118
+
### `RpcLocaleNegotiator`
119
+
120
+
Розширенням, що мають власні переклади, доступний сервіс вибору мови, яким користується документація:
121
+
122
+
```php
123
+
use Ufo\JsonRpcBundle\Server\RpcLocaleNegotiator;
124
+
125
+
public function __construct(private RpcLocaleNegotiator $localeNegotiator) {}
126
+
127
+
$locale = $this->localeNegotiator->negotiate($request, ['en', 'uk']); // null, якщо список порожній
128
+
$this->localeNegotiator->applyLocale($request); // після LocaleListener (пріоритет 16)
129
+
$this->localeNegotiator->addLanguageHeaders($request, $response); // Content-Language + Vary
130
+
```
131
+
132
+
## Кешування документації
133
+
134
+
Поза debug-режимом згенерований документ кешується й віддається з `ETag`. Клієнт, що надсилає `If-None-Match`, отримує `304 Not Modified` без повторної генерації. Ключ кешу враховує маршрут, версію, `?info`, групу, хост, мову, склад методів і `container.build_id`, тож кеш оновлюється при будь-якій зміні методів чи перебудові контейнера. Налаштовувати нічого не треба; пул задає `cache.pool`.