gitverse-api-sdk 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +328 -114
  2. package/dist/api/actions.d.ts +506 -0
  3. package/dist/api/actions.js +4 -0
  4. package/dist/api/actions.js.map +10 -0
  5. package/dist/api/branches.d.ts +154 -0
  6. package/dist/api/branches.js +4 -0
  7. package/dist/api/branches.js.map +10 -0
  8. package/dist/api/collaborators.d.ts +224 -0
  9. package/dist/api/collaborators.js +4 -0
  10. package/dist/api/collaborators.js.map +10 -0
  11. package/dist/api/commits.d.ts +302 -0
  12. package/dist/api/commits.js +4 -0
  13. package/dist/api/commits.js.map +10 -0
  14. package/dist/api/contents.d.ts +345 -0
  15. package/dist/api/contents.js +4 -0
  16. package/dist/api/contents.js.map +10 -0
  17. package/dist/api/emails.d.ts +184 -0
  18. package/dist/api/emails.js +4 -0
  19. package/dist/api/emails.js.map +10 -0
  20. package/dist/api/forks.d.ts +325 -0
  21. package/dist/api/forks.js +4 -0
  22. package/dist/api/forks.js.map +10 -0
  23. package/dist/api/git.d.ts +228 -0
  24. package/dist/api/git.js +4 -0
  25. package/dist/api/git.js.map +10 -0
  26. package/dist/api/issues.d.ts +380 -0
  27. package/dist/api/issues.js +4 -0
  28. package/dist/api/issues.js.map +10 -0
  29. package/dist/api/organizations.d.ts +140 -0
  30. package/dist/api/organizations.js +4 -0
  31. package/dist/api/organizations.js.map +10 -0
  32. package/dist/api/pulls.d.ts +517 -0
  33. package/dist/api/pulls.js +4 -0
  34. package/dist/api/pulls.js.map +10 -0
  35. package/dist/api/releases.d.ts +400 -0
  36. package/dist/api/releases.js +4 -0
  37. package/dist/api/releases.js.map +10 -0
  38. package/dist/api/repositories.d.ts +502 -0
  39. package/dist/api/repositories.js +4 -0
  40. package/dist/api/repositories.js.map +10 -0
  41. package/dist/api/stars.d.ts +328 -0
  42. package/dist/api/stars.js +4 -0
  43. package/dist/api/stars.js.map +10 -0
  44. package/dist/api/teams.d.ts +287 -0
  45. package/dist/api/teams.js +4 -0
  46. package/dist/api/teams.js.map +10 -0
  47. package/dist/api/users.d.ts +244 -0
  48. package/dist/api/users.js +4 -0
  49. package/dist/api/users.js.map +10 -0
  50. package/dist/client.d.ts +122 -0
  51. package/dist/client.js +4 -0
  52. package/dist/client.js.map +10 -0
  53. package/dist/enums.d.ts +57 -0
  54. package/dist/enums.js +4 -0
  55. package/dist/enums.js.map +10 -0
  56. package/dist/errors.d.ts +78 -0
  57. package/dist/errors.js +4 -0
  58. package/dist/errors.js.map +10 -0
  59. package/dist/index.d.ts +1801 -453
  60. package/dist/index.js +3 -1
  61. package/dist/index.js.map +10 -0
  62. package/dist/types.d.ts +1256 -0
  63. package/dist/types.js +2 -0
  64. package/dist/types.js.map +9 -0
  65. package/dist/utils.d.ts +39 -0
  66. package/dist/utils.js +3 -0
  67. package/dist/utils.js.map +10 -0
  68. package/package.json +99 -7
package/README.md CHANGED
@@ -1,167 +1,381 @@
1
1
  # GitVerse SDK
2
2
 
3
- ![Build Status](https://img.shields.io/badge/tests-passing-brightgreen)
4
- ![Coverage](https://img.shields.io/badge/coverage-100%25-blue)
5
- ![Version](https://img.shields.io/npm/v/@onreza/gitverse-sdk)
3
+ [![npm version](https://img.shields.io/npm/v/gitverse-api-sdk.svg)](https://www.npmjs.com/package/gitverse-api-sdk)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![Test Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen.svg)](https://gitverse.ru/rainypixel/gitverse-sdk)
6
6
 
7
- **Легковесный TypeScript SDK для взаимодействия с GitVerse API**
7
+ Полнофункциональный TypeScript SDK для GitVerse API с поддержкой всех эндпоинтов, обработкой Rate Limits и версионирования.
8
8
 
9
- > 🚀 Без внешних зависимостей
9
+ ## Ключевые особенности
10
10
 
11
- ---
12
-
13
- ## 📋 Оглавление
14
-
15
- - [Установка](#-установка)
16
- - [Быстрый старт](#-быстрый-старт)
17
- - [Использование](#-использование)
18
- - [Особенности](#-особенности)
19
- - [API](#-api)
20
- - [Тестирование](#-тестирование)
21
- - [Разработка](#-разработка)
22
- - [Contributing](#-contributing)
23
- - [Лицензия](#-лицензия)
11
+ - ✅ **100% покрытие API** — Все 90 эндпоинтов GitVerse API поддерживаются
12
+ - ✅ **Rate Limits** — Автоматическая обработка лимитов запросов с информативными ошибками
13
+ - **Версионирование API** — Предупреждения об устаревших версиях API
14
+ - ✅ **Специализированные ошибки** — `RateLimitError`, `ApiVersionWarning` для точной обработки
15
+ - ✅ **100% покрытие тестами** — Полное тестирование всех методов
16
+ - **Нет зависимостей** — Только нативный `fetch` API и `Buffer`
17
+ - ✅ **Tree-shakable** — Модульная архитектура для минимального размера бандла
18
+ - ✅ **TypeScript** — Полная типизация из коробки
24
19
 
25
- ---
26
-
27
- ## 🚀 Быстрый старт
20
+ ## Установка
28
21
 
29
22
  ```bash
30
- # bun
31
- bun add @onreza/gitverse-sdk
32
23
  # npm
33
- npm install @onreza/gitverse-sdk
24
+ npm install gitverse-api-sdk
25
+
34
26
  # yarn
35
- yarn add @onreza/gitverse-sdk
27
+ yarn add gitverse-api-sdk
28
+
36
29
  # pnpm
37
- pnpm add @onreza/gitverse-sdk
30
+ pnpm add gitverse-api-sdk
31
+
32
+ # bun
33
+ bun add gitverse-api-sdk
38
34
  ```
39
35
 
40
- ## 📖 Использование
36
+ ## Быстрый старт
41
37
 
42
38
  ```typescript
43
- import GitVerse from '@onreza/gitverse-sdk';
39
+ import { GitVerse } from 'gitverse-api-sdk';
40
+
41
+ // Создание клиента с токеном
42
+ const client = new GitVerse({ token: 'your-token-here' });
43
+
44
+ // Получение информации о текущем пользователе
45
+ const user = await client.users.getCurrent();
46
+ console.log(user.login);
47
+
48
+ // Получение репозитория
49
+ const repo = await client.repos.get('owner', 'repo-name');
50
+ console.log(repo.full_name);
51
+
52
+ // Создание Pull Request
53
+ const pr = await client.pulls.create('owner', 'repo', {
54
+ title: 'New feature',
55
+ head: 'feature-branch',
56
+ base: 'main',
57
+ body: 'Description of changes'
58
+ });
59
+ ```
60
+
61
+ ## Обработка Rate Limits
44
62
 
45
- (async () => {
46
- const sdk = new GitVerse({ token: 'YOUR_TOKEN' });
63
+ SDK автоматически отслеживает лимиты запросов и предоставляет подробную информацию при их превышении:
47
64
 
48
- // Получить текущего пользователя
49
- const me = await sdk.users.getCurrent();
50
- console.log(me);
65
+ ```typescript
66
+ import { GitVerse, RateLimitError } from 'gitverse-api-sdk';
67
+
68
+ const client = new GitVerse({ token: 'your-token' });
69
+
70
+ try {
71
+ await client.repos.get('owner', 'repo');
72
+ } catch (error) {
73
+ if (error instanceof RateLimitError) {
74
+ console.log(`Rate limit exceeded!`);
75
+ console.log(`Limit: ${error.rateLimit.limit}`);
76
+ console.log(`Remaining: ${error.rateLimit.remaining}`);
77
+ console.log(`Reset at: ${new Date(error.rateLimit.reset * 1000)}`);
78
+
79
+ // Ожидание сброса лимита
80
+ const waitTime = error.rateLimit.reset * 1000 - Date.now();
81
+ await new Promise(resolve => setTimeout(resolve, waitTime));
82
+ }
83
+ }
84
+ ```
85
+
86
+ ## Обработка версионирования API
51
87
 
52
- // Получить репозиторий
53
- const repo = await sdk.repos.get('owner', 'repo');
54
- console.log(repo);
88
+ SDK предупреждает об использовании устаревших версий API:
55
89
 
56
- // Создать репозиторий
57
- const newRepo = await sdk.repos.create({
58
- name: 'my-new-repo',
59
- description: 'Описание репозитория',
60
- private: false
61
- });
90
+ ```typescript
91
+ import { GitVerse } from 'gitverse-api-sdk';
92
+
93
+ const client = new GitVerse({
94
+ token: 'your-token',
95
+ apiVersion: '2022-11-28', // Указание версии API
96
+ onApiVersionWarning: (warning) => {
97
+ console.warn(`API Warning: ${warning.message}`);
98
+ console.warn(`Current version: ${warning.currentVersion}`);
99
+ console.warn(`Sunset date: ${warning.sunsetDate}`);
100
+ }
101
+ });
102
+ ```
62
103
 
63
- // Управление email адресами
64
- const emails = await sdk.emails.list();
65
- await sdk.emails.add({ emails: ['new@example.com'] });
104
+ ## API Модули
66
105
 
67
- // Работа со звездами
68
- await sdk.stars.add('owner', 'repo');
69
- const isStarred = await sdk.stars.check('owner', 'repo');
106
+ SDK организован в специализированные модули для различных областей GitVerse API:
70
107
 
71
- // Получить issues
72
- const issues = await sdk.issues.list('owner', 'repo');
108
+ ### 👤 Users (2 метода)
73
109
 
74
- // Создать файл
75
- const file = await sdk.contents.createFile('owner', 'repo', 'path.txt', {
76
- content: Buffer.from('Hello').toString('base64'),
77
- message: 'feat: add greeting',
78
- });
79
- console.log(file);
80
- })();
110
+ ```typescript
111
+ await client.users.getCurrent();
112
+ await client.users.getByUsername('username');
81
113
  ```
82
114
 
83
- ## Особенности
115
+ ### 📦 Repositories (7 методов)
84
116
 
85
- - **100% покрытие** тестов (lines/functions/statements)
86
- - **Нет сторонних зависимостей**
87
- - Поддержка **Conventional Commits**
88
- - Интуитивный API, единообразный интерфейс
89
- - Работа через **fetch**, совместим с Bun и браузером
117
+ ```typescript
118
+ await client.repos.get('owner', 'repo');
119
+ await client.repos.create({ name: 'new-repo', private: true });
120
+ await client.repos.update('owner', 'repo', { description: 'Updated' });
121
+ await client.repos.delete('owner', 'repo');
122
+ await client.repos.compare('owner', 'repo', 'main...dev');
123
+ await client.repos.getLanguages('owner', 'repo');
124
+ await client.repos.listForAuthenticatedUser();
125
+ ```
90
126
 
91
- ## 🔍 API
127
+ ### 📁 Contents (4 метода)
92
128
 
93
- ### Users
129
+ ```typescript
130
+ await client.contents.get('owner', 'repo', 'path/to/file');
131
+ await client.contents.create('owner', 'repo', 'path', { message: 'Add file', content: 'base64' });
132
+ await client.contents.update('owner', 'repo', 'path', { message: 'Update', content: 'base64', sha: 'sha' });
133
+ await client.contents.delete('owner', 'repo', 'path', { message: 'Delete', sha: 'sha' });
134
+ ```
94
135
 
95
- - `sdk.users.getCurrent()`
96
- - `sdk.users.getByUsername(username: string)`
136
+ ### 🔀 Pull Requests (7 методов)
97
137
 
98
- ### Repositories
138
+ ```typescript
139
+ await client.pulls.list('owner', 'repo');
140
+ await client.pulls.create('owner', 'repo', { title: 'New PR', head: 'feature', base: 'main' });
141
+ await client.pulls.get('owner', 'repo', 123);
142
+ await client.pulls.update('owner', 'repo', 123, { title: 'Updated title' });
143
+ await client.pulls.merge('owner', 'repo', 123);
144
+ await client.pulls.getFiles('owner', 'repo', 123);
145
+ await client.pulls.updateBranch('owner', 'repo', 123);
146
+ ```
99
147
 
100
- - `sdk.repos.get(owner: string, repo: string)`
101
- - `sdk.repos.getLanguages(owner: string, repo: string)`
102
- - `sdk.repos.listForAuthenticatedUser()`
103
- - `sdk.repos.create(params: CreateRepositoryParams)`
148
+ ### 🐛 Issues (6 методов)
104
149
 
105
- ### Contents
150
+ ```typescript
151
+ await client.issues.list('owner', 'repo');
152
+ await client.issues.create('owner', 'repo', { title: 'Bug report' });
153
+ await client.issues.get('owner', 'repo', 123);
154
+ await client.issues.getComment('owner', 'repo', 456);
155
+ await client.issues.getComments('owner', 'repo', 123);
156
+ await client.issues.getLabels('owner', 'repo', 123);
157
+ ```
106
158
 
107
- - `sdk.contents.get(owner: string, repo: string, path: string)`
108
- - `sdk.contents.createFile(owner: string, repo: string, path: string, params)`
109
- - `sdk.contents.updateFile(owner: string, repo: string, path: string, params)`
110
- - `sdk.contents.deleteFile(owner: string, repo: string, path: string, params)`
159
+ ### 🍴 Forks (1 метод)
111
160
 
112
- ### Pulls
161
+ ```typescript
162
+ await client.forks.create('owner', 'repo');
163
+ ```
113
164
 
114
- - `sdk.pulls.list(owner: string, repo: string, state?)`
115
- - `sdk.pulls.get(owner: string, repo: string, number: number)`
116
- - `sdk.pulls.create(owner: string, repo: string, params)`
165
+ ### Stars (4 метода)
117
166
 
118
- ### Forks
167
+ ```typescript
168
+ await client.stars.list('owner', 'repo');
169
+ await client.stars.listForAuthenticatedUser();
170
+ await client.stars.star('owner', 'repo');
171
+ await client.stars.unstar('owner', 'repo');
172
+ ```
119
173
 
120
- - `sdk.forks.list(owner: string, repo: string)`
121
- - `sdk.forks.create(owner: string, repo: string)`
174
+ ### 📧 Emails (3 метода)
122
175
 
123
- ### Emails
176
+ ```typescript
177
+ await client.emails.list();
178
+ await client.emails.add(['email@example.com']);
179
+ await client.emails.delete(['email@example.com']);
180
+ ```
124
181
 
125
- - `sdk.emails.list()`
126
- - `sdk.emails.add(params: AddEmailParams)`
127
- - `sdk.emails.remove(params: RemoveEmailParams)`
182
+ ### 🌿 Branches (1 метод)
128
183
 
129
- ### Issues
184
+ ```typescript
185
+ await client.branches.list('owner', 'repo');
186
+ ```
130
187
 
131
- - `sdk.issues.list(owner: string, repo: string, state?: IssueState)`
132
- - `sdk.issues.get(owner: string, repo: string, number: number)`
188
+ ### 📝 Commits (3 метода)
133
189
 
134
- ### Stars
190
+ ```typescript
191
+ await client.commits.list('owner', 'repo');
192
+ await client.commits.get('owner', 'repo', 'sha');
193
+ await client.commits.getCommits('owner', 'repo', 123);
194
+ ```
135
195
 
136
- - `sdk.stars.add(owner: string, repo: string)`
137
- - `sdk.stars.check(owner: string, repo: string)`
138
- - `sdk.stars.remove(owner: string, repo: string)`
196
+ ### 👥 Collaborators (2 метода)
197
+
198
+ ```typescript
199
+ await client.collaborators.list('owner', 'repo');
200
+ await client.collaborators.add('owner', 'repo', 'username');
201
+ ```
202
+
203
+ ### 🏢 Organizations (1 метод)
204
+
205
+ ```typescript
206
+ await client.organizations.list();
207
+ ```
208
+
209
+ ### 👨‍👩‍👧‍👦 Teams (4 метода)
210
+
211
+ ```typescript
212
+ await client.teams.list('org');
213
+ await client.teams.get('org', 'team-slug');
214
+ await client.teams.listMembers('org', 'team-slug');
215
+ await client.teams.getMembershipForUser('org', 'team-slug', 'username');
216
+ ```
139
217
 
140
- ## 🧪 Тестирование
218
+ ### 🚀 Releases (10 методов)
219
+
220
+ ```typescript
221
+ await client.releases.list('owner', 'repo');
222
+ await client.releases.create('owner', 'repo', { tag_name: 'v1.0.0' });
223
+ await client.releases.get('owner', 'repo', 123);
224
+ await client.releases.getByTag('owner', 'repo', 'v1.0.0');
225
+ await client.releases.update('owner', 'repo', 123, { name: 'New name' });
226
+ await client.releases.delete('owner', 'repo', 123);
227
+ await client.releases.deleteByTag('owner', 'repo', 'v1.0.0');
228
+ await client.releases.getAssets('owner', 'repo', 123);
229
+ await client.releases.uploadAsset('owner', 'repo', 123, { name: 'asset.zip' });
230
+ await client.releases.deleteAsset('owner', 'repo', 123, 456);
231
+ ```
232
+
233
+ ### 🔧 Git Objects (3 метода)
234
+
235
+ ```typescript
236
+ await client.git.getTree('owner', 'repo', 'sha');
237
+ await client.git.getBlob('owner', 'repo', 'sha');
238
+ await client.git.getRef('owner', 'repo', 'heads/main');
239
+ ```
240
+
241
+ ### ⚡ Actions (33 метода)
242
+
243
+ Полная поддержка GitHub Actions API, включая:
244
+
245
+ **Runners (8 методов)**
246
+ ```typescript
247
+ await client.actions.listOrgRunners('org');
248
+ await client.actions.createOrgRegistrationToken('org');
249
+ await client.actions.getOrgRunner('org', 123);
250
+ await client.actions.deleteOrgRunner('org', 123);
251
+ await client.actions.listRepoRunners('owner', 'repo');
252
+ await client.actions.createRepoRegistrationToken('owner', 'repo');
253
+ await client.actions.getRepoRunner('owner', 'repo', 123);
254
+ await client.actions.deleteRepoRunner('owner', 'repo', 123);
255
+ ```
256
+
257
+ **Secrets (8 методов)**
258
+ ```typescript
259
+ await client.actions.listOrgSecrets('org');
260
+ await client.actions.getOrgSecret('org', 'SECRET_NAME');
261
+ await client.actions.createOrUpdateOrgSecret('org', 'SECRET_NAME', { encrypted_value: '...' });
262
+ await client.actions.deleteOrgSecret('org', 'SECRET_NAME');
263
+ await client.actions.listRepoSecrets('owner', 'repo');
264
+ await client.actions.getRepoSecret('owner', 'repo', 'SECRET_NAME');
265
+ await client.actions.createOrUpdateRepoSecret('owner', 'repo', 'SECRET_NAME', { encrypted_value: '...' });
266
+ await client.actions.deleteRepoSecret('owner', 'repo', 'SECRET_NAME');
267
+ ```
268
+
269
+ **Variables (10 методов)**
270
+ ```typescript
271
+ await client.actions.listOrgVariables('org');
272
+ await client.actions.createOrgVariable('org', { name: 'VAR', value: 'value' });
273
+ await client.actions.getOrgVariable('org', 'VAR');
274
+ await client.actions.updateOrgVariable('org', 'VAR', { value: 'new-value' });
275
+ await client.actions.deleteOrgVariable('org', 'VAR');
276
+ await client.actions.listRepoVariables('owner', 'repo');
277
+ await client.actions.createRepoVariable('owner', 'repo', { name: 'VAR', value: 'value' });
278
+ await client.actions.getRepoVariable('owner', 'repo', 'VAR');
279
+ await client.actions.updateRepoVariable('owner', 'repo', 'VAR', { value: 'new' });
280
+ await client.actions.deleteRepoVariable('owner', 'repo', 'VAR');
281
+ ```
282
+
283
+ **Artifacts (5 методов)**
284
+ ```typescript
285
+ await client.actions.listArtifacts('owner', 'repo');
286
+ await client.actions.getArtifact('owner', 'repo', 123);
287
+ await client.actions.deleteArtifact('owner', 'repo', 123);
288
+ await client.actions.downloadArtifact('owner', 'repo', 123);
289
+ await client.actions.downloadArtifactRaw('owner', 'repo', 123);
290
+ ```
291
+
292
+ **Workflows (2 метода)**
293
+ ```typescript
294
+ await client.actions.getWorkflowDispatchInputs('owner', 'repo', 'workflow.yml');
295
+ await client.actions.dispatchWorkflow('owner', 'repo', 'workflow.yml', { ref: 'main' });
296
+ ```
297
+
298
+ ## Продвинутое использование
299
+
300
+ ### Tree-shaking
301
+
302
+ Для минимального размера бандла импортируйте только нужные модули:
303
+
304
+ ```typescript
305
+ import { RepositoriesApi, GitVerseClient } from 'gitverse-api-sdk/api/repositories';
306
+ import { PullsApi } from 'gitverse-api-sdk/api/pulls';
307
+
308
+ const client = new GitVerseClient({ token: 'your-token' });
309
+ const repos = new RepositoriesApi(client);
310
+ const pulls = new PullsApi(client);
311
+
312
+ const repo = await repos.get('owner', 'repo');
313
+ const prList = await pulls.list('owner', 'repo');
314
+ ```
315
+
316
+ ### Обработка ошибок
317
+
318
+ ```typescript
319
+ import { GitVerse, GitVerseApiError, RateLimitError } from 'gitverse-api-sdk';
320
+
321
+ const client = new GitVerse({ token: 'your-token' });
322
+
323
+ try {
324
+ await client.repos.get('owner', 'repo');
325
+ } catch (error) {
326
+ if (error instanceof RateLimitError) {
327
+ console.error('Rate limit exceeded:', error.rateLimit);
328
+ } else if (error instanceof GitVerseApiError) {
329
+ console.error(`API Error ${error.status}:`, error.message);
330
+ } else {
331
+ console.error('Unexpected error:', error);
332
+ }
333
+ }
334
+ ```
335
+
336
+ ### Конфигурация клиента
337
+
338
+ ```typescript
339
+ import { GitVerse } from 'gitverse-api-sdk';
340
+
341
+ const client = new GitVerse({
342
+ token: 'your-token',
343
+ baseUrl: 'https://gitverse.ru/api/v1', // По умолчанию
344
+ apiVersion: '2022-11-28', // Версия API
345
+ onApiVersionWarning: (warning) => {
346
+ console.warn('API version warning:', warning);
347
+ }
348
+ });
349
+ ```
350
+
351
+ ## Разработка
141
352
 
142
353
  ```bash
354
+ # Установка зависимостей
355
+ bun install
356
+
357
+ # Запуск тестов
143
358
  bun test
144
- bun test --coverage
145
- ```
146
359
 
147
- ## 🛠 Разработка
360
+ # Проверка покрытия (требуется 100%)
361
+ bun test:coverage
148
362
 
149
- 1. Форк и клон:
150
- ```bash
151
- git clone https://gitverse.ru/onreza/gitverse-sdk.git
152
- ```
153
- 2. Установка зависимостей:
154
- ```bash
155
- bun install
156
- ```
157
- 3. Запуск серверов/скриптов по необходимости
158
- 4. Написание **семантических коммитов** по [Conventional Commits]
159
- 5. Поддержание **100% покрытия** тестов
363
+ # Сборка проекта
364
+ bun run build
160
365
 
161
- ## 🤝 Contributing
366
+ # Линтинг
367
+ bun run lint
368
+ bun run lint:fix
369
+ ```
162
370
 
163
- См. детали в [CONTRIBUTING.md](./CONTRIBUTING.md).
371
+ ## Лицензия
164
372
 
165
- ## 📝 Лицензия
373
+ MIT © [Ivan Bobchenkov](https://bobchenkov.ru)
374
+
375
+ ---
166
376
 
167
- MIT
377
+ **Ссылки:**
378
+ - [GitVerse](https://gitverse.ru)
379
+ - [Репозиторий](https://gitverse.ru/rainypixel/gitverse-sdk)
380
+ - [Issues](https://gitverse.ru/rainypixel/gitverse-sdk/issues)
381
+ - [npm пакет](https://www.npmjs.com/package/gitverse-api-sdk)