Class: Portless::Config

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

Overview

Per-project config: an optional portless.json (or portless.yml) plus inferred defaults. Mirrors portless's config.ts/auto.ts: name is inferred from the config, the git root, or the directory; tld defaults to "localhost".

Constant Summary collapse

RISKY_TLDS =

Real/reserved TLDs that can intercept live traffic or clash with mDNS.

%w[dev app page zip mov local].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data, dir = Dir.pwd) ⇒ Config

Returns a new instance of Config.



16
17
18
19
20
21
22
23
24
# File 'lib/portless/config.rb', line 16

def initialize(data, dir = Dir.pwd)
  @dir = dir
  @name = sanitize_label(data["name"] || infer_name(dir))
  @tld = (data["tld"] || Constants::DEFAULT_TLD).to_s
  @app_port = data["appPort"] || data["app_port"]
  @tls = data.fetch("tls", true)
  # Monorepo: { "apps": { "web": "bin/rails server", "api": "node api.js" } }.
  @apps = (data["apps"] || {}).transform_keys { |k| sanitize_label(k) }
end

Instance Attribute Details

#app_portObject (readonly)

Returns the value of attribute app_port.



10
11
12
# File 'lib/portless/config.rb', line 10

def app_port
  @app_port
end

#appsObject (readonly)

Returns the value of attribute apps.



10
11
12
# File 'lib/portless/config.rb', line 10

def apps
  @apps
end

#nameObject (readonly)

Returns the value of attribute name.



10
11
12
# File 'lib/portless/config.rb', line 10

def name
  @name
end

#tldObject (readonly)

Returns the value of attribute tld.



10
11
12
# File 'lib/portless/config.rb', line 10

def tld
  @tld
end

#tlsObject (readonly)

Returns the value of attribute tls.



10
11
12
# File 'lib/portless/config.rb', line 10

def tls
  @tls
end

Class Method Details

.load(dir = Dir.pwd) ⇒ Object



12
13
14
# File 'lib/portless/config.rb', line 12

def self.load(dir = Dir.pwd)
  new(read_file(dir), dir)
end

.read_file(dir) ⇒ Object



56
57
58
59
60
61
62
63
# File 'lib/portless/config.rb', line 56

def self.read_file(dir)
  json = File.join(dir, "portless.json")
  return JSON.parse(File.read(json)) if File.exist?(json)

  {}
rescue JSON::ParserError => e
  raise Error, "invalid portless.json: #{e.message}"
end

Instance Method Details

#hostname(name = nil, worktree: true) ⇒ Object

The full hostname an app registers (e.g. "shirabe.org.localhost" when tld is set to that, or ".localhost" by default). name overrides the base (used by --name); worktree: prepends the git-worktree branch prefix so a linked worktree gets its own URL (auth.<name>.localhost).



30
31
32
33
34
35
# File 'lib/portless/config.rb', line 30

def hostname(name = nil, worktree: true)
  base = name ? sanitize_label(name) : @name
  host = tld.split(".").include?(base) ? tld : "#{base}.#{tld}"
  prefix = worktree ? worktree_prefix : nil
  prefix ? "#{prefix}.#{host}" : host
end

#tld_warningObject

A warning string if the tld looks risky, else nil. (.localhost / .test are safe.)



49
50
51
52
53
54
# File 'lib/portless/config.rb', line 49

def tld_warning
  last = tld.split(".").last
  return unless RISKY_TLDS.include?(last)

  "tld \".#{last}\" is a real/reserved TLD — prefer \".localhost\" so you don't intercept real traffic"
end

#worktree_prefixObject

The git-worktree subdomain prefix for this project dir (nil if none). Memoized — it shells out to git.



39
40
41
42
43
# File 'lib/portless/config.rb', line 39

def worktree_prefix
  return @worktree_prefix if defined?(@worktree_prefix)

  @worktree_prefix = Worktree.prefix(@dir)
end