Плагин на JavaScript и TypeScript
Глобальный объект opensd: действия, кнопки, сеть, приложения, таймеры и журнал.
Плагин на JavaScript это один файл с исходным кодом. Он попадает в пакет как есть и исполняется в изолированном воркере движка WebView приложения. Самому плагину на JavaScript Node.js и сборка не нужны: Node.js нужен только для установки CLI через npm. TypeScript собирается в один файл через esbuild.
Проект
npm create @opensd my-plugin
opensd new my-plugin --lang jsПервая команда создаёт проект на TypeScript, вторая на JavaScript. Установка описана в быстром старте.
JavaScript:
opensd.toml манифест с [runtime] type = "js", main = "plugin.js"
plugin.js код плагина
opensd.d.ts типы API для подсказок редактора
jsconfig.json проверка типов в редакторе
assets/ картинкиTypeScript: код лежит в src/plugin.ts. npm install ставит @opensd/cli, esbuild и TypeScript. npm run dev и npm run pack вызывают opensd dev и opensd pack, а те сами запускают npm run build, который пишет plugin.js.
Действия
opensd.action("com.example.counter.counter", {
appear({ key, settings }) {
key.setTitle(String(settings.count ?? 0));
},
tap({ key, settings }) {
const count = (settings.count ?? 0) + 1;
key.saveSettings({ ...settings, count }).setTitle(String(count));
},
longPress({ key, settings }) {
key.saveSettings({ ...settings, count: 0 }).setTitle("0").flash("ok");
},
});Обработчик получает событие со свойствами context, action, controller, position, settings, state и готовым key. Обработчики могут быть асинхронными. Исключение или отклонённый Promise пишется в журнал плагина, плагин продолжает работать.
Имена обработчиков совпадают с типами событий: appear, disappear, keyDown, keyUp, tap, longPress, holdStart, holdRepeat, holdEnd, settings, inspectorOpen, inspectorClose, inspectorMessage.
События без кнопки слушаются через opensd.on:
opensd.on("init", ({ app, device, globals }) => opensd.log("started in", app.language));
opensd.on("globals", ({ settings }) => applyGlobals(settings));
opensd.on("settingsPageMessage", ({ payload }) => handle(payload));Кнопка
Методы возвращают ту же кнопку, поэтому вызовы соединяются в цепочку. opensd.keys(action) перечисляет видимые кнопки, opensd.key(context) даёт кнопку по контексту.
Состояние плагина
Хранить состояние можно в обычных переменных модуля: экземпляр живёт, пока плагин запущен.
Сеть и приложения
const list = await opensd.http("http://127.0.0.1:9222/json/list", { timeout: 2000 });
const weather = await opensd.http("https://api.example.com/v1/now");
const socket = opensd.ws("ws://127.0.0.1:9222/devtools/page/X");
socket.onmessage = (data) => opensd.log(data);
const status = await opensd.app.status("editor");
await opensd.app.launch("editor", [9222]);
await opensd.clipboard("https://example.com/track/1");- Адреса
127.0.0.1иlocalhostидут через брокер приложения: нужно разрешениеloopback, CORS и заголовкаOriginнет. - Остальные адреса требуют разрешения
network. Для них работают и обычныеfetchиWebSocket, иopensd.http, но действует политика CORS браузерного движка. appиclipboardтребуют разрешенийlaunchиclipboard.
Без согласия пользователя промисы отклоняются с сообщением о недостающем разрешении.
Таймеры
Обычные setTimeout и setInterval работают. Держите интервалы только пока они нужны: плагин, у которого нет видимых кнопок, не должен тратить процессор.
let refresh = null;
opensd.on("appear", () => {
refresh ??= setInterval(update, 1000);
});
opensd.on("disappear", () => {
if (opensd.keys().length === 0) {
clearInterval(refresh);
refresh = null;
}
});Журнал
console.log, console.warn, console.error, а также opensd.log, opensd.warn, opensd.error пишут в журнал плагина. opensd dev выводит его в терминал, в приложении журнал открывается кнопкой «Журнал» в «Настройки», «Плагины».
Что недоступно
eval, new Function, importScripts и import() по сети, IndexedDB, Cache Storage, cookies, localStorage, DOM. Код плагина должен быть одним файлом: зависимости из npm собирайте в него через esbuild, как в шаблоне TypeScript.