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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pushler/vue

v1.1.0

Published

Vue.js SDK for Pushler.ru real-time messaging

Downloads

37

Readme

Pushler Vue SDK

Реактивный Vue.js SDK для работы с Pushler.ru WebSocket сервером.

npm version npm downloads license

Установка

npm / yarn / pnpm

npm install @pushler/vue

# или
yarn add @pushler/vue

# или
pnpm add @pushler/vue

CDN

<!-- Последняя версия -->
<script src="https://unpkg.com/@pushler/vue"></script>

<!-- Конкретная версия -->
<script src="https://unpkg.com/@pushler/[email protected]/dist/pushler-vue.umd.min.js"></script>

<!-- jsDelivr -->
<script src="https://cdn.jsdelivr.net/npm/@pushler/vue"></script>

Быстрый старт

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

<script setup>
import { usePushler } from '@pushler/vue';

// Создаём экземпляр Pushler
const pushler = usePushler({
  appKey: 'your-app-key',
  autoConnect: true, // Автоматическое подключение
});

// Подписка на канал
const channel = pushler.subscribe('my-channel');

// Слушаем события
channel.on('message', (data) => {
  console.log('Получено сообщение:', data);
});

channel.on('notification', (data) => {
  console.log('Уведомление:', data);
});
</script>

<template>
  <div>
    <p>Статус: {{ pushler.connectionState }}</p>
    <p v-if="pushler.socketId">Socket ID: {{ pushler.socketId }}</p>
    <button @click="pushler.connect()" :disabled="pushler.isConnected.value">
      Подключиться
    </button>
    <button @click="pushler.disconnect()" :disabled="!pushler.isConnected.value">
      Отключиться
    </button>
  </div>
</template>

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

// main.js
import { createApp } from 'vue';
import { PushlerPlugin } from '@pushler/vue';
import App from './App.vue';

const app = createApp(App);

app.use(PushlerPlugin, {
  appKey: 'your-app-key',
  autoConnect: true,
});

app.mount('#app');

Затем в любом компоненте:

<script setup>
import { inject } from 'vue';
import { PushlerKey } from '@pushler/vue';

const pushler = inject(PushlerKey);

const channel = pushler.subscribe('notifications');
channel.on('new', (data) => {
  console.log('Новое уведомление:', data);
});
</script>

API Reference

usePushler(options)

Основной composable для работы с WebSocket подключением.

Опции

| Параметр | Тип | По умолчанию | Описание | |----------|-----|--------------|----------| | appKey | string | — | Ключ приложения Pushler (обязательный) | | authEndpoint | string | '/pushler/auth' | Эндпоинт для авторизации приватных каналов | | autoConnect | boolean | false | Автоматическое подключение при инициализации | | reconnectDelay | number | 1000 | Задержка между попытками переподключения (мс) | | maxReconnectAttempts | number | 5 | Максимальное количество попыток переподключения |

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

Реактивное состояние
const pushler = usePushler(options);

// Состояние подключения: 'connecting' | 'connected' | 'disconnected' | 'reconnecting' | 'failed'
pushler.connectionState // Ref<string>

// ID сокета (после подключения)
pushler.socketId // Ref<string | null>

// Ошибка (если есть)
pushler.error // Ref<string | null>

// Количество попыток переподключения
pushler.reconnectAttempts // Ref<number>

// Вычисляемые свойства
pushler.isConnected // ComputedRef<boolean>
pushler.isConnecting // ComputedRef<boolean>
pushler.isReconnecting // ComputedRef<boolean>
Методы
// Подключение к серверу
pushler.connect(options?: { appKey? })

// Отключение
pushler.disconnect()

// Подписка на канал
const channel = pushler.subscribe('channel-name', { 
  signature?: 'pre-signed-signature',
  user?: { id: 1, name: 'User' } // для presence-каналов
})

// Отписка от канала
pushler.unsubscribe('channel-name')

// Получение канала
const channel = pushler.channel('channel-name')

// Получение списка каналов
const channels = pushler.getChannels()
// [{ name, fullName, type, subscribed }]

// Подписка на глобальные события
pushler.on('connected', (data) => console.log('Connected:', data.socketId))
pushler.on('message', (msg) => console.log('Message:', msg))
pushler.on('auth_error', (err) => console.error('Auth error:', err))

// Отписка от событий
pushler.off('connected', handler)

Канал

const channel = pushler.subscribe('my-channel');

// Свойства канала
channel.name        // Полное имя с appKey
channel.originalName // Оригинальное имя
channel.type        // 'public' | 'private' | 'presence'
channel.subscribed  // boolean

// Методы
channel.on('event-name', callback)
channel.off('event-name', callback)
channel.unsubscribe()

Типы каналов

// Публичные каналы (без авторизации)
pushler.subscribe('public-channel')

// Приватные каналы (требуют авторизации через бэкенд)
pushler.subscribe('private-channel')
// SDK автоматически запросит подпись с authEndpoint

// Или можно передать предварительно полученную подпись
pushler.subscribe('private-channel', {
  signature: 'hmac-signature-from-backend'
})

// Presence-каналы (информация о присутствии)
pushler.subscribe('presence-chat', {
  user: {
    id: 123,
    name: 'Иван Петров',
    avatar: 'https://...'
  }
})

Безопасность

⚠️ Важно: Секретный ключ

НИКОГДА не храните секретный ключ в клиентском коде!

Секретный ключ (secret) должен храниться только на вашем бэкенде. Для приватных каналов SDK автоматически запрашивает подпись с вашего бэкенда через authEndpoint.

Схема авторизации приватных каналов

┌─────────────┐    1. subscribe('private-chat')    ┌─────────────────┐
│   Browser   │ ──────────────────────────────────►│  Pushler WS     │
│   (SDK)     │                                    │  Server         │
└──────┬──────┘                                    └────────┬────────┘
       │                                                    │
       │ 2. POST /pushler/auth                              │
       │    { channel, socket_id }                          │
       ▼                                                    │
┌─────────────┐    3. Проверка авторизации                  │
│  Ваш        │    + генерация подписи (с secret)           │
│  Backend    │ ───────────────────────────────────────────►│
└─────────────┘    4. signature                             │

Пример бэкенда для авторизации

// Laravel пример
Route::post('/pushler/auth', function (Request $request) {
    $user = auth()->user();
    
    // Проверяем право доступа к каналу
    $channelName = $request->channel_name;
    if (!$user->canAccessChannel($channelName)) {
        return response()->json(['error' => 'Forbidden'], 403);
    }
    
    // Генерируем подпись
    $socketId = $request->socket_id;
    $signature = hash_hmac('sha256', "{$socketId}:{$channelName}", env('PUSHLER_SECRET'));
    
    return response()->json(['signature' => $signature]);
});

Кастомные заголовки авторизации

Вы можете передать дополнительные заголовки для запросов авторизации:

// Статические заголовки
const pushler = usePushler({
  appKey: 'your-app-key',
  authEndpoint: '/api/pushler/auth',
  authHeaders: {
    'Authorization': 'Bearer your-token',
    'X-Custom-Header': 'value'
  }
});

// Динамические заголовки (рекомендуется)
const pushler = usePushler({
  appKey: 'your-app-key',
  authEndpoint: '/api/pushler/auth',
  getAuthHeaders: () => ({
    'Authorization': `Bearer ${authStore.token}`
  })
});

При использовании authHeaders или getAuthHeaders SDK не отправляет cookies (credentials: 'include').

Promise-based API

Ожидание подключения

connect() возвращает Promise, который резолвится при успешном подключении:

const pushler = usePushler({ appKey: 'your-app-key' });

// Ожидаем подключения
const { socketId } = await pushler.connect();
console.log('Подключены с socketId:', socketId);

// Теперь можно подписываться на приватные каналы
pushler.subscribe('private-user-123');

Метод waitForConnection()

Для случаев, когда нужно дождаться соединения с таймаутом:

try {
  await pushler.waitForConnection(10000); // 10 секунд
  console.log('Подключены!');
} catch (error) {
  console.error('Не удалось подключиться:', error.message);
}

usePushlerChannel(pushler, channelName, options)

Composable для работы с отдельным каналом.

<script setup>
import { usePushler, usePushlerChannel } from '@pushler/vue';

const pushler = usePushler({ ... });
const { channel, isSubscribed, events, lastEvent, on, clearEvents } = usePushlerChannel(
  pushler,
  'notifications',
  { 
    autoSubscribe: true,
    maxEvents: 50 
  }
);

on('new', (data) => {
  console.log('Новое уведомление:', data);
});
</script>

<template>
  <div>
    <p>Подписан: {{ isSubscribed }}</p>
    <p>Последнее событие: {{ lastEvent }}</p>
    <ul>
      <li v-for="event in events" :key="event.timestamp">
        {{ event.event }}: {{ event.data }}
      </li>
    </ul>
    <button @click="clearEvents">Очистить</button>
  </div>
</template>

Константы

import { ConnectionStates, ChannelTypes } from '@pushler/vue';

// Состояния подключения
ConnectionStates.CONNECTING   // 'connecting'
ConnectionStates.CONNECTED    // 'connected'
ConnectionStates.DISCONNECTED // 'disconnected'
ConnectionStates.RECONNECTING // 'reconnecting'
ConnectionStates.FAILED       // 'failed'

// Типы каналов
ChannelTypes.PUBLIC   // 'public'
ChannelTypes.PRIVATE  // 'private'
ChannelTypes.PRESENCE // 'presence'

Примеры

Чат в реальном времени

<script setup>
import { ref } from 'vue';
import { usePushler } from '@pushler/vue';

const pushler = usePushler({
  appKey: 'chat-app-key',
  autoConnect: true,
});

const messages = ref([]);
const newMessage = ref('');

// Подписка на канал чата
const chatChannel = pushler.subscribe('chat-room-1');

chatChannel.on('message', (data) => {
  messages.value.push(data);
});

chatChannel.on('user_joined', (data) => {
  messages.value.push({
    type: 'system',
    text: `${data.name} присоединился к чату`
  });
});

async function sendMessage() {
  // Отправка через ваш API
  await fetch('/api/chat/send', {
    method: 'POST',
    body: JSON.stringify({
      channel: 'chat-room-1',
      message: newMessage.value
    })
  });
  newMessage.value = '';
}
</script>

Уведомления

<script setup>
import { usePushler } from '@pushler/vue';
import { useNotifications } from './composables/useNotifications';

const pushler = usePushler({ autoConnect: true, ... });
const { show } = useNotifications();

// Приватный канал для уведомлений пользователя
const notificationChannel = pushler.subscribe('private-user-notifications');

notificationChannel.on('new', (data) => {
  show({
    title: data.title,
    message: data.message,
    type: data.type || 'info'
  });
});

notificationChannel.on('badge_update', (data) => {
  // Обновление счётчика непрочитанных
  document.title = data.count > 0 
    ? `(${data.count}) Мой сайт` 
    : 'Мой сайт';
});
</script>

Индикатор набора текста (Typing indicator)

<script setup>
import { ref, computed } from 'vue';
import { usePushler } from '@pushler/vue';

const pushler = usePushler({ ... });
const typingUsers = ref(new Set());

const channel = pushler.subscribe('presence-chat', {
  user: { id: currentUserId, name: currentUserName }
});

channel.on('typing_start', (data) => {
  typingUsers.value.add(data.user_name);
});

channel.on('typing_stop', (data) => {
  typingUsers.value.delete(data.user_name);
});

const typingText = computed(() => {
  const users = Array.from(typingUsers.value);
  if (users.length === 0) return '';
  if (users.length === 1) return `${users[0]} печатает...`;
  if (users.length === 2) return `${users.join(' и ')} печатают...`;
  return `${users.length} человек печатают...`;
});
</script>

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

<!DOCTYPE html>
<html>
<head>
  <title>Pushler Vue Example</title>
  <script src="https://unpkg.com/vue@3"></script>
  <script src="https://unpkg.com/@pushler/vue"></script>
</head>
<body>
  <div id="app">
    <p>Status: {{ connectionState }}</p>
    <p v-if="socketId">Socket ID: {{ socketId }}</p>
    <button @click="connect" :disabled="isConnected">Connect</button>
    <button @click="disconnect" :disabled="!isConnected">Disconnect</button>
  </div>

  <script>
    const { createApp } = Vue;
    const { usePushler } = PushlerVue;

    createApp({
      setup() {
        const pushler = usePushler({
          appKey: 'your-app-key'
        });

        return {
          connectionState: pushler.connectionState,
          socketId: pushler.socketId,
          isConnected: pushler.isConnected,
          connect: () => pushler.connect(),
          disconnect: () => pushler.disconnect()
        };
      }
    }).mount('#app');
  </script>
</body>
</html>

TypeScript

SDK включает TypeScript определения. Импортируйте типы:

import type { 
  UsePushlerReturn, 
  PushlerChannel, 
  ChannelInfo,
  ConnectionState,
  ChannelType 
} from '@pushler/vue';

Лицензия

MIT