foobara 0.0.121 → 0.0.122

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 80f2fbb04c10d91d28ece159f2a3c229ba4698579acac813e19625380564928b
4
- data.tar.gz: acbe6117c76fc36741583db4bffdf26db37f8f54f75d74b2c810b7f44a37a8f4
3
+ metadata.gz: 58d1193f368aef3f0903e67152b0b7a3a1a84370a319a0f046d2d328249897be
4
+ data.tar.gz: 27617857c8d1ce1fd392fdfdad9348206fea4dad29f2ca8f68fa712abc52c048
5
5
  SHA512:
6
- metadata.gz: 70b1abede851dcafe1209e13c2d725e39240ab4746666a3b5683274f19051f6dfc84d188a05aac77b3ca7642c0c86661bcf040b5d444109a1a9884ff3f668071
7
- data.tar.gz: ca9b9cdeca157bc2595f9de3888f88eb4ef358036591bfd74793306fb5ff20912bde4570ea97c13bfc396c8e025f2d41051815d02fe1c77f1c4761ef624c2c69
6
+ metadata.gz: daf5f6327e44917051a5c00a53d2e875dc744b20af07b84801c1fea3f3b581e0afa3d38636b77b2e044ee85b25c280461fb78e1f9d0150a2e7023f39749d91e4
7
+ data.tar.gz: 5cdc61d92d02180c083bb764ae52b6ae903f08bb186b6a60f66af4b47e8c32b90b950ba50a613409eda941ed1fb95d66b6751a9b580841102cffcf3b99e7d34e
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ # [0.0.122] - 2025-05-13
2
+
3
+ - Add command connector sugar features and implement several command connector sugars
4
+
1
5
  # [0.0.121] - 2025-05-11
2
6
 
3
7
  - Handle gnarly bugs that arise when creating a custom type named model (or entity or detached_entity)
@@ -6,6 +6,27 @@ require "json"
6
6
  module Foobara
7
7
  module CommandConnectors
8
8
  foobara_domain!
9
+
10
+ class << self
11
+ def install!
12
+ CommandConnector.add_desugarizer Desugarizers::SymbolsToTrue
13
+ CommandConnector.add_desugarizer Desugarizers.rename :allow_if, :allowed_rule
14
+ CommandConnector.add_desugarizer Desugarizers.rename :inputs, :inputs_transformers
15
+ CommandConnector.add_desugarizer Desugarizers.rename :result, :result_transformers
16
+ CommandConnector.add_desugarizer Desugarizers.rename :request, :request_mutators
17
+ CommandConnector.add_desugarizer Desugarizers.rename :response, :response_mutators
18
+ CommandConnector.add_desugarizer Desugarizers::Attributes::OnlyInputs
19
+ CommandConnector.add_desugarizer Desugarizers::Attributes::RejectInputs
20
+ CommandConnector.add_desugarizer Desugarizers::Attributes::OnlyResult
21
+ CommandConnector.add_desugarizer Desugarizers::Attributes::RejectResult
22
+ CommandConnector.add_desugarizer Desugarizers::Auth
23
+ end
24
+
25
+ def reset_all
26
+ remove_instance_variable("@desugarizer") if defined?(@desugarizer)
27
+ remove_instance_variable("@desugarizers") if defined?(@desugarizers)
28
+ end
29
+ end
9
30
  end
10
31
 
11
32
  Monorepo.project "command_connectors"
@@ -0,0 +1,51 @@
1
+ module Foobara
2
+ class CommandConnector
3
+ module Concerns
4
+ module Desugarizers
5
+ include Concern
6
+
7
+ module ClassMethods
8
+ def add_desugarizer(desugarizer)
9
+ if desugarizer.is_a?(::Class)
10
+ desugarizer = desugarizer.new
11
+ end
12
+
13
+ desugarizers << desugarizer
14
+ remove_instance_variable("@desugarizer") if defined?(@desugarizer)
15
+ end
16
+
17
+ def desugarizer
18
+ return @desugarizer if defined?(@desugarizer)
19
+
20
+ processors = desugarizers
21
+
22
+ case processors.size
23
+ when 0
24
+ # TODO: test this code path by removing all desugarizers in a spec.
25
+ # :nocov:
26
+ nil
27
+ # :nocov:
28
+ when 1
29
+ # TODO: test this code path by removing all desugarizers in a spec.
30
+ # :nocov:
31
+ processors.first
32
+ # :nocov:
33
+ else
34
+ Value::Processor::Pipeline.new(processors:)
35
+ end
36
+ end
37
+
38
+ def desugarizers
39
+ @desugarizers ||= []
40
+
41
+ if superclass == Object
42
+ @desugarizers
43
+ else
44
+ @desugarizers + superclass.desugarizers
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -2,6 +2,8 @@ module Foobara
2
2
  class CommandConnector
3
3
  class UnexpectedSensitiveTypeInManifestError < StandardError; end
4
4
 
5
+ include Concerns::Desugarizers
6
+
5
7
  class << self
6
8
  def find_builtin_command_class(command_class_name)
7
9
  Util.find_constant_through_class_hierarchy(self, "Commands::#{command_class_name}")
@@ -313,9 +315,15 @@ module Foobara
313
315
  delayed_connections.clear
314
316
  end
315
317
 
316
- def connect(registerable, *, authenticator: nil, **)
317
- if authenticator
318
+ def connect(*args, **opts)
319
+ args, opts = desugarize_connect_args(args, opts)
320
+
321
+ registerable = args.first
322
+
323
+ if opts.key?(:authenticator)
324
+ authenticator = opts[:authenticator]
318
325
  authenticator = self.class.to_authenticator(authenticator)
326
+ opts = opts.merge(authenticator:)
319
327
  end
320
328
 
321
329
  case registerable
@@ -326,15 +334,15 @@ module Foobara
326
334
  # :nocov:
327
335
  end
328
336
 
329
- command_registry.register(registerable, *, authenticator:, **)
337
+ command_registry.register(*args, **opts)
330
338
  when Module
331
339
  if registerable.foobara_organization?
332
340
  registerable.foobara_domains.map do |domain|
333
- connect(domain, *, authenticator:, **)
341
+ connect(domain, *args[1..], **opts)
334
342
  end.flatten
335
343
  elsif registerable.foobara_domain?
336
344
  registerable.foobara_all_command(mode: Namespace::LookupMode::DIRECT).map do |command_class|
337
- Util.array(connect(command_class, *, authenticator:, **))
345
+ Util.array(connect(command_class, *args[1..], **opts))
338
346
  end.flatten
339
347
  else
340
348
  # :nocov:
@@ -342,7 +350,7 @@ module Foobara
342
350
  # :nocov:
343
351
  end
344
352
  when Symbol, String
345
- connect_delayed(registerable, *, authenticator:, **)
353
+ connect_delayed(*args, **opts)
346
354
  else
347
355
  # :nocov:
348
356
  raise "Don't know how to register #{registerable} (#{registerable.class})"
@@ -350,6 +358,17 @@ module Foobara
350
358
  end
351
359
  end
352
360
 
361
+ def desugarize_connect_args(args, opts)
362
+ if self.class.desugarizer
363
+ self.class.desugarizer.process_value!([args, opts])
364
+ else
365
+ # TODO: test this code path by removing all desugarizers in a spec.
366
+ # :nocov:
367
+ [args, opts]
368
+ # :nocov:
369
+ end
370
+ end
371
+
353
372
  def build_request(...)
354
373
  self.class::Request.new(...).tap do |request|
355
374
  # TODO: feels like a smell
@@ -0,0 +1,44 @@
1
+ module Foobara
2
+ module CommandConnectors
3
+ class Desugarizer < Value::Transformer
4
+ class << self
5
+ def requires_declaration_data?
6
+ false
7
+ end
8
+ end
9
+
10
+ def transform(value)
11
+ desugarize(value)
12
+ end
13
+
14
+ # in case of tie, right wins, like with Hash#merge
15
+ def merge(left, right)
16
+ return left if right.nil?
17
+ return right if left.nil?
18
+
19
+ if left.is_a?(::Hash) && right.is_a?(::Hash)
20
+ # TODO: remove :nocov: once we have an only: and/or reject: desugarizer with a test that
21
+ # merges them together.
22
+ # :nocov:
23
+ left.merge(right)
24
+ # :nocov:
25
+ else
26
+ Util.array(left) + Util.array(right)
27
+ end
28
+ end
29
+
30
+ def rename(args_and_opts, sugar_name, official_name)
31
+ args, opts = args_and_opts
32
+
33
+ opts = opts.dup
34
+ sugar = opts.delete(sugar_name)
35
+ official = opts.delete(official_name)
36
+
37
+ [
38
+ args,
39
+ opts.merge(official_name => merge(sugar, official))
40
+ ]
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,19 @@
1
+ require_relative "../attributes"
2
+
3
+ module Foobara
4
+ module CommandConnectors
5
+ module Desugarizers
6
+ class Attributes < Desugarizer
7
+ class OnlyInputs < Attributes
8
+ def desugarizer_symbol
9
+ :only
10
+ end
11
+
12
+ def opts_key
13
+ :inputs_transformers
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ require_relative "../attributes"
2
+
3
+ module Foobara
4
+ module CommandConnectors
5
+ module Desugarizers
6
+ class Attributes < Desugarizer
7
+ class OnlyResult < Attributes
8
+ def desugarizer_symbol
9
+ :only
10
+ end
11
+
12
+ def opts_key
13
+ :result_transformers
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ require_relative "../attributes"
2
+
3
+ module Foobara
4
+ module CommandConnectors
5
+ module Desugarizers
6
+ class Attributes < Desugarizer
7
+ class RejectInputs < Attributes
8
+ def desugarizer_symbol
9
+ :reject
10
+ end
11
+
12
+ def opts_key
13
+ :inputs_transformers
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ require_relative "../attributes"
2
+
3
+ module Foobara
4
+ module CommandConnectors
5
+ module Desugarizers
6
+ class Attributes < Desugarizer
7
+ class RejectResult < Attributes
8
+ def desugarizer_symbol
9
+ :reject
10
+ end
11
+
12
+ def opts_key
13
+ :result_transformers
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,58 @@
1
+ require_relative "../desugarizer"
2
+
3
+ module Foobara
4
+ module CommandConnectors
5
+ module Desugarizers
6
+ class Attributes < Desugarizer
7
+ def desugarizer_symbol
8
+ # :nocov:
9
+ raise "subclass responsibility"
10
+ # :nocov:
11
+ end
12
+
13
+ def opts_key
14
+ # :nocov:
15
+ raise "subclass responsibility"
16
+ # :nocov:
17
+ end
18
+
19
+ def applicable?(args_and_opts)
20
+ _args, opts = args_and_opts
21
+
22
+ return false unless opts.key?(opts_key)
23
+
24
+ transformers = opts[opts_key]
25
+ transformers = Util.array(transformers)
26
+
27
+ transformers.any? do |transformer|
28
+ transformer.is_a?(::Hash) && transformer.key?(desugarizer_symbol)
29
+ end
30
+ end
31
+
32
+ def desugarize(args_and_opts)
33
+ args, opts = args_and_opts
34
+
35
+ transformers = opts[opts_key]
36
+ is_array = transformers.is_a?(::Array)
37
+
38
+ transformers = Util.array(transformers)
39
+
40
+ transformers = transformers.map do |transformer|
41
+ if transformer.is_a?(::Hash) && transformer.key?(desugarizer_symbol)
42
+ params = transformer[desugarizer_symbol]
43
+ AttributesTransformers.send(desugarizer_symbol, *params)
44
+ else
45
+ transformer
46
+ end
47
+ end
48
+
49
+ transformers = transformers.first unless is_array
50
+
51
+ opts = opts.merge(opts_key => transformers)
52
+
53
+ [args, opts]
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,20 @@
1
+ module Foobara
2
+ module CommandConnectors
3
+ module Desugarizers
4
+ class Auth < Desugarizer
5
+ def applicable?(args_and_opts)
6
+ args_and_opts.last.key?(:auth)
7
+ end
8
+
9
+ def desugarize(args_and_opts)
10
+ args, opts = args_and_opts
11
+
12
+ opts = opts.dup
13
+ auth = opts.delete(:auth)
14
+
15
+ [args, opts.merge(requires_authentication: auth)]
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,45 @@
1
+ module Foobara
2
+ module CommandConnectors
3
+ module Desugarizers
4
+ class << self
5
+ def rename(sugar_name, official_name)
6
+ class_name = [name, Util.classify(sugar_name)].join("::")
7
+
8
+ Util.make_class(class_name, RenameKey).tap do |klass|
9
+ klass.singleton_class.attr_accessor :sugar_name, :official_name
10
+ klass.sugar_name = sugar_name
11
+ klass.official_name = official_name
12
+ end
13
+ end
14
+ end
15
+
16
+ # TODO: Make this the default. Deprecate :inputs_transformers
17
+ class RenameKey < Desugarizer
18
+ class << self
19
+ attr_accessor :sugar_name, :official_name
20
+ end
21
+
22
+ def applicable?(args_and_opts)
23
+ _args, opts = args_and_opts
24
+ opts.key?(sugar_name)
25
+ end
26
+
27
+ def sugar_name
28
+ self.class.sugar_name
29
+ end
30
+
31
+ def official_name
32
+ self.class.official_name
33
+ end
34
+
35
+ def desugarize(args_and_opts)
36
+ rename(args_and_opts, sugar_name, official_name)
37
+ end
38
+
39
+ def priority
40
+ Priority::HIGH
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,38 @@
1
+ require_relative "../desugarizer"
2
+
3
+ module Foobara
4
+ module CommandConnectors
5
+ module Desugarizers
6
+ class SymbolsToTrue < Desugarizer
7
+ def applicable?(args_and_opts)
8
+ args, _opts = args_and_opts
9
+ args.size > 1
10
+ end
11
+
12
+ def desugarize(args_and_opts)
13
+ args, opts = args_and_opts
14
+
15
+ command_class, *symbols = args
16
+
17
+ new_opts = {}
18
+
19
+ symbols.each do |arg|
20
+ if arg.is_a?(::Symbol)
21
+ new_opts[arg] = true
22
+ else
23
+ # :nocov:
24
+ raise "Was not expecting non-symbol arg: #{arg}"
25
+ # :nocov:
26
+ end
27
+ end
28
+
29
+ [[command_class], opts.merge(new_opts)]
30
+ end
31
+
32
+ def priority
33
+ Priority::FIRST
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -2,6 +2,11 @@ module Foobara
2
2
  class AttributesTransformers < TypeDeclarations::TypedTransformer
3
3
  class << self
4
4
  def only(*attribute_names)
5
+ symbol = symbol_for_attribute_names(attribute_names)
6
+ existing = Only.foobara_lookup(symbol, mode: Namespace::LookupMode::DIRECT)
7
+
8
+ return existing if existing
9
+
5
10
  transformer_class = Class.new(Only)
6
11
  transformer_class.only_attributes = attribute_names
7
12
 
@@ -18,7 +23,9 @@ module Foobara
18
23
  attr_accessor :only_attributes
19
24
 
20
25
  def symbol
21
- only_attributes&.sort&.join("_")&.to_sym
26
+ if only_attributes
27
+ symbol_for_attribute_names(only_attributes)
28
+ end
22
29
  end
23
30
 
24
31
  def will_set_scoped_path?
@@ -18,7 +18,9 @@ module Foobara
18
18
  attr_accessor :reject_attributes
19
19
 
20
20
  def symbol
21
- reject_attributes&.sort&.join("_")&.to_sym
21
+ if reject_attributes
22
+ symbol_for_attribute_names(reject_attributes)
23
+ end
22
24
  end
23
25
 
24
26
  def will_set_scoped_path?
@@ -1,5 +1,11 @@
1
1
  module Foobara
2
2
  class AttributesTransformers < TypeDeclarations::TypedTransformer
3
+ class << self
4
+ def symbol_for_attribute_names(attribute_names)
5
+ attribute_names.sort.join("__")&.to_sym
6
+ end
7
+ end
8
+
3
9
  def initialize(...)
4
10
  super
5
11
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foobara
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.121
4
+ version: 0.0.122
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miles Georgi
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-05-11 00:00:00.000000000 Z
10
+ date: 2025-05-13 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: bigdecimal
@@ -188,6 +188,7 @@ files:
188
188
  - projects/command_connectors/src/command_connector/commands/list_commands.rb
189
189
  - projects/command_connectors/src/command_connector/commands/ping.rb
190
190
  - projects/command_connectors/src/command_connector/commands/query_git_commit_info.rb
191
+ - projects/command_connectors/src/command_connector/concerns/desugarizers.rb
191
192
  - projects/command_connectors/src/command_connector/invalid_context_error.rb
192
193
  - projects/command_connectors/src/command_connector/no_command_found_error.rb
193
194
  - projects/command_connectors/src/command_connector/no_command_or_type_found_error.rb
@@ -203,6 +204,15 @@ files:
203
204
  - projects/command_connectors/src/command_registry/exposed_command.rb
204
205
  - projects/command_connectors/src/command_registry/exposed_domain.rb
205
206
  - projects/command_connectors/src/command_registry/exposed_organization.rb
207
+ - projects/command_connectors/src/desugarizer.rb
208
+ - projects/command_connectors/src/desugarizers/attributes.rb
209
+ - projects/command_connectors/src/desugarizers/attributes/only_inputs.rb
210
+ - projects/command_connectors/src/desugarizers/attributes/only_result.rb
211
+ - projects/command_connectors/src/desugarizers/attributes/reject_inputs.rb
212
+ - projects/command_connectors/src/desugarizers/attributes/reject_result.rb
213
+ - projects/command_connectors/src/desugarizers/auth.rb
214
+ - projects/command_connectors/src/desugarizers/rename_key.rb
215
+ - projects/command_connectors/src/desugarizers/symbols_to_true.rb
206
216
  - projects/command_connectors/src/request_mutator.rb
207
217
  - projects/command_connectors/src/response_mutator.rb
208
218
  - projects/command_connectors/src/serializer.rb