Приложение API скриптов
Цель
Описывает возможности window.api, доступные скриптам страниц сайта и скриптам перехвата API: чтение конфигурации, HTTP-запросы, пользовательские данные, инструменты DOM, общие утилиты и чтение заголовков запросов/ответов.
Скрипты страниц и скрипты перехвата обычных API могут использовать window.api. Для SSE-скриптов гарантируется только передача data; обычно они не зависят от window.api.
interface Window {
api: {
user: UserApi;
http: HttpApi;
config: Record<string, unknown>;
dom: DomApi;
utils: UtilsApi;
header(headerName: string, isRequestHeader: boolean): Promise<string | string[] | undefined>;
};
}api.config
Читает пользовательскую конфигурацию из окружения скриптов сайта.
config: Record<string, unknown>Пример:
const apiBase = api.config.apiBase;api.http
api.http предоставляет HTTP-хелперы для пользовательских скриптов. api.http.ajax выполняет фактический запрос в основном процессе браузера, поэтому он не ограничен CORS-политикой страницы.
api.http.ajax(options)
Отправляет HTTP-запрос.
ajax(options: {
url: string;
method?: string;
data?: any;
headers?: Record<string, string>;
timeout?: number;
dataType?: 'json' | 'text' | 'html' | 'arrayBuffer';
contentType?: string;
processData?: boolean;
}): Promise<{
ok: boolean;
status: number;
statusText: string;
data?: any;
error?: string;
timeout?: boolean;
}>| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
url | string | - | URL запроса. |
method | string | GET | HTTP-метод. |
data | any | - | Данные запроса. Для GET и HEAD сериализуются в строку запроса. Для других методов записываются в тело запроса. |
headers | Record<string, string> | {} | Заголовки запроса. |
timeout | number | - | Таймаут в миллисекундах. Применяется только если значение больше 0. |
dataType | 'json' | 'text' | 'html' | 'arrayBuffer' | json | Режим разбора ответа. |
contentType | string | application/x-www-form-urlencoded; charset=UTF-8 | Content-Type тела запроса. |
processData | boolean | true | Нужно ли автоматически сериализовать data. Установите false, чтобы передать data напрямую как тело запроса. |
Возвращаемое значение:
| Поле | Тип | Описание |
|---|---|---|
ok | boolean | true для HTTP-ответов 2xx; false для ошибок разбора, HTTP-ошибок, таймаута, abort или сетевых ошибок. |
status | number | HTTP-код состояния. 0 означает таймаут, abort или сбой на сетевом уровне. |
statusText | string | Текст HTTP-статуса или timeout, abort, error для не-HTTP сбоев. |
data | any | Разобранные данные ответа, если разбор успешен. |
error | string | Сообщение об ошибке при сбое разбора или не-HTTP сбое. |
timeout | boolean | true, если запрос был прерван настроенным таймаутом. |
Примеры:
const ret = await api.http.ajax({
url: 'https://example.com/api/profile',
method: 'GET',
dataType: 'json',
timeout: 10000
});
if (ret.ok) {
console.log(ret.data);
}const ret = await api.http.ajax({
url: 'https://example.com/api/items',
method: 'POST',
contentType: 'application/json',
data: { name: 'demo' }
});api.user
api.user используется для чтения и записи пользовательских связанных данных во время выполнения скрипта.
Общие параметры:
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
site | boolean | false | Хранить ли данные отдельно по сайтам. |
account | boolean | false | Хранить ли данные отдельно по учетным записям. |
did | boolean | false | Хранить ли данные отдельно по устройствам. |
api.user.put(name, value, site, account, did)
Сохраняет указанную пару ключ-значение.
put(
name: string,
value: string,
site?: boolean,
account?: boolean,
did?: boolean
): Promise<{ status: boolean }>Пример:
await api.user.put('token', 'abc123');api.user.get(name, site, account, did)
Читает указанную пару ключ-значение.
get(
name: string,
site?: boolean,
account?: boolean,
did?: boolean
): Promise<{ value: string | null, status: boolean }>Пример:
const ret = await api.user.get('token');
console.log(ret.value);api.user.remove(name, site, account, did)
Удаляет указанную пару ключ-значение.
remove(
name: string,
site?: boolean,
account?: boolean,
did?: boolean
): Promise<{ status: boolean }>Пример:
await api.user.remove('token');api.user.incr(name, step, site, account, did)
Увеличивает числовое значение указанного ключа на шаг. Если ключ не существует, он создается со значением step.
incr(
name: string,
step?: number,
site?: boolean,
account?: boolean,
did?: boolean
): Promise<{ status: boolean, value: number | string }>Пример:
const ret = await api.user.incr('count', 1);
console.log(ret.value);api.user.decr(name, step, site, account, did)
Уменьшает числовое значение указанного ключа на шаг. Если ключ не существует, он создается со значением step * -1.
decr(
name: string,
step?: number,
site?: boolean,
account?: boolean,
did?: boolean
): Promise<{ status: boolean, value: number | string }>Пример:
const ret = await api.user.decr('count', 1);
console.log(ret.value);api.user.startsWith(prefix, site, account, did)
Находит все данные, имена ключей которых начинаются с указанного префикса.
startsWith(
prefix: string,
site?: boolean,
account?: boolean,
did?: boolean
): Promise<Array<{ name: string, value: string }>>Пример:
const items = await api.user.startsWith('cache:');api.user.countAll(name, site, account)
Считает количество записей с указанным именем ключа.
countAll(
name: string,
site?: boolean,
account?: boolean
): Promise<{ value: number, status: boolean }>Пример:
const ret = await api.user.countAll('token');
console.log(ret.value);api.user.sumAll(name, site, account)
Считает числовую сумму значений для указанного имени ключа.
sumAll(
name: string,
site?: boolean,
account?: boolean
): Promise<{ value: number, status: boolean }>Пример:
const ret = await api.user.sumAll('score');
console.log(ret.value);api.dom
api.dom предоставляет запросы DOM, проверку видимости, слушатели подключения, слушатели размера и создание оверлеев.
Поддержка селекторов:
| Формат | Описание |
|---|---|
.button.primary | CSS-селектор. |
xpath://div[@id="app"] | XPath-селектор. |
.dialog:p | Возвращает родительский элемент найденного элемента. |
.dialog:p2 | Возвращает родителя на два уровня выше найденного элемента. |
.header:bottom | Использует нижнюю границу целевого элемента в методах границ оверлея. |
.sidebar:right | Использует правую границу целевого элемента в методах границ оверлея. |
api.dom.createMutationObserver(ele, bindStr, childList, subtree, attributes, characterData, fn)
Создает и кэширует MutationObserver. Если ele[bindStr] уже существует, напрямую возвращает существующий observer.
createMutationObserver(
ele: Element,
bindStr: string,
childList: boolean,
subtree: boolean,
attributes: boolean,
characterData: boolean,
fn: (mutations: MutationRecord[]) => void
): MutationObserverПример:
api.dom.createMutationObserver(
document.body,
'__bodyObserver__',
true,
true,
false,
false,
(mutations) => console.log(mutations)
);api.dom.querySelector(doc, cssOrXPathSelector)
Ищет первый совпадающий элемент.
querySelector(doc: Document, cssOrXPathSelector: string): HTMLElement | nullПример:
const el = api.dom.querySelector(document, 'xpath://button[contains(.,"Submit")]');api.dom.querySelectorAll(doc, cssOrXPathSelector)
Ищет все совпадающие элементы.
querySelectorAll(doc: Document, cssOrXPathSelector: string): HTMLElement[]Пример:
const buttons = api.dom.querySelectorAll(document, 'button.primary');api.dom.isVisible(ele)
Определяет, находится ли элемент в видимой области пересечения.
isVisible(ele: HTMLElement): Promise<boolean>Пример:
if (await api.dom.isVisible(el)) {
console.log('visible');
}api.dom.getVisibleRect(ele)
Получает текущий видимый прямоугольник элемента.
getVisibleRect(ele: HTMLElement): Promise<DOMRectReadOnly>Пример:
const rect = await api.dom.getVisibleRect(el);
console.log(rect.left, rect.top, rect.width, rect.height);api.dom.getConnectListeners()
Получает текущий список слушателей подключения.
getConnectListeners(): Array<{
querySelector: string;
callback: (isConnected: boolean) => void;
isConnected?: boolean;
}>Пример:
api.dom.addConnectListener('.modal', () => {});
console.log(api.dom.getConnectListeners());api.dom.addConnectListener(cssOrXPathSelector, callback)
Отслеживает появление целевого элемента в документе или его исчезновение из документа.
addConnectListener(
cssOrXPathSelector: string,
callback: (isConnected: boolean) => void
): voidПример:
api.dom.addConnectListener('.dialog', (isConnected) => {
console.log('dialog:', isConnected);
});api.dom.removeConnectListener(cssOrXPathSelectors)
Удаляет слушатели подключения для указанных селекторов.
removeConnectListener(cssOrXPathSelectors: string[]): voidПример:
api.dom.removeConnectListener(['.dialog', '.toast']);api.dom.addResizeListener(cssOrXPathSelector, bindWindowStr, callback, createObserver, delayTime)
Отслеживает изменения размера и позиции целевого элемента. Если элемент не существует, callback получает new DOMRect(0, 0, 0, 0).
addResizeListener(
cssOrXPathSelector: string,
bindWindowStr: string,
callback: (rect: DOMRect) => void,
createObserver?: boolean,
delayTime?: number
): ResizeObserver | (() => void)Пример:
api.dom.addResizeListener('.target', '__targetResize__', (rect) => {
console.log(rect.width, rect.height);
});api.dom.createOverlayBy(cssOrXPathSelector, bindWindowStr, createObserver, delayTime, fn)
Создает fixed-оверлей, следующий за видимой областью целевого элемента.
createOverlayBy(
cssOrXPathSelector: string,
bindWindowStr: string,
createObserver?: boolean,
delayTime?: number,
fn?: (rect: DOMRectReadOnly) => void
): HTMLElementПример:
const overlay = api.dom.createOverlayBy('.target', '__overlay__');
overlay.style.border = '2px solid #f00';
overlay.style.pointerEvents = 'none';
overlay.style.zIndex = '999999';api.dom.createOverlayByBorder(bindWindowStr, top, right, bottom, left, createObserver, delayTime)
Создает fixed-оверлей по четырем границам. Каждая граница может быть числовым значением пикселей или селектором; селекторы могут использовать :top, :right, :bottom, :left.
createOverlayByBorder(
bindWindowStr: string,
top: string | number,
right: string | number,
bottom: string | number,
left: string | number,
createObserver?: boolean,
delayTime?: number
): HTMLElementПример:
const panel = api.dom.createOverlayByBorder(
'__centerPanel__',
'header:bottom',
20,
'footer:top',
'.sidebar:right'
);
panel.style.background = 'rgba(0,0,0,.08)';api.utils
api.utils.wait(fn, timeoutMs, intervalMs)
Опрашивает, пока функция условия не вернет истинное значение.
wait(
fn: () => boolean,
timeoutMs: number,
intervalMs?: number
): Promise<void>После тайм-аута выбрасывает Error("Timeout: function did not return true in time.").
Пример:
await api.utils.wait(
() => !!api.dom.querySelector(document, '.ready'),
10000,
200
);api.utils.runScript(code, callback)
Выполняет JavaScript-код на текущей странице.
runScript(
code: string,
callback?: (result: any, error: Error) => void
): Promise<any>Пример:
const title = await api.utils.runScript('document.title');
console.log(title);api.header(headerName, isRequestHeader)
Читает заголовки запросов или ответов, записанные удаленным браузером.
header(
headerName: string,
isRequestHeader: boolean
): Promise<string | string[] | undefined>| Параметр | Тип | Описание |
|---|---|---|
headerName | string | Имя заголовка запроса или ответа; при чтении переводится в нижний регистр. |
isRequestHeader | boolean | true читает заголовки запроса, false читает заголовки ответа. |
Примечания:
- Записываются только заголовки, добавленные в настройках сайта.
- Заголовки запросов берутся из headers, отправленных удаленным браузером.
- Заголовки ответов берутся из headers, полученных удаленным браузером.
- Заголовки ответов могут возвращать массивы строк.
Пример:
const cookie = await api.header('cookie', true);
const setCookie = await api.header('set-cookie', false);