@elcrm/socket
v0.6.0
Published
SharedWorker WebSocket client для elCRM (serverConnect — в @elcrm/server).
Maintainers
Readme
@elcrm/socket
Клиентский WebSocket-стек для elCRM/elWMS: SharedWorker + React-хук. Серверная часть — в @elcrm/server.
Установка
npm install @elcrm/socket
# или
bun add @elcrm/socketТребования: Node.js ≥ 18 (браузер). Peer (опционально, для хука): react ≥ 18, react-dom ≥ 18. Для Bun WS — @elcrm/server.
| Entry | Назначение |
| ----- | ---------- |
| @elcrm/socket | клиент SharedWorker |
| @elcrm/socket/react | useConnect |
| @elcrm/socket/worker | raw SharedWorker script |
Для разработки пакета удобен Bun ≥ 1.3 (см. deploy.md / dev.md).
Протокол
- Tab → Worker:
{ type: "connect", ukey, link } - Worker → Server:
{ path: "connect", ukey } - Server → ack
{ type: 1, user }(и/илиhello) - Дальше: path-RPC
Socket.send("/x", data)или сырой JSONSocket.sendRaw({ type: "ping" })
link.path по умолчанию /connect; для tenant API elWMS — /ws через Socket.createFromApiUrl(apiUrl, ukey, "/ws").
Быстрый старт (клиент)
import { Socket } from "@elcrm/socket";
// Опционально: ключ localStorage для ukey (по умолчанию `d`, как @elcrm/api)
Socket.configure({ storageKey: "elwms_ssid" });
await Socket.createFromApiUrl(apiUrl, ukey, "/ws");
await Socket.connect(ukey);Сохранение link и подключение
// Явно: host / port / ip
await Socket.create(
{ url: "api.example.com", port: 443, ip: false, path: "/ws" },
ukey,
);
// Из URL API (wss://host/ws)
await Socket.createFromApiUrl("https://api.example.com", ukey, "/ws");
await Socket.connect(ukey);Link шифруется (AES-GCM) и кладётся в localStorage (w + ukey по storageKey, по умолчанию d).
| Поле Socket.configure | Описание |
| ----------------------- | -------- |
| storageKey | Ключ localStorage для ukey/ssid (по умолчанию d) |
React: useConnect
import { useConnect } from "@elcrm/socket/react";
function App({ ukey }: { ukey: string }) {
const [isConnect, connect, error] = useConnect(ukey);
return (
<button type="button" onClick={() => connect()} disabled={isConnect}>
{isConnect ? "Online" : "Connect"}
{error != null ? ` (err ${error})` : null}
</button>
);
}Перед connect() нужен сохранённый link (Socket.create / createFromApiUrl).
Server
Серверный serverConnect / createWsHub живут в @elcrm/server (см. major.md):
import { createServer, createWsHub, serverConnect } from "@elcrm/server";API (Socket)
| Метод | Описание |
| ----- | -------- |
| supported() | Есть ли SharedWorker в окружении |
| isConnected() | Текущий статус |
| onStatus(handler) | Подписка на online/offline; сразу вызывает с текущим статусом; возвращает unsubscribe |
| onMessage(handler) | Fan-out сырых сообщений с сервера |
| create(connect, ukey) | Сохранить link (url, port, ip, path?) |
| createFromApiUrl(apiUrl, ukey, path?) | Link из URL API; path по умолчанию /ws |
| connect(ukey?) | Подключить worker; ukey или localStorage.d |
| detach() | Отвязать вкладку от worker |
| disconnect() | Закрыть сокет для всех вкладок, сбросить ukey |
| send(path, data?) | Path-RPC: { ...data, path } |
| sendRaw(json) | Произвольный JSON на сервер |
| fetch(path, data?) | RPC с listen-колбэком → Promise |
| useListener(name, fn) / setListener(name, data) | Именованные слушатели ответов |
| getSharedUkey() / setSharedUkey(ukey) | ukey, общий для вкладок через worker |
Экспорт ./worker
Raw-скрипт SharedWorker — если нужно подключать worker отдельно (Vite):
import workerUrl from "@elcrm/socket/worker?sharedworker&url";В основном бандле (@elcrm/socket) worker уже обёрнут через Vite ?sharedworker&inline (data: URL).
Лицензия
MIT © MaSkal
