rb-portless 0.3.0 → 0.3.1.dev.20260630.bb085fc
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 +4 -4
- data/CHANGELOG.md +12 -0
- data/lib/portless/cli.rb +0 -5
- data/lib/portless/config.rb +1 -4
- data/lib/portless/hosts.rb +0 -5
- data/lib/portless/multi.rb +3 -23
- data/lib/portless/run_support.rb +44 -0
- data/lib/portless/runner.rb +3 -36
- data/lib/portless/state.rb +0 -1
- data/lib/portless/version.rb +1 -1
- data/lib/rb-portless.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b934378f7d59599eebee06f392753bc4d33e5dea46132ca43ff4a13c9c587367
|
|
4
|
+
data.tar.gz: 4756b624abf40832afbd71ed570548e12228a26df9740e821fc901eba5fe74ff
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 223dc8fc2262c78440ddb19a1ebfbf31ed05092dab9180bd7b54808d0976ab885d4d3e25f3c8890a90f8eb8fda6f733c5111283575223bb0581e146439d724b0
|
|
7
|
+
data.tar.gz: b8e2c24702cb74ea1de7b60d8db33ac1c8a504928c04bc53d516370c980733525610b0bf44d924cebfe3c6700df95eb128ef04dbeba9b67b51bdb522a189035c
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ All notable changes to this project are documented here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/), and the project adheres to
|
|
5
5
|
[Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [0.3.1]
|
|
8
|
+
|
|
9
|
+
### Changed (internal — no behaviour change)
|
|
10
|
+
|
|
11
|
+
- **Deduped the two run paths.** `Runner` and `Multi` shared three methods
|
|
12
|
+
(`child_env`, `display_url`, `ensure_trusted`); they now live in a `RunSupport`
|
|
13
|
+
mixin. Multi-app mode picks up the actionable first-run CA-trust hints the
|
|
14
|
+
single-app path already had.
|
|
15
|
+
- **Dropped dead code** — `CLI#todo`, the unread `Config#script`/`DEFAULT_SCRIPT`,
|
|
16
|
+
`State.ca_serial` (no on-disk serial; the native CA sets it on the cert), and
|
|
17
|
+
`Hosts.managed_hostnames` (no caller).
|
|
18
|
+
|
|
7
19
|
## [0.3.0]
|
|
8
20
|
|
|
9
21
|
### Fixed / hardened
|
data/lib/portless/cli.rb
CHANGED
|
@@ -205,11 +205,6 @@ module Portless
|
|
|
205
205
|
i ? Integer(args[i + 1], exception: false) : nil
|
|
206
206
|
end
|
|
207
207
|
|
|
208
|
-
def todo(name, desc, _args = nil)
|
|
209
|
-
warn "rb-portless #{name}: #{desc} — not yet implemented (#{Portless::VERSION})"
|
|
210
|
-
exit 1
|
|
211
|
-
end
|
|
212
|
-
|
|
213
208
|
def rest(command)
|
|
214
209
|
@argv.first == command ? @argv[1..] : @argv
|
|
215
210
|
end
|
data/lib/portless/config.rb
CHANGED
|
@@ -7,9 +7,7 @@ module Portless
|
|
|
7
7
|
# defaults. Mirrors portless's config.ts/auto.ts: name is inferred from the
|
|
8
8
|
# config, the git root, or the directory; tld defaults to "localhost".
|
|
9
9
|
class Config
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
attr_reader :name, :tld, :script, :app_port, :tls, :apps
|
|
10
|
+
attr_reader :name, :tld, :app_port, :tls, :apps
|
|
13
11
|
|
|
14
12
|
def self.load(dir = Dir.pwd)
|
|
15
13
|
new(read_file(dir), dir)
|
|
@@ -19,7 +17,6 @@ module Portless
|
|
|
19
17
|
@dir = dir
|
|
20
18
|
@name = sanitize_label(data["name"] || infer_name(dir))
|
|
21
19
|
@tld = (data["tld"] || Constants::DEFAULT_TLD).to_s
|
|
22
|
-
@script = data["script"] || DEFAULT_SCRIPT
|
|
23
20
|
@app_port = data["appPort"] || data["app_port"]
|
|
24
21
|
@tls = data.fetch("tls", true)
|
|
25
22
|
# Monorepo: { "apps": { "web": "bin/rails server", "api": "node api.js" } }.
|
data/lib/portless/hosts.rb
CHANGED
|
@@ -24,11 +24,6 @@ module Portless
|
|
|
24
24
|
write(strip_block(read))
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
def managed_hostnames
|
|
28
|
-
read[/#{Regexp.escape(Constants::HOSTS_BEGIN)}\n(.*?)#{Regexp.escape(Constants::HOSTS_END)}/m, 1]
|
|
29
|
-
.to_s.scan(/^\s*127\.0\.0\.1\s+(\S+)/).flatten
|
|
30
|
-
end
|
|
31
|
-
|
|
32
27
|
def build_block(hostnames)
|
|
33
28
|
return "" if hostnames.empty?
|
|
34
29
|
lines = hostnames.uniq.map { |h| "127.0.0.1\t#{h}" }
|
data/lib/portless/multi.rb
CHANGED
|
@@ -7,6 +7,8 @@ module Portless
|
|
|
7
7
|
# supervised + torn down together. Ruby sets env per-spawn, so there's no
|
|
8
8
|
# NODE_OPTIONS loader hack (cf. portless's turbo.ts).
|
|
9
9
|
class Multi
|
|
10
|
+
include RunSupport
|
|
11
|
+
|
|
10
12
|
App = Struct.new(:name, :hostname, :port, :url, :pid, keyword_init: true)
|
|
11
13
|
|
|
12
14
|
def initialize(config: Config.load, route_store: RouteStore.new)
|
|
@@ -18,7 +20,7 @@ module Portless
|
|
|
18
20
|
def run
|
|
19
21
|
raise Error, "no apps defined — add an \"apps\" map to portless.json" if @config.apps.empty?
|
|
20
22
|
|
|
21
|
-
ensure_trusted
|
|
23
|
+
ensure_trusted
|
|
22
24
|
proxy_port = Daemon.ensure_running(tls: @config.tls)
|
|
23
25
|
@apps = @config.apps.map { |name, command| start_app(name, command, proxy_port) }
|
|
24
26
|
|
|
@@ -57,27 +59,5 @@ module Portless
|
|
|
57
59
|
@apps.each { |app| @route_store.remove(app.hostname, owner_pid: Process.pid) }
|
|
58
60
|
kill_all("TERM")
|
|
59
61
|
end
|
|
60
|
-
|
|
61
|
-
def child_env(port, url)
|
|
62
|
-
{
|
|
63
|
-
"PORT" => port.to_s,
|
|
64
|
-
"HOST" => "127.0.0.1",
|
|
65
|
-
"PORTLESS_URL" => url,
|
|
66
|
-
"SSL_CERT_FILE" => (File.exist?(State.ca_cert) ? State.ca_cert : nil)
|
|
67
|
-
}.compact
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def display_url(hostname, proxy_port)
|
|
71
|
-
scheme = @config.tls ? "https" : "http"
|
|
72
|
-
default = @config.tls ? Constants::HTTPS_PORT : Constants::HTTP_PORT
|
|
73
|
-
suffix = proxy_port && proxy_port != default ? ":#{proxy_port}" : ""
|
|
74
|
-
"#{scheme}://#{hostname}#{suffix}"
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def ensure_trusted
|
|
78
|
-
Trust.install! if Privilege.interactive? && !Trust.trusted?
|
|
79
|
-
rescue Portless::Error
|
|
80
|
-
nil
|
|
81
|
-
end
|
|
82
62
|
end
|
|
83
63
|
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Portless
|
|
4
|
+
# Shared bits of the two run paths (single-app Runner + multi-app Multi):
|
|
5
|
+
# the child env, the display URL, and first-run CA trust. Both expect a
|
|
6
|
+
# `@config`.
|
|
7
|
+
module RunSupport
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def child_env(port, url)
|
|
11
|
+
{
|
|
12
|
+
"PORT" => port.to_s,
|
|
13
|
+
"HOST" => "127.0.0.1",
|
|
14
|
+
"PORTLESS_URL" => url,
|
|
15
|
+
# Let the app's own server-side TLS verification trust our CA.
|
|
16
|
+
"SSL_CERT_FILE" => (File.exist?(State.ca_cert) ? State.ca_cert : nil)
|
|
17
|
+
}.compact
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def display_url(hostname, proxy_port)
|
|
21
|
+
scheme = @config.tls ? "https" : "http"
|
|
22
|
+
default = @config.tls ? Constants::HTTPS_PORT : Constants::HTTP_PORT
|
|
23
|
+
suffix = proxy_port && proxy_port != default ? ":#{proxy_port}" : ""
|
|
24
|
+
"#{scheme}://#{hostname}#{suffix}"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Trust the local CA on first run (HTTPS only, interactive; never blocks the
|
|
28
|
+
# run), so HTTPS works without browser warnings — like portless.
|
|
29
|
+
def ensure_trusted
|
|
30
|
+
return unless @config.tls
|
|
31
|
+
return if Trust.trusted?
|
|
32
|
+
|
|
33
|
+
unless Privilege.interactive?
|
|
34
|
+
warn "rb-portless: CA not trusted — run `rb-portless trust` (HTTPS shows warnings until then)"
|
|
35
|
+
return
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
warn "rb-portless: trusting the local CA (first run)…"
|
|
39
|
+
Trust.install!
|
|
40
|
+
rescue Portless::Error => e
|
|
41
|
+
warn "rb-portless: couldn't auto-trust the CA (#{e.message}) — run `rb-portless trust`"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
data/lib/portless/runner.rb
CHANGED
|
@@ -6,6 +6,8 @@ module Portless
|
|
|
6
6
|
# group (forwarding signals), and deregister on exit. Rails/puma respect PORT
|
|
7
7
|
# natively. Mirrors portless's runApp/spawnCommand.
|
|
8
8
|
class Runner
|
|
9
|
+
include RunSupport
|
|
10
|
+
|
|
9
11
|
def initialize(command:, config: Config.load, route_store: RouteStore.new, options: {})
|
|
10
12
|
@command = Array(command)
|
|
11
13
|
@config = config
|
|
@@ -22,7 +24,7 @@ module Portless
|
|
|
22
24
|
hostname = @config.hostname
|
|
23
25
|
|
|
24
26
|
warn "rb-portless: #{@config.tld_warning}" if @config.tld_warning
|
|
25
|
-
ensure_trusted
|
|
27
|
+
ensure_trusted
|
|
26
28
|
proxy_port = Daemon.ensure_running(tls: @config.tls)
|
|
27
29
|
@route_store.add(hostname: hostname, port: port, pid: Process.pid, force: true)
|
|
28
30
|
|
|
@@ -41,13 +43,6 @@ module Portless
|
|
|
41
43
|
|
|
42
44
|
private
|
|
43
45
|
|
|
44
|
-
def display_url(hostname, proxy_port)
|
|
45
|
-
scheme = @config.tls ? "https" : "http"
|
|
46
|
-
default = @config.tls ? Constants::HTTPS_PORT : Constants::HTTP_PORT
|
|
47
|
-
suffix = proxy_port && proxy_port != default ? ":#{proxy_port}" : ""
|
|
48
|
-
"#{scheme}://#{hostname}#{suffix}"
|
|
49
|
-
end
|
|
50
|
-
|
|
51
46
|
# ── LAN mode (--lan) ──────────────────────────────────────────────────
|
|
52
47
|
# Register a `<name>.local` route, publish it over mDNS, and surface the URL
|
|
53
48
|
# so phones/tablets on the Wi-Fi can reach the app.
|
|
@@ -84,24 +79,6 @@ module Portless
|
|
|
84
79
|
Share::Tailscale.stop(@tailscale) if @tailscale
|
|
85
80
|
end
|
|
86
81
|
|
|
87
|
-
# Trust the local CA on first run (like portless), so HTTPS works without
|
|
88
|
-
# browser warnings out of the box. Interactive only — macOS prompts for
|
|
89
|
-
# keychain auth; in CI/no-TTY we skip with a hint rather than hang. Never
|
|
90
|
-
# blocks the run if trusting fails.
|
|
91
|
-
def ensure_trusted
|
|
92
|
-
return if Trust.trusted?
|
|
93
|
-
|
|
94
|
-
unless Privilege.interactive?
|
|
95
|
-
warn "rb-portless: CA not trusted — run `rb-portless trust` (HTTPS shows warnings until then)"
|
|
96
|
-
return
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
warn "rb-portless: trusting the local CA (first run)…"
|
|
100
|
-
Trust.install!
|
|
101
|
-
rescue Portless::Error => e
|
|
102
|
-
warn "rb-portless: couldn't auto-trust the CA (#{e.message}) — run `rb-portless trust`"
|
|
103
|
-
end
|
|
104
|
-
|
|
105
82
|
# Run the child in its own process group so we can signal the whole tree,
|
|
106
83
|
# forwarding INT/TERM and propagating its exit status.
|
|
107
84
|
def supervise(command, port, url)
|
|
@@ -123,16 +100,6 @@ module Portless
|
|
|
123
100
|
nil
|
|
124
101
|
end
|
|
125
102
|
|
|
126
|
-
def child_env(port, url)
|
|
127
|
-
{
|
|
128
|
-
"PORT" => port.to_s,
|
|
129
|
-
"HOST" => "127.0.0.1",
|
|
130
|
-
"PORTLESS_URL" => url,
|
|
131
|
-
# Let the app's own server-side TLS verification trust our CA.
|
|
132
|
-
"SSL_CERT_FILE" => (File.exist?(State.ca_cert) ? State.ca_cert : nil)
|
|
133
|
-
}.compact
|
|
134
|
-
end
|
|
135
|
-
|
|
136
103
|
# Explicit command wins; bare `rb-portless` falls back to the project's dev
|
|
137
104
|
# runner (bin/dev, then bin/rails server).
|
|
138
105
|
def resolved_command
|
data/lib/portless/state.rb
CHANGED
data/lib/portless/version.rb
CHANGED
data/lib/rb-portless.rb
CHANGED
|
@@ -22,6 +22,7 @@ require_relative "portless/lan_ip"
|
|
|
22
22
|
require_relative "portless/mdns"
|
|
23
23
|
require_relative "portless/share/ngrok"
|
|
24
24
|
require_relative "portless/share/tailscale"
|
|
25
|
+
require_relative "portless/run_support"
|
|
25
26
|
require_relative "portless/runner"
|
|
26
27
|
require_relative "portless/multi"
|
|
27
28
|
require_relative "portless/cli"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rb-portless
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.1.dev.20260630.bb085fc
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Afonso
|
|
@@ -74,6 +74,7 @@ files:
|
|
|
74
74
|
- lib/portless/rails.rb
|
|
75
75
|
- lib/portless/rails_hosts.rb
|
|
76
76
|
- lib/portless/route_store.rb
|
|
77
|
+
- lib/portless/run_support.rb
|
|
77
78
|
- lib/portless/runner.rb
|
|
78
79
|
- lib/portless/service.rb
|
|
79
80
|
- lib/portless/share/ngrok.rb
|