Class: SmilyCli::Config
- Inherits:
-
Object
- Object
- SmilyCli::Config
- Defined in:
- lib/smily_cli/config.rb
Overview
On-disk configuration: a YAML file holding one or more named profiles, each a bag of credentials/settings (token, base_url, refresh_token, client_id, client_secret, ...). Precedence between file, environment and flags lives in Context; this class only owns reading and writing the file.
File shape:
current_profile: default
profiles:
default:
token: "..."
base_url: "https://www.bookingsync.com"
Constant Summary collapse
- KNOWN_KEYS =
Keys that are meaningful inside a profile. Unknown keys are preserved on save but this list drives validation and
config setcompletion. %w[ token base_url refresh_token client_id client_secret redirect_uri scope account_id mcp_token mcp_url ].freeze
- DEFAULT_PROFILE =
"default"
Instance Attribute Summary collapse
-
#path ⇒ String
readonly
Absolute path to the config file backing this instance.
Class Method Summary collapse
-
.default_path ⇒ String
Resolve the default config path, honoring
SMILY_CONFIG(full path), thenXDG_CONFIG_HOME, then~/.config. -
.load(path = default_path) ⇒ Config
Load configuration from
path(missing file yields an empty config).
Instance Method Summary collapse
-
#current_profile_name ⇒ String
Name of the active profile: explicit
current_profileor DEFAULT_PROFILE. - #current_profile_name=(name) ⇒ Object
-
#delete_profile(name) ⇒ Hash?
Delete an entire profile.
-
#exist? ⇒ Boolean
Whether the backing file exists on disk.
-
#initialize(path = self.class.default_path) ⇒ Config
constructor
A new instance of Config.
-
#profile(name = current_profile_name) ⇒ Hash{String=>Object}
Fetch a profile's settings hash (never nil).
- #profile?(name = current_profile_name) ⇒ Boolean
-
#profile_names ⇒ Array<String>
Sorted profile names present in the file.
-
#profiles ⇒ Hash{String=>Hash}
The profiles map (mutable).
-
#save ⇒ String
Persist the config to #path, creating the directory and locking down permissions (the file holds secrets).
-
#set(key, value, profile: current_profile_name) ⇒ void
Set a single key on a profile (creating the profile if needed).
-
#unset(key, profile: current_profile_name) ⇒ Object?
Remove a key from a profile.
Constructor Details
#initialize(path = self.class.default_path) ⇒ Config
Returns a new instance of Config.
52 53 54 55 |
# File 'lib/smily_cli/config.rb', line 52 def initialize(path = self.class.default_path) @path = path @data = read end |
Instance Attribute Details
#path ⇒ String (readonly)
Returns absolute path to the config file backing this instance.
29 30 31 |
# File 'lib/smily_cli/config.rb', line 29 def path @path end |
Class Method Details
.default_path ⇒ String
Resolve the default config path, honoring SMILY_CONFIG (full path),
then XDG_CONFIG_HOME, then ~/.config.
35 36 37 38 39 40 41 |
# File 'lib/smily_cli/config.rb', line 35 def self.default_path return ENV["SMILY_CONFIG"] if ENV["SMILY_CONFIG"] && !ENV["SMILY_CONFIG"].empty? base = ENV.fetch("XDG_CONFIG_HOME", nil) base = File.join(Dir.home, ".config") if base.nil? || base.empty? File.join(base, "smily", "config.yml") end |
.load(path = default_path) ⇒ Config
Load configuration from path (missing file yields an empty config).
47 48 49 |
# File 'lib/smily_cli/config.rb', line 47 def self.load(path = default_path) new(path) end |
Instance Method Details
#current_profile_name ⇒ String
Name of the active profile: explicit current_profile or DEFAULT_PROFILE.
64 65 66 |
# File 'lib/smily_cli/config.rb', line 64 def current_profile_name @data["current_profile"] || DEFAULT_PROFILE end |
#current_profile_name=(name) ⇒ Object
69 70 71 |
# File 'lib/smily_cli/config.rb', line 69 def current_profile_name=(name) @data["current_profile"] = name.to_s end |
#delete_profile(name) ⇒ Hash?
Delete an entire profile.
114 115 116 |
# File 'lib/smily_cli/config.rb', line 114 def delete_profile(name) profiles.delete(name.to_s) end |
#exist? ⇒ Boolean
Returns whether the backing file exists on disk.
58 59 60 |
# File 'lib/smily_cli/config.rb', line 58 def exist? File.exist?(path) end |
#profile(name = current_profile_name) ⇒ Hash{String=>Object}
Fetch a profile's settings hash (never nil).
82 83 84 |
# File 'lib/smily_cli/config.rb', line 82 def profile(name = current_profile_name) profiles[name.to_s] || {} end |
#profile?(name = current_profile_name) ⇒ Boolean
88 89 90 |
# File 'lib/smily_cli/config.rb', line 88 def profile?(name = current_profile_name) profiles.key?(name.to_s) end |
#profile_names ⇒ Array<String>
Returns sorted profile names present in the file.
74 75 76 |
# File 'lib/smily_cli/config.rb', line 74 def profile_names profiles.keys.sort end |
#profiles ⇒ Hash{String=>Hash}
Returns the profiles map (mutable).
139 140 141 |
# File 'lib/smily_cli/config.rb', line 139 def profiles @data["profiles"] ||= {} end |
#save ⇒ String
Persist the config to #path, creating the directory and locking down permissions (the file holds secrets).
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/smily_cli/config.rb', line 122 def save dir = File.dirname(path) created_dir = !File.directory?(dir) FileUtils.mkdir_p(dir) # Only tighten a directory we created, so we never clobber the perms of a # pre-existing (possibly shared) parent. File.chmod(0o700, dir) if created_dir # Create with 0600 from the start so there is no world-readable window; # re-chmod covers a pre-existing file whose perms may have drifted. File.open(path, File::WRONLY | File::CREAT | File::TRUNC, 0o600) do |file| file.write(YAML.dump(prune(@data))) end File.chmod(0o600, path) path end |
#set(key, value, profile: current_profile_name) ⇒ void
This method returns an undefined value.
Set a single key on a profile (creating the profile if needed).
98 99 100 101 |
# File 'lib/smily_cli/config.rb', line 98 def set(key, value, profile: current_profile_name) profiles[profile.to_s] ||= {} profiles[profile.to_s][key.to_s] = value end |
#unset(key, profile: current_profile_name) ⇒ Object?
Remove a key from a profile.
106 107 108 |
# File 'lib/smily_cli/config.rb', line 106 def unset(key, profile: current_profile_name) (profiles[profile.to_s] || {}).delete(key.to_s) end |