npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@horuzhenko/guac-adapter

v6.0.10

Published

Адаптер для взаимодействия с Apache Guacamole

Readme

b# @horuzhenko/guac-adapter

Адаптер для взаимодействия с Apache Guacamole в Node.js среде.

Возможности

  • ✅ Подключение к Guacamole серверу через REST API
  • ✅ Установка WebSocket соединения с guacd
  • ✅ Рендеринг удаленного рабочего стола в виртуальный canvas
  • ✅ Создание скриншотов в форматах PNG и WebP
  • ✅ Управление сессиями подключения
  • ✅ Обработка Guacamole протокола
  • Интерактивный ввод:
    • Движение мыши
    • Клики левой, правой и средней кнопкой
    • Прокрутка колесом мыши
    • Комбинации клавиш (Ctrl+C, Alt+Tab и т.д.)
    • Ввод текста с настраиваемыми задержками

Установка

pnpm add @horuzhenko/guac-adapter

Использование

Базовое подключение

import { GuacAdapter } from '@horuzhenko/guac-adapter';
import { ConnectParams } from '@horuzhenko/protocol';

const adapter = new GuacAdapter();

const connectParams: ConnectParams = {
  auth: {
    baseUrl: 'http://192.168.2.109:8080/guacamole',
    token: 'your-auth-token'
  },
  display: {
    width: 1024,
    height: 768,
    dpi: 96
  }
};

// Подключение
const sessionInfo = await adapter.connect(connectParams);
console.log('Сессия создана:', sessionInfo.id);

// Ожидание готовности соединения
await new Promise(resolve => setTimeout(resolve, 5000));

// Создание скриншота
const screenshot = await adapter.screenshot(sessionInfo.id, {
  format: 'png',
  quality: 80
});

// Сохранение скриншота
const fs = require('fs');
const imageBuffer = Buffer.from(screenshot.imageBase64, 'base64');
fs.writeFileSync('screenshot.png', imageBuffer);

// Интерактивный ввод
console.log('Демонстрация интерактивного ввода...');

// Движение мыши
await adapter.move(sessionInfo.id, { x: 100, y: 100 });

// Клик левой кнопкой
await adapter.click(sessionInfo.id, { x: 100, y: 100, button: 'left' });

// Двойной клик
await adapter.click(sessionInfo.id, { x: 100, y: 100, button: 'left', count: 2 });

// Комбинация клавиш (Ctrl+Alt+T для открытия терминала)
await adapter.keyCombo(sessionInfo.id, {
  keys: ['Ctrl', 'Alt', 't'],
  pressDelayMs: 100
});

// Ввод текста
await adapter.typeText(sessionInfo.id, {
  text: 'echo "Hello World!"',
  perCharDelayMs: 50
});

// Нажатие Enter
await adapter.keyCombo(sessionInfo.id, { keys: ['Return'] });

// Прокрутка
await adapter.scroll(sessionInfo.id, { x: 400, y: 300, deltaY: -240 });

// Отключение
await adapter.disconnect(sessionInfo.id);

Создание скриншотов

// PNG скриншот
const pngScreenshot = await adapter.screenshot(sessionId, {
  format: 'png'
});

// WebP скриншот с настройкой качества
const webpScreenshot = await adapter.screenshot(sessionId, {
  format: 'webp',
  quality: 70
});

API

GuacAdapter

connect(params: ConnectParams): Promise<SessionInfo>

Создает новое подключение к удаленному рабочему столу.

Параметры:

  • params.auth.baseUrl - URL Guacamole сервера
  • params.auth.token - Токен аутентификации
  • params.display - Настройки дисплея (опционально)

Возвращает: Информацию о созданной сессии

screenshot(sessionId: string, options?): Promise<Screenshot>

Создает скриншот удаленного рабочего стола.

Параметры:

  • sessionId - Идентификатор сессии
  • options.format - Формат изображения ('png' | 'webp')
  • options.quality - Качество для WebP (1-100)

Возвращает: Объект скриншота с base64 данными

move(sessionId: string, move: MouseMove): Promise<void>

Перемещает курсор мыши в указанные координаты.

Параметры:

  • sessionId - Идентификатор сессии
  • move.x - Координата X
  • move.y - Координата Y

click(sessionId: string, click: MouseClick): Promise<void>

Выполняет клик мыши в указанных координатах.

Параметры:

  • sessionId - Идентификатор сессии
  • click.x - Координата X
  • click.y - Координата Y
  • click.button - Кнопка мыши ('left' | 'right' | 'middle')
  • click.count - Количество кликов (опционально, по умолчанию 1)

scroll(sessionId: string, scroll: Scroll): Promise<void>

Выполняет прокрутку в указанных координатах.

Параметры:

  • sessionId - Идентификатор сессии
  • scroll.x - Координата X
  • scroll.y - Координата Y
  • scroll.deltaY - Величина прокрутки (положительная - вниз, отрицательная - вверх)

keyCombo(sessionId: string, combo: KeyCombo): Promise<void>

Выполняет комбинацию клавиш.

Параметры:

  • sessionId - Идентификатор сессии
  • combo.keys - Массив клавиш (['Ctrl', 'c'], ['Alt', 'Tab'])
  • combo.pressDelayMs - Задержка между нажатиями (опционально)

typeText(sessionId: string, input: TypeText): Promise<void>

Вводит текст символ за символом.

Параметры:

  • sessionId - Идентификатор сессии
  • input.text - Текст для ввода
  • input.perCharDelayMs - Задержка между символами (опционально)

clipboardSet(sessionId: string, data: ClipboardSet): Promise<void>

Записывает текстовые данные в буфер обмена удаленной машины.

Параметры:

  • sessionId - Идентификатор сессии
  • data.text - Текст для записи в буфер обмена
  • data.mime - MIME-тип (по умолчанию 'text/plain')

Важно: Поддерживается передача только текстовых данных. Перенос файлов через буфер обмена не реализован. Стабильность синхронизации буфера обмена сильно зависит от используемого протокола (RDP работает надежнее, VNC имеет ограничения) и настроек сервера Guacamole. Возможны проблемы с кодировками при использовании VNC, так как стандарт не определяет передачу UTF-8.

clipboardGet(sessionId: string, query?: ClipboardGet): Promise<ClipboardGet>

Читает текстовые данные из буфера обмена удаленной машины.

Параметры:

  • sessionId - Идентификатор сессии
  • query.selection - Тип буфера ('CLIPBOARD' или 'PRIMARY', по умолчанию 'CLIPBOARD')

Возвращает: Объект с полями text, mime, selection

disconnect(sessionId: string): Promise<void>

Отключает сессию и освобождает ресурсы.

Работа с клавиатурой и модификаторами

Клавиши-модификаторы

Строковые псевдонимы Meta, Cmd, Win, Windows, Command преобразуются в один и тот же keysym Super_L. Guacamole-сервер и удаленная ОС сами решают, как его интерпретировать:

  • На macOS: интерпретируется как ⌘ (Command)
  • На Windows: интерпретируется как Win (клавиша Windows)
  • На Linux: интерпретируется как Super

Важное предупреждение

⚠️ Операционная система или браузер, на которых запущен клиентский код, могут перехватывать системные комбинации клавиш (например, Alt+Tab, Cmd+Q, Ctrl+Alt+Delete). Такие комбинации могут не дойти до удаленной машины. Это является ограничением окружения, а не адаптера.

Примеры проблемных комбинаций:

  • Alt+Tab - переключение окон в локальной ОС
  • Cmd+Q / Alt+F4 - закрытие приложений
  • Ctrl+Alt+Delete - системные функции
  • Win+L - блокировка экрана Windows

Архитектура

Адаптер работает по следующей схеме:

  1. Аутентификация - подключение к Guacamole REST API
  2. WebSocket соединение - установка связи с guacd
  3. Протокол Guacamole - обмен инструкциями с сервером
  4. Canvas рендеринг - отрисовка графических команд в памяти
  5. Скриншоты - извлечение изображений из canvas

Требования

  • Node.js >= 18.0.0
  • Запущенный Apache Guacamole сервер
  • Доступ к guacd (обычно порт 4822)

Тестирование

Базовые тесты

pnpm test

Интеграционные тесты

Для запуска интеграционных тестов нужен запущенный Guacamole сервер:

INTEGRATION_TESTS=true pnpm test

Интеграционные тесты:

  • Подключаются к реальному Guacamole серверу
  • Создают скриншоты и сохраняют их в файлы
  • Проверяют полный цикл работы адаптера

Отладка

Адаптер выводит отладочную информацию в консоль с префиксом [DEBUG]. Для продакшена эти логи можно отключить.

Ограничения

  • Поддерживается только VNC протокол (в текущей версии)
  • Требуется предварительная настройка Guacamole сервера
  • Canvas рендеринг работает только в Node.js среде

Разработка

# Сборка
pnpm build

# Тесты
pnpm test

# Разработка с автоперезагрузкой
pnpm dev