itd-sdk-js 1.0.4 → 1.0.5
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.
- package/API_REFERENCE.md +23 -2
- package/README.md +3 -3
- package/package.json +2 -2
- package/src/auth.js +3 -3
- package/src/client.js +34 -12
- package/src/token-storage.js +15 -17
package/API_REFERENCE.md
CHANGED
|
@@ -30,15 +30,17 @@ import { ITDClient } from 'itd-sdk-js';
|
|
|
30
30
|
|
|
31
31
|
Для работы автоматического обновления токена создайте файл `.cookies` в корне проекта. Скопируйте содержимое заголовка `Cookie` из любого сетевого запроса к сайту в браузере и вставьте в этот файл.
|
|
32
32
|
|
|
33
|
+
**Пути к .env и .cookies:** по умолчанию SDK ищет и сохраняет эти файлы в **корне проекта** (`process.cwd()`). При refresh токена обновлённые значения пишутся в ваш проект, а не в папку пакета. При необходимости можно задать свой корень или явные пути через опции конструктора (см. ниже).
|
|
34
|
+
|
|
33
35
|
---
|
|
34
36
|
|
|
35
37
|
## Авторизация и сессии
|
|
36
38
|
|
|
37
39
|
### Инициализация клиента
|
|
38
40
|
|
|
39
|
-
|
|
41
|
+
**Простой вариант (корень проекта = текущая рабочая директория):**
|
|
40
42
|
|
|
41
|
-
```
|
|
43
|
+
```javascript
|
|
42
44
|
import { ITDClient } from 'itd-sdk-js';
|
|
43
45
|
import dotenv from 'dotenv';
|
|
44
46
|
|
|
@@ -49,6 +51,25 @@ client.setAccessToken(process.env.ITD_ACCESS_TOKEN);
|
|
|
49
51
|
client.auth.isAuthenticated = true;
|
|
50
52
|
```
|
|
51
53
|
|
|
54
|
+
**С опциями (projectRoot / envPath / cookiesPath):**
|
|
55
|
+
|
|
56
|
+
Если скрипт запускается из подпапки или нужны явные пути:
|
|
57
|
+
|
|
58
|
+
```javascript
|
|
59
|
+
const client = new ITDClient({
|
|
60
|
+
baseUrl: 'https://xn--d1ah4a.com',
|
|
61
|
+
userAgent: '...',
|
|
62
|
+
projectRoot: process.cwd(), // корень проекта (по умолчанию process.cwd())
|
|
63
|
+
// либо явные пути:
|
|
64
|
+
// envPath: '/path/to/project/.env',
|
|
65
|
+
// cookiesPath: '/path/to/project/.cookies',
|
|
66
|
+
});
|
|
67
|
+
client.setAccessToken(process.env.ITD_ACCESS_TOKEN);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
- `projectRoot` — директория, в которой ищутся `.env` и `.cookies` (по умолчанию `process.cwd()`).
|
|
71
|
+
- `envPath` / `cookiesPath` — при указании переопределяют пути, собранные из `projectRoot`.
|
|
72
|
+
|
|
52
73
|
### Автоматическое обновление (Refresh Token)
|
|
53
74
|
|
|
54
75
|
При получении ошибки `401 Unauthorized` клиент автоматически обращается к эндпоинту `/api/v1/auth/refresh`, используя данные из `.cookies`. В случае успеха новый токен сохраняется в `.env`, обновляются куки, и исходный запрос повторяется.
|
package/README.md
CHANGED
|
@@ -26,11 +26,11 @@ npm install
|
|
|
26
26
|
|
|
27
27
|
## Настройка
|
|
28
28
|
|
|
29
|
-
1. Создайте `.env` на основе `.env.example` (или используйте переменные окружения).
|
|
29
|
+
1. Создайте `.env` в корне проекта на основе `.env.example` (или используйте переменные окружения).
|
|
30
30
|
2. Вставьте свой `ITD_ACCESS_TOKEN` (его можно вытащить из Network в DevTools).
|
|
31
|
-
3. Для работы авто-обновления сессии создайте файл `.cookies` и вставьте туда строку `Cookie` из любого запроса к сайту в браузере.
|
|
31
|
+
3. Для работы авто-обновления сессии создайте файл `.cookies` в корне проекта и вставьте туда строку `Cookie` из любого запроса к сайту в браузере.
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
SDK по умолчанию читает и пишет `.env` и `.cookies` в корне проекта (`process.cwd()`). При обновлении токена изменения сохраняются в ваш проект. При необходимости можно задать `projectRoot` или явные пути в конструкторе — см. [API_REFERENCE.md](API_REFERENCE.md).
|
|
34
34
|
|
|
35
35
|
## Примеры
|
|
36
36
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "itd-sdk-js",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "Unofficial SDK for итд.com - Node.js library for working with API. Automatic token refresh, session management, and convenient methods for posts, comments, users, and notifications.",
|
|
5
5
|
"main": "src/client.js",
|
|
6
6
|
"type": "module",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"license": "MIT",
|
|
40
40
|
"repository": {
|
|
41
41
|
"type": "git",
|
|
42
|
-
"url": "https://github.com/FriceKa/ITD-SDK-js.git"
|
|
42
|
+
"url": "git+https://github.com/FriceKa/ITD-SDK-js.git"
|
|
43
43
|
},
|
|
44
44
|
"bugs": {
|
|
45
45
|
"url": "https://github.com/FriceKa/ITD-SDK-js/issues"
|
package/src/auth.js
CHANGED
|
@@ -68,8 +68,8 @@ export class AuthManager {
|
|
|
68
68
|
this.client.setAccessToken(newToken);
|
|
69
69
|
this.isAuthenticated = true;
|
|
70
70
|
|
|
71
|
-
// Сохраняем токен в .env файл
|
|
72
|
-
await saveAccessToken(newToken);
|
|
71
|
+
// Сохраняем токен в .env файл (в корне проекта)
|
|
72
|
+
await saveAccessToken(newToken, this.client.envPath);
|
|
73
73
|
|
|
74
74
|
// Обновляем cookies, если они пришли в ответе
|
|
75
75
|
if (response.headers['set-cookie']) {
|
|
@@ -94,7 +94,7 @@ export class AuthManager {
|
|
|
94
94
|
);
|
|
95
95
|
if (importantCookies.length > 0) {
|
|
96
96
|
const cookieHeader = importantCookies.map(c => `${c.key}=${c.value}`).join('; ');
|
|
97
|
-
await saveCookieHeader(cookieHeader);
|
|
97
|
+
await saveCookieHeader(cookieHeader, this.client.cookiesPath);
|
|
98
98
|
}
|
|
99
99
|
} catch (e) {
|
|
100
100
|
console.warn('⚠️ Не удалось сохранить обновленные cookies:', e.message);
|
package/src/client.js
CHANGED
|
@@ -5,7 +5,6 @@ import axios from 'axios';
|
|
|
5
5
|
import dotenv from 'dotenv';
|
|
6
6
|
import fs from 'fs';
|
|
7
7
|
import path from 'path';
|
|
8
|
-
import { fileURLToPath } from 'url';
|
|
9
8
|
import { CookieJar } from 'tough-cookie';
|
|
10
9
|
import { wrapper } from 'axios-cookiejar-support';
|
|
11
10
|
import { AuthManager } from './auth.js';
|
|
@@ -20,22 +19,46 @@ import { SearchManager } from './search.js';
|
|
|
20
19
|
|
|
21
20
|
dotenv.config();
|
|
22
21
|
|
|
23
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
24
|
-
const __dirname = path.dirname(__filename);
|
|
25
|
-
|
|
26
22
|
export class ITDClient {
|
|
27
23
|
/**
|
|
28
24
|
* Инициализация клиента
|
|
29
25
|
*
|
|
30
|
-
* @param {string}
|
|
31
|
-
* @param {string} userAgent - User-Agent
|
|
26
|
+
* @param {string|Object} baseUrlOrOptions - Базовый URL сайта или объект опций
|
|
27
|
+
* @param {string} [userAgent] - User-Agent (если первый аргумент — baseUrl)
|
|
28
|
+
*
|
|
29
|
+
* Опции (если первый аргумент — объект):
|
|
30
|
+
* @param {string} [options.baseUrl] - Базовый URL сайта
|
|
31
|
+
* @param {string} [options.userAgent] - User-Agent
|
|
32
|
+
* @param {string} [options.projectRoot] - Корень проекта (по умолчанию process.cwd()); .env и .cookies ищутся здесь
|
|
33
|
+
* @param {string} [options.envPath] - Полный путь к .env (переопределяет projectRoot для .env)
|
|
34
|
+
* @param {string} [options.cookiesPath] - Полный путь к .cookies (переопределяет projectRoot для .cookies)
|
|
32
35
|
*/
|
|
33
|
-
constructor(
|
|
36
|
+
constructor(baseUrlOrOptions = null, userAgent = null) {
|
|
37
|
+
let baseUrl, projectRoot, envPath, cookiesPath;
|
|
38
|
+
|
|
39
|
+
if (baseUrlOrOptions && typeof baseUrlOrOptions === 'object' && !(baseUrlOrOptions instanceof URL)) {
|
|
40
|
+
const opts = baseUrlOrOptions;
|
|
41
|
+
baseUrl = opts.baseUrl ?? process.env.ITD_BASE_URL ?? 'https://xn--d1ah4a.com';
|
|
42
|
+
userAgent = opts.userAgent ?? process.env.ITD_USER_AGENT ?? null;
|
|
43
|
+
projectRoot = opts.projectRoot ?? process.cwd();
|
|
44
|
+
envPath = opts.envPath ?? path.join(projectRoot, '.env');
|
|
45
|
+
cookiesPath = opts.cookiesPath ?? path.join(projectRoot, '.cookies');
|
|
46
|
+
} else {
|
|
47
|
+
projectRoot = process.cwd();
|
|
48
|
+
baseUrl = baseUrlOrOptions || process.env.ITD_BASE_URL || 'https://xn--d1ah4a.com';
|
|
49
|
+
envPath = path.join(projectRoot, '.env');
|
|
50
|
+
cookiesPath = path.join(projectRoot, '.cookies');
|
|
51
|
+
}
|
|
52
|
+
|
|
34
53
|
// Используем реальный домен (IDN: итд.com = xn--d1ah4a.com)
|
|
35
|
-
this.baseUrl = baseUrl
|
|
36
|
-
this.userAgent = userAgent || process.env.ITD_USER_AGENT ||
|
|
54
|
+
this.baseUrl = baseUrl;
|
|
55
|
+
this.userAgent = userAgent || process.env.ITD_USER_AGENT ||
|
|
37
56
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
|
|
38
57
|
|
|
58
|
+
/** Пути к .env и .cookies (корень проекта по умолчанию) */
|
|
59
|
+
this.envPath = envPath;
|
|
60
|
+
this.cookiesPath = cookiesPath;
|
|
61
|
+
|
|
39
62
|
/** @type {string|null} */
|
|
40
63
|
this.accessToken = null;
|
|
41
64
|
|
|
@@ -178,13 +201,12 @@ export class ITDClient {
|
|
|
178
201
|
*/
|
|
179
202
|
_loadCookiesFromFile() {
|
|
180
203
|
try {
|
|
181
|
-
|
|
182
|
-
if (!fs.existsSync(cookiesPath)) {
|
|
204
|
+
if (!fs.existsSync(this.cookiesPath)) {
|
|
183
205
|
// Файл не существует - это нормально, просто пропускаем
|
|
184
206
|
return;
|
|
185
207
|
}
|
|
186
208
|
|
|
187
|
-
const cookieHeader = fs.readFileSync(cookiesPath, 'utf8').trim();
|
|
209
|
+
const cookieHeader = fs.readFileSync(this.cookiesPath, 'utf8').trim();
|
|
188
210
|
if (!cookieHeader) {
|
|
189
211
|
return;
|
|
190
212
|
}
|
package/src/token-storage.js
CHANGED
|
@@ -3,27 +3,24 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import fs from 'fs';
|
|
5
5
|
import path from 'path';
|
|
6
|
-
import { fileURLToPath } from 'url';
|
|
7
|
-
|
|
8
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
-
const __dirname = path.dirname(__filename);
|
|
10
6
|
|
|
11
7
|
/**
|
|
12
8
|
* Обновляет ITD_ACCESS_TOKEN в .env файле
|
|
13
|
-
*
|
|
9
|
+
*
|
|
14
10
|
* @param {string} newToken - Новый access token
|
|
11
|
+
* @param {string} [envPath] - Путь к .env (по умолчанию process.cwd() + '/.env')
|
|
15
12
|
* @returns {Promise<boolean>} True если успешно
|
|
16
13
|
*/
|
|
17
|
-
export async function saveAccessToken(newToken) {
|
|
14
|
+
export async function saveAccessToken(newToken, envPath = null) {
|
|
18
15
|
try {
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
if (!fs.existsSync(
|
|
16
|
+
const targetPath = envPath ?? path.join(process.cwd(), '.env');
|
|
17
|
+
|
|
18
|
+
if (!fs.existsSync(targetPath)) {
|
|
22
19
|
console.warn('⚠️ Файл .env не найден, токен не сохранен');
|
|
23
20
|
return false;
|
|
24
21
|
}
|
|
25
|
-
|
|
26
|
-
let content = fs.readFileSync(
|
|
22
|
+
|
|
23
|
+
let content = fs.readFileSync(targetPath, 'utf8');
|
|
27
24
|
|
|
28
25
|
// Ищем строку с ITD_ACCESS_TOKEN
|
|
29
26
|
const tokenRegex = /^ITD_ACCESS_TOKEN=.*$/m;
|
|
@@ -36,7 +33,7 @@ export async function saveAccessToken(newToken) {
|
|
|
36
33
|
content += `\nITD_ACCESS_TOKEN=${newToken}\n`;
|
|
37
34
|
}
|
|
38
35
|
|
|
39
|
-
fs.writeFileSync(
|
|
36
|
+
fs.writeFileSync(targetPath, content, 'utf8');
|
|
40
37
|
console.log('✅ Токен сохранен в .env');
|
|
41
38
|
return true;
|
|
42
39
|
} catch (error) {
|
|
@@ -47,16 +44,17 @@ export async function saveAccessToken(newToken) {
|
|
|
47
44
|
|
|
48
45
|
/**
|
|
49
46
|
* Сохраняет cookies в файл .cookies
|
|
50
|
-
*
|
|
47
|
+
*
|
|
51
48
|
* @param {string} newCookieHeader - Новый cookie header
|
|
49
|
+
* @param {string} [cookiesPath] - Путь к .cookies (по умолчанию process.cwd() + '/.cookies')
|
|
52
50
|
* @returns {Promise<boolean>} True если успешно
|
|
53
51
|
*/
|
|
54
|
-
export async function saveCookieHeader(newCookieHeader) {
|
|
52
|
+
export async function saveCookieHeader(newCookieHeader, cookiesPath = null) {
|
|
55
53
|
try {
|
|
56
|
-
const
|
|
57
|
-
|
|
54
|
+
const targetPath = cookiesPath ?? path.join(process.cwd(), '.cookies');
|
|
55
|
+
|
|
58
56
|
// Просто записываем cookies в файл (одна строка)
|
|
59
|
-
fs.writeFileSync(
|
|
57
|
+
fs.writeFileSync(targetPath, newCookieHeader, 'utf8');
|
|
60
58
|
console.log('✅ Cookies сохранены в .cookies');
|
|
61
59
|
return true;
|
|
62
60
|
} catch (error) {
|