diff --git a/apps/docs/app/api/(guides)/[slug]/page.tsx b/apps/docs/app/api/(guides)/[slug]/page.tsx index d09ee917..c3233036 100644 --- a/apps/docs/app/api/(guides)/[slug]/page.tsx +++ b/apps/docs/app/api/(guides)/[slug]/page.tsx @@ -117,11 +117,13 @@ export default async function ApiGuidePage({ params }: { params: Promise<{ slug: __html: JSON.stringify(jsonLd).replace(/ - + {!data.frontmatter.hideHeader && ( + + )} ); diff --git a/apps/docs/components/api/code-examples.tsx b/apps/docs/components/api/code-examples.tsx index 8908459f..39d870d1 100644 --- a/apps/docs/components/api/code-examples.tsx +++ b/apps/docs/components/api/code-examples.tsx @@ -1,15 +1,17 @@ 'use client'; -import { useState, useMemo, useEffect } from 'react'; +import { useMemo } from 'react'; import * as DropdownMenu from '@radix-ui/react-dropdown-menu'; import { ChevronDown } from 'lucide-react'; import type { Endpoint } from '@/lib/openapi/types'; import { generateCurl } from '@/lib/code-generators/curl'; import { generateCLI } from '@/lib/code-generators/cli'; import { generateResponseExample, type ExampleOptions } from '@/lib/openapi/example-generator'; +import { useCodeLang } from '@/lib/use-code-lang'; import { CopyButton } from './copy-button'; import { CodeBlock } from './code-block'; import { BoxedPanel } from './boxed-panel'; +import { LangTabs } from './lang-tabs'; interface CodeExamplesProps { endpoint: Endpoint; @@ -20,13 +22,13 @@ interface CodeExamplesProps { sdkExamples?: Record; langs?: Language[]; defaultLang?: Language; + /** Language switcher style in the request header: dropdown (default) or inline tabs. */ + variant?: 'dropdown' | 'tabs'; className?: string; } type Language = 'curl' | 'cli' | 'typescript' | 'python' | 'go' | 'kotlin' | 'swift' | 'csharp'; -const STORAGE_KEY = 'pachca-docs-code-lang'; - const languageLabels: Record = { cli: 'Pachca CLI', curl: 'cURL', @@ -47,26 +49,20 @@ export function CodeExamples({ sdkExamples, langs, defaultLang: defaultLangProp, + variant = 'dropdown', className, }: CodeExamplesProps) { const allLangs = Object.keys(languageLabels) as Language[]; const visibleLangs = langs ?? allLangs; const fallbackLang = visibleLangs[0]; - const [activeTab, setActiveTab] = useState(defaultLangProp ?? fallbackLang); - - useEffect(() => { - if (defaultLangProp) return; - const saved = localStorage.getItem(STORAGE_KEY); - if (saved && saved in languageLabels && visibleLangs.includes(saved as Language)) { - setActiveTab(saved as Language); // eslint-disable-line react-hooks/set-state-in-effect - } - }, []); // eslint-disable-line react-hooks/exhaustive-deps + const [storedLang, setStoredLang] = useCodeLang(fallbackLang, defaultLangProp); + // The shared value may be a language this instance doesn't show — fall back then. + const activeTab: Language = visibleLangs.includes(storedLang as Language) + ? (storedLang as Language) + : fallbackLang; - const handleTabChange = (lang: Language) => { - setActiveTab(lang); - localStorage.setItem(STORAGE_KEY, lang); - }; + const handleTabChange = (lang: Language) => setStoredLang(lang); const code = useMemo(() => { if (activeTab === 'curl') return generateCurl(endpoint, baseUrl); @@ -124,49 +120,63 @@ export function CodeExamples({ id="request-examples" className={showResponse ? 'mt-0 mb-6' : (className ?? 'my-0')} header={ - <> - - {title || endpoint.title || endpoint.summary || endpoint.path} - - -
- - - - - - - - {(Object.keys(languages) as Language[]).map((lang) => ( - handleTabChange(lang)} - className={`flex items-center px-2.5 py-1.5 text-[13px] font-medium rounded-md cursor-pointer outline-none transition-colors ${ - activeTab === lang - ? 'bg-primary/15 text-primary' - : 'text-text-primary hover:bg-glass-hover' - }`} - > - {languages[lang]} - - ))} - - - - + variant === 'tabs' ? ( + <> + ({ + id: l, + label: languages[l], + }))} + activeId={activeTab} + onSelect={(id) => handleTabChange(id as Language)} + /> -
- + + ) : ( + <> + + {title || endpoint.title || endpoint.summary || endpoint.path} + + +
+ + + + + + + + {(Object.keys(languages) as Language[]).map((lang) => ( + handleTabChange(lang)} + className={`flex items-center px-2.5 py-1.5 text-[13px] font-medium rounded-md cursor-pointer outline-none transition-colors ${ + activeTab === lang + ? 'bg-primary/15 text-primary' + : 'text-text-primary hover:bg-glass-hover' + }`} + > + {languages[lang]} + + ))} + + + + + +
+ + ) } contentClassName="px-6 py-2 pl-0 overflow-x-auto custom-scrollbar" > diff --git a/apps/docs/components/api/lang-tabs.tsx b/apps/docs/components/api/lang-tabs.tsx new file mode 100644 index 00000000..41b4fcb9 --- /dev/null +++ b/apps/docs/components/api/lang-tabs.tsx @@ -0,0 +1,47 @@ +'use client'; + +export interface LangTabItem { + id: string; + label: string; +} + +/** + * Inline language/tool switcher rendered as tabs, styled like the header nav: + * normal text color with a thin primary underline on the active tab. Sits in a + * row with a `border-b`; the tab height matches `--boxed-header-height` so the + * underline lands on the divider both in a BoxedPanel header and a plain row. + * + * Shared by and . + */ +export function LangTabs({ + items, + activeId, + onSelect, + className, +}: { + items: LangTabItem[]; + activeId: string | undefined; + onSelect: (id: string) => void; + className?: string; +}) { + return ( +
+ {items.map((it) => { + const isActive = it.id === activeId; + return ( + + ); + })} +
+ ); +} diff --git a/apps/docs/components/api/markdown-content.tsx b/apps/docs/components/api/markdown-content.tsx index cdfdcda3..3c5f0d80 100644 --- a/apps/docs/components/api/markdown-content.tsx +++ b/apps/docs/components/api/markdown-content.tsx @@ -38,6 +38,8 @@ import { SdkCommands } from '@/components/mdx/sdk-commands'; import { NpmBadge } from '@/components/mdx/npm-badge'; import { PackageBadge } from '@/components/mdx/package-badge'; import { HomeHero, HomeHeroContent, HomeHeroCode } from '@/components/mdx/home-hero'; +import { ApiClientPanel } from '@/components/mdx/api-client-panel'; +import { ApiIntroNotes } from '@/components/mdx/api-intro-notes'; import { Tabs, Tab } from '@/components/mdx/tabs'; import { WebhookPlayground } from '@/components/mdx/webhook-playground'; import { MessagePlayground } from '@/components/mdx/message-playground'; @@ -239,6 +241,8 @@ const components = { HomeHero, HomeHeroContent, HomeHeroCode, + ApiClientPanel, + ApiIntroNotes, Tabs, Tab, WebhookPlayground, diff --git a/apps/docs/components/mdx/api-client-panel-client.tsx b/apps/docs/components/mdx/api-client-panel-client.tsx new file mode 100644 index 00000000..25ba080c --- /dev/null +++ b/apps/docs/components/mdx/api-client-panel-client.tsx @@ -0,0 +1,66 @@ +'use client'; + +import Link from 'next/link'; +import { GuideCodeBlock } from '@/components/api/guide-code-block'; +import { CodeBlock } from '@/components/api/code-block'; +import { CopyButton } from '@/components/api/copy-button'; +import { LangTabs } from '@/components/api/lang-tabs'; +import { useCodeLang } from '@/lib/use-code-lang'; +import type { ApiClient } from '@/lib/api-clients'; + +export function ApiClientPanelClient({ + baseUrl, + clients, +}: { + baseUrl: string; + clients: ApiClient[]; +}) { + const [lang, setLang] = useCodeLang(clients[0]?.id ?? 'cli'); + // The shared value may be a language without an install entry (e.g. cURL) — fall back then. + const active = clients.find((c) => c.id === lang) ?? clients[0]; + + return ( +
+ {/* Base URL — standard titled code block */} + + + {/* Client libraries — tabs header (scrolls on narrow), code below the divider */} +
+
+ {/* Tab bar: scrolls on narrow; copy button pinned right (blur like a code block) */} +
+
+ ({ id: c.id, label: c.short ?? c.label }))} + activeId={active?.id} + onSelect={setLang} + className="w-max pl-4 pr-12" + /> +
+ {active && ( +
+ +
+ )} +
+ {/* Active install command */} +
+ {active && } +
+
+ + {active && ( +
+ {active.blurb} в{' '} + + документации {active.label} + +
+ )} +
+
+ ); +} diff --git a/apps/docs/components/mdx/api-client-panel.tsx b/apps/docs/components/mdx/api-client-panel.tsx new file mode 100644 index 00000000..8422f43a --- /dev/null +++ b/apps/docs/components/mdx/api-client-panel.tsx @@ -0,0 +1,29 @@ +import { getBaseUrl } from '@/lib/openapi/parser'; +import { API_CLIENTS } from '@/lib/api-clients'; +import { Card } from '@/components/mdx/cards'; +import { ApiClientPanelClient } from './api-client-panel-client'; + +/** Downloadable specs and files, shown below the client panel. */ +const RESOURCES = [ + { title: 'OpenAPI', icon: 'FileSearch', href: '/openapi.yaml' }, + { title: 'Postman', icon: 'LayoutList', href: '/pachca.postman_collection.json' }, +]; + +/** + * Right-column panel for /api/overview: the base URL (read from the spec), a + * tabbed switcher over the official clients (CLI and the six SDKs), and + * downloadable resources (spec, Postman, llms.txt). + */ +export async function ApiClientPanel() { + const baseUrl = await getBaseUrl(); + return ( +
+ +
+ {RESOURCES.map((r) => ( + + ))} +
+
+ ); +} diff --git a/apps/docs/components/mdx/api-intro-notes.tsx b/apps/docs/components/mdx/api-intro-notes.tsx new file mode 100644 index 00000000..7554abe7 --- /dev/null +++ b/apps/docs/components/mdx/api-intro-notes.tsx @@ -0,0 +1,22 @@ +import Link from 'next/link'; + +/** + * Extra intro paragraphs for the /api/overview left column (passed to + * ): getting-started and no-code pointers as plain + * prose, no headings. + */ +export function ApiIntroNotes() { + return ( +

+ Если только начинаете, загляните в{' '} + + руководства + {' '} + с пошаговыми примерами. Чтобы автоматизировать Пачку без кода, используйте{' '} + + n8n + {' '} + и визуальные сценарии. +

+ ); +} diff --git a/apps/docs/components/mdx/cards.tsx b/apps/docs/components/mdx/cards.tsx index e11694d5..84ba02dd 100644 --- a/apps/docs/components/mdx/cards.tsx +++ b/apps/docs/components/mdx/cards.tsx @@ -20,6 +20,9 @@ import { ClipboardList, MessageSquare, MessagesSquare, + Hash, + Smile, + Plus, Users, Tag, UserPlus, @@ -73,6 +76,9 @@ const iconMap: Record = { ClipboardList, MessageSquare, MessagesSquare, + Hash, + Smile, + Plus, Users, Tag, UserPlus, @@ -256,9 +262,16 @@ function CardWrapper({ ); } +/** Display order for HTTP method badges — POST first, then GET, PUT, PATCH, DELETE */ +const METHOD_ORDER: HttpMethod[] = ['POST', 'GET', 'PUT', 'PATCH', 'DELETE']; + export function Card({ title, icon, href, download, compact, methods, children }: CardProps) { const Icon = icon ? iconMap[icon] : null; - const methodList = methods ? (methods.split(/[\s,]+/).filter(Boolean) as HttpMethod[]) : null; + const methodList = methods + ? (methods.split(/[\s,]+/).filter(Boolean) as HttpMethod[]).sort( + (a, b) => METHOD_ORDER.indexOf(a) - METHOD_ORDER.indexOf(b) + ) + : null; if (compact) { return ( @@ -276,7 +289,11 @@ export function Card({ title, icon, href, download, compact, methods, children } {children} )} - + {download ? ( + + ) : ( + + )} ); } @@ -319,7 +336,7 @@ export function Card({ title, icon, href, download, compact, methods, children } } export function CardRow({ children }: { children: React.ReactNode }) { - return
{children}
; + return
{children}
; } export { GUIDE_ICONS, API_SECTION_META }; diff --git a/apps/docs/components/mdx/home-hero.tsx b/apps/docs/components/mdx/home-hero.tsx index 6ca9f5aa..ded85cc0 100644 --- a/apps/docs/components/mdx/home-hero.tsx +++ b/apps/docs/components/mdx/home-hero.tsx @@ -12,10 +12,21 @@ interface HomeHeroContentProps { subtitle?: string; title: string; description: string; + /** Page URL for the "Copy for LLM" / "View as Markdown" actions */ + pageUrl?: string; + /** Extra paragraphs rendered below the description, above the cards */ + lead?: React.ReactNode; children?: React.ReactNode; } -export function HomeHeroContent({ subtitle, title, description, children }: HomeHeroContentProps) { +export function HomeHeroContent({ + subtitle, + title, + description, + pageUrl = '/', + lead, + children, +}: HomeHeroContentProps) { return (
{subtitle && ( @@ -25,9 +36,14 @@ export function HomeHeroContent({ subtitle, title, description, children }: Home )}

{title}

- +

{description}

+ {lead && ( +
+ {lead} +
+ )} {children &&
{children}
}
); diff --git a/apps/docs/components/mdx/mdx-components.tsx b/apps/docs/components/mdx/mdx-components.tsx index dde34e3e..90108cb4 100644 --- a/apps/docs/components/mdx/mdx-components.tsx +++ b/apps/docs/components/mdx/mdx-components.tsx @@ -27,6 +27,8 @@ import { SdkCommands } from '@/components/mdx/sdk-commands'; import { NpmBadge } from '@/components/mdx/npm-badge'; import { PackageBadge } from '@/components/mdx/package-badge'; import { HomeHero, HomeHeroContent, HomeHeroCode } from '@/components/mdx/home-hero'; +import { ApiClientPanel } from '@/components/mdx/api-client-panel'; +import { ApiIntroNotes } from '@/components/mdx/api-intro-notes'; import { Tabs, Tab } from '@/components/mdx/tabs'; import { WebhookPlayground } from '@/components/mdx/webhook-playground'; import { MessagePlayground } from '@/components/mdx/message-playground'; @@ -579,5 +581,7 @@ export const customMdxComponents = { HomeHero, HomeHeroContent, HomeHeroCode, + ApiClientPanel, + ApiIntroNotes, ProductUpdatesLink, }; diff --git a/apps/docs/content/api/models.mdx b/apps/docs/content/api/models.mdx index 315a924b..62656941 100644 --- a/apps/docs/content/api/models.mdx +++ b/apps/docs/content/api/models.mdx @@ -62,13 +62,13 @@ hideTableOfContents: true ## Сотрудник +- [Создать сотрудника](POST /users) - [Информация о профиле](GET /profile) - [Информация о сотруднике](GET /users/{id}) - [Список сотрудников](GET /users) - [Список сотрудников тега](GET /group_tags/{id}/users) - [Список участников чата](GET /chats/{id}/members) - [Поиск сотрудников](GET /search/users) -- [Создать сотрудника](POST /users) - [Редактирование сотрудника](PUT /users/{id}) - [Удаление сотрудника](DELETE /users/{id}) @@ -76,10 +76,10 @@ hideTableOfContents: true ## Тег -- [Информация о теге](GET /group_tags/{id}) -- [Список тегов сотрудников](GET /group_tags) - [Новый тег](POST /group_tags) - [Добавление тегов](POST /chats/{id}/group_tags) +- [Информация о теге](GET /group_tags/{id}) +- [Список тегов сотрудников](GET /group_tags) - [Редактирование тега](PUT /group_tags/{id}) - [Исключение тега](DELETE /chats/{id}/group_tags/{tag_id}) - [Удаление тега](DELETE /group_tags/{id}) @@ -88,13 +88,13 @@ hideTableOfContents: true ## Чат +- [Новый чат](POST /chats) +- [Добавление пользователей](POST /chats/{id}/members) +- [Экспорт сообщений](POST /chats/exports) - [Информация о чате](GET /chats/{id}) - [Список чатов](GET /chats) - [Поиск чатов](GET /search/chats) - [Скачать архив экспорта](GET /chats/exports/{id}) -- [Новый чат](POST /chats) -- [Добавление пользователей](POST /chats/{id}/members) -- [Экспорт сообщений](POST /chats/exports) - [Обновление чата](PUT /chats/{id}) - [Архивация чата](PUT /chats/{id}/archive) - [Разархивация чата](PUT /chats/{id}/unarchive) @@ -106,21 +106,21 @@ hideTableOfContents: true ## Тред +- [Новый тред](POST /messages/{id}/thread) - [Информация о треде](GET /threads/{id}) - [Список тредов](GET /threads) -- [Новый тред](POST /messages/{id}/thread) ## Сообщение +- [Новое сообщение](POST /messages) +- [Закрепление сообщения](POST /messages/{id}/pin) +- [Unfurl (разворачивание ссылок)](POST /messages/{id}/link_previews) - [Информация о сообщении](GET /messages/{id}) - [Список сообщений чата](GET /messages) - [Поиск сообщений](GET /search/messages) - [Список прочитавших сообщение](GET /messages/{id}/read_member_ids) -- [Новое сообщение](POST /messages) -- [Закрепление сообщения](POST /messages/{id}/pin) -- [Unfurl (разворачивание ссылок)](POST /messages/{id}/link_previews) - [Редактирование сообщения](PUT /messages/{id}) - [Открепление сообщения](DELETE /messages/{id}/pin) - [Удаление сообщения](DELETE /messages/{id}) @@ -129,17 +129,17 @@ hideTableOfContents: true ## Реакция на сообщение -- [Список реакций](GET /messages/{id}/reactions) - [Добавление реакции](POST /messages/{id}/reactions) +- [Список реакций](GET /messages/{id}/reactions) - [Удаление реакции](DELETE /messages/{id}/reactions) ## Напоминание +- [Новое напоминание](POST /tasks) - [Информация о напоминании](GET /tasks/{id}) - [Список напоминаний](GET /tasks) -- [Новое напоминание](POST /tasks) - [Редактирование напоминания](PUT /tasks/{id}) - [Удаление напоминания](DELETE /tasks/{id}) diff --git a/apps/docs/content/api/overview.mdx b/apps/docs/content/api/overview.mdx new file mode 100644 index 00000000..e8323bb6 --- /dev/null +++ b/apps/docs/content/api/overview.mdx @@ -0,0 +1,59 @@ +--- +title: Обзор +description: "Обзор REST API Пачки: базовый URL, авторизация по Bearer-токену, формат запросов и ответов, клиенты и SDK для CLI, TypeScript, Python, Go, Kotlin, Swift и C#" +hideTableOfContents: true +hideHeader: true +--- + + + } + > + + + + + +## Популярные методы + +Частые операции для быстрого старта. Все модели API и доступные для них методы можно посмотреть на странице [Модели](/api/models). + + + + + + + + + + + + +## Основы API + +Базовые концепции для работы с API: авторизация, формат запросов и ответов, обработка ошибок, лимиты, пагинация и загрузка файлов. + + + + Bearer-токен и доступ к API + + + Базовый URL, заголовки, формат данных + + + Обход больших списков по курсору + + + Прямая загрузка в S3 одной командой + + + HTTP-коды и структуры ответов + + + Rate limits и повторные запросы + + diff --git a/apps/docs/content/home.mdx b/apps/docs/content/home.mdx index 876b85f2..6329f4c5 100644 --- a/apps/docs/content/home.mdx +++ b/apps/docs/content/home.mdx @@ -8,7 +8,7 @@ hideTableOfContents: true diff --git a/apps/docs/lib/api-clients.ts b/apps/docs/lib/api-clients.ts new file mode 100644 index 00000000..d696bc6c --- /dev/null +++ b/apps/docs/lib/api-clients.ts @@ -0,0 +1,89 @@ +/** + * Client libraries and tools for the API overview panel. + * + * One entry per official client: the CLI and the six generated SDKs. Used by + * (rendered on /api/overview) and by the mdx-expander so the + * same list appears in generated .md / llms-full.txt. + * + * Install commands and package names mirror the dedicated docs pages + * (guides/cli, guides/sdk/*) — keep them in sync. + */ + +export interface ApiClient { + /** Stable id, also the tab key */ + id: string; + /** Full label (used in generated markdown) */ + label: string; + /** Optional shorter label for the tab bar (falls back to label) */ + short?: string; + /** Shiki language for the install snippet */ + lang: string; + /** Install command or package identifier */ + install: string; + /** One-line teaser of what the client's docs cover (panel docs link) */ + blurb: string; + /** Docs page for this client */ + href: string; +} + +export const API_CLIENTS: ApiClient[] = [ + { + id: 'cli', + label: 'CLI', + lang: 'bash', + install: 'npm install -g @pachca/cli', + blurb: 'Установка, автодополнение и все команды для работы из терминала и агентов', + href: '/guides/cli/overview', + }, + { + id: 'typescript', + label: 'TypeScript', + short: 'TS', + lang: 'bash', + install: 'npm install @pachca/sdk', + blurb: 'Установка, создание клиента и типизированные запросы с автодополнением', + href: '/guides/sdk/typescript', + }, + { + id: 'python', + label: 'Python', + lang: 'bash', + install: 'pip install pachca-sdk', + blurb: 'Установка, авторизация и асинхронные запросы с моделями-датаклассами', + href: '/guides/sdk/python', + }, + { + id: 'go', + label: 'Go', + lang: 'bash', + install: 'go get github.com/pachca/openapi/sdk/go/generated', + blurb: 'Установка, синхронный клиент с context и обходом всех страниц', + href: '/guides/sdk/go', + }, + { + id: 'kotlin', + label: 'Kotlin', + lang: 'kotlin', + install: + '// build.gradle.kts\ndependencies {\n implementation("com.pachca:pachca-sdk:latest.release")\n}', + blurb: 'Установка через Gradle, клиент на корутинах и сериализация моделей', + href: '/guides/sdk/kotlin', + }, + { + id: 'swift', + label: 'Swift', + lang: 'swift', + install: + '// Package.swift\ndependencies: [\n .package(url: "https://github.com/pachca/openapi", from: "1.0.0")\n]', + blurb: 'Установка через SPM, клиент на async/await и модели Codable', + href: '/guides/sdk/swift', + }, + { + id: 'csharp', + label: 'C#', + lang: 'bash', + install: 'dotnet add package Pachca.Sdk', + blurb: 'Установка, асинхронный клиент на HttpClient с поддержкой отмены', + href: '/guides/sdk/csharp', + }, +]; diff --git a/apps/docs/lib/content-loader.ts b/apps/docs/lib/content-loader.ts index e3f67af2..d5067ae1 100644 --- a/apps/docs/lib/content-loader.ts +++ b/apps/docs/lib/content-loader.ts @@ -21,6 +21,8 @@ export interface GuideFrontmatter { title: string; description?: string; hideTableOfContents?: boolean; + /** Skip the auto page header (title + markdown actions) — for pages with their own hero. */ + hideHeader?: boolean; useUpdatesComponent?: boolean; /** Curated "Связанные разделы" links shown above the prev/next pager. */ related?: RelatedLink[]; @@ -82,6 +84,7 @@ export function getGuideData(guidePath: string): GuideData | null { title: data.title || path.basename(fileName), description: data.description, hideTableOfContents: data.hideTableOfContents, + hideHeader: data.hideHeader, useUpdatesComponent: data.useUpdatesComponent, related: data.related, }, diff --git a/apps/docs/lib/mdx-expander.ts b/apps/docs/lib/mdx-expander.ts index fe315ecf..bccd6972 100644 --- a/apps/docs/lib/mdx-expander.ts +++ b/apps/docs/lib/mdx-expander.ts @@ -13,6 +13,7 @@ import { generateCurl } from './code-generators/curl'; import { groupEndpointsByTag, generateUrlFromOperation, generateTitle } from './openapi/mapper'; import { schemaToMarkdown } from './markdown-generator'; import { getSdkExampleForLang } from './sdk-examples'; +import { API_CLIENTS } from './api-clients'; import type { Schema } from './openapi/types'; import { HTTP_CODES } from './schemas/guide-schemas'; import { getOrderedPages } from './ordered-pages'; @@ -336,15 +337,16 @@ export async function expandMdxComponents(content: string): Promise { // ... -> unwrap (markdown table inside) result = result.replace(/([\s\S]*?)<\/ParamsTable>/g, (_, inner) => inner.trim()); - // Standalone children -> markdown link + // Standalone children or self-closing -> markdown list item + // Leading horizontal whitespace is consumed so unwrapped CardRow pills form a flat list. result = result.replace( - /([\s\S]*?)<\/Card>/g, + /[ \t]*([\s\S]*?)<\/Card>|\/>)/g, (_, attrs, children) => { const title = attrs.match(/title="([^"]+)"/)?.[1] ?? ''; const href = attrs.match(/href="([^"]+)"/)?.[1]; - const text = children.trim(); + const text = (children ?? '').trim(); const titlePart = href ? `[${title}](${href})` : `**${title}**`; - return text ? `${titlePart} ${text}\n` : `${titlePart}\n`; + return text ? `- ${titlePart} ${text}\n` : `- ${titlePart}\n`; } ); @@ -482,6 +484,18 @@ export async function expandMdxComponents(content: string): Promise { result = result.replace(//g, apiCardsMarkdown); } + // -> getting-started pointers + base URL + client libraries list + if (result.includes(' `**${c.label}** — [документация](${c.href})\n\n\`\`\`${c.lang}\n${c.install}\n\`\`\`` + ).join('\n\n'); + const resources = + '- [OpenAPI](/openapi.yaml)\n' + '- [Postman](/pachca.postman_collection.json)'; + const md = `Базовый URL: \`${baseUrl}\`\n\nКлиенты и SDK:\n\n${libs}\n\nРесурсы:\n\n${resources}\n`; + result = result.replace(//g, md); + } + // -> markdown table of SDK methods if (result.includes('/g; diff --git a/apps/docs/lib/tabs-config.ts b/apps/docs/lib/tabs-config.ts index 10d8fe15..2438bb56 100644 --- a/apps/docs/lib/tabs-config.ts +++ b/apps/docs/lib/tabs-config.ts @@ -46,7 +46,7 @@ export const TABS: TabConfig[] = [ title: 'Документация API', shortTitle: 'API', prefix: '/api', - defaultHref: '/api/authorization', + defaultHref: '/api/overview', hasSidebar: true, }, { @@ -238,6 +238,7 @@ export const N8N_SECTIONS: SidebarSection[] = [ * The "Справочник методов" section is generated dynamically from OpenAPI. */ export const API_GUIDE_PAGES: SidebarPageItem[] = [ + { title: 'Обзор', path: '/api/overview' }, { title: 'Авторизация', path: '/api/authorization' }, { title: 'Запросы и ответы', path: '/api/requests-responses' }, { title: 'Пагинация', path: '/api/pagination' }, diff --git a/apps/docs/lib/use-code-lang.ts b/apps/docs/lib/use-code-lang.ts new file mode 100644 index 00000000..cd89c532 --- /dev/null +++ b/apps/docs/lib/use-code-lang.ts @@ -0,0 +1,58 @@ +'use client'; + +import { useState, useEffect, useCallback } from 'react'; + +/** + * Shared selected-language state for code examples and the client panel. + * + * Persists to localStorage and broadcasts a custom event so every switcher on + * the page (dropdowns in , tabs in ) stays in + * sync live, and the choice is remembered across pages. + * + * Pass `pinned` to lock an instance to a specific language (e.g. the home hero): + * it won't follow the shared value, but selecting in it still updates others. + */ +const STORAGE_KEY = 'pachca-docs-code-lang'; +const CHANGE_EVENT = 'pachca-code-lang-change'; + +export function useCodeLang( + fallback: string, + pinned?: string +): readonly [string, (lang: string) => void] { + const [lang, setLangState] = useState(pinned ?? fallback); + + useEffect(() => { + if (pinned) return; + + const saved = localStorage.getItem(STORAGE_KEY); + if (saved) setLangState(saved); // eslint-disable-line react-hooks/set-state-in-effect + + const onChange = (e: Event) => { + const detail = (e as CustomEvent).detail; + if (detail) setLangState(detail); + }; + const onStorage = () => { + const next = localStorage.getItem(STORAGE_KEY); + if (next) setLangState(next); + }; + + window.addEventListener(CHANGE_EVENT, onChange); + window.addEventListener('storage', onStorage); + return () => { + window.removeEventListener(CHANGE_EVENT, onChange); + window.removeEventListener('storage', onStorage); + }; + }, [pinned]); + + const setLang = useCallback((next: string) => { + setLangState(next); + try { + localStorage.setItem(STORAGE_KEY, next); + window.dispatchEvent(new CustomEvent(CHANGE_EVENT, { detail: next })); + } catch { + // localStorage unavailable — selection still updates locally + } + }, []); + + return [lang, setLang] as const; +} diff --git a/apps/docs/package.json b/apps/docs/package.json index d44a258b..f29774a2 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -12,7 +12,8 @@ "format": "prettier --write .", "format:check": "prettier --check .", "generate-llms": "bun scripts/generate-llms.ts", - "check-urls": "node scripts/check-url-conflicts.mjs" + "check-urls": "node scripts/check-url-conflicts.mjs", + "check-models": "node scripts/check-models-coverage.mjs" }, "dependencies": { "@radix-ui/react-accordion": "^1.2.2", diff --git a/apps/docs/public/api/llms.txt b/apps/docs/public/api/llms.txt index f1b8ce8f..d503216a 100644 --- a/apps/docs/public/api/llms.txt +++ b/apps/docs/public/api/llms.txt @@ -5,6 +5,7 @@ [Родительский индекс](https://dev.pachca.com/llms.txt) ## Основы API +- [Обзор](https://dev.pachca.com/api/overview.md): Обзор REST API Пачки: базовый URL, авторизация по Bearer-токену, формат запросов и ответов, клиенты и SDK для CLI, TypeScript, Python, Go, Kotlin, Swift и C# - [Авторизация](https://dev.pachca.com/api/authorization.md): Авторизация в API Пачки: персональный токен и токен бота, скоупы методов, настройка доступа для администраторов и сотрудников, смена владельца пространства - [Запросы и ответы](https://dev.pachca.com/api/requests-responses.md): Формат запросов и ответов API Пачки: базовый URL, заголовки Authorization и Content-Type, структура JSON-тела, коллекции Postman и Bruno для тестирования - [Пагинация](https://dev.pachca.com/api/pagination.md): Пагинация в API Пачки по курсору: две группы методов (списочные и поиск) с разной структурой meta, поля next_page, prev_page, has_next, has_prev, обход всех записей и polling новых данных через prev_page diff --git a/apps/docs/public/api/models.md b/apps/docs/public/api/models.md index 2de758d6..c8d27074 100644 --- a/apps/docs/public/api/models.md +++ b/apps/docs/public/api/models.md @@ -72,13 +72,13 @@ ## Сотрудник +- [Создать сотрудника](POST /users) - [Информация о профиле](GET /profile) - [Информация о сотруднике](GET /users/{id}) - [Список сотрудников](GET /users) - [Список сотрудников тега](GET /group_tags/{id}/users) - [Список участников чата](GET /chats/{id}/members) - [Поиск сотрудников](GET /search/users) -- [Создать сотрудника](POST /users) - [Редактирование сотрудника](PUT /users/{id}) - [Удаление сотрудника](DELETE /users/{id}) @@ -122,10 +122,10 @@ ## Тег -- [Информация о теге](GET /group_tags/{id}) -- [Список тегов сотрудников](GET /group_tags) - [Новый тег](POST /group_tags) - [Добавление тегов](POST /chats/{id}/group_tags) +- [Информация о теге](GET /group_tags/{id}) +- [Список тегов сотрудников](GET /group_tags) - [Редактирование тега](PUT /group_tags/{id}) - [Исключение тега](DELETE /chats/{id}/group_tags/{tag_id}) - [Удаление тега](DELETE /group_tags/{id}) @@ -139,13 +139,13 @@ ## Чат +- [Новый чат](POST /chats) +- [Добавление пользователей](POST /chats/{id}/members) +- [Экспорт сообщений](POST /chats/exports) - [Информация о чате](GET /chats/{id}) - [Список чатов](GET /chats) - [Поиск чатов](GET /search/chats) - [Скачать архив экспорта](GET /chats/exports/{id}) -- [Новый чат](POST /chats) -- [Добавление пользователей](POST /chats/{id}/members) -- [Экспорт сообщений](POST /chats/exports) - [Обновление чата](PUT /chats/{id}) - [Архивация чата](PUT /chats/{id}/archive) - [Разархивация чата](PUT /chats/{id}/unarchive) @@ -170,9 +170,9 @@ ## Тред +- [Новый тред](POST /messages/{id}/thread) - [Информация о треде](GET /threads/{id}) - [Список тредов](GET /threads) -- [Новый тред](POST /messages/{id}/thread) Тред @@ -185,13 +185,13 @@ ## Сообщение +- [Новое сообщение](POST /messages) +- [Закрепление сообщения](POST /messages/{id}/pin) +- [Unfurl (разворачивание ссылок)](POST /messages/{id}/link_previews) - [Информация о сообщении](GET /messages/{id}) - [Список сообщений чата](GET /messages) - [Поиск сообщений](GET /search/messages) - [Список прочитавших сообщение](GET /messages/{id}/read_member_ids) -- [Новое сообщение](POST /messages) -- [Закрепление сообщения](POST /messages/{id}/pin) -- [Unfurl (разворачивание ссылок)](POST /messages/{id}/link_previews) - [Редактирование сообщения](PUT /messages/{id}) - [Открепление сообщения](DELETE /messages/{id}/pin) - [Удаление сообщения](DELETE /messages/{id}) @@ -242,8 +242,8 @@ ## Реакция на сообщение -- [Список реакций](GET /messages/{id}/reactions) - [Добавление реакции](POST /messages/{id}/reactions) +- [Список реакций](GET /messages/{id}/reactions) - [Удаление реакции](DELETE /messages/{id}/reactions) Реакция на сообщение @@ -256,9 +256,9 @@ ## Напоминание +- [Новое напоминание](POST /tasks) - [Информация о напоминании](GET /tasks/{id}) - [Список напоминаний](GET /tasks) -- [Новое напоминание](POST /tasks) - [Редактирование напоминания](PUT /tasks/{id}) - [Удаление напоминания](DELETE /tasks/{id}) diff --git a/apps/docs/public/api/overview.md b/apps/docs/public/api/overview.md new file mode 100644 index 00000000..d632ab61 --- /dev/null +++ b/apps/docs/public/api/overview.md @@ -0,0 +1,99 @@ +> Расположение: Основы API +> Краткое содержание: Обзор REST API Пачки: базовый URL, авторизация по Bearer-токену, формат запросов и ответов, клиенты и SDK для CLI, TypeScript, Python, Go, Kotlin, Swift и C# +> Это Markdown-версия конкретной страницы. Для контекста за её пределами (правила API, полный перечень методов, авторизация) ОБЯЗАТЕЛЬНО открой [llms.txt](https://dev.pachca.com/llms.txt) перед ответом — это сэкономит токены и предотвратит неполный ответ. + + +# Обзор + +REST API Пачки позволяет автоматизировать работу в мессенджере: отправлять сообщения, управлять чатами и сотрудниками, создавать ботов и реагировать на события через вебхуки. + +Базовый URL: `https://api.pachca.com/api/shared/v1` + +Клиенты и SDK: + +**CLI** — [документация](/guides/cli/overview) + +```bash +npm install -g @pachca/cli +``` + +**TypeScript** — [документация](/guides/sdk/typescript) + +```bash +npm install @pachca/sdk +``` + +**Python** — [документация](/guides/sdk/python) + +```bash +pip install pachca-sdk +``` + +**Go** — [документация](/guides/sdk/go) + +```bash +go get github.com/pachca/openapi/sdk/go/generated +``` + +**Kotlin** — [документация](/guides/sdk/kotlin) + +```kotlin +// build.gradle.kts +dependencies { + implementation("com.pachca:pachca-sdk:latest.release") +} +``` + +**Swift** — [документация](/guides/sdk/swift) + +```swift +// Package.swift +dependencies: [ + .package(url: "https://github.com/pachca/openapi", from: "1.0.0") +] +``` + +**C#** — [документация](/guides/sdk/csharp) + +```bash +dotnet add package Pachca.Sdk +``` + +Ресурсы: + +- [OpenAPI](/openapi.yaml) +- [Postman](/pachca.postman_collection.json) + + +## Популярные методы + +Частые операции для быстрого старта. Все модели API и доступные для них методы можно посмотреть на странице [Модели](/api/models). + +- [Новое сообщение](/api/messages/create) + +- [Список сообщений чата](/api/messages/list) + +- [Поиск сообщений](/api/search/list-messages) + +- [Создать чат](/api/chats/create) + +- [Создать сотрудника](/api/users/create) + +- [Новый статус](/api/profile/update-status) + +- [Новое напоминание](/api/tasks/create) + +- [Создание бота](/api/bots/create) + + +## Основы API + +Базовые концепции для работы с API: авторизация, формат запросов и ответов, обработка ошибок, лимиты, пагинация и загрузка файлов. + +- [Авторизация](/api/authorization) — Bearer-токен и доступ к API +- [Запросы и ответы](/api/requests-responses) — Базовый URL, заголовки, формат данных +- [Пагинация](/api/pagination) — Обход больших списков по курсору +- [Загрузка файлов](/api/file-uploads) — Прямая загрузка в S3 одной командой +- [Ошибки](/api/errors) — HTTP-коды и структуры ответов +- [Лимиты](/api/limits) — Rate limits и повторные запросы + diff --git a/apps/docs/public/guides/cli/overview.md b/apps/docs/public/guides/cli/overview.md index ff6147e0..d040b908 100644 --- a/apps/docs/public/guides/cli/overview.md +++ b/apps/docs/public/guides/cli/overview.md @@ -5,7 +5,7 @@ # CLI -[@pachca/cli](https://www.npmjs.com/package/@pachca/cli) npm +- [@pachca/cli](https://www.npmjs.com/package/@pachca/cli) npm Официальный CLI для Pachca API: авторизация, сообщения, управление пространством — всё из терминала. Каждый метод API доступен как команда с типизированными флагами, валидацией и подсказками. Нужен Node.js 20+. diff --git a/apps/docs/public/guides/sdk/csharp.md b/apps/docs/public/guides/sdk/csharp.md index 70d7eb8d..48f2b886 100644 --- a/apps/docs/public/guides/sdk/csharp.md +++ b/apps/docs/public/guides/sdk/csharp.md @@ -5,7 +5,7 @@ # C# -[Pachca.Sdk](https://www.nuget.org/packages/Pachca.Sdk) NuGet +- [Pachca.Sdk](https://www.nuget.org/packages/Pachca.Sdk) NuGet Типизированный клиент для Pachca API. Работает в .NET 8+ с поддержкой `async/await` и `CancellationToken`. diff --git a/apps/docs/public/guides/sdk/go.md b/apps/docs/public/guides/sdk/go.md index e03c842e..4ed3f8d2 100644 --- a/apps/docs/public/guides/sdk/go.md +++ b/apps/docs/public/guides/sdk/go.md @@ -5,7 +5,7 @@ # Go -[github.com/pachca/openapi/sdk/go](https://pkg.go.dev/github.com/pachca/openapi/sdk/go/generated) pkg.go.dev +- [github.com/pachca/openapi/sdk/go](https://pkg.go.dev/github.com/pachca/openapi/sdk/go/generated) pkg.go.dev Типизированный клиент для Pachca API на Go. Синхронный, с контекстами (`context.Context`), автопагинацией и обработкой retry. Требуется Go 1.24+. diff --git a/apps/docs/public/guides/sdk/kotlin.md b/apps/docs/public/guides/sdk/kotlin.md index 9d269252..b008f020 100644 --- a/apps/docs/public/guides/sdk/kotlin.md +++ b/apps/docs/public/guides/sdk/kotlin.md @@ -5,7 +5,7 @@ # Kotlin -[com.pachca:pachca-sdk](https://github.com/pachca/openapi/tree/main/sdk/kotlin) JitPack +- [com.pachca:pachca-sdk](https://github.com/pachca/openapi/tree/main/sdk/kotlin) JitPack Типизированный клиент для Pachca API на Kotlin. Построен на Ktor с корутинами (`suspend`), kotlinx.serialization и встроенным retry. Требуется Kotlin 2.2+ и Java 11+. diff --git a/apps/docs/public/guides/sdk/overview.md b/apps/docs/public/guides/sdk/overview.md index 9ac6fa36..62fd1848 100644 --- a/apps/docs/public/guides/sdk/overview.md +++ b/apps/docs/public/guides/sdk/overview.md @@ -19,7 +19,7 @@ ## Генератор -[@pachca/generator](https://www.npmjs.com/package/@pachca/generator) npm +- [@pachca/generator](https://www.npmjs.com/package/@pachca/generator) npm Генерирует типы и клиент из OpenAPI-спецификации прямо в вашем проекте. Сгенерированный код можно закоммитить в репозиторий и добавить генерацию в CI как проверку совместимости с актуальным API. [Исходный код на GitHub](https://github.com/pachca/openapi/tree/main/packages/generator). diff --git a/apps/docs/public/guides/sdk/python.md b/apps/docs/public/guides/sdk/python.md index d7364df1..736c95a5 100644 --- a/apps/docs/public/guides/sdk/python.md +++ b/apps/docs/public/guides/sdk/python.md @@ -5,7 +5,7 @@ # Python -[pachca-sdk](https://pypi.org/project/pachca-sdk/) PyPI +- [pachca-sdk](https://pypi.org/project/pachca-sdk/) PyPI Асинхронный типизированный клиент для Pachca API. Построен на httpx с поддержкой type hints и dataclass-моделей. Требуется Python 3.10+. diff --git a/apps/docs/public/guides/sdk/swift.md b/apps/docs/public/guides/sdk/swift.md index 709dd1f3..4b411ef6 100644 --- a/apps/docs/public/guides/sdk/swift.md +++ b/apps/docs/public/guides/sdk/swift.md @@ -5,7 +5,7 @@ # Swift -[PachcaSDK](https://github.com/pachca/openapi/tree/main/sdk/swift) Swift Package +- [PachcaSDK](https://github.com/pachca/openapi/tree/main/sdk/swift) Swift Package Типизированный клиент для Pachca API на Swift. Построен на URLSession с `async throws`, Codable-моделями и встроенным retry. Требуется Swift 5.9+, macOS 13+ или iOS 16+. diff --git a/apps/docs/public/guides/sdk/typescript.md b/apps/docs/public/guides/sdk/typescript.md index c4bad2b2..5f3184df 100644 --- a/apps/docs/public/guides/sdk/typescript.md +++ b/apps/docs/public/guides/sdk/typescript.md @@ -5,7 +5,7 @@ # TypeScript -[@pachca/sdk](https://www.npmjs.com/package/@pachca/sdk) npm +- [@pachca/sdk](https://www.npmjs.com/package/@pachca/sdk) npm Типизированный клиент для Pachca API. Работает в Node.js 18+ и в любом окружении с поддержкой `fetch`. ES Module с TypeScript-декларациями. diff --git a/apps/docs/public/index.md b/apps/docs/public/index.md index d3557ffe..f936a5ca 100644 --- a/apps/docs/public/index.md +++ b/apps/docs/public/index.md @@ -4,7 +4,7 @@ # Обзор -REST API Пачки позволяет автоматизировать работу в мессенджере: отправлять сообщения, управлять чатами и сотрудниками, создавать ботов и реагировать на события через вебхуки. +Автоматизируйте рабочие процессы и стройте интеграции с Пачкой: уведомления из мониторинга и CRM, боты и AI-агенты, реакция на события в реальном времени. Работайте через REST API, CLI, типизированные SDK, n8n или Agent Skills. - [Быстрый старт](/guides/quickstart) - [Авторизация](/api/authorization) diff --git a/apps/docs/public/llms-full.txt b/apps/docs/public/llms-full.txt index 9f0f36ac..72363ade 100644 --- a/apps/docs/public/llms-full.txt +++ b/apps/docs/public/llms-full.txt @@ -14,84 +14,85 @@ | Раздел | Строки | |--------|--------| -| LIBRARY RULES — правила: auth, пагинация, лимиты, ошибки, SDK | 96–198 | -| How-to Guides — рецепты задач с кодом TS/Python | 199–882 | -| Руководства — гайды: SDK, вебхуки, боты, формы, n8n, CLI | 883–11334 | -| · Обзор | 888–990 | -| · Быстрый старт | 991–1080 | -| · AI агенты | 1081–1216 | -| · Взаимодействие с агентом | 1217–1285 | -| · Markdown и документы | 1286–1342 | -| · Треды | 1343–1470 | -| · Боты | 1471–1533 | -| · Создание и настройка | 1534–1660 | -| · Доступы к чатам и сообщениям | 1661–1733 | -| · Готовые примеры реализации | 1734–1768 | -| · Входящие вебхуки | 1769–1909 | -| · Исходящие вебхуки | 1910–1954 | -| · Настройка и типы событий | 1955–2129 | -| · Безопасность и обработчик | 2130–2320 | -| · Поллинг | 2321–2504 | -| · Кнопки в сообщениях | 2505–2660 | -| · Формы | 2661–2730 | -| · Блоки представления | 2731–2944 | -| · Обработка форм | 2945–3084 | -| · Разворачивание ссылок | 3085–3197 | -| · Экспорт сообщений | 3198–3339 | -| · DLP-система | 3340–3547 | -| · Пачка Audit Events API | 3548–3622 | -| · Форматирование текста | 3623–3703 | -| · Сценарии | 3704–4200 | -| · CLI | 4201–4294 | -| · Установка | 4295–4387 | -| · Авторизация | 4388–4461 | -| · Вывод | 4462–4565 | -| · Флаги и скрипты | 4566–4792 | -| · Сценарии | 4793–4840 | -| · Файлы | 4841–4875 | -| · Прямые запросы | 4876–4986 | -| · Команды | 4987–5123 | -| · SDK и генератор | 5124–5209 | -| · TypeScript | 5210–5626 | -| · Python | 5627–6037 | -| · Go | 6038–6473 | -| · Kotlin | 6474–6901 | -| · Swift | 6902–7298 | -| · C# | 7299–7756 | -| · n8n | 7757–7832 | -| · Начало работы | 7833–8060 | -| · Ресурсы и операции | 8061–8435 | -| · Триггер | 8436–8685 | -| · Тестирование | 8686–8959 | -| · Примеры workflow | 8960–9175 | -| · Продвинутые функции | 9176–9412 | -| · Устранение ошибок | 9413–9605 | -| · Миграция с v1 | 9606–9727 | -| · Последние обновления | 9728–9737 | -| · Авторизация | 9738–9916 | -| · Запросы и ответы | 9917–10109 | -| · Пагинация | 10110–10346 | -| · Загрузка файлов | 10347–10564 | -| · Ошибки | 10565–10638 | -| · Лимиты | 10639–10756 | -| · Модели | 10757–11334 | -| API-методы — все эндпоинты со схемами и примерами | 11335–27312 | -| · Common | 11337–12131 | -| · Profile | 12132–13133 | -| · Users | 13134–15519 | -| · Group tags | 15520–16867 | -| · Chats | 16868–18133 | -| · Members | 18134–19478 | -| · Threads | 19479–20036 | -| · Messages | 20037–21917 | -| · Read members | 21918–22164 | -| · Reactions | 22165–22811 | -| · Link Previews | 22812–23067 | -| · Search | 23068–23877 | -| · Tasks | 23878–25169 | -| · Views | 25170–25738 | -| · Bots | 25739–27000 | -| · Security | 27001–27312 | +| LIBRARY RULES — правила: auth, пагинация, лимиты, ошибки, SDK | 97–199 | +| How-to Guides — рецепты задач с кодом TS/Python | 200–883 | +| Руководства — гайды: SDK, вебхуки, боты, формы, n8n, CLI | 884–11435 | +| · Обзор | 889–991 | +| · Быстрый старт | 992–1081 | +| · AI агенты | 1082–1217 | +| · Взаимодействие с агентом | 1218–1286 | +| · Markdown и документы | 1287–1343 | +| · Треды | 1344–1471 | +| · Боты | 1472–1534 | +| · Создание и настройка | 1535–1661 | +| · Доступы к чатам и сообщениям | 1662–1734 | +| · Готовые примеры реализации | 1735–1769 | +| · Входящие вебхуки | 1770–1910 | +| · Исходящие вебхуки | 1911–1955 | +| · Настройка и типы событий | 1956–2130 | +| · Безопасность и обработчик | 2131–2321 | +| · Поллинг | 2322–2505 | +| · Кнопки в сообщениях | 2506–2661 | +| · Формы | 2662–2731 | +| · Блоки представления | 2732–2945 | +| · Обработка форм | 2946–3085 | +| · Разворачивание ссылок | 3086–3198 | +| · Экспорт сообщений | 3199–3340 | +| · DLP-система | 3341–3548 | +| · Пачка Audit Events API | 3549–3623 | +| · Форматирование текста | 3624–3704 | +| · Сценарии | 3705–4201 | +| · CLI | 4202–4295 | +| · Установка | 4296–4388 | +| · Авторизация | 4389–4462 | +| · Вывод | 4463–4566 | +| · Флаги и скрипты | 4567–4793 | +| · Сценарии | 4794–4841 | +| · Файлы | 4842–4876 | +| · Прямые запросы | 4877–4987 | +| · Команды | 4988–5124 | +| · SDK и генератор | 5125–5210 | +| · TypeScript | 5211–5627 | +| · Python | 5628–6038 | +| · Go | 6039–6474 | +| · Kotlin | 6475–6902 | +| · Swift | 6903–7299 | +| · C# | 7300–7757 | +| · n8n | 7758–7833 | +| · Начало работы | 7834–8061 | +| · Ресурсы и операции | 8062–8436 | +| · Триггер | 8437–8686 | +| · Тестирование | 8687–8960 | +| · Примеры workflow | 8961–9176 | +| · Продвинутые функции | 9177–9413 | +| · Устранение ошибок | 9414–9606 | +| · Миграция с v1 | 9607–9728 | +| · Последние обновления | 9729–9738 | +| · Обзор | 9739–9838 | +| · Авторизация | 9839–10017 | +| · Запросы и ответы | 10018–10210 | +| · Пагинация | 10211–10447 | +| · Загрузка файлов | 10448–10665 | +| · Ошибки | 10666–10739 | +| · Лимиты | 10740–10857 | +| · Модели | 10858–11435 | +| API-методы — все эндпоинты со схемами и примерами | 11436–27413 | +| · Common | 11438–12232 | +| · Profile | 12233–13234 | +| · Users | 13235–15620 | +| · Group tags | 15621–16968 | +| · Chats | 16969–18234 | +| · Members | 18235–19579 | +| · Threads | 19580–20137 | +| · Messages | 20138–22018 | +| · Read members | 22019–22265 | +| · Reactions | 22266–22912 | +| · Link Previews | 22913–23168 | +| · Search | 23169–23978 | +| · Tasks | 23979–25270 | +| · Views | 25271–25839 | +| · Bots | 25840–27101 | +| · Security | 27102–27413 | # LIBRARY RULES @@ -887,7 +888,7 @@ setInterval(() => reconcileUsers(externalDb), 15 * 60 * 1000) // Every 15 minute # Обзор -REST API Пачки позволяет автоматизировать работу в мессенджере: отправлять сообщения, управлять чатами и сотрудниками, создавать ботов и реагировать на события через вебхуки. +Автоматизируйте рабочие процессы и стройте интеграции с Пачкой: уведомления из мониторинга и CRM, боты и AI-агенты, реакция на события в реальном времени. Работайте через REST API, CLI, типизированные SDK, n8n или Agent Skills. - [Быстрый старт](/guides/quickstart) - [Авторизация](/api/authorization) @@ -4200,7 +4201,7 @@ curl "https://api.pachca.com/api/shared/v1/audit_events?start_time=2025-05-01T00 # CLI -[@pachca/cli](https://www.npmjs.com/package/@pachca/cli) npm +- [@pachca/cli](https://www.npmjs.com/package/@pachca/cli) npm Официальный CLI для Pachca API: авторизация, сообщения, управление пространством — всё из терминала. Каждый метод API доступен как команда с типизированными флагами, валидацией и подсказками. Нужен Node.js 20+. @@ -5137,7 +5138,7 @@ pachca commands --available ## Генератор -[@pachca/generator](https://www.npmjs.com/package/@pachca/generator) npm +- [@pachca/generator](https://www.npmjs.com/package/@pachca/generator) npm Генерирует типы и клиент из OpenAPI-спецификации прямо в вашем проекте. Сгенерированный код можно закоммитить в репозиторий и добавить генерацию в CI как проверку совместимости с актуальным API. [Исходный код на GitHub](https://github.com/pachca/openapi/tree/main/packages/generator). @@ -5209,7 +5210,7 @@ curl "https://api.pachca.com/api/shared/v1/profile" \ # TypeScript -[@pachca/sdk](https://www.npmjs.com/package/@pachca/sdk) npm +- [@pachca/sdk](https://www.npmjs.com/package/@pachca/sdk) npm Типизированный клиент для Pachca API. Работает в Node.js 18+ и в любом окружении с поддержкой `fetch`. ES Module с TypeScript-декларациями. @@ -5626,7 +5627,7 @@ const response = client.tasks.createTask(request) # Python -[pachca-sdk](https://pypi.org/project/pachca-sdk/) PyPI +- [pachca-sdk](https://pypi.org/project/pachca-sdk/) PyPI Асинхронный типизированный клиент для Pachca API. Построен на httpx с поддержкой type hints и dataclass-моделей. Требуется Python 3.10+. @@ -6037,7 +6038,7 @@ response = await client.tasks.create_task(request=request) # Go -[github.com/pachca/openapi/sdk/go](https://pkg.go.dev/github.com/pachca/openapi/sdk/go/generated) pkg.go.dev +- [github.com/pachca/openapi/sdk/go](https://pkg.go.dev/github.com/pachca/openapi/sdk/go/generated) pkg.go.dev Типизированный клиент для Pachca API на Go. Синхронный, с контекстами (`context.Context`), автопагинацией и обработкой retry. Требуется Go 1.24+. @@ -6473,7 +6474,7 @@ response, err := client.Tasks.CreateTask(ctx, request) # Kotlin -[com.pachca:pachca-sdk](https://github.com/pachca/openapi/tree/main/sdk/kotlin) JitPack +- [com.pachca:pachca-sdk](https://github.com/pachca/openapi/tree/main/sdk/kotlin) JitPack Типизированный клиент для Pachca API на Kotlin. Построен на Ktor с корутинами (`suspend`), kotlinx.serialization и встроенным retry. Требуется Kotlin 2.2+ и Java 11+. @@ -6901,7 +6902,7 @@ val response = client.tasks.createTask(request = request) # Swift -[PachcaSDK](https://github.com/pachca/openapi/tree/main/sdk/swift) Swift Package +- [PachcaSDK](https://github.com/pachca/openapi/tree/main/sdk/swift) Swift Package Типизированный клиент для Pachca API на Swift. Построен на URLSession с `async throws`, Codable-моделями и встроенным retry. Требуется Swift 5.9+, macOS 13+ или iOS 16+. @@ -7298,7 +7299,7 @@ let response = try await client.tasks.createTask(body: body) # C# -[Pachca.Sdk](https://www.nuget.org/packages/Pachca.Sdk) NuGet +- [Pachca.Sdk](https://www.nuget.org/packages/Pachca.Sdk) NuGet Типизированный клиент для Pachca API. Работает в .NET 8+ с поддержкой `async/await` и `CancellationToken`. @@ -9730,6 +9731,106 @@ AI Agent самостоятельно выбирает подходящий ин > **Обновление продукта** — [Показать все обновления](https://pachca.com/updates) +--- + +--- [Document source](https://dev.pachca.com/api/overview.md) --- + + +# Обзор + +REST API Пачки позволяет автоматизировать работу в мессенджере: отправлять сообщения, управлять чатами и сотрудниками, создавать ботов и реагировать на события через вебхуки. + +Базовый URL: `https://api.pachca.com/api/shared/v1` + +Клиенты и SDK: + +**CLI** — [документация](/guides/cli/overview) + +```bash +npm install -g @pachca/cli +``` + +**TypeScript** — [документация](/guides/sdk/typescript) + +```bash +npm install @pachca/sdk +``` + +**Python** — [документация](/guides/sdk/python) + +```bash +pip install pachca-sdk +``` + +**Go** — [документация](/guides/sdk/go) + +```bash +go get github.com/pachca/openapi/sdk/go/generated +``` + +**Kotlin** — [документация](/guides/sdk/kotlin) + +```kotlin +// build.gradle.kts +dependencies { + implementation("com.pachca:pachca-sdk:latest.release") +} +``` + +**Swift** — [документация](/guides/sdk/swift) + +```swift +// Package.swift +dependencies: [ + .package(url: "https://github.com/pachca/openapi", from: "1.0.0") +] +``` + +**C#** — [документация](/guides/sdk/csharp) + +```bash +dotnet add package Pachca.Sdk +``` + +Ресурсы: + +- [OpenAPI](/openapi.yaml) +- [Postman](/pachca.postman_collection.json) + + +## Популярные методы + +Частые операции для быстрого старта. Все модели API и доступные для них методы можно посмотреть на странице [Модели](/api/models). + +- [Новое сообщение](/api/messages/create) + +- [Список сообщений чата](/api/messages/list) + +- [Поиск сообщений](/api/search/list-messages) + +- [Создать чат](/api/chats/create) + +- [Создать сотрудника](/api/users/create) + +- [Новый статус](/api/profile/update-status) + +- [Новое напоминание](/api/tasks/create) + +- [Создание бота](/api/bots/create) + + +## Основы API + +Базовые концепции для работы с API: авторизация, формат запросов и ответов, обработка ошибок, лимиты, пагинация и загрузка файлов. + +- [Авторизация](/api/authorization) — Bearer-токен и доступ к API +- [Запросы и ответы](/api/requests-responses) — Базовый URL, заголовки, формат данных +- [Пагинация](/api/pagination) — Обход больших списков по курсору +- [Загрузка файлов](/api/file-uploads) — Прямая загрузка в S3 одной командой +- [Ошибки](/api/errors) — HTTP-коды и структуры ответов +- [Лимиты](/api/limits) — Rate limits и повторные запросы + + --- --- [Document source](https://dev.pachca.com/api/authorization.md) --- @@ -10823,13 +10924,13 @@ users = await with_retry(lambda: client.users.list_users()) ## Сотрудник +- [Создать сотрудника](POST /users) - [Информация о профиле](GET /profile) - [Информация о сотруднике](GET /users/{id}) - [Список сотрудников](GET /users) - [Список сотрудников тега](GET /group_tags/{id}/users) - [Список участников чата](GET /chats/{id}/members) - [Поиск сотрудников](GET /search/users) -- [Создать сотрудника](POST /users) - [Редактирование сотрудника](PUT /users/{id}) - [Удаление сотрудника](DELETE /users/{id}) @@ -10873,10 +10974,10 @@ users = await with_retry(lambda: client.users.list_users()) ## Тег -- [Информация о теге](GET /group_tags/{id}) -- [Список тегов сотрудников](GET /group_tags) - [Новый тег](POST /group_tags) - [Добавление тегов](POST /chats/{id}/group_tags) +- [Информация о теге](GET /group_tags/{id}) +- [Список тегов сотрудников](GET /group_tags) - [Редактирование тега](PUT /group_tags/{id}) - [Исключение тега](DELETE /chats/{id}/group_tags/{tag_id}) - [Удаление тега](DELETE /group_tags/{id}) @@ -10890,13 +10991,13 @@ users = await with_retry(lambda: client.users.list_users()) ## Чат +- [Новый чат](POST /chats) +- [Добавление пользователей](POST /chats/{id}/members) +- [Экспорт сообщений](POST /chats/exports) - [Информация о чате](GET /chats/{id}) - [Список чатов](GET /chats) - [Поиск чатов](GET /search/chats) - [Скачать архив экспорта](GET /chats/exports/{id}) -- [Новый чат](POST /chats) -- [Добавление пользователей](POST /chats/{id}/members) -- [Экспорт сообщений](POST /chats/exports) - [Обновление чата](PUT /chats/{id}) - [Архивация чата](PUT /chats/{id}/archive) - [Разархивация чата](PUT /chats/{id}/unarchive) @@ -10921,9 +11022,9 @@ users = await with_retry(lambda: client.users.list_users()) ## Тред +- [Новый тред](POST /messages/{id}/thread) - [Информация о треде](GET /threads/{id}) - [Список тредов](GET /threads) -- [Новый тред](POST /messages/{id}/thread) Тред @@ -10936,13 +11037,13 @@ users = await with_retry(lambda: client.users.list_users()) ## Сообщение +- [Новое сообщение](POST /messages) +- [Закрепление сообщения](POST /messages/{id}/pin) +- [Unfurl (разворачивание ссылок)](POST /messages/{id}/link_previews) - [Информация о сообщении](GET /messages/{id}) - [Список сообщений чата](GET /messages) - [Поиск сообщений](GET /search/messages) - [Список прочитавших сообщение](GET /messages/{id}/read_member_ids) -- [Новое сообщение](POST /messages) -- [Закрепление сообщения](POST /messages/{id}/pin) -- [Unfurl (разворачивание ссылок)](POST /messages/{id}/link_previews) - [Редактирование сообщения](PUT /messages/{id}) - [Открепление сообщения](DELETE /messages/{id}/pin) - [Удаление сообщения](DELETE /messages/{id}) @@ -10993,8 +11094,8 @@ users = await with_retry(lambda: client.users.list_users()) ## Реакция на сообщение -- [Список реакций](GET /messages/{id}/reactions) - [Добавление реакции](POST /messages/{id}/reactions) +- [Список реакций](GET /messages/{id}/reactions) - [Удаление реакции](DELETE /messages/{id}/reactions) Реакция на сообщение @@ -11007,9 +11108,9 @@ users = await with_retry(lambda: client.users.list_users()) ## Напоминание +- [Новое напоминание](POST /tasks) - [Информация о напоминании](GET /tasks/{id}) - [Список напоминаний](GET /tasks) -- [Новое напоминание](POST /tasks) - [Редактирование напоминания](PUT /tasks/{id}) - [Удаление напоминания](DELETE /tasks/{id}) diff --git a/apps/docs/public/llms.txt b/apps/docs/public/llms.txt index 253a2739..ca496641 100644 --- a/apps/docs/public/llms.txt +++ b/apps/docs/public/llms.txt @@ -51,10 +51,10 @@ | CLI Quick Start | Установка, команды, точечная справка по API | 59–77 | | SDK | Типизированные клиенты для 6 языков | 78–104 | | Agent Skills | Скиллы для AI-агентов и установка | 105–127 | -| Руководства | Страницы-руководства (Markdown по `.md`) | 128–187 | -| API-методы | Все эндпоинты, сгруппированы по разделам | 188–290 | -| Обновления | Журнал обновлений по датам | 291–341 | -| Дополнительно | Прочие ссылки и контакты | 342–350 | +| Руководства | Страницы-руководства (Markdown по `.md`) | 128–188 | +| API-методы | Все эндпоинты, сгруппированы по разделам | 189–291 | +| Обновления | Журнал обновлений по датам | 292–342 | +| Дополнительно | Прочие ссылки и контакты | 343–351 | ## CLI Quick Start @@ -177,6 +177,7 @@ C#: new PachcaClient("TOKEN") → await client.Messages.CreateMessage - [n8n, Устранение ошибок](https://dev.pachca.com/guides/n8n/troubleshooting.md): Частые ошибки при работе с Пачкой в n8n: неверный Access Token, 401 Unauthorized, 403 Forbidden, 429 Too Many Requests и проблемы с доставкой вебхука - [n8n, Миграция с v1](https://dev.pachca.com/guides/n8n/migration.md): Обновление расширения Пачки для n8n с v1 на v2: таблицы переименований, новые возможности и полная обратная совместимость для существующих workflow - [Последние обновления](https://dev.pachca.com/updates.md): История изменений API Пачки, CLI, SDK и расширения для n8n. Новые методы, параметры и возможности. RSS-лента и markdown-версия для AI-агентов и интеграций +- [Основы API, Обзор](https://dev.pachca.com/api/overview.md): Обзор REST API Пачки: базовый URL, авторизация по Bearer-токену, формат запросов и ответов, клиенты и SDK для CLI, TypeScript, Python, Go, Kotlin, Swift и C# - [Основы API, Авторизация](https://dev.pachca.com/api/authorization.md): Авторизация в API Пачки: персональный токен и токен бота, скоупы методов, настройка доступа для администраторов и сотрудников, смена владельца пространства - [Основы API, Запросы и ответы](https://dev.pachca.com/api/requests-responses.md): Формат запросов и ответов API Пачки: базовый URL, заголовки Authorization и Content-Type, структура JSON-тела, коллекции Postman и Bruno для тестирования - [Основы API, Пагинация](https://dev.pachca.com/api/pagination.md): Пагинация в API Пачки по курсору: две группы методов (списочные и поиск) с разной структурой meta, поля next_page, prev_page, has_next, has_prev, обход всех записей и polling новых данных через prev_page diff --git a/apps/docs/public/skill.md b/apps/docs/public/skill.md index 218c8e57..e282d6f4 100644 --- a/apps/docs/public/skill.md +++ b/apps/docs/public/skill.md @@ -277,6 +277,7 @@ Detailed documentation on specific topics is available at: - [n8n, Устранение ошибок](https://dev.pachca.com/guides/n8n/troubleshooting) — Частые ошибки при работе с Пачкой в n8n: неверный Access Token, 401 Unauthorized, 403 Forbidden, 429 Too Many Requests и проблемы с доставкой вебхука - [n8n, Миграция с v1](https://dev.pachca.com/guides/n8n/migration) — Обновление расширения Пачки для n8n с v1 на v2: таблицы переименований, новые возможности и полная обратная совместимость для существующих workflow - [Последние обновления](https://dev.pachca.com/updates) — История изменений API Пачки, CLI, SDK и расширения для n8n. Новые методы, параметры и возможности. RSS-лента и markdown-версия для AI-агентов и интеграций +- [Основы API, Обзор](https://dev.pachca.com/api/overview) — Обзор REST API Пачки: базовый URL, авторизация по Bearer-токену, формат запросов и ответов, клиенты и SDK для CLI, TypeScript, Python, Go, Kotlin, Swift и C# - [Основы API, Авторизация](https://dev.pachca.com/api/authorization) — Авторизация в API Пачки: персональный токен и токен бота, скоупы методов, настройка доступа для администраторов и сотрудников, смена владельца пространства - [Основы API, Запросы и ответы](https://dev.pachca.com/api/requests-responses) — Формат запросов и ответов API Пачки: базовый URL, заголовки Authorization и Content-Type, структура JSON-тела, коллекции Postman и Bruno для тестирования - [Основы API, Пагинация](https://dev.pachca.com/api/pagination) — Пагинация в API Пачки по курсору: две группы методов (списочные и поиск) с разной структурой meta, поля next_page, prev_page, has_next, has_prev, обход всех записей и polling новых данных через prev_page diff --git a/apps/docs/scripts/check-models-coverage.mjs b/apps/docs/scripts/check-models-coverage.mjs new file mode 100644 index 00000000..f8ca3c95 --- /dev/null +++ b/apps/docs/scripts/check-models-coverage.mjs @@ -0,0 +1,84 @@ +import yaml from 'js-yaml'; +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const openapiPath = path.join(__dirname, '..', '..', '..', 'packages', 'spec', 'openapi.yaml'); +const modelsPath = path.join(__dirname, '..', 'content', 'api', 'models.mdx'); + +const HTTP_METHODS = ['get', 'post', 'put', 'delete', 'patch']; + +/** + * The models page (content/api/models.mdx) maps every data model to the methods + * that operate on it. Unlike the left nav it is hand-curated — endpoints are + * grouped by the model they read/write, a dimension that does not exist in the + * spec (DELETE/action endpoints carry no response schema $ref, and model + * sections cut across tags). So it cannot be generated. + * + * This guard makes drift loud instead of silent: every operation in the spec + * must be referenced on the page (as `(METHOD /path)`), and every reference on + * the page must still exist in the spec. When the backend adds or removes an + * endpoint, `turbo check` fails until models.mdx is updated. + * + * Operations that genuinely never belong on the models page (if any ever + * appear) go in ALLOWLIST below with a reason. + */ +const ALLOWLIST = new Set([ + // 'METHOD /path', // reason +]); + +const openapi = yaml.load(fs.readFileSync(openapiPath, 'utf8')); + +const specOps = new Set(); +for (const [pathStr, pathItem] of Object.entries(openapi.paths)) { + for (const method of Object.keys(pathItem)) { + if (HTTP_METHODS.includes(method.toLowerCase())) { + specOps.add(`${method.toUpperCase()} ${pathStr}`); + } + } +} + +const mdx = fs.readFileSync(modelsPath, 'utf8'); +const referenced = new Set(); +const refRe = /\((GET|POST|PUT|DELETE|PATCH)\s+(\/[^)]+)\)/g; +let m; +while ((m = refRe.exec(mdx)) !== null) { + referenced.add(`${m[1]} ${m[2]}`); +} + +const missing = [...specOps].filter((op) => !referenced.has(op) && !ALLOWLIST.has(op)).sort(); +const stale = [...referenced].filter((op) => !specOps.has(op)).sort(); + +console.log('=== MODELS PAGE COVERAGE ===\n'); +console.log(`Spec operations: ${specOps.size}`); +console.log(`Referenced on page: ${referenced.size}`); +console.log(`Allowlisted: ${ALLOWLIST.size}\n`); + +let failed = false; + +if (missing.length > 0) { + failed = true; + console.error('❌ In the spec but NOT on the models page (content/api/models.mdx):\n'); + missing.forEach((op) => console.error(` ${op}`)); + console.error( + '\n Add each new endpoint to the matching model section in models.mdx,' + + '\n or add it to ALLOWLIST in this script if it does not return a data model.\n' + ); +} + +if (stale.length > 0) { + failed = true; + console.error('❌ On the models page but NOT in the spec (stale references):\n'); + stale.forEach((op) => console.error(` ${op}`)); + console.error('\n Remove or fix these references in models.mdx.\n'); +} + +if (failed) { + console.error('❌ Build failed: models page is out of sync with the OpenAPI spec.\n'); + process.exit(1); +} + +console.log('✅ Models page covers every spec operation.\n'); diff --git a/turbo.json b/turbo.json index 541eddfa..c75ba492 100644 --- a/turbo.json +++ b/turbo.json @@ -107,13 +107,18 @@ "cache": true }, "check": { - "dependsOn": ["lint", "typecheck", "knip", "format:check", "test", "@pachca/spec#overlay:validate"], + "dependsOn": ["lint", "typecheck", "knip", "format:check", "test", "@pachca/spec#overlay:validate", "check-models"], "cache": false }, "check-urls": { "dependsOn": ["@pachca/spec#generate"], "cache": true }, + "check-models": { + "dependsOn": ["@pachca/spec#generate"], + "inputs": ["scripts/check-models-coverage.mjs", "content/api/models.mdx"], + "cache": true + }, "update-snapshots": { "inputs": ["src/**", "tests/**/fixture.yaml"], "outputs": ["tests/**/snapshots/**"],