Class: Belt::CLI::FrontendRegistry

Inherits:
Object
  • Object
show all
Defined in:
lib/belt/cli/frontend_registry.rb

Overview

Discovers and resolves frontends for CLI commands.

Config (first match wins):

config/frontends.yml
config/frontends.yaml
.belt/frontends.yml
.belt/frontends.yaml

If no config exists and frontend/ is present, that directory is the single implicit frontend (backwards compatible).

Example:

frontends:
customer:
  path: app
  dist: build
  default: true
  bucket_output: web_app_bucket_name
  url_output: web_app_url
  cloudfront_domain_output: web_app_cloudfront_domain
ops:
  path: ops-app
  dist: build
  bucket_output: ops_app_bucket_name
  url_output: ops_app_url

Constant Summary collapse

CONFIG_CANDIDATES =
[
  File.join('config', 'frontends.yml'),
  File.join('config', 'frontends.yaml'),
  File.join('.belt', 'frontends.yml'),
  File.join('.belt', 'frontends.yaml')
].freeze
WRITE_PATH =
File.join('config', 'frontends.yml')

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeFrontendRegistry

Returns a new instance of FrontendRegistry.



184
185
186
187
# File 'lib/belt/cli/frontend_registry.rb', line 184

def initialize
  @config_path = self.class.find_config_path
  @frontends = load_frontends
end

Class Method Details

.extract_flag!(args, flag) ⇒ Object

Pull --flag VALUE or --flag=VALUE out of args, mutating the array.



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/belt/cli/frontend_registry.rb', line 156

def self.extract_flag!(args, flag)
  i = 0
  while i < args.length
    arg = args[i]
    if arg == flag
      args.delete_at(i)
      return args.delete_at(i)
    elsif arg.start_with?("#{flag}=")
      args.delete_at(i)
      return arg.split('=', 2).last
    else
      i += 1
    end
  end
  nil
end

.find_config_pathObject



151
152
153
# File 'lib/belt/cli/frontend_registry.rb', line 151

def self.find_config_path
  CONFIG_CANDIDATES.find { |path| File.file?(path) }
end

.loadObject



173
174
175
# File 'lib/belt/cli/frontend_registry.rb', line 173

def self.load
  new
end

.register!(name:, path:, default: nil) ⇒ Object

Add (or update) a frontend and persist config/frontends.yml.



178
179
180
181
182
# File 'lib/belt/cli/frontend_registry.rb', line 178

def self.register!(name:, path:, default: nil)
  registry = new
  registry.add(name: name, path: path, default: default)
  registry.write!
end

Instance Method Details

#add(name:, path:, default: nil) ⇒ Object



230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/belt/cli/frontend_registry.rb', line 230

def add(name:, path:, default: nil)
  name = name.to_s
  path = path.to_s.sub(%r{/\z}, '')
  existing = named(name)

  becomes_default = if !default.nil?
                      default
                    elsif existing
                      existing.default?
                    else
                      @frontends.empty?
                    end

  @frontends.each { |fe| fe.default = false } if becomes_default

  if existing
    existing.default = becomes_default
    existing.path = path
  else
    @frontends << Frontend.new(name: name, path: path, default: becomes_default)
  end

  named(name)
end

#allObject



189
190
191
# File 'lib/belt/cli/frontend_registry.rb', line 189

def all
  @frontends
end

#defaultObject

Default frontend: explicit default: true, otherwise the only one.



210
211
212
# File 'lib/belt/cli/frontend_registry.rb', line 210

def default
  @frontends.find(&:default?) || (@frontends.length == 1 ? @frontends.first : nil)
end

#empty?Boolean

Returns:

  • (Boolean)


193
194
195
# File 'lib/belt/cli/frontend_registry.rb', line 193

def empty?
  @frontends.empty?
end

#empty_messageObject



272
273
274
275
# File 'lib/belt/cli/frontend_registry.rb', line 272

def empty_message
  'Error: No frontend found. Run `belt generate frontend react` first, ' \
    'or add config/frontends.yml.'
end

#existingObject



197
198
199
# File 'lib/belt/cli/frontend_registry.rb', line 197

def existing
  @frontends.select(&:exists?)
end

#multiple_messageObject



267
268
269
270
# File 'lib/belt/cli/frontend_registry.rb', line 267

def multiple_message
  "Error: Multiple frontends found (#{names.join(', ')}). " \
    'Specify one with --frontend <name>.'
end

#named(name) ⇒ Object



201
202
203
204
205
206
207
# File 'lib/belt/cli/frontend_registry.rb', line 201

def named(name)
  return nil if name.nil? || name.to_s.empty?

  key = name.to_s
  slug = Frontend.slug(key)
  @frontends.find { |fe| fe.name == key || fe.slug == slug }
end

#namesObject



277
278
279
# File 'lib/belt/cli/frontend_registry.rb', line 277

def names
  @frontends.map(&:name)
end

#resolve!(name = nil) ⇒ Object

Resolve a frontend for generate/server/auth. Aborts when ambiguous.



215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/belt/cli/frontend_registry.rb', line 215

def resolve!(name = nil)
  if name && !name.to_s.empty?
    fe = named(name)
    abort unknown_message(name) unless fe
    return fe
  end

  fe = default
  return fe if fe

  abort empty_message if @frontends.empty?

  abort multiple_message
end

#unknown_message(name) ⇒ Object



263
264
265
# File 'lib/belt/cli/frontend_registry.rb', line 263

def unknown_message(name)
  "Error: Unknown frontend '#{name}'. #{known_suffix}"
end

#write!Object



255
256
257
258
259
260
261
# File 'lib/belt/cli/frontend_registry.rb', line 255

def write!
  dest = @config_path || WRITE_PATH
  FileUtils.mkdir_p(File.dirname(dest))
  File.write(dest, dump_yaml)
  @config_path = dest
  dest
end