bin/peerjs.ts
#!/usr/bin/env node
import path from "node:path";
import fs from "node:fs";
const optimistUsageLength = 98;
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import { PeerServer } from "../src/index.ts";
import type { AddressInfo } from "node:net";
import type { CorsOptions } from "cors";
const y = yargs(hideBin(process.argv));
const portEnvIsSet = !!process.env["PORT"];
const opts = y
.usage("Usage: $0")
.wrap(Math.min(optimistUsageLength, y.terminalWidth()))
.options({
expire_timeout: {
demandOption: false,
alias: "t",
describe: "timeout (milliseconds)",
default: 5000,
},
concurrent_limit: {
demandOption: false,
alias: "c",
describe: "concurrent limit",
default: 5000,
},
alive_timeout: {
demandOption: false,
describe: "broken connection check timeout (milliseconds)",
default: 60000,
},
key: {
demandOption: false,
alias: "k",
describe: "connection key",
default: "peerjs",
},
sslkey: {
type: "string",
demandOption: false,
describe: "path to SSL key",
},
sslcert: {
type: "string",
demandOption: false,
describe: "path to SSL certificate",
},
host: {
type: "string",
demandOption: false,
alias: "H",
describe: "host",
},
port: {
type: "number",
demandOption: !portEnvIsSet,
alias: "p",
describe: "port",
},
path: {
type: "string",
demandOption: false,
describe: "custom path",
default: process.env["PEERSERVER_PATH"] ?? "/",
},
allow_discovery: {
type: "boolean",
demandOption: false,
describe: "allow discovery of peers",
},
proxied: {
type: "boolean",
demandOption: false,
describe: "Set true if PeerServer stays behind a reverse proxy",
default: false,
},
cors: {
type: "string",
array: true,
describe: "Set the list of CORS origins",
},
})
.boolean("allow_discovery")
.parseSync();
if (!opts.port) {
// .port is only not set if the PORT env var is set
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
opts.port = parseInt(process.env["PORT"]!);
}
if (opts.cors) {
opts["corsOptions"] = {
origin: opts.cors,
} satisfies CorsOptions;
}
process.on("uncaughtException", function (e) {
console.error("Error: " + e.toString());
});
if (opts.sslkey ?? opts.sslcert) {
if (opts.sslkey && opts.sslcert) {
opts["ssl"] = {
key: fs.readFileSync(path.resolve(opts.sslkey)),
cert: fs.readFileSync(path.resolve(opts.sslcert)),
};
} else {
console.error(
"Warning: PeerServer will not run because either " +
"the key or the certificate has not been provided.",
);
process.exit(1);
}
}
const userPath = opts.path;
const server = PeerServer(opts, (server) => {
const { address: host, port } = server.address() as AddressInfo;
console.log(
"Started PeerServer on %s, port: %s, path: %s",
host,
port,
userPath || "/",
);
const shutdownApp = () => {
server.close(() => {
console.log("Http server closed.");
process.exit(0);
});
};
process.on("SIGINT", shutdownApp);
process.on("SIGTERM", shutdownApp);
});
server.on("connection", (client) => {
console.log(`Client connected: ${client.getId()}`);
});
server.on("disconnect", (client) => {
console.log(`Client disconnected: ${client.getId()}`);
});