Skip to content

Приложение API скриптов

Цель

Описывает возможности window.api, доступные скриптам страниц сайта и скриптам перехвата API: чтение конфигурации, HTTP-запросы, пользовательские данные, инструменты DOM, общие утилиты и чтение заголовков запросов/ответов.

Скрипты страниц и скрипты перехвата обычных API могут использовать window.api. Для SSE-скриптов гарантируется только передача data; обычно они не зависят от window.api.

ts
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

Читает пользовательскую конфигурацию из окружения скриптов сайта.

ts
config: Record<string, unknown>

Пример:

js
const apiBase = api.config.apiBase;

api.http

api.http предоставляет HTTP-хелперы для пользовательских скриптов. api.http.ajax выполняет фактический запрос в основном процессе браузера, поэтому он не ограничен CORS-политикой страницы.

api.http.ajax(options)

Отправляет HTTP-запрос.

ts
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;
}>
ПараметрТипПо умолчаниюОписание
urlstring-URL запроса.
methodstringGETHTTP-метод.
dataany-Данные запроса. Для GET и HEAD сериализуются в строку запроса. Для других методов записываются в тело запроса.
headersRecord<string, string>{}Заголовки запроса.
timeoutnumber-Таймаут в миллисекундах. Применяется только если значение больше 0.
dataType'json' | 'text' | 'html' | 'arrayBuffer'jsonРежим разбора ответа.
contentTypestringapplication/x-www-form-urlencoded; charset=UTF-8Content-Type тела запроса.
processDatabooleantrueНужно ли автоматически сериализовать data. Установите false, чтобы передать data напрямую как тело запроса.

Возвращаемое значение:

ПолеТипОписание
okbooleantrue для HTTP-ответов 2xx; false для ошибок разбора, HTTP-ошибок, таймаута, abort или сетевых ошибок.
statusnumberHTTP-код состояния. 0 означает таймаут, abort или сбой на сетевом уровне.
statusTextstringТекст HTTP-статуса или timeout, abort, error для не-HTTP сбоев.
dataanyРазобранные данные ответа, если разбор успешен.
errorstringСообщение об ошибке при сбое разбора или не-HTTP сбое.
timeoutbooleantrue, если запрос был прерван настроенным таймаутом.

Примеры:

js
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);
}
js
const ret = await api.http.ajax({
  url: 'https://example.com/api/items',
  method: 'POST',
  contentType: 'application/json',
  data: { name: 'demo' }
});

api.user

api.user используется для чтения и записи пользовательских связанных данных во время выполнения скрипта.

Общие параметры:

ПараметрТипПо умолчаниюОписание
sitebooleanfalseХранить ли данные отдельно по сайтам.
accountbooleanfalseХранить ли данные отдельно по учетным записям.
didbooleanfalseХранить ли данные отдельно по устройствам.

api.user.put(name, value, site, account, did)

Сохраняет указанную пару ключ-значение.

ts
put(
  name: string,
  value: string,
  site?: boolean,
  account?: boolean,
  did?: boolean
): Promise<{ status: boolean }>

Пример:

js
await api.user.put('token', 'abc123');

api.user.get(name, site, account, did)

Читает указанную пару ключ-значение.

ts
get(
  name: string,
  site?: boolean,
  account?: boolean,
  did?: boolean
): Promise<{ value: string | null, status: boolean }>

Пример:

js
const ret = await api.user.get('token');
console.log(ret.value);

api.user.remove(name, site, account, did)

Удаляет указанную пару ключ-значение.

ts
remove(
  name: string,
  site?: boolean,
  account?: boolean,
  did?: boolean
): Promise<{ status: boolean }>

Пример:

js
await api.user.remove('token');

api.user.incr(name, step, site, account, did)

Увеличивает числовое значение указанного ключа на шаг. Если ключ не существует, он создается со значением step.

ts
incr(
  name: string,
  step?: number,
  site?: boolean,
  account?: boolean,
  did?: boolean
): Promise<{ status: boolean, value: number | string }>

Пример:

js
const ret = await api.user.incr('count', 1);
console.log(ret.value);

api.user.decr(name, step, site, account, did)

Уменьшает числовое значение указанного ключа на шаг. Если ключ не существует, он создается со значением step * -1.

ts
decr(
  name: string,
  step?: number,
  site?: boolean,
  account?: boolean,
  did?: boolean
): Promise<{ status: boolean, value: number | string }>

Пример:

js
const ret = await api.user.decr('count', 1);
console.log(ret.value);

api.user.startsWith(prefix, site, account, did)

Находит все данные, имена ключей которых начинаются с указанного префикса.

ts
startsWith(
  prefix: string,
  site?: boolean,
  account?: boolean,
  did?: boolean
): Promise<Array<{ name: string, value: string }>>

Пример:

js
const items = await api.user.startsWith('cache:');

api.user.countAll(name, site, account)

Считает количество записей с указанным именем ключа.

ts
countAll(
  name: string,
  site?: boolean,
  account?: boolean
): Promise<{ value: number, status: boolean }>

Пример:

js
const ret = await api.user.countAll('token');
console.log(ret.value);

api.user.sumAll(name, site, account)

Считает числовую сумму значений для указанного имени ключа.

ts
sumAll(
  name: string,
  site?: boolean,
  account?: boolean
): Promise<{ value: number, status: boolean }>

Пример:

js
const ret = await api.user.sumAll('score');
console.log(ret.value);

api.dom

api.dom предоставляет запросы DOM, проверку видимости, слушатели подключения, слушатели размера и создание оверлеев.

Поддержка селекторов:

ФорматОписание
.button.primaryCSS-селектор.
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.

ts
createMutationObserver(
  ele: Element,
  bindStr: string,
  childList: boolean,
  subtree: boolean,
  attributes: boolean,
  characterData: boolean,
  fn: (mutations: MutationRecord[]) => void
): MutationObserver

Пример:

js
api.dom.createMutationObserver(
  document.body,
  '__bodyObserver__',
  true,
  true,
  false,
  false,
  (mutations) => console.log(mutations)
);

api.dom.querySelector(doc, cssOrXPathSelector)

Ищет первый совпадающий элемент.

ts
querySelector(doc: Document, cssOrXPathSelector: string): HTMLElement | null

Пример:

js
const el = api.dom.querySelector(document, 'xpath://button[contains(.,"Submit")]');

api.dom.querySelectorAll(doc, cssOrXPathSelector)

Ищет все совпадающие элементы.

ts
querySelectorAll(doc: Document, cssOrXPathSelector: string): HTMLElement[]

Пример:

js
const buttons = api.dom.querySelectorAll(document, 'button.primary');

api.dom.isVisible(ele)

Определяет, находится ли элемент в видимой области пересечения.

ts
isVisible(ele: HTMLElement): Promise<boolean>

Пример:

js
if (await api.dom.isVisible(el)) {
  console.log('visible');
}

api.dom.getVisibleRect(ele)

Получает текущий видимый прямоугольник элемента.

ts
getVisibleRect(ele: HTMLElement): Promise<DOMRectReadOnly>

Пример:

js
const rect = await api.dom.getVisibleRect(el);
console.log(rect.left, rect.top, rect.width, rect.height);

api.dom.getConnectListeners()

Получает текущий список слушателей подключения.

ts
getConnectListeners(): Array<{
  querySelector: string;
  callback: (isConnected: boolean) => void;
  isConnected?: boolean;
}>

Пример:

js
api.dom.addConnectListener('.modal', () => {});
console.log(api.dom.getConnectListeners());

api.dom.addConnectListener(cssOrXPathSelector, callback)

Отслеживает появление целевого элемента в документе или его исчезновение из документа.

ts
addConnectListener(
  cssOrXPathSelector: string,
  callback: (isConnected: boolean) => void
): void

Пример:

js
api.dom.addConnectListener('.dialog', (isConnected) => {
  console.log('dialog:', isConnected);
});

api.dom.removeConnectListener(cssOrXPathSelectors)

Удаляет слушатели подключения для указанных селекторов.

ts
removeConnectListener(cssOrXPathSelectors: string[]): void

Пример:

js
api.dom.removeConnectListener(['.dialog', '.toast']);

api.dom.addResizeListener(cssOrXPathSelector, bindWindowStr, callback, createObserver, delayTime)

Отслеживает изменения размера и позиции целевого элемента. Если элемент не существует, callback получает new DOMRect(0, 0, 0, 0).

ts
addResizeListener(
  cssOrXPathSelector: string,
  bindWindowStr: string,
  callback: (rect: DOMRect) => void,
  createObserver?: boolean,
  delayTime?: number
): ResizeObserver | (() => void)

Пример:

js
api.dom.addResizeListener('.target', '__targetResize__', (rect) => {
  console.log(rect.width, rect.height);
});

api.dom.createOverlayBy(cssOrXPathSelector, bindWindowStr, createObserver, delayTime, fn)

Создает fixed-оверлей, следующий за видимой областью целевого элемента.

ts
createOverlayBy(
  cssOrXPathSelector: string,
  bindWindowStr: string,
  createObserver?: boolean,
  delayTime?: number,
  fn?: (rect: DOMRectReadOnly) => void
): HTMLElement

Пример:

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

ts
createOverlayByBorder(
  bindWindowStr: string,
  top: string | number,
  right: string | number,
  bottom: string | number,
  left: string | number,
  createObserver?: boolean,
  delayTime?: number
): HTMLElement

Пример:

js
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)

Опрашивает, пока функция условия не вернет истинное значение.

ts
wait(
  fn: () => boolean,
  timeoutMs: number,
  intervalMs?: number
): Promise<void>

После тайм-аута выбрасывает Error("Timeout: function did not return true in time.").

Пример:

js
await api.utils.wait(
  () => !!api.dom.querySelector(document, '.ready'),
  10000,
  200
);

api.utils.runScript(code, callback)

Выполняет JavaScript-код на текущей странице.

ts
runScript(
  code: string,
  callback?: (result: any, error: Error) => void
): Promise<any>

Пример:

js
const title = await api.utils.runScript('document.title');
console.log(title);

api.header(headerName, isRequestHeader)

Читает заголовки запросов или ответов, записанные удаленным браузером.

ts
header(
  headerName: string,
  isRequestHeader: boolean
): Promise<string | string[] | undefined>
ПараметрТипОписание
headerNamestringИмя заголовка запроса или ответа; при чтении переводится в нижний регистр.
isRequestHeaderbooleantrue читает заголовки запроса, false читает заголовки ответа.

Примечания:

  • Записываются только заголовки, добавленные в настройках сайта.
  • Заголовки запросов берутся из headers, отправленных удаленным браузером.
  • Заголовки ответов берутся из headers, полученных удаленным браузером.
  • Заголовки ответов могут возвращать массивы строк.

Пример:

js
const cookie = await api.header('cookie', true);
const setCookie = await api.header('set-cookie', false);

Sa2web 1.0.0