@xmpp/client
Version:
288 lines (200 loc) • 7.6 kB
Markdown
# client
An XMPP client is an entity that connects to an XMPP server.
`@xmpp/client` package includes a minimal set of features to connect and authenticate securely and reliably.
It supports Node.js, browsers and React Native. See [below](#transports) for differences.
## Install
`npm install @xmpp/client @xmpp/debug`
## Setup
```js
const { client, xml, jid } = require("@xmpp/client");
```
or
```html
<script
src="https://unpkg.com/@xmpp/client@VERSION/dist/xmpp.min.js"
crossorigin
></script>
```
Replace `VERSION` with the desired version number.
```js
const { client, xml, jid } = window.XMPP;
```
## Example
```js
const { client, xml } = require("@xmpp/client");
const debug = require("@xmpp/debug");
const xmpp = client({
service: "ws://localhost:5280/xmpp-websocket",
domain: "localhost",
resource: "example",
username: "username",
password: "password",
});
debug(xmpp, true);
xmpp.on("error", (err) => {
console.error(err);
});
xmpp.on("offline", () => {
console.log("offline");
});
xmpp.on("stanza", async (stanza) => {
if (stanza.is("message")) {
await xmpp.send(xml("presence", { type: "unavailable" }));
await xmpp.stop();
}
});
xmpp.on("online", async (address) => {
// Makes itself available
await xmpp.send(xml("presence"));
// Sends a chat message to itself
const message = xml(
"message",
{ type: "chat", to: address },
xml("body", {}, "hello world"),
);
await xmpp.send(message);
});
xmpp.start().catch(console.error);
```
## xml
See [xml package](/packages/xml)
## jid
See [jid package](/packages/jid)
## client
- `options` <`Object`>
- `service` `<string>` The service to connect to, accepts an URI or a domain.
- `domain` lookup and connect to the most secure endpoint using [@xmpp/resolve](/packages/resolve)
- `xmpp://hostname:port` plain TCP, may be upgraded to TLS by [@xmpp/starttls](/packages/starttls)
- `xmpps://hostname:port` direct TLS
- `ws://hostname:port/path` plain WebSocket
- `wss://hostname:port/path` secure WebSocket
- `domain` `<string>` Optional domain of the service, if omitted will use the hostname from `service`. Useful when the service domain is different than the service hostname.
- `resource` `<string`> Optional resource for [resource binding](/packages/resource-binding)
- `username` `<string>` Optional username for [sasl](/packages/sasl)
- `password` `<string>` Optional password for [sasl](/packages/sasl)
Returns an [xmpp](#xmpp) object.
## xmpp
`xmpp` is an instance of [EventEmitter](https://nodejs.org/api/events.html).
### status
`online` indicates that `xmpp` is authenticated and addressable. It is emitted every time there is a successfull (re)connection.
`offline` indicates that `xmpp` disconnected and no automatic attempt to reconnect will happen (after calling `xmpp.stop()`).
Additional status:
- `connecting`: Socket is connecting
- `connect`: Socket is connected
- `opening`: Stream is opening
- `open`: Stream is open
- `closing`: Stream is closing
- `close`: Stream is closed
- `disconnecting`: Socket is disconnecting
- `disconnect`: Socket is disconnected
You can read the current status using the `status` property.
```js
const isOnline = xmpp.status === "online";
```
You can listen for status change using the `status` event.
### Event `status`
Emitted when the status changes.
```js
xmpp.on("status", (status) => {
console.debug(status);
});
```
### Event `error`
Emitted when an error occurs. For connection errors, `xmpp` will reconnect on its own using [@xmpp/reconnect](/packages/reconnect) however a listener MUST be attached to avoid uncaught exceptions.
- `<Error>`
```js
xmpp.on("error", (error) => {
console.error(error);
});
```
### Event `stanza`
Emitted when a stanza is received and parsed.
- [`<Element>`](/packages/xml)
```js
// Simple echo bot example
xmpp.on("stanza", (stanza) => {
console.log(stanza.toString());
if (!stanza.is("message")) return;
const { to, from } = stanza.attrs;
stanza.attrs.from = to;
stanza.attrs.to = from;
xmpp.send(stanza);
});
```
### Event `online`
Emitted when connected, authenticated and ready to receive/send stanzas.
- [`<Jid>`](/packages/jid)
```js
xmpp.on("online", (address) => {
console.log("online as", address.toString());
});
```
### Event `offline`
Emitted when the connection is closed an no further attempt to reconnect will happen, after calling [xmpp.stop()](#xmpp.stop).
```js
xmpp.on("offline", () => {
console.log("offline");
});
```
### start
Starts the connection. Attempts to reconnect will automatically happen if it cannot connect or gets disconnected.
```js
xmpp.start().catch(console.error);
xmpp.on("online", (address) => {
console.log("online", address.toString());
});
```
Returns a promise that resolves if the first attempt succeed or rejects if the first attempt fails.
### stop
Stops the connection and prevent any further auto reconnect/retry.
```js
xmpp.stop().catch(console.error);
xmpp.on("offline", () => {
console.log("offline");
});
```
Returns a promise that resolves once the stream closes and the socket disconnects.
### send
Sends a stanza.
```js
xmpp.send(xml("presence")).catch(console.error);
```
Returns a promise that resolves once the stanza is serialized and written to the socket or rejects if any of those fails.
### sendMany
Sends multiple stanzas.
Here is an example sending the same text message to multiple recipients.
```js
const message = "Hello";
const recipients = ["romeo@example.com", "juliet@example.com"];
const stanzas = recipients.map((address) =>
xml("message", { to: address, type: "chat" }, xml("body", null, message)),
);
xmpp.sendMany(stanzas).catch(console.error);
```
Returns a promise that resolves once all the stanzas have been sent.
If you need to send a stanza to multiple recipients we recommend using [Extended Stanza Addressing](https://xmpp.org/extensions/xep-0033.html) instead.
### xmpp.reconnect
See [@xmpp/reconnect](/packages/reconnect).
## Transports
XMPP supports multiple transports, this table list `@xmpp/client` supported and unsupported transport for each environment.
| transport | protocols | Node.js | Browser | React Native |
| :------------------------------: | :--------: | :-----: | :-----: | :----------: |
| [WebSocket](/packages/websocket) | `ws(s)://` | ✔ | ✔ | ✔ |
| [TCP](/packages/tcp) | `xmpp://` | ✔ | ✗ | ✗ |
| [TLS](/packages/tls) | `xmpps://` | ✔ | ✗ | ✗ |
## Authentication
Multiple authentication mechanisms are supported.
PLAIN should only be used over secure WebSocket (`wss://)`, direct TLS (`xmpps:`) or a TCP (`xmpp:`) connection upgraded to TLS via [STARTTLS](/packages/starttls)
| SASL | Node.js | Browser | React Native |
| :---------------------------------------: | :-----: | :-----: | :----------: |
| [ANONYMOUS](/packages/sasl-anonymous) | ✔ | ✔ | ✔ |
| [PLAIN](/packages/sasl-plain) | ✔ | ✔ | ✔ |
| [SCRAM-SHA-1](/packages/sasl-scram-sha-1) | ✔ | ☐ | ✗ |
- ☐ : Optional
- ✗ : Unavailable
- ✔ : Included
## Common issues
<details>
<summary><strong>Unable to resolve module</strong></summary>
<p>If you are using an older React Native version, please require/import <code>@xmpp/client/reat-native</code> instead of <code>@xmpp/client</code>.</p>
</details>