phone_preview 0.1.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dc78569a84670e434020eb9ce555cd7e21c00228025ceb52e18d9420adc8f8c2
4
- data.tar.gz: e8e46b0e1f29452f1e90a012f4089cfeb190f7ae64fd5d11af0d1ac4dc6220cb
3
+ metadata.gz: 2dbc9e0b2f71df5089e74928aae948c2dee2586f548a7f1e264999a13f2ced8c
4
+ data.tar.gz: ca7b5f90b0083f533290e4662f8d0a409eefaf7731e00e3752adac06f18f5c47
5
5
  SHA512:
6
- metadata.gz: 2768cd8b0e3058463d1839358c3d0693ac95cbe87aba06126de22176f0c67ea2c0e62dc971e332ba38ca8995b6270d2c6e668c3207a502010d81a3e50e484ca3
7
- data.tar.gz: 97b463e508fc83fa547a938a5a3336ee2c416f1d0e9974213446cc3ec355bc2d6ea866cb890f852fe920f06270c9d6368d542c4afa851728829de2fb43a332d8
6
+ metadata.gz: d64daa6df8cb0a84f3fad478184328478d5284805ccf5bc345a05bdb0bcfb4e0f4717874b87e014e79dc0b74b6960ed219cdeca6112dda2ecb2c5df3bca036de
7
+ data.tar.gz: 8ffd3f6a9a6c9e705a8db739a280b0438ca81105580ac44fc21fa8f7539b7aeb325ad868096e3b59cb3652a8a6842c7c1d7709ba3a9e50252813b4dccb5cc235
data/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.2.0] - 2026-10-22
6
+
7
+ ### Added
8
+
9
+ - `phone_preview` says ngrok is not installed, or not signed in to an account, and starts nothing.
10
+ - `phone_preview` names a port already in use, or an address already held by another running tunnel, and starts nothing.
11
+ - When the tunnel stops while the app runs, the terminal says the phone can no longer reach the app.
12
+
13
+ ## [0.1.0] - 2026-10-22
14
+
5
15
  ### Added
6
16
 
7
17
  - `phone_preview` starts the app's server and an ngrok tunnel on one port, and prints the public address and a QR code of it.
data/README.md CHANGED
@@ -41,6 +41,12 @@ Open the printed address on the phone, or scan the QR code.
41
41
 
42
42
  With no `PORT` set, the server starts on port 3000.
43
43
 
44
+ Before starting anything, `phone_preview` stops with a message when ngrok is not
45
+ installed, when ngrok is not signed in to an account, when the port is already
46
+ in use, or when another running tunnel already holds the public address. If the
47
+ tunnel stops while the app runs, the terminal says the phone can no longer
48
+ reach the app.
49
+
44
50
  When `PUBLIC_BASE_URL` is set in development, emailed links use it over https
45
51
  with no port. With it unset, or outside development, emailed links keep the
46
52
  app's own `action_mailer.default_url_options`.
data/exe/phone_preview CHANGED
@@ -1,9 +1,54 @@
1
1
  #!/usr/bin/env ruby
2
2
  require "rqrcode"
3
+ require "yaml"
4
+ require "socket"
5
+ require "net/http"
6
+
7
+ def stop(message)
8
+ warn "phone_preview: #{message}"
9
+ exit 1
10
+ end
11
+
12
+ def installed?(command)
13
+ ENV.fetch("PATH", "").split(File::PATH_SEPARATOR).any? { |dir| File.executable?(File.join(dir, command)) }
14
+ end
15
+
16
+ stop "ngrok is not installed. Install it with `brew install ngrok`." unless installed?("ngrok")
17
+
18
+ def signed_in?
19
+ return true if ENV["NGROK_AUTHTOKEN"].to_s != ""
20
+
21
+ config = IO.popen(%w[ngrok config check], err: File::NULL, &:read)[/Valid configuration file at (.+)$/, 1]
22
+ config && File.exist?(config) && YAML.safe_load_file(config).to_h.then { |settings| settings.dig("agent", "authtoken") || settings["authtoken"] }.to_s != ""
23
+ end
24
+
25
+ stop "ngrok is not signed in to an account. Sign in with `ngrok config add-authtoken <token>`." unless signed_in?
3
26
 
4
27
  address = ENV.fetch("PUBLIC_BASE_URL")
5
28
  ENV["PORT"] ||= "3000"
6
29
 
30
+ def port_in_use?(port)
31
+ %w[127.0.0.1 ::1].any? do |host|
32
+ TCPServer.new(host, port.to_i).close
33
+ false
34
+ rescue Errno::EADDRINUSE
35
+ true
36
+ rescue SystemCallError, SocketError
37
+ false
38
+ end
39
+ end
40
+
41
+ stop "port #{ENV["PORT"]} is already in use. Stop what is using it, or start with another PORT." if port_in_use?(ENV["PORT"])
42
+
43
+ def held_by_another_tunnel?(address)
44
+ response = Net::HTTP.get_response(URI(address))
45
+ !response.body.to_s.include?("ERR_NGROK_3200")
46
+ rescue SystemCallError, SocketError, IOError, Timeout::Error
47
+ false
48
+ end
49
+
50
+ stop "#{address} is already held by another running tunnel. Stop that tunnel first." if held_by_another_tunnel?(address)
51
+
7
52
  puts RQRCode::QRCode.new(address).as_ansi
8
53
  puts "Open #{address} on your phone"
9
54
 
@@ -1,2 +1,2 @@
1
1
  web: bin/rails server -p $PORT
2
- tunnel: ngrok http --url=$PUBLIC_BASE_URL $PORT --log=stdout
2
+ tunnel: ngrok http --url=$PUBLIC_BASE_URL $PORT --log=stdout; echo "The tunnel stopped, so the phone can no longer reach the app."
@@ -1,3 +1,3 @@
1
1
  module PhonePreview
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phone_preview
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tyler Schneider