-
Notifications
You must be signed in to change notification settings - Fork 28
/
nodejs-fetch-and-websocket-options.ts
113 lines (101 loc) · 4.01 KB
/
nodejs-fetch-and-websocket-options.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import { createDfuseClient, InboundMessage, InboundMessageType, waitFor } from "@dfuse/client"
import { IncomingMessage } from "http"
/**
* In this example, we will showcase how to avoid polluting the global
* scope to configure the `fetch` and `WebSocket` values.
*
* Indeed, polluting the global scope is not a recommended practicte,
* especially when alternatives are present to handle those cases.
*
* We will configure the `DfuseClient` instance when creating it via
* the factory to pass the `fetch` and `WebSocket options directly.
*
* **Note** This example completely avoids importing `../config` to ensure
* we really do not pollute the global scope. Ensures you have the
* appropriate environment variables set.
*/
// We add the example imports here to make the example clearer, in your
// own code, group them with yours.
import nodeFetch from "node-fetch"
import WebSocketClient from "ws"
import { runMain } from "../../config"
async function main(): Promise<void> {
const client = createDfuseClient({
apiKey: process.env.DFUSE_API_KEY || "",
network: process.env.DFUSE_API_NETWORK || "mainnet.eos.dfuse.io",
httpClientOptions: {
fetch: nodeFetch,
},
graphqlStreamClientOptions: {
socketOptions: {
// The WebSocket factory used for GraphQL stream must use this special protocols set
// We intend on making the library handle this for you automatically in the future,
// for now, it's required otherwise, the GraphQL will not connect correctly.
webSocketFactory: (url) => webSocketFactory(url, ["graphql-ws"]),
},
},
streamClientOptions: {
socketOptions: {
webSocketFactory: (url) => webSocketFactory(url),
},
},
})
const onMessage = (message: InboundMessage): void => {
if (message.type === InboundMessageType.LISTENING) {
console.log("Stream is now listening.")
}
}
const stream = await client.streamActionTraces(
{
accounts: "eosio.token",
action_names: "issue",
},
onMessage
)
console.log("Socket is now connected.")
await waitFor(35000)
await stream.close()
client.release()
}
/**
* The factory receives the full resolved URL, API token included,
* of the remote endpoint to connect to.
*
* When using the Node.js enviroment in your own
* factory, it is here that you can customize the WebSocket client instance.
* In the factory below, we jump the `maxPayload` size to 200M,
* which can be useful when streaming really big tables like the
* `voters` table on EOS.
*
* We also add error logging for errors occurring at the HTTP Upgrade
* level before turning the connection into a WebSocket connection. This
* can happen when authorization happens with your API token.
*
* **Note** Don't try to override the `onOpen`, `onClose`, `onError`
* and `onMessage` handler, they are overwritten by the `Socket` instance
* for its own usage.
*
* **Important Web Browser Usage Notice**
* We are in a Node.js context here, the `WebSocketClient` is a
* Node.js implementation of WebSocket Protocol. It does not have
* quite the same API interface. The configuration done below
* will not work in a Browser environment! Check W3C Browser
* WebSocket API to see what is accepted as it's second argument.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket#Parameters
*/
async function webSocketFactory(url: string, protocols: string[] = []): Promise<WebSocketClient> {
const webSocket = new WebSocketClient(url, protocols, {
handshakeTimeout: 30 * 1000, // 30s
maxPayload: 10 * 1024 * 1024, // 10 MiB (max accepted value from the server)
})
const onUpgrade = (response: IncomingMessage): void => {
console.log("Socket upgrade response status code.", response.statusCode)
// You need to remove the listener at some point since this factory
// is called at each reconnection with the remote endpoint!
webSocket.removeListener("upgrade", onUpgrade)
}
webSocket.on("upgrade", onUpgrade)
return webSocket
}
runMain(main)