# frozen_string_literal: true # Requirements # ======================================================================= # Stdlib # ----------------------------------------------------------------------- # Deps # ----------------------------------------------------------------------- require 'plist' require 'fileutils' require 'nrser' require 'nrser/props/immutable/hash' # Project / Package # ----------------------------------------------------------------------- # Refinements # ======================================================================= require 'nrser/refinements/types' using NRSER::Types # Definitions # ======================================================================= # Represents a backend agent that the proxy can route to. # # Agents are managed by `launchd`, macOS's system service manager, and # created on-demand by generating "property list" files (`.plist`, XML format) # and installing them in the user's `~/Library/LaunchAgents` directory. # # From there they can be managed directly with macOS's `launchctl` utility, # with the `lunchy` gem, etc. # class Locd::Agent # Constants # ========================================================================== # Attribute / method names that {#to_h} uses. # # @return [Hamster::SortedSet] # TO_H_NAMES = Hamster::SortedSet[:label, :path, :plist, :status] # Structs # ============================================================================ class Status < Hamster::Hash include NRSER::Props::Immutable::Hash # @!attribute [r] loaded # `true` if the agent is loaded in launchd. # # @return [Boolean] # prop :loaded, type: t.bool # @!attribute [r] running # `true` if the agent is currently running. # # @return [Boolean] prop :running, type: t.bool # @!attribute [r] pid # The process ID the agent is running as (if any). # # @return [Integer?] prop :pid, type: t.non_neg_int? # @!attribute [r] last_exit_code # The last status code the agent exited with, if any is available. # # @return [Integer?] prop :last_exit_code, type: t.int? end # class Status # Mixins # ========================================================================== # Add {.logger} and {#logger} methods include NRSER::Log::Mixin # Make agents sortable by label include Comparable # Class Methods # ========================================================================== # Test if the parse of a property list is for a Loc'd agent by seeing if # it has the config key (from `Locd.config[:agent, :config_key]`) as a key. # # @param [Hash] plist # {include:file:doc/include/plist.md} # # @return [Boolean] # `true` if the plist looks like it's from Loc'd. # def self.plist? plist plist.key? Locd.config[:agent, :config_key] end # .plist? # @!group Computing Paths # -------------------------------------------------------------------------- # Absolute path to `launchd` plist directory for the current user, which is # an expansion of `~/Library/LaunchAgents`. # # @return [Pathname] # def self.user_plist_abs_dir Pathname.new( '~/Library/LaunchAgents' ).expand_path end # Absolute path for the plist file given it's label, equivalent to expanding # `~/Library/LaunchAgents/