Class: Portless::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/portless/runner.rb

Overview

rb-portless run <cmd>: pick a free backend port, inject PORT/HOST, ensure the proxy is up, register the named route, run the child in its own process group (forwarding signals), and deregister on exit. Rails/puma respect PORT natively. Mirrors portless's runApp/spawnCommand.

Instance Method Summary collapse

Constructor Details

#initialize(command:, config: Config.load, route_store: RouteStore.new, options: {}) ⇒ Runner

Returns a new instance of Runner.



9
10
11
12
13
14
# File 'lib/portless/runner.rb', line 9

def initialize(command:, config: Config.load, route_store: RouteStore.new, options: {})
  @command = Array(command)
  @config = config
  @route_store = route_store
  @options = options # :lan, :ip, :ngrok, :tailscale, :funnel
end

Instance Method Details

#runObject



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/portless/runner.rb', line 16

def run
  command = resolved_command
  raise Error, "nothing to run — pass a command, e.g. rb-portless run bin/dev" if command.empty?

  port = @config.app_port&.to_i || FreePort.find
  command = Frameworks.inject(command, port) # --port/--host for vite/astro/etc.
  hostname = @config.hostname

  ensure_trusted if @config.tls
  proxy_port = Daemon.ensure_running(tls: @config.tls)
  @route_store.add(hostname: hostname, port: port, pid: Process.pid, force: true)

  url = display_url(hostname, proxy_port)
  rows = [ [ "Local", url, :cyan ] ]
  rows.concat(lan_rows(port, proxy_port))
  rows.concat(share_rows(hostname, port))
  Banner.app(rows: rows, backend_port: port)

  status = supervise(command, port, url)
  exit(status)
ensure
  teardown
  @route_store.remove(hostname, owner_pid: Process.pid) if hostname
end