next-ws 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +160 -0
  2. package/package.json +67 -0
package/README.md ADDED
@@ -0,0 +1,160 @@
1
+ <center>
2
+ <h1><strong>Next WS</strong></h1>
3
+ <i>Add support for WebSockets in Next.js 13 app directory</i><br>
4
+ <code>npm install next-ws</code>
5
+ </center>
6
+
7
+ <center>
8
+ <img alt="package version" src="https://img.shields.io/npm/v/next-ws?label=version">
9
+ <img alt="total downloads" src="https://img.shields.io/npm/dt/next-ws">
10
+ <br>
11
+ <a href="https://github.com/apteryxxyz/next-ws"><img alt="next-ws repo stars" src="https://img.shields.io/github/stars/apteryxxyz/next-ws?style=social"></a>
12
+ <a href="https://github.com/apteryxxyz"><img alt="apteryxxyz followers" src="https://img.shields.io/github/followers/apteryxxyz?style=social"></a>
13
+ <a href="https://discord.gg/vZQbMhwsKY"><img src="https://discordapp.com/api/guilds/829836158007115806/widget.png?style=shield" alt="Discord Banner 2"/></a>
14
+ </center>
15
+
16
+ ## 🤔 About
17
+
18
+ Next WS (`next-ws`) is an advanced Next.js **13** plugin designed to seamlessly integrate WebSocket server functionality into API routes within the **app directory**. With Next WS, you no longer require a separate server for WebSocket functionality.
19
+
20
+ It's important to note that this module can only be used when working with a server. Unfortunately, in serverless environments like Vercel, WebSocket servers cannot be used. Additionally, this module was built for the app directory and is incompatible with the older pages directory.
21
+
22
+ This module is inspired by the now outdated `next-plugin-websocket`, if you are using an older version of Next.js, that module may work for you.
23
+
24
+ ## 🏓 Table of Contents
25
+
26
+ - [🤔 About](#-about)
27
+ - [🏓 Table of Contents](#-table-of-contents)
28
+ - [📦 Installation](#-installation)
29
+ - [🚀 Usage](#-api)
30
+ - [🌀 Example](#-example)
31
+ - [📁 Server](#-server)
32
+ - [📁 Client](#-client)
33
+
34
+ ---
35
+
36
+ ## 📦 Installation
37
+
38
+ ```sh
39
+ npm install next-ws
40
+ yarn add next-ws
41
+ pnpm add next-ws
42
+ ```
43
+
44
+ Upon installation, Next WS will automatically patch your existing Next.js installation to add support for WebSockets in API routes in the app directory.
45
+
46
+ <details>
47
+ <summary><strong>Caveats</strong></summary>
48
+
49
+ As this module modifies the Next.js installation, if for any reason it changes (such as when you update Next.js), you will need to reinstall Next WS. And if you want to uninstall Next WS, you will need to reinstall Next.js.
50
+ </details>
51
+
52
+ ---
53
+
54
+ ## 🚀 Usage
55
+
56
+ Using Next WS is a breeze, requiring zero configuration. Simply export a `SOCKET` function from an API route. This function gets called whenever a client connects to the WebSocket server at the respective API path.
57
+
58
+ The `SOCKET` function receives two arguments: the WebSocket client and the HTTP request, which you can use to get the URL path, query parameters, and headers.
59
+
60
+ ```ts
61
+ export function SOCKET(
62
+ client: import('ws').WebSocket,
63
+ request: import('http').IncomingMessage,
64
+ ) {
65
+ // ...
66
+ }
67
+ ```
68
+
69
+ With this straightforward setup, you can fully leverage the capabilities of Next WS and efficiently handle WebSocket connections within your Next.js application.
70
+
71
+ ---
72
+
73
+ ## 🌀 Example
74
+
75
+ ### 📁 Server
76
+
77
+ Create an API route anywhere within the app directory, and export a `SOCKET` function from it, below is an example of a simple echo server, which sends back any message it receives.
78
+
79
+ ```ts
80
+ // app/api/ws/route.ts (can be any route file in the app directory)
81
+ export function SOCKET(
82
+ client: import('ws').WebSocket,
83
+ request: import('http').IncomingMessage,
84
+ ) {
85
+ console.log('A client connected!');
86
+
87
+ client.on('message', message => {
88
+ client.send(message);
89
+ });
90
+
91
+ client.on('close', () => {
92
+ console.log('A client disconnected!');
93
+ });
94
+ }
95
+ ```
96
+
97
+ You are pretty much done at this point, you can now connect to the WebSocket server using the native WebSocket API in the browser.
98
+
99
+ ---
100
+
101
+ ### 📁 Client
102
+
103
+ To make it easier to connect to your new WebSocker server, Next WS also provides some client-side utilities. These are not required, you can use the native WebSocket API if you prefer.
104
+
105
+ ```tsx
106
+ // layout.tsx
107
+ 'use client';
108
+
109
+ import { WebSocketProvider } from 'next-ws/client';
110
+
111
+ export default function Layout() {
112
+ return <WebSocketProvider url="ws://localhost:3000/api/ws">
113
+ {...}
114
+ </WebSocketProvider>;
115
+ }
116
+ ```
117
+
118
+ ```tsx
119
+ // page.tsx
120
+ 'use client';
121
+
122
+ import { useWebSocket } from 'next-ws/client';
123
+ import { useCallback, useEffect, useState } from 'react';
124
+
125
+ export default function Page() {
126
+ const ws = useWebSocket();
127
+ // ^? WebSocket on the client, null on the server
128
+
129
+ const [value, setValue] = useState('');
130
+ const [message, setMessage] = useState<string | null>('');
131
+
132
+ const onMessage = useCallback((event: MessageEvent) => {
133
+ const text = await event.data.text();
134
+ setMessage(text);
135
+ }, []);
136
+
137
+ useEffect(() => {
138
+ ws?.addEventListener('message', onMessage);
139
+ return () => ws?.removeEventListener('message', onMessage);
140
+ }, []);
141
+
142
+ return <>
143
+ <input
144
+ type="text"
145
+ value={value}
146
+ onChange={event => setValue(event.target.value)}
147
+ />
148
+
149
+ <button onClick={() => ws.send(value)}>
150
+ Send message to server
151
+ </button>
152
+
153
+ <p>
154
+ {message === null
155
+ ? 'Waiting for server to send a message...'
156
+ : `Got message: ${message}`}
157
+ </p>
158
+ </>
159
+ }
160
+ ```
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "next-ws",
3
+ "private": false,
4
+ "version": "0.1.0",
5
+ "description": "Add support for WebSockets in Next.js 13 app directory",
6
+ "packageManager": "yarn@3.6.0",
7
+ "license": "MIT",
8
+ "keywords": ["next", "websocket", "ws", "server", "client"],
9
+ "homepage": "https://github.com/apteryxxyz/next-ws#readme",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/apteryxxyz/next-ws.git"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/apteryxxyz/next-ws/issues"
16
+ },
17
+ "files": ["{client,server,patch}.{js,d.ts}"],
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "clean": "rimraf ./*.{js,d.ts,js.map}",
21
+ "lint": "eslint --ext .ts,.tsx src",
22
+ "format": "prettier --write src/**/*.{ts,tsx} && eslint --fix --ext .ts,.tsx src/",
23
+ "postinstall": "node patch.js"
24
+ },
25
+ "dependencies": {
26
+ "@babel/generator": "^7.22.3",
27
+ "@babel/parser": "^7.22.4",
28
+ "@babel/template": "^7.21.9"
29
+ },
30
+ "peerDependencies": {
31
+ "next": "*",
32
+ "react": "*",
33
+ "ws": "*"
34
+ },
35
+ "devDependencies": {
36
+ "@babel/types": "^7.22.4",
37
+ "@rushstack/eslint-patch": "^1.3.0",
38
+ "@types/babel__generator": "^7",
39
+ "@types/babel__template": "^7",
40
+ "@types/eslint": "^8",
41
+ "@types/node": "^20.2.5",
42
+ "@types/prettier": "^2",
43
+ "@types/react": "^18",
44
+ "@types/ws": "^8",
45
+ "@typescript-eslint/eslint-plugin": "^5.59.8",
46
+ "@typescript-eslint/parser": "^5.59.8",
47
+ "eslint": "^8.41.0",
48
+ "eslint-config-apteryx": "^2.1.6",
49
+ "eslint-config-prettier": "^8.8.0",
50
+ "eslint-plugin-import": "^2.27.5",
51
+ "eslint-plugin-jsdoc": "^46.1.0",
52
+ "eslint-plugin-n": "^16.0.0",
53
+ "eslint-plugin-prettier": "^4.2.1",
54
+ "eslint-plugin-promise": "^6.1.1",
55
+ "eslint-plugin-sonarjs": "^0.19.0",
56
+ "eslint-plugin-unicorn": "^47.0.0",
57
+ "next": "^13.4.4",
58
+ "prettier": "^2.8.8",
59
+ "prettier-config-apteryx": "^2.1.0",
60
+ "react": "^18.2.0",
61
+ "rimraf": "^5.0.1",
62
+ "ts-config-apteryx": "^2.1.0",
63
+ "typescript": "<5.1.0",
64
+ "ws": "^8.13.0"
65
+ },
66
+ "prettier": "prettier-config-apteryx"
67
+ }