Fix some bugs with message delivery
This commit is contained in:
@@ -19,5 +19,6 @@ module.exports = {
|
|||||||
"rules": {
|
"rules": {
|
||||||
"@typescript-eslint/no-unused-vars": ["error", {args: "none"}],
|
"@typescript-eslint/no-unused-vars": ["error", {args: "none"}],
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"@typescript-eslint/ban-ts-comment": "off",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
# Paravel
|
# Paravel
|
||||||
|
|
||||||
Another nostr toolkit, focused on creating highly a configurable client system.
|
Another nostr toolkit, focused on creating highly a configurable client system. What paravel provides is less a library of code than a library of abstractions. Odds are you will end up creating a custom implementation of every component to suit your needs, but if you start with paravel that will be much easier than if you pile on parameters over time.
|
||||||
|
|
||||||
# Utilities
|
# Utilities
|
||||||
|
|
||||||
- [Deferred](./lib/Deferred.ts') is just a promise with `resolve` and `reject` methods.
|
- [Deferred](./src/Deferred.ts') is just a promise with `resolve` and `reject` methods.
|
||||||
- [EventBus](./lib/EventBus.ts') is an implementation of an event bus.
|
- [EventBus](./src/EventBus.ts') is an implementation of an event bus.
|
||||||
- [Socket](./lib/Socket.ts') is a wrapper around isomorphic-ws that handles connection status and json parsing/serialization.
|
- [Socket](./src/Socket.ts') is a wrapper around isomorphic-ws that handles connection status and json parsing/serialization.
|
||||||
|
|
||||||
# Components
|
# Components
|
||||||
|
|
||||||
- [Pool](./lib/Pool.ts') is a thin wrapper around `Map` for use with `Relay`s.
|
- [Pool](./src/Pool.ts') is a thin wrapper around `Map` for use with `Relay`s.
|
||||||
- [Executor](./lib/Executor.ts') implements common nostr flows on `target`
|
- [Executor](./src/Executor.ts') implements common nostr flows on `target`
|
||||||
|
|
||||||
# Executables
|
# Executor targets
|
||||||
|
|
||||||
Executables have an event `bus` and a `send` method and are passed to an `Executor` for use.
|
Executor targets have an event `bus`, a `send` method, a `cleanup` method, and are passed to an `Executor` for use.
|
||||||
|
|
||||||
- [Relay](./lib/Relay.ts') takes a `Socket` and provides listeners for different verbs.
|
- [Relay](./src/Relay.ts') takes a `Socket` and provides listeners for different verbs.
|
||||||
- [Relays](./lib/Relays.ts') takes an array of `Socket`s and provides listeners for different verbs, merging all events into a single stream.
|
- [Relays](./src/Relays.ts') takes an array of `Socket`s and provides listeners for different verbs, merging all events into a single stream.
|
||||||
- [Plex](./lib/Plex.ts') takes an array of urls and a `Socket` and sends and receives wrapped nostr messages over that connection.
|
- [Plex](./src/Plex.ts') takes an array of urls and a `Socket` and sends and receives wrapped nostr messages over that connection.
|
||||||
|
|
||||||
# Example
|
# Example
|
||||||
|
|
||||||
@@ -33,9 +33,8 @@ class Agent {
|
|||||||
}
|
}
|
||||||
getTarget(urls) {
|
getTarget(urls) {
|
||||||
return this.multiplexerUrl
|
return this.multiplexerUrl
|
||||||
? new Plex(urls, this.pool.add(this.multiplexerUrl))
|
? new Plex(urls, this.pool.get(this.multiplexerUrl))
|
||||||
: new Relays(urls.map(url => this.pool.add(url)))
|
: new Relays(urls.map(url => this.pool.get(url)))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
subscribe(urls, filters, id, {onEvent, onEose}) {
|
subscribe(urls, filters, id, {onEvent, onEose}) {
|
||||||
const executor = new Executor(this.getTarget(urls))
|
const executor = new Executor(this.getTarget(urls))
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ const {build} = require('esbuild')
|
|||||||
|
|
||||||
const common = {
|
const common = {
|
||||||
bundle: true,
|
bundle: true,
|
||||||
entryPoints: ['lib/main.ts'],
|
entryPoints: ['src/main.ts'],
|
||||||
sourcemap: 'external'
|
sourcemap: 'external'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
import type {EventBus} from './util/EventBus.ts'
|
|
||||||
|
|
||||||
type Executable = {
|
|
||||||
bus: EventBus
|
|
||||||
send: (verb: string, ...args) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Executor {
|
|
||||||
target: Executable
|
|
||||||
constructor(target) {
|
|
||||||
this.target = target
|
|
||||||
}
|
|
||||||
subscribe(filters, id, {onEvent, onEose}) {
|
|
||||||
const [eventChannel, eoseChannel] = [
|
|
||||||
this.target.bus.on("EVENT", (subid, e) => subid === id && onEvent?.(e)),
|
|
||||||
this.target.bus.on("EOSE", subid => subid === id && onEose?.()),
|
|
||||||
]
|
|
||||||
|
|
||||||
this.target.send("REQ", id, ...filters)
|
|
||||||
|
|
||||||
return {
|
|
||||||
unsubscribe: () => {
|
|
||||||
this.target.send("CLOSE", id)
|
|
||||||
this.target.bus.off("EVENT", eventChannel)
|
|
||||||
this.target.bus.off("EOSE", eoseChannel)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
publish(event, {onOk, onError}) {
|
|
||||||
const withCleanup = cb => (id, ...payload) => {
|
|
||||||
if (id === event.id) {
|
|
||||||
cb(id, ...payload)
|
|
||||||
this.target.bus.off("OK", okChannel)
|
|
||||||
this.target.bus.off("ERROR", errorChannel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const [okChannel, errorChannel] = [
|
|
||||||
this.target.bus.on("OK", withCleanup(onOk)),
|
|
||||||
this.target.bus.on("ERROR", withCleanup(onError)),
|
|
||||||
]
|
|
||||||
|
|
||||||
this.target.send("EVENT", event)
|
|
||||||
}
|
|
||||||
count(filter, id, {onCount}) {
|
|
||||||
const channel = this.target.bus.on("COUNT", (subid, ...payload) => {
|
|
||||||
if (subid === id) {
|
|
||||||
onCount(...payload)
|
|
||||||
|
|
||||||
this.target.bus.off("COUNT", channel)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
this.target.send("COUNT", id, ...filter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-31
@@ -1,31 +0,0 @@
|
|||||||
import {Socket} from "./util/Socket"
|
|
||||||
|
|
||||||
export class Pool {
|
|
||||||
relays: Map<string, Socket>
|
|
||||||
constructor() {
|
|
||||||
this.relays = new Map()
|
|
||||||
this.interval = setInterval(() => {
|
|
||||||
for (const relay of this.relays) {
|
|
||||||
relay.reconnect()
|
|
||||||
}
|
|
||||||
}, 30_000)
|
|
||||||
}
|
|
||||||
add(url) {
|
|
||||||
if (!this.relays.has(url)) {
|
|
||||||
this.relays.set(url, new Socket(url))
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.relays.get(url)
|
|
||||||
}
|
|
||||||
remove(url) {
|
|
||||||
this.relays.get(url)?.disconnect()
|
|
||||||
this.relays.delete(url)
|
|
||||||
}
|
|
||||||
cleanup() {
|
|
||||||
this.interval = clearInterval(this.interval)
|
|
||||||
|
|
||||||
for (const url of this.relays.keys()) {
|
|
||||||
this.remove(url)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import {EventBus} from "./util/EventBus"
|
|
||||||
|
|
||||||
export class Relay {
|
|
||||||
constructor(socket) {
|
|
||||||
this.socket = socket
|
|
||||||
this.bus = new EventBus()
|
|
||||||
this.onMessage = this.onMessage.bind(this)
|
|
||||||
|
|
||||||
this.socket.bus.on('message', this.onMessage)
|
|
||||||
}
|
|
||||||
async send(...payload) {
|
|
||||||
await this.socket.connect()
|
|
||||||
|
|
||||||
this.socket.send(payload)
|
|
||||||
}
|
|
||||||
onMessage(message) {
|
|
||||||
const [verb, ...payload] = message
|
|
||||||
|
|
||||||
this.bus.handle(verb, ...payload)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
import {Socket} from './util/Socket'
|
|
||||||
import {EventBus} from './util/EventBus'
|
|
||||||
|
|
||||||
export class Relays {
|
|
||||||
sockets: Socket[]
|
|
||||||
bus: EventBus
|
|
||||||
constructor(sockets) {
|
|
||||||
this.sockets = sockets
|
|
||||||
this.bus = new EventBus()
|
|
||||||
this.onMessage = this.onMessage.bind(this)
|
|
||||||
|
|
||||||
sockets.forEach(socket => socket.bus.on('message', this.onMessage))
|
|
||||||
}
|
|
||||||
send(...payload) {
|
|
||||||
this.sockets.forEach(socket => {
|
|
||||||
await socket.connect()
|
|
||||||
|
|
||||||
socket.send(...payload)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
onMessage(message) {
|
|
||||||
const [verb, ...payload] = message
|
|
||||||
|
|
||||||
this.bus.handle(verb, ...payload)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
export type EventBusHandler = (...args: any[]) => void
|
|
||||||
|
|
||||||
export class EventBus {
|
|
||||||
static ANY = Math.random().toString().slice(2)
|
|
||||||
listeners: Record<string, Array<EventBusHandler>> = {}
|
|
||||||
on(name: string, handler: EventBusHandler) {
|
|
||||||
this.listeners[name] = this.listeners[name] || ([] as Array<EventBusHandler>)
|
|
||||||
this.listeners[name].push(handler)
|
|
||||||
}
|
|
||||||
off(name: string, handler: EventBusHandler) {
|
|
||||||
this.listeners[name] = this.listeners[name].filter(h => h !== handler)
|
|
||||||
}
|
|
||||||
clear() {
|
|
||||||
this.listeners = {}
|
|
||||||
}
|
|
||||||
handle(k: string, ...payload: any) {
|
|
||||||
for (const handler of this.listeners[k] || []) {
|
|
||||||
handler(...payload)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const handler of this.listeners[EventBus.ANY] || []) {
|
|
||||||
handler(k, ...payload)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pipe(k: string, bus: EventBus) {
|
|
||||||
this.on(k, (...payload: any[]) => bus.handle(k, ...payload))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "paravel",
|
"name": "paravel",
|
||||||
"version": "0.1.4",
|
"version": "0.1.5",
|
||||||
"description": "Yet another toolkit for nostr",
|
"description": "Yet another toolkit for nostr",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -15,8 +15,8 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "node build.js",
|
"build": "node build.js",
|
||||||
"pub": "npm i && node build.js && npm publish",
|
"pub": "npm i && node build.js && npm publish",
|
||||||
"check:ts": "tsc --noEmit --esModuleInterop --strict lib/**/*",
|
"check:ts": "tsc --noEmit --esModuleInterop --strict src/**/*",
|
||||||
"check:es": "eslint lib/*",
|
"check:es": "eslint src/*",
|
||||||
"check": "run-p check:*"
|
"check": "run-p check:*"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
import type {EventBus} from './util/EventBus.ts'
|
||||||
|
|
||||||
|
const createFilterId = filters =>
|
||||||
|
[Math.random().toString().slice(2, 6), filters.map(describeFilter).join(":")].join("-")
|
||||||
|
|
||||||
|
const describeFilter = ({kinds = [], ...filter}) => {
|
||||||
|
const parts = []
|
||||||
|
|
||||||
|
parts.push(kinds.join(","))
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(filter)) {
|
||||||
|
if (value instanceof Array) {
|
||||||
|
parts.push(`${key}[${value.length}]`)
|
||||||
|
} else {
|
||||||
|
parts.push(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "(" + parts.join(",") + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
type Executable = {
|
||||||
|
bus: EventBus
|
||||||
|
send: (verb: string, ...args) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Executor {
|
||||||
|
target: Executable
|
||||||
|
constructor(target) {
|
||||||
|
this.target = target
|
||||||
|
}
|
||||||
|
subscribe(filters, {onEvent, onEose}) {
|
||||||
|
const id = createFilterId(filters)
|
||||||
|
const unsubscribe = this.target.bus.addListeners({
|
||||||
|
EVENT: (url, subid, e) => subid === id && onEvent?.(url, e),
|
||||||
|
EOSE: (url, subid) => subid === id && onEose?.(url),
|
||||||
|
})
|
||||||
|
|
||||||
|
this.target.send("REQ", id, ...filters)
|
||||||
|
|
||||||
|
return {
|
||||||
|
unsubscribe: () => {
|
||||||
|
this.target.send("CLOSE", id)
|
||||||
|
|
||||||
|
unsubscribe()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
publish(event, {onOk, onError}) {
|
||||||
|
const unsubscribe = this.target.bus.addListeners({
|
||||||
|
OK: (url, id, ...payload) => id === event.id && onOk(url, ...payload),
|
||||||
|
ERROR: (url, id, ...payload) => id === event.id && onError(url, ...payload),
|
||||||
|
})
|
||||||
|
|
||||||
|
this.target.send("EVENT", event)
|
||||||
|
|
||||||
|
return {unsubscribe}
|
||||||
|
}
|
||||||
|
count(filters, {onCount}) {
|
||||||
|
const id = createFilterId(filters)
|
||||||
|
const unsubscribe = this.target.bus.addListeners({
|
||||||
|
COUNT: (url, subid, ...payload) => {
|
||||||
|
if (subid === id) {
|
||||||
|
onCount(url, ...payload)
|
||||||
|
unsubscribe()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.target.send("COUNT", id, ...filters)
|
||||||
|
|
||||||
|
return {unsubscribe}
|
||||||
|
}
|
||||||
|
handleAuth({onAuth, onOk}) {
|
||||||
|
let event
|
||||||
|
|
||||||
|
const unsubscribe = this.target.bus.addListeners({
|
||||||
|
AUTH: async (url, challenge) => {
|
||||||
|
event = await onAuth(url, challenge)
|
||||||
|
},
|
||||||
|
OK: (url, id, ok, message) => {
|
||||||
|
if (id === event?.id) {
|
||||||
|
event = null
|
||||||
|
onOk(url, id, ok, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return {unsubscribe}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,18 +5,19 @@ export class Plex {
|
|||||||
this.urls = urls
|
this.urls = urls
|
||||||
this.socket = socket
|
this.socket = socket
|
||||||
this.bus = new EventBus()
|
this.bus = new EventBus()
|
||||||
this.onMessage = this.onMessage.bind(this)
|
this.listeners = sockets.map(socket => {
|
||||||
|
return socket.bus.addListener('message', (url, [verb, ...payload]) => {
|
||||||
this.socket.bus.on('message', this.onMessage)
|
this.bus.emit(verb, url, ...payload)
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
async send(...payload) {
|
async send(...payload) {
|
||||||
await this.socket.connect()
|
await this.socket.connect()
|
||||||
|
|
||||||
this.socket.send([{relays: this.urls}, payload])
|
this.socket.send([{relays: this.urls}, payload])
|
||||||
}
|
}
|
||||||
onMessage(message) {
|
cleanup() {
|
||||||
const [verb, ...payload] = message[1]
|
this.bus.clear()
|
||||||
|
this.listeners.map(unsubscribe => unsubscribe())
|
||||||
this.bus.handle(verb, ...payload)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
import {Socket} from "./util/Socket"
|
||||||
|
|
||||||
|
export class Pool {
|
||||||
|
data: Map<string, Socket>
|
||||||
|
constructor() {
|
||||||
|
this.data = new Map()
|
||||||
|
}
|
||||||
|
has(url) {
|
||||||
|
return this.data.has(url)
|
||||||
|
}
|
||||||
|
get(url) {
|
||||||
|
if (!this.data.has(url)) {
|
||||||
|
this.data.set(url, new Socket(url))
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.data.get(url)
|
||||||
|
}
|
||||||
|
remove(url) {
|
||||||
|
const socket = this.data.get(url)
|
||||||
|
|
||||||
|
if (socket) {
|
||||||
|
socket.disconnect()
|
||||||
|
this.data.delete(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clear() {
|
||||||
|
for (const url of this.data.keys()) {
|
||||||
|
this.remove(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import {EventBus} from "./util/EventBus"
|
||||||
|
|
||||||
|
export class Relay {
|
||||||
|
constructor(socket) {
|
||||||
|
this.socket = socket
|
||||||
|
this.bus = new EventBus()
|
||||||
|
this.listeners = sockets.map(socket => {
|
||||||
|
return socket.bus.addListener('message', (url, [verb, ...payload]) => {
|
||||||
|
this.bus.emit(verb, url, ...payload)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
async send(...payload) {
|
||||||
|
await this.socket.connect()
|
||||||
|
|
||||||
|
this.socket.send(payload)
|
||||||
|
}
|
||||||
|
cleanup() {
|
||||||
|
this.bus.clear()
|
||||||
|
this.listeners.map(unsubscribe => unsubscribe())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import {Socket} from './util/Socket'
|
||||||
|
import {EventBus} from './util/EventBus'
|
||||||
|
|
||||||
|
export class Relays {
|
||||||
|
sockets: Socket[]
|
||||||
|
bus: EventBus
|
||||||
|
constructor(sockets) {
|
||||||
|
this.sockets = sockets
|
||||||
|
this.bus = new EventBus()
|
||||||
|
this.listeners = sockets.map(socket => {
|
||||||
|
return socket.bus.addListener('message', (url, [verb, ...payload]) => {
|
||||||
|
this.bus.emit(verb, url, ...payload)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
send(...payload) {
|
||||||
|
this.sockets.forEach(async socket => {
|
||||||
|
await socket.connect()
|
||||||
|
|
||||||
|
socket.send(payload)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
cleanup() {
|
||||||
|
this.bus.clear()
|
||||||
|
this.listeners.map(unsubscribe => unsubscribe())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
export * from "./util/EventBus"
|
export * from "./util/EventBus"
|
||||||
export * from "./util/Deferred"
|
export * from "./util/Deferred"
|
||||||
export * from "./Relay"
|
export * from "./util/Socket"
|
||||||
|
export * from "./Executor"
|
||||||
|
export * from "./Plex"
|
||||||
export * from "./Pool"
|
export * from "./Pool"
|
||||||
|
export * from "./Relay"
|
||||||
|
export * from "./Relays"
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
export type EventBusHandler = (...args: any[]) => void
|
||||||
|
|
||||||
|
export class EventBus {
|
||||||
|
static ANY = Math.random().toString().slice(2)
|
||||||
|
listeners: Record<string, Array<EventBusHandler>> = {}
|
||||||
|
addListener(name: string, handler: EventBusHandler) {
|
||||||
|
this.listeners[name] = this.listeners[name] || ([] as Array<EventBusHandler>)
|
||||||
|
this.listeners[name].push(handler)
|
||||||
|
|
||||||
|
return () => this.removeListener(name, handler)
|
||||||
|
}
|
||||||
|
addListeners(config: Record<string, EventBusHandler>) {
|
||||||
|
const callbacks = [] as Array<() => void>
|
||||||
|
for (const [name, handler] of Object.entries(config)) {
|
||||||
|
callbacks.push(this.addListener(name, handler))
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => callbacks.forEach(unsubscribe => unsubscribe())
|
||||||
|
}
|
||||||
|
removeListener(name: string, handler: EventBusHandler) {
|
||||||
|
this.listeners[name] = (this.listeners[name] || []).filter(h => h !== handler)
|
||||||
|
}
|
||||||
|
clear() {
|
||||||
|
this.listeners = {}
|
||||||
|
}
|
||||||
|
emit(k: string, ...payload: any) {
|
||||||
|
for (const handler of this.listeners[k] || []) {
|
||||||
|
handler(...payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const handler of this.listeners[EventBus.ANY] || []) {
|
||||||
|
handler(k, ...payload)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,9 @@ export class Socket {
|
|||||||
queue: string[]
|
queue: string[]
|
||||||
bus: EventBus
|
bus: EventBus
|
||||||
status: string
|
status: string
|
||||||
|
_onOpen: (e: any) => void
|
||||||
|
_onMessage: (e: any) => void
|
||||||
|
_onClose: (e: any) => void
|
||||||
static STATUS = {
|
static STATUS = {
|
||||||
NEW: "new",
|
NEW: "new",
|
||||||
PENDING: "pending",
|
PENDING: "pending",
|
||||||
@@ -24,6 +27,25 @@ export class Socket {
|
|||||||
this.queue = []
|
this.queue = []
|
||||||
this.bus = new EventBus()
|
this.bus = new EventBus()
|
||||||
this.status = Socket.STATUS.NEW
|
this.status = Socket.STATUS.NEW
|
||||||
|
|
||||||
|
this._onOpen = e => {
|
||||||
|
this.status = Socket.STATUS.READY
|
||||||
|
this.ready?.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
this._onMessage = e => {
|
||||||
|
this.queue.push(e.data as string)
|
||||||
|
|
||||||
|
if (!this.timeout) {
|
||||||
|
this.handleMessagesAsync()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._onClose = e => {
|
||||||
|
this.disconnect()
|
||||||
|
this.ready?.reject()
|
||||||
|
this.status = Socket.STATUS.CLOSED
|
||||||
|
}
|
||||||
}
|
}
|
||||||
async connect() {
|
async connect() {
|
||||||
if ([Socket.STATUS.NEW, Socket.STATUS.CLOSED].includes(this.status)) {
|
if ([Socket.STATUS.NEW, Socket.STATUS.CLOSED].includes(this.status)) {
|
||||||
@@ -35,45 +57,20 @@ export class Socket {
|
|||||||
this.ws = new WebSocket(this.url)
|
this.ws = new WebSocket(this.url)
|
||||||
this.status = Socket.STATUS.PENDING
|
this.status = Socket.STATUS.PENDING
|
||||||
|
|
||||||
this.ws.addEventListener("open", () => {
|
this.ws.addEventListener("open", this._onOpen)
|
||||||
console.log(`Opened connection to ${this.url}`)
|
this.ws.addEventListener("message", this._onMessage)
|
||||||
|
this.ws.addEventListener("close", this._onClose)
|
||||||
this.status = Socket.STATUS.READY
|
|
||||||
this.ready?.resolve()
|
|
||||||
})
|
|
||||||
|
|
||||||
this.ws.addEventListener("message", e => {
|
|
||||||
this.queue.push(e.data as string)
|
|
||||||
|
|
||||||
if (!this.timeout) {
|
|
||||||
this.timeout = this.handleMessagesAsync()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
this.ws.addEventListener("error", e => {
|
|
||||||
console.log(`Error on connection to ${this.url}`)
|
|
||||||
|
|
||||||
this.disconnect()
|
|
||||||
this.ready?.reject()
|
|
||||||
this.status = Socket.STATUS.CLOSED
|
|
||||||
})
|
|
||||||
|
|
||||||
this.ws.addEventListener("close", () => {
|
|
||||||
console.log(`Closed connection to ${this.url}`)
|
|
||||||
|
|
||||||
this.disconnect()
|
|
||||||
this.ready?.reject()
|
|
||||||
this.status = Socket.STATUS.CLOSED
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.ready?.catch(() => null)
|
await this.ready?.catch(() => null)
|
||||||
}
|
}
|
||||||
disconnect() {
|
disconnect() {
|
||||||
if (this.ws) {
|
if (this.ws) {
|
||||||
console.log(`Disconnecting from ${this.url}`)
|
|
||||||
|
|
||||||
this.ws.close()
|
this.ws.close()
|
||||||
|
this.ws.removeEventListener("open", this._onOpen)
|
||||||
|
this.ws.removeEventListener("message", this._onMessage)
|
||||||
|
this.ws.removeEventListener("error", this._onClose)
|
||||||
|
this.ws.removeEventListener("close", this._onClose)
|
||||||
this.ws = undefined
|
this.ws = undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,13 +83,17 @@ export class Socket {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bus.handle('message', message)
|
this.bus.emit('message', this.url, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.timeout = this.queue.length > 0 ? this.handleMessagesAsync() : undefined
|
if (this.queue.length > 0) {
|
||||||
|
this.handleMessagesAsync()
|
||||||
|
} else {
|
||||||
|
this.timeout = undefined
|
||||||
|
}
|
||||||
}
|
}
|
||||||
handleMessagesAsync() {
|
handleMessagesAsync() {
|
||||||
return setTimeout(() => this.handleMessages(), 10) as NodeJS.Timeout
|
this.timeout = setTimeout(() => this.handleMessages(), 10) as NodeJS.Timeout
|
||||||
}
|
}
|
||||||
send(message: any) {
|
send(message: any) {
|
||||||
if (this.status === Socket.STATUS.READY) {
|
if (this.status === Socket.STATUS.READY) {
|
||||||
+1
-1
@@ -5,7 +5,7 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
name: 'paravel',
|
name: 'paravel',
|
||||||
entry: path.resolve(__dirname, 'lib/main.ts'),
|
entry: path.resolve(__dirname, 'src/main.ts'),
|
||||||
fileName: (format) => `paravel.${format}.js`
|
fileName: (format) => `paravel.${format}.js`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user