foobara 0.1.3 → 0.1.6

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.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +19 -1
  3. data/projects/builtin_types/src/builtin_types.rb +3 -1
  4. data/projects/callback/src/registry/chained_conditioned.rb +7 -1
  5. data/projects/callback/src/registry/chained_multiple_action.rb +7 -1
  6. data/projects/callback/src/registry/joined_conditioned.rb +7 -1
  7. data/projects/command/src/command_pattern_implementation/concerns/errors.rb +3 -1
  8. data/projects/command/src/command_pattern_implementation/concerns/inputs_type.rb +3 -1
  9. data/projects/command/src/command_pattern_implementation/concerns/result_type.rb +3 -1
  10. data/projects/command_connectors/src/command_connector/commands/describe.rb +3 -1
  11. data/projects/command_connectors/src/command_connector.rb +3 -25
  12. data/projects/command_connectors/src/transformed_command.rb +58 -25
  13. data/projects/command_connectors/src/transformers/entity_to_primary_key_inputs_transformer.rb +1 -0
  14. data/projects/common/src/outcome.rb +9 -5
  15. data/projects/detached_entity/src/concerns/associations.rb +3 -5
  16. data/projects/detached_entity/src/extensions/type_declarations/handlers/extend_detached_entity_type_declaration/to_type_transformer.rb +1 -0
  17. data/projects/domain/src/is_manifestable.rb +14 -4
  18. data/projects/entity/src/concerns/callbacks.rb +10 -2
  19. data/projects/entity/src/extensions/builtin_types/entity/validators/model_instance_is_valid.rb +1 -1
  20. data/projects/entity/src/sensitive_type_removers/entity.rb +7 -3
  21. data/projects/entity/src/sensitive_value_removers/entity.rb +5 -13
  22. data/projects/manifest/src/foobara/manifest/organization.rb +4 -0
  23. data/projects/manifest/src/foobara/manifest/root_manifest.rb +4 -0
  24. data/projects/manifest/src/foobara/manifest/type.rb +1 -1
  25. data/projects/persistence/src/entity_base/transaction/concerns/state_transitions.rb +5 -1
  26. data/projects/persistence/src/entity_base/transaction.rb +3 -1
  27. data/version.rb +6 -0
  28. metadata +2 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 382dbd4fb1743f89af17bc70f7acdbef0ad2851767122f702e2503dcfacddf12
4
- data.tar.gz: 02dfabf373e9ec1545ecbcaeeed6c31b0f6338bcc5e9095b3e0efe9bc9f61c03
3
+ metadata.gz: b3eea1befe835410f5c6ecc372c5db94e3641f90711a773b0a7685a18afe677f
4
+ data.tar.gz: 7fe5e33084023a8d475e0fe491520a179d9123b5109c0ebc2ad52ed5643752bd
5
5
  SHA512:
6
- metadata.gz: 535af52cbd9ad41609694db0b23e69f003d5959ccff113bc98dcedc13ff15df685b6abfcafe510f26243888d979b4724b061d00a76164805167d8f90cc3f4d39
7
- data.tar.gz: 692827d4929a901e5127c706c5f63d5da40330dfc5a5e868ea0661ef5885b25dbb5a4db43f8b76e980076ded3d876637ea1328bd164a16fed9e86664d99b9d4c
6
+ metadata.gz: 67bbdfab3b295bbe38f39d978f2855a239092f9feba4a417bbb853759dae9527dcbd0ba3a34647925f2b90fc15693c03ddb56a5d5e9247678c22c236deedba2c
7
+ data.tar.gz: bc09a9a484f9c1e6487a7ce112e33aabb5132b77071f195ed06cafb79895c070ee895be8e3cdd01abf75c4fc4eb54c51dd23d0bd4b22f7d1e0ef3b584c5874d7
data/CHANGELOG.md CHANGED
@@ -1,4 +1,22 @@
1
- # [0.1.3] - 2025-08-25
1
+ # [0.1.6] - 2025-08-25
2
+
3
+ - Allow constructing a thunk-like record when removing sensitive values from a thunk
4
+ - Undo automatically converting connected entities to detached entities
5
+ - Honor imported builtin types in manifest
6
+ - Add Foobara version to manifest metadata
7
+ - Add RootManifest#detached_entities
8
+ - Remove some items from the manifest that should be safe to remove
9
+ - Let's use GlobalDomain in the manifest for objects scoped to Foobara::Value
10
+
11
+ # [0.1.4] - 2025-08-24
12
+
13
+ - Fix TransformedCommand#foobara_manifest bug that failed to overwrite transformed possible_errors
14
+ if the new possible errors is empty
15
+ - Make sure we set nil inputs_type in TransformedCommand#foobara_manifest to empty attributes
16
+ for compatibility with other projects
17
+ - Sets the parent for various Foobara::Value children to be GlobalDomain in manifests
18
+
19
+ # [0.1.3] - 2025-08-24
2
20
 
3
21
  - Add Command#abstract and exclude abstract commands from CommandConnector#connect when connecting domains/orgs
4
22
 
@@ -5,7 +5,9 @@ module Foobara
5
5
 
6
6
  module BuiltinTypes
7
7
  class << self
8
- foobara_delegate :global_type_declaration_handler_registry, to: TypeDeclarations
8
+ def global_type_declaration_handler_registry
9
+ TypeDeclarations.global_type_declaration_handler_registry
10
+ end
9
11
 
10
12
  # TODO: break this up
11
13
  # TODO: much of this behavior is helpful to non-builtin types as well.
@@ -6,7 +6,13 @@ module Foobara
6
6
  class ChainedConditioned < Conditioned
7
7
  attr_accessor :other_conditions_registry
8
8
 
9
- foobara_delegate :possible_conditions, :possible_condition_keys, to: :other_conditions_registry
9
+ def possible_conditions
10
+ other_conditions_registry.possible_conditions
11
+ end
12
+
13
+ def possible_condition_keys
14
+ other_conditions_registry.possible_condition_keys
15
+ end
10
16
 
11
17
  def initialize(other_conditions_registry)
12
18
  self.other_conditions_registry = other_conditions_registry
@@ -8,7 +8,13 @@ module Foobara
8
8
 
9
9
  class InvalidConditions < StandardError; end
10
10
 
11
- foobara_delegate :possible_actions, :allowed_types, to: :other_multiple_actions_registry
11
+ def possible_actions
12
+ other_multiple_actions_registry.possible_actions
13
+ end
14
+
15
+ def allowed_types
16
+ other_multiple_actions_registry.allowed_types
17
+ end
12
18
 
13
19
  def initialize(other_multiple_actions_registry)
14
20
  self.other_multiple_actions_registry = other_multiple_actions_registry
@@ -6,7 +6,13 @@ module Foobara
6
6
  class JoinedConditioned < Conditioned
7
7
  attr_accessor :first, :second
8
8
 
9
- foobara_delegate :possible_conditions, :possible_condition_keys, to: :first
9
+ def possible_conditions
10
+ first.possible_conditions
11
+ end
12
+
13
+ def possible_condition_keys
14
+ first.possible_condition_keys
15
+ end
10
16
 
11
17
  def initialize(first, second)
12
18
  self.first = first
@@ -53,7 +53,9 @@ module Foobara
53
53
  super
54
54
  end
55
55
 
56
- foobara_delegate :has_errors?, to: :error_collection
56
+ def has_errors?
57
+ error_collection.has_errors?
58
+ end
57
59
 
58
60
  private
59
61
 
@@ -61,7 +61,9 @@ module Foobara
61
61
  end
62
62
  end
63
63
 
64
- foobara_delegate :inputs_type, to: :class
64
+ def inputs_type
65
+ self.class.inputs_type
66
+ end
65
67
  end
66
68
  end
67
69
  end
@@ -18,7 +18,9 @@ module Foobara
18
18
  end
19
19
  end
20
20
 
21
- foobara_delegate :result_type, :raw_result_type_declaration, to: :class
21
+ def result_type
22
+ self.class.result_type
23
+ end
22
24
  end
23
25
  end
24
26
  end
@@ -1,3 +1,5 @@
1
+ require_relative "../../../../../version"
2
+
1
3
  module Foobara
2
4
  class CommandConnector
3
5
  module Commands
@@ -20,7 +22,7 @@ module Foobara
20
22
  end
21
23
 
22
24
  def stamp_request_metadata
23
- manifest[:metadata] = { when: Time.now }
25
+ manifest[:metadata] = { when: Time.now, foobara_version: Foobara::Version::VERSION }
24
26
  end
25
27
  end
26
28
  end
@@ -352,7 +352,9 @@ module Foobara
352
352
  args = args[1..]
353
353
  connected = []
354
354
 
355
- registerable.foobara_each_command(mode: Namespace::LookupMode::DIRECT) do |command_class|
355
+ registerable = registerable.foobara_all_command(mode: Namespace::LookupMode::DIRECT)
356
+
357
+ registerable.each do |command_class|
356
358
  unless command_class.abstract?
357
359
  connected << connect(command_class, *args, **opts)
358
360
  end
@@ -567,29 +569,6 @@ module Foobara
567
569
  additional_to_include << exposed_organization
568
570
  end
569
571
  end
570
-
571
- if o.extends_type?(BuiltinTypes[:entity])
572
- declaration_data = o.declaration_data
573
-
574
- if declaration_data.is_a?(::Hash) && declaration_data[:type] == :entity
575
- if o.foobara_root_namespace != command_registry.foobara_root_namespace
576
- # Let's swap it out with a detached type
577
- detached_entity = command_registry.foobara_lookup_type(o.scoped_full_name, mode:)
578
-
579
- unless detached_entity
580
- declaration_data = o.declaration_data.merge(
581
- type: :detached_entity,
582
- model_base_class: "Foobara::DetachedEntity"
583
- )
584
-
585
- detached_entity = exposed_domain.foobara_type_from_declaration(declaration_data)
586
- end
587
-
588
- additional_to_include << detached_entity
589
- next
590
- end
591
- end
592
- end
593
572
  end
594
573
  end
595
574
 
@@ -637,7 +616,6 @@ module Foobara
637
616
  end
638
617
 
639
618
  h = normalize_manifest(h)
640
-
641
619
  patch_up_broken_parents_for_errors_with_missing_command_parents(h)
642
620
  end
643
621
 
@@ -61,10 +61,11 @@ module Foobara
61
61
  end
62
62
  end
63
63
 
64
- foobara_delegate :description,
65
- :domain,
66
- :organization,
67
- to: :command_class
64
+ foobara_delegate :domain, :organization, to: :command_class
65
+
66
+ def description
67
+ command_class.description
68
+ end
68
69
 
69
70
  def result_transformers
70
71
  return @result_transformers if @considered_sensitive_value_remover
@@ -350,7 +351,7 @@ module Foobara
350
351
  response_mutators = processors_to_manifest_symbols(self.response_mutators)
351
352
  request_mutators = processors_to_manifest_symbols(self.request_mutators)
352
353
 
353
- authenticator_details = if authenticator
354
+ authenticator_details = if requires_authentication && authenticator
354
355
  {
355
356
  symbol: authenticator.symbol,
356
357
  explanation: authenticator.explanation
@@ -369,27 +370,59 @@ module Foobara
369
370
  command_class.foobara_manifest
370
371
  end
371
372
 
373
+ # TODO: This should support nil as an inputs_type but it breaks other projects for now
374
+ inputs_type = inputs_type_for_manifest&.reference_or_declaration_data ||
375
+ { type: :attributes, element_type_declarations: {} }
376
+
372
377
  # TODO: handle errors_types_depended_on!
373
- manifest.merge(
374
- Util.remove_blank(
375
- inputs_types_depended_on:,
376
- result_types_depended_on:,
377
- types_depended_on: types,
378
- inputs_type: inputs_type_for_manifest&.reference_or_declaration_data,
379
- result_type: result_type&.reference_or_declaration_data,
380
- possible_errors: possible_errors_manifest,
381
- capture_unknown_error:,
382
- inputs_transformers:,
383
- result_transformers:,
384
- errors_transformers:,
385
- pre_commit_transformers:,
386
- serializers:,
387
- response_mutators:,
388
- request_mutators:,
389
- requires_authentication:,
390
- authenticator: authenticator_details
391
- )
392
- )
378
+ to_merge = {
379
+ inputs_types_depended_on:,
380
+ result_types_depended_on:,
381
+ types_depended_on: types,
382
+ inputs_type:,
383
+ result_type: result_type&.reference_or_declaration_data,
384
+ possible_errors: possible_errors_manifest,
385
+ capture_unknown_error:,
386
+ inputs_transformers:,
387
+ result_transformers:,
388
+ errors_transformers:,
389
+ pre_commit_transformers:,
390
+ serializers:,
391
+ response_mutators:,
392
+ request_mutators:,
393
+ requires_authentication:,
394
+ authenticator: authenticator_details
395
+ }
396
+
397
+ manifest = manifest.dup
398
+
399
+ # TODO: we should remove all blank valued keys but keeping many for now for stability
400
+ safe_to_remove = [
401
+ :pre_commit_transformers,
402
+ :response_mutators,
403
+ :request_mutators,
404
+ :capture_unknown_error,
405
+ :inputs_transformers,
406
+ :result_transformers,
407
+ :errors_transformers,
408
+ :requires_authentication,
409
+ :authenticator
410
+ ]
411
+
412
+ to_merge.each_pair do |key, value|
413
+ # TODO: we could probably remove empty strings and nils, too, and from the whole hash
414
+ if value.nil? || ((value.is_a?(::Hash) || value.is_a?(::Array)) && value.empty?)
415
+ if safe_to_remove.include?(key)
416
+ manifest.delete(key)
417
+ else
418
+ manifest[key] = value
419
+ end
420
+ else
421
+ manifest[key] = value
422
+ end
423
+ end
424
+
425
+ manifest
393
426
  end
394
427
 
395
428
  def processors_to_manifest_symbols(processors)
@@ -54,6 +54,7 @@ module Foobara
54
54
 
55
55
  description = "#{to_type.target_class.model_name} #{to_type.target_class.primary_key_attribute}"
56
56
 
57
+ # TODO: doesn't everything that extends :entity also extend :detached_entity?
57
58
  unless to_type.extends_directly?(Foobara::BuiltinTypes[:detached_entity]) ||
58
59
  to_type.extends_directly?(Foobara::BuiltinTypes[:entity])
59
60
 
@@ -55,11 +55,15 @@ module Foobara
55
55
  end
56
56
  end
57
57
 
58
- foobara_delegate :has_errors?,
59
- :has_error?,
60
- :add_error,
61
- :add_errors,
62
- to: :error_collection
58
+ foobara_delegate :has_error, :add_errors, to: :error_collection
59
+
60
+ def has_errors?
61
+ error_collection.has_errors?
62
+ end
63
+
64
+ def add_errors(...)
65
+ error_collection.add_errors(...)
66
+ end
63
67
 
64
68
  def errors
65
69
  error_collection
@@ -157,13 +157,11 @@ module Foobara
157
157
  result = {},
158
158
  initial: true
159
159
  )
160
- if initial && type.extends?(BuiltinTypes[:detached_entity])
161
- return construct_associations(type.element_types, path, result, initial: false)
162
- end
163
-
164
160
  remove_sensitive = TypeDeclarations.foobara_manifest_context_remove_sensitive?
165
161
 
166
- if type.extends?(BuiltinTypes[:entity])
162
+ if initial && type.extends?(BuiltinTypes[:detached_entity])
163
+ construct_associations(type.target_class.foobara_attributes_type, path, result, initial: false)
164
+ elsif type.extends?(BuiltinTypes[:entity])
167
165
  result[path.to_s] = type
168
166
  elsif type.extends?(BuiltinTypes[:tuple])
169
167
  element_types = type.element_types
@@ -3,6 +3,7 @@ module Foobara
3
3
  module Handlers
4
4
  class ExtendDetachedEntityTypeDeclaration < ExtendModelTypeDeclaration
5
5
  class ToTypeTransformer < ExtendModelTypeDeclaration::ToTypeTransformer
6
+ # TODO: use constants for these arrays for performance reasons
6
7
  def non_processor_keys
7
8
  [:primary_key, *super]
8
9
  end
@@ -63,16 +63,26 @@ module Foobara
63
63
 
64
64
  if parent_category
65
65
  if include_processors || (parent_category != :processor && parent_category != :processor_class)
66
- if candidate != Foobara::Value
67
- parent = candidate
68
- break
69
- end
66
+ parent = if candidate == Foobara::Value
67
+ GlobalDomain
68
+ else
69
+ candidate
70
+ end
71
+ break
70
72
  end
71
73
  end
72
74
 
73
75
  candidate = candidate.scoped_namespace
74
76
  end
75
77
 
78
+ if parent == GlobalDomain
79
+ h[:scoped_path] = scoped_full_path
80
+ h[:scoped_name] = scoped_full_name
81
+ h[:scoped_prefix] = scoped_full_path[..-2]
82
+ h[:domain] = parent.foobara_manifest_reference
83
+ h[:organization] = parent.foobara_organization.foobara_manifest_reference
84
+ end
85
+
76
86
  if parent
77
87
  to_include << parent
78
88
  h[:parent] = [parent_category, parent.foobara_manifest_reference]
@@ -35,7 +35,9 @@ module Foobara
35
35
  end
36
36
  end
37
37
 
38
- foobara_delegate :register_callback, to: :callback_registry
38
+ def register_callback(...)
39
+ callback_registry.register_callback(...)
40
+ end
39
41
 
40
42
  module ClassMethods
41
43
  def class_callback_registry
@@ -68,7 +70,13 @@ module Foobara
68
70
  end
69
71
  end
70
72
 
71
- foobara_delegate :register_callback, :possible_actions, to: :class_callback_registry
73
+ def register_callback(...)
74
+ class_callback_registry.register_callback(...)
75
+ end
76
+
77
+ def possible_actions
78
+ class_callback_registry.possible_actions
79
+ end
72
80
  end
73
81
 
74
82
  on_include do
@@ -4,7 +4,7 @@ module Foobara
4
4
  module Validators
5
5
  class ModelInstanceIsValid < DetachedEntity::Validators::ModelInstanceIsValid
6
6
  def applicable?(record)
7
- record && (record.created? || record.built?)
7
+ record && (record.created? || record.built?) && !record.skip_validations
8
8
  end
9
9
 
10
10
  def expected_type_symbol
@@ -7,10 +7,14 @@ module Foobara
7
7
 
8
8
  if strict_type_declaration != new_type_declaration
9
9
  if new_type_declaration[:type] == :entity
10
- new_type_declaration[:type] = :detached_entity
10
+ if Namespace.current.foobara_root_namespace == Namespace.global.foobara_root_namespace
11
+ # Nervous about creating two entities with the same name in the same namespace
12
+ # So going to create a detached entity instead
13
+ new_type_declaration[:type] = :detached_entity
11
14
 
12
- if new_type_declaration[:model_base_class] == "Foobara::Entity"
13
- new_type_declaration[:model_base_class] = "Foobara::DetachedEntity"
15
+ if new_type_declaration[:model_base_class] == "Foobara::Entity"
16
+ new_type_declaration[:model_base_class] = "Foobara::DetachedEntity"
17
+ end
14
18
  end
15
19
  end
16
20
  end
@@ -8,11 +8,10 @@ module Foobara
8
8
  elsif record.persisted?
9
9
  # We will assume that we do not need to clean up the primary key itself as
10
10
  # we will assume we don't allow sensitive primary keys for now.
11
- # We use .new because the target_class should be a detached entity
12
- to_type.target_class.new(
13
- { record.class.primary_key_attribute => record.primary_key },
14
- { mutable: false, skip_validations: true }
15
- )
11
+ thunkish = to_type.target_class.build(record.class.primary_key_attribute => record.primary_key)
12
+ thunkish.skip_validations = true
13
+ thunkish.mutable = false
14
+ thunkish
16
15
  else
17
16
  # :nocov:
18
17
  raise "Not sure what to do with a record that isn't loaded, created, or persisted"
@@ -21,14 +20,7 @@ module Foobara
21
20
  end
22
21
 
23
22
  def build_method
24
- if to_type.extends_type?(BuiltinTypes[:entity])
25
- # TODO: test this code path
26
- # :nocov:
27
- :build
28
- # :nocov:
29
- else
30
- :new
31
- end
23
+ :build
32
24
  end
33
25
  end
34
26
  end
@@ -21,6 +21,10 @@ module Foobara
21
21
  domains.map(&:types).flatten
22
22
  end
23
23
 
24
+ def detached_entities
25
+ domains.map(&:detached_entities).flatten
26
+ end
27
+
24
28
  def entities
25
29
  domains.map(&:entities).flatten
26
30
  end
@@ -31,6 +31,10 @@ module Foobara
31
31
  end
32
32
  end
33
33
 
34
+ def detached_entities
35
+ organizations.map(&:detached_entities).flatten
36
+ end
37
+
34
38
  def entities
35
39
  organizations.map(&:entities).flatten
36
40
  end
@@ -72,7 +72,7 @@ module Foobara
72
72
 
73
73
  # TODO: replace this with primitive?
74
74
  def builtin?
75
- BuiltinTypes.builtin_reference?(reference)
75
+ BuiltinTypes.builtin_reference?(reference) || self[:builtin]
76
76
  end
77
77
 
78
78
  def primitive?
@@ -7,7 +7,11 @@ module Foobara
7
7
 
8
8
  module Concerns
9
9
  module StateTransitions
10
- foobara_delegate :close!, :currently_open?, to: :state_machine
10
+ foobara_delegate :close, to: :state_machine
11
+
12
+ def currently_open?
13
+ state_machine.currently_open?
14
+ end
11
15
 
12
16
  def open!
13
17
  state_machine.open! do
@@ -14,7 +14,9 @@ module Foobara
14
14
  self.tables = {}
15
15
  end
16
16
 
17
- foobara_delegate :entity_attributes_crud_driver, to: :entity_base
17
+ def entity_attributes_crud_driver
18
+ entity_base.entity_attributes_crud_driver
19
+ end
18
20
 
19
21
  def create(entity_class, attributes = {})
20
22
  Persistence.to_base(entity_class).transaction(existing_transaction: self) do
data/version.rb ADDED
@@ -0,0 +1,6 @@
1
+ module Foobara
2
+ module Version
3
+ VERSION = "0.1.6".freeze
4
+ MINIMUM_RUBY_VERSION = ">= 3.4.0".freeze
5
+ end
6
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foobara
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miles Georgi
@@ -491,6 +491,7 @@ files:
491
491
  - projects/value/src/validator.rb
492
492
  - projects/weak_object_set/lib/foobara/weak_object_set.rb
493
493
  - projects/weak_object_set/src/weak_object_set.rb
494
+ - version.rb
494
495
  homepage: https://foobara.com
495
496
  licenses:
496
497
  - MPL-2.0