Документація API

← Документація API

Ashterix

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`.