#Fastify
## [[Fastify]]で[[WebSocket]]を使う
[[fastify-websocket]]を使う。
## プロジェクトベースの作成
```console:powershell
npx degit tadashi-aikawa/typescript-vscode-base fastify-websocket-use
cd fastify-websocket-use
init.ps1
```
## [[Fastify]]と[[fastify-websocket]]インストール
```console:powershell
npm i fastify fastify-websocket
```
## ソースコードを書く
[[FastifyでTypeScript]]のコードを書く。まずは[[fastify-websocket]]なしで。
```ts:index.ts
import fastify from 'fastify'
const server = fastify()
server.get('/ping', async (request, reply) => {
return 'pong\n'
})
server.listen(8080, (err, address) => {
if (err) {
console.error(err)
process.exit(1)
}
console.log(`Server listening at ${address}`)
})
```
疎通確認。
```console
$ curl localhost:8080/ping
pong
```
## [[fastify-websocket]]を使う
```ts:index.ts
import fastify, { FastifyRequest } from "fastify";
import { SocketStream } from "fastify-websocket";
const server = fastify();
server.register(require("fastify-websocket"));
server.get("/ping", async (request, reply) => {
return "pong\n";
});
server.get(
"/subscribe",
{ websocket: true },
(connection: SocketStream, req: FastifyRequest) => {
connection.socket.on("message", (message: string) => {
connection.socket.send(`I got your message: ${message}`);
});
}
);
server.listen(8080, (err, address) => {
if (err) {
console.error(err);
process.exit(1);
}
console.log(`Server listening at ${address}`);
});
```
`ws:locahost:8080/subscribe`に接続してメッセージを送ると反応がある。
## サーバーからクライアントにメッセージを送る
5秒おきに現在時刻のタイムスタンプを返却するAPIを作る。
```ts:index.ts
import fastify, { FastifyRequest } from "fastify";
import { SocketStream } from "fastify-websocket";
const server = fastify();
server.register(require("fastify-websocket"));
server.get("/ping", async (request, reply) => {
return "pong\n";
});
server.get(
"/timer",
{ websocket: true },
(connection: SocketStream, req: FastifyRequest) => {
setInterval(() => {
connection.socket.send(Date.now());
}, 5000);
connection.socket.on("message", (message: string) => {
connection.socket.send(`I am alive.`);
});
}
);
server.listen(8080, (err, address) => {
if (err) {
console.error(err);
process.exit(1);
}
console.log(`Server listening at ${address}`);
});
```
`ws:locahost:8080/timer`に接続すると5分おきにメッセージを受信する。
## ファイルの変更があったら知らせる
サーバーでファイルが変更されたらクライアントに通知するAPIをつくる。
```console:chokidarのインストール
npm i chokidar
```
```ts:index.ts
import chokidar from "chokidar";
import fastify from "fastify";
import { SocketStream } from "fastify-websocket";
const server = fastify();
server.register(require("fastify-websocket"));
server.get("/ping", async (request, reply) => {
return "pong\n";
});
server.get<{
Querystring: { path: string };
}>("/watch", { websocket: true }, (connection: SocketStream, req) => {
const watcher = chokidar.watch(req.query.path, {
ignoreInitial: true,
ignored: "node_modules/*",
});
watcher
.on("add", (path) => {
connection.socket.send(`Added ${path}`);
})
.on("change", (path) => {
connection.socket.send(`Updated ${path}`);
})
.on("unlink", (path) => {
connection.socket.send(`Deleted ${path}`);
});
connection.socket.on("message", (message: string) => {
connection.socket.send(`I am alive.`);
});
connection.socket.on("close", () => {
console.log("disconnect watcher");
watcher.close();
});
});
server.listen(8080, (err, address) => {
if (err) {
console.error(err);
process.exit(1);
}
console.log(`Server listening at ${address}`);
});
```
`ws://localhost:8080/watch?path=*`ですべてのエントリを監視。`path`に指定することで細かく監視対象を制御できる。