UNPKG

@homebridge-plugins/homebridge-cloudflared-tunnel

Version:

The Cloudflared Tunnel plugin allows you to run a Cloudflare-Tunnel for exposing your homebridge instance for remote access.

123 lines 3.82 kB
/* Copyright(C) 2023-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved. * * cloudflared-tunnel.ts: @homebridge-plugins/homebridge-cloudflared-tunnel. */ import * as childProcess from 'node:child_process'; import * as process from 'node:process'; import { sync as commandExistsSync } from 'command-exists'; class CloudflaredTunnel { cloudflaredPath; _token; url; hostname; running; childProcess; change; error; constructor(cloudflaredPath = 'cloudflared') { this.cloudflaredPath = cloudflaredPath; this.url = 'http://localhost:80'; this.hostname = ''; this.running = false; this.childProcess = null; } get token() { return this._token; } set token(token) { if (token && typeof token === 'string') { token = token.trim(); // try to strip out "cloudflared.exe service install" const array = token.split(' '); if (array.length > 1) { for (let i = 0; i < array.length - 1; i++) { if (array[i] === 'install') { token = array[i + 1]; } } } } this._token = token; } checkInstalled() { return commandExistsSync(this.cloudflaredPath); } emitChange(msg, code) { if (this.change) { this.change(this.running, msg, code); } } emitError(msg) { if (this.error) { this.error(msg); } } start() { if (this.childProcess) { this.emitError('Already started'); return; } if (!this.checkInstalled()) { this.emitError(`Cloudflared error: ${this.cloudflaredPath} is not found`); return; } if (!this.token) { this.emitError('Cloudflared error: Token is not set'); return; } const args = [ 'tunnel', '--no-autoupdate', ]; if (this.hostname) { args.push('--hostname'); args.push(this.hostname); } if (this.url) { args.push('--url'); args.push(this.url); } args.push('run'); args.push('--token'); args.push(this.token); this.running = true; this.emitChange('Starting cloudflared'); this.childProcess = childProcess.spawn(this.cloudflaredPath, args); if (this.childProcess && this.childProcess.stdout) { this.childProcess.stdout.pipe(process.stdout); } if (this.childProcess && this.childProcess.stderr) { this.childProcess.stderr.pipe(process.stderr); } this.childProcess.on('close', (code) => { this.running = false; this.childProcess = null; this.emitChange('Stopped cloudflared', code ?? undefined); }); this.childProcess.on('error', (err) => { if (err.code === 'ENOENT') { this.emitError(`Cloudflared error: ${this.cloudflaredPath} is not found`); } else { this.emitError(err.message); } }); if (this.childProcess && this.childProcess.stderr) { this.childProcess.stderr.on('data', (data) => { this.emitError(data.toString()); }); } } stop() { this.emitChange('Stopping cloudflared'); if (this.childProcess) { this.childProcess.kill('SIGINT'); this.childProcess = null; } } setChildProcess(childProcess) { this.childProcess = childProcess; } } export { CloudflaredTunnel }; //# sourceMappingURL=cloudflared-tunnel.js.map