foobara 0.0.1

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 (359) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +5 -0
  3. data/.rubocop.yml +20 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +10 -0
  6. data/DECISION_LOG.md +220 -0
  7. data/Guardfile +9 -0
  8. data/LICENSE-AGPL.txt +666 -0
  9. data/LICENSE.txt +4 -0
  10. data/README.md +50 -0
  11. data/Rakefile +10 -0
  12. data/concepts.md +153 -0
  13. data/projects/builtin_types/lib/foobara/builtin_types.rb +67 -0
  14. data/projects/builtin_types/src/README.md +140 -0
  15. data/projects/builtin_types/src/array/casters/arrayable.rb +22 -0
  16. data/projects/builtin_types/src/array/supported_processors/element_type_declaration.rb +41 -0
  17. data/projects/builtin_types/src/array/supported_validators/size.rb +43 -0
  18. data/projects/builtin_types/src/associative_array/casters/array.rb +22 -0
  19. data/projects/builtin_types/src/associative_array/supported_processors/key_type_declaration.rb +44 -0
  20. data/projects/builtin_types/src/associative_array/supported_processors/value_type_declaration.rb +44 -0
  21. data/projects/builtin_types/src/atomic_duck.rb +6 -0
  22. data/projects/builtin_types/src/attributes/casters/array.rb +33 -0
  23. data/projects/builtin_types/src/attributes/casters/hash.rb +28 -0
  24. data/projects/builtin_types/src/attributes/supported_processors/element_type_declarations.rb +89 -0
  25. data/projects/builtin_types/src/attributes/supported_transformers/defaults/type_declaration_extension/extend_attributes_type_declaration/desugarizers/move_defaults_from_element_types_to_root.rb +40 -0
  26. data/projects/builtin_types/src/attributes/supported_transformers/defaults/type_declaration_extension/extend_attributes_type_declaration/desugarizers/symbolize_defaults.rb +31 -0
  27. data/projects/builtin_types/src/attributes/supported_transformers/defaults/type_declaration_extension/extend_attributes_type_declaration/type_declaration_validators/hash_with_symbolic_keys.rb +37 -0
  28. data/projects/builtin_types/src/attributes/supported_transformers/defaults/type_declaration_extension/extend_attributes_type_declaration/type_declaration_validators/valid_attribute_names.rb +60 -0
  29. data/projects/builtin_types/src/attributes/supported_transformers/defaults.rb +41 -0
  30. data/projects/builtin_types/src/attributes/supported_validators/required/type_declaration_extension/extend_attributes_type_declaration/desugarizers/move_required_from_element_types_to_root.rb +55 -0
  31. data/projects/builtin_types/src/attributes/supported_validators/required/type_declaration_extension/extend_attributes_type_declaration/type_declaration_validators/array_of_symbols.rb +47 -0
  32. data/projects/builtin_types/src/attributes/supported_validators/required/type_declaration_extension/extend_attributes_type_declaration/type_declaration_validators/array_with_valid_attribute_names.rb +54 -0
  33. data/projects/builtin_types/src/attributes/supported_validators/required.rb +51 -0
  34. data/projects/builtin_types/src/big_decimal/casters/integer.rb +21 -0
  35. data/projects/builtin_types/src/big_decimal/casters/string.rb +24 -0
  36. data/projects/builtin_types/src/boolean/casters/numeric.rb +21 -0
  37. data/projects/builtin_types/src/boolean/casters/string_or_symbol.rb +27 -0
  38. data/projects/builtin_types/src/builtin_types.rb +189 -0
  39. data/projects/builtin_types/src/date/casters/hash.rb +23 -0
  40. data/projects/builtin_types/src/date/casters/string.rb +40 -0
  41. data/projects/builtin_types/src/datetime/casters/date.rb +21 -0
  42. data/projects/builtin_types/src/datetime/casters/hash.rb +77 -0
  43. data/projects/builtin_types/src/datetime/casters/seconds_since_epoch.rb +21 -0
  44. data/projects/builtin_types/src/datetime/casters/string.rb +31 -0
  45. data/projects/builtin_types/src/duck/supported_casters/allow_nil.rb +38 -0
  46. data/projects/builtin_types/src/duck/supported_validators/instance_of/type_declaration_extension/extend_registered_type_declaration/desugarizers/class_desugarizer.rb +29 -0
  47. data/projects/builtin_types/src/duck/supported_validators/instance_of/type_declaration_extension/extend_registered_type_declaration/desugarizers/instance_of_class_desugarizer.rb +31 -0
  48. data/projects/builtin_types/src/duck/supported_validators/instance_of/type_declaration_extension/extend_registered_type_declaration/desugarizers/instance_of_symbol_desugarizer.rb +31 -0
  49. data/projects/builtin_types/src/duck/supported_validators/instance_of/type_declaration_extension/extend_registered_type_declaration/type_declaration_validators/is_valid_class.rb +43 -0
  50. data/projects/builtin_types/src/duck/supported_validators/instance_of.rb +42 -0
  51. data/projects/builtin_types/src/duck/supported_validators/one_of/type_declaration_extension/extend_registered_type_declaration/desugarizers/cast_one_of.rb +37 -0
  52. data/projects/builtin_types/src/duck/supported_validators/one_of/type_declaration_extension/extend_registered_type_declaration/desugarizers/module_desugarizer.rb +41 -0
  53. data/projects/builtin_types/src/duck/supported_validators/one_of.rb +41 -0
  54. data/projects/builtin_types/src/duck.rb +6 -0
  55. data/projects/builtin_types/src/duckture.rb +6 -0
  56. data/projects/builtin_types/src/email/transformers/downcase.rb +15 -0
  57. data/projects/builtin_types/src/email/validator_base.rb +94 -0
  58. data/projects/builtin_types/src/float/casters/integer.rb +21 -0
  59. data/projects/builtin_types/src/float/casters/string.rb +24 -0
  60. data/projects/builtin_types/src/integer/casters/string.rb +23 -0
  61. data/projects/builtin_types/src/number/supported_validators/max.rb +41 -0
  62. data/projects/builtin_types/src/number/supported_validators/min.rb +41 -0
  63. data/projects/builtin_types/src/string/casters/numeric.rb +21 -0
  64. data/projects/builtin_types/src/string/casters/symbol.rb +21 -0
  65. data/projects/builtin_types/src/string/supported_transformers/downcase.rb +11 -0
  66. data/projects/builtin_types/src/string/supported_validators/matches.rb +41 -0
  67. data/projects/builtin_types/src/string/supported_validators/max_length.rb +37 -0
  68. data/projects/builtin_types/src/symbol/casters/string.rb +21 -0
  69. data/projects/builtin_types/src/tuple/supported_processors/element_type_declarations/type_declaration_extension/extend_tuple_type_declaration/desugarizers/set_size.rb +32 -0
  70. data/projects/builtin_types/src/tuple/supported_processors/element_type_declarations/type_declaration_extension/extend_tuple_type_declaration/type_declaration_validators/size_matches.rb +50 -0
  71. data/projects/builtin_types/src/tuple/supported_processors/element_type_declarations.rb +59 -0
  72. data/projects/callback/lib/foobara/callback.rb +1 -0
  73. data/projects/callback/src/block/after.rb +10 -0
  74. data/projects/callback/src/block/around.rb +10 -0
  75. data/projects/callback/src/block/before.rb +10 -0
  76. data/projects/callback/src/block/concerns/block_parameter_not_allowed.rb +21 -0
  77. data/projects/callback/src/block/concerns/block_parameter_required.rb +21 -0
  78. data/projects/callback/src/block/concerns/keyword_argumentable_block.rb +31 -0
  79. data/projects/callback/src/block/concerns/single_argument_block.rb +22 -0
  80. data/projects/callback/src/block/concerns/type.rb +17 -0
  81. data/projects/callback/src/block/error.rb +10 -0
  82. data/projects/callback/src/block.rb +83 -0
  83. data/projects/callback/src/registry/base.rb +90 -0
  84. data/projects/callback/src/registry/chained_conditioned.rb +24 -0
  85. data/projects/callback/src/registry/chained_multiple_action.rb +24 -0
  86. data/projects/callback/src/registry/conditioned.rb +101 -0
  87. data/projects/callback/src/registry/multiple_action.rb +110 -0
  88. data/projects/callback/src/registry/single_action.rb +15 -0
  89. data/projects/callback/src/runner.rb +89 -0
  90. data/projects/callback/src/set.rb +56 -0
  91. data/projects/command/lib/foobara/command.rb +9 -0
  92. data/projects/command/src/command/entity_helpers.rb +145 -0
  93. data/projects/command/src/command.rb +36 -0
  94. data/projects/command/src/concerns/callbacks.rb +93 -0
  95. data/projects/command/src/concerns/description.rb +23 -0
  96. data/projects/command/src/concerns/domain_mappers.rb +35 -0
  97. data/projects/command/src/concerns/entities.rb +88 -0
  98. data/projects/command/src/concerns/errors.rb +181 -0
  99. data/projects/command/src/concerns/errors_type.rb +124 -0
  100. data/projects/command/src/concerns/inputs.rb +59 -0
  101. data/projects/command/src/concerns/inputs_type.rb +58 -0
  102. data/projects/command/src/concerns/namespace.rb +49 -0
  103. data/projects/command/src/concerns/reflection.rb +137 -0
  104. data/projects/command/src/concerns/result.rb +25 -0
  105. data/projects/command/src/concerns/result_type.rb +29 -0
  106. data/projects/command/src/concerns/runtime.rb +119 -0
  107. data/projects/command/src/concerns/state_machine.rb +12 -0
  108. data/projects/command/src/concerns/subcommands.rb +102 -0
  109. data/projects/command/src/concerns/transactions.rb +81 -0
  110. data/projects/command/src/state_machine.rb +57 -0
  111. data/projects/command/src/transformed_command.rb +459 -0
  112. data/projects/command_connectors/lib/foobara/command_connectors.rb +12 -0
  113. data/projects/command_connectors/src/command_connector.rb +401 -0
  114. data/projects/command_connectors/src/command_registry/allowed_rule.rb +29 -0
  115. data/projects/command_connectors/src/command_registry/exposed_command.rb +140 -0
  116. data/projects/command_connectors/src/command_registry/exposed_domain.rb +30 -0
  117. data/projects/command_connectors/src/command_registry/exposed_organization.rb +30 -0
  118. data/projects/command_connectors/src/command_registry.rb +257 -0
  119. data/projects/command_connectors/src/commands/describe.rb +36 -0
  120. data/projects/command_connectors/src/commands/list_commands.rb +51 -0
  121. data/projects/command_connectors/src/commands/ping.rb +21 -0
  122. data/projects/command_connectors/src/commands/query_git_commit_info.rb +81 -0
  123. data/projects/command_connectors/src/request.rb +99 -0
  124. data/projects/command_connectors/src/response.rb +17 -0
  125. data/projects/command_connectors/src/serializer.rb +25 -0
  126. data/projects/command_connectors/src/serializers/aggregate_serializer.rb +32 -0
  127. data/projects/command_connectors/src/serializers/atomic_serializer.rb +25 -0
  128. data/projects/command_connectors/src/serializers/entities_to_primary_keys_serializer.rb +28 -0
  129. data/projects/command_connectors/src/serializers/errors_serializer.rb +18 -0
  130. data/projects/command_connectors/src/serializers/json_serializer.rb +20 -0
  131. data/projects/command_connectors/src/serializers/noop_serializer.rb +20 -0
  132. data/projects/command_connectors/src/serializers/record_store_serializer.rb +31 -0
  133. data/projects/command_connectors/src/serializers/success_serializer.rb +14 -0
  134. data/projects/command_connectors/src/serializers/yaml_serializer.rb +20 -0
  135. data/projects/command_connectors/src/transformers/auth_errors_transformer.rb +35 -0
  136. data/projects/command_connectors/src/transformers/load_aggregates_pre_commit_transformer.rb +36 -0
  137. data/projects/command_connectors_http/lib/foobara/command_connectors_http.rb +6 -0
  138. data/projects/command_connectors_http/src/http/commands/get_options.rb +16 -0
  139. data/projects/command_connectors_http/src/http/commands/help/presenter/command.rb +14 -0
  140. data/projects/command_connectors_http/src/http/commands/help/presenter/domain.rb +14 -0
  141. data/projects/command_connectors_http/src/http/commands/help/presenter/entity.rb +14 -0
  142. data/projects/command_connectors_http/src/http/commands/help/presenter/error.rb +14 -0
  143. data/projects/command_connectors_http/src/http/commands/help/presenter/model.rb +14 -0
  144. data/projects/command_connectors_http/src/http/commands/help/presenter/organization.rb +14 -0
  145. data/projects/command_connectors_http/src/http/commands/help/presenter/processor.rb +14 -0
  146. data/projects/command_connectors_http/src/http/commands/help/presenter/processor_class.rb +14 -0
  147. data/projects/command_connectors_http/src/http/commands/help/presenter/root.rb +14 -0
  148. data/projects/command_connectors_http/src/http/commands/help/presenter/type.rb +14 -0
  149. data/projects/command_connectors_http/src/http/commands/help/presenter.rb +162 -0
  150. data/projects/command_connectors_http/src/http/commands/help/templates/command.html.erb +11 -0
  151. data/projects/command_connectors_http/src/http/commands/help/templates/domain.html.erb +1 -0
  152. data/projects/command_connectors_http/src/http/commands/help/templates/entity.html.erb +1 -0
  153. data/projects/command_connectors_http/src/http/commands/help/templates/error.html.erb +1 -0
  154. data/projects/command_connectors_http/src/http/commands/help/templates/model.html.erb +1 -0
  155. data/projects/command_connectors_http/src/http/commands/help/templates/organization.html.erb +1 -0
  156. data/projects/command_connectors_http/src/http/commands/help/templates/processor.html.erb +1 -0
  157. data/projects/command_connectors_http/src/http/commands/help/templates/processor_class.html.erb +1 -0
  158. data/projects/command_connectors_http/src/http/commands/help/templates/root.html.erb +3 -0
  159. data/projects/command_connectors_http/src/http/commands/help/templates/type.html.erb +1 -0
  160. data/projects/command_connectors_http/src/http/commands/help.rb +98 -0
  161. data/projects/command_connectors_http/src/http/request.rb +98 -0
  162. data/projects/command_connectors_http/src/http/response.rb +14 -0
  163. data/projects/command_connectors_http/src/http.rb +84 -0
  164. data/projects/common/lib/foobara/common.rb +11 -0
  165. data/projects/common/src/data_path.rb +272 -0
  166. data/projects/common/src/error.rb +215 -0
  167. data/projects/common/src/error_collection.rb +97 -0
  168. data/projects/common/src/error_key.rb +168 -0
  169. data/projects/common/src/outcome.rb +101 -0
  170. data/projects/common/src/possible_error.rb +80 -0
  171. data/projects/common/src/runtime_error.rb +24 -0
  172. data/projects/concerns/lib/foobara/concerns.rb +1 -0
  173. data/projects/concerns/src/concern.rb +93 -0
  174. data/projects/delegate/lib/foobara/delegate.rb +1 -0
  175. data/projects/delegate/src/extensions/module.rb +12 -0
  176. data/projects/domain/lib/foobara/domain.rb +25 -0
  177. data/projects/domain/src/domain.rb +65 -0
  178. data/projects/domain/src/domain_mapper/registry.rb +47 -0
  179. data/projects/domain/src/domain_mapper.rb +162 -0
  180. data/projects/domain/src/domain_module_extension.rb +510 -0
  181. data/projects/domain/src/extensions/foobara.rb +69 -0
  182. data/projects/domain/src/global_domain.rb +14 -0
  183. data/projects/domain/src/global_organization.rb +12 -0
  184. data/projects/domain/src/is_manifestable.rb +68 -0
  185. data/projects/domain/src/manifestable.rb +12 -0
  186. data/projects/domain/src/module_extension.rb +122 -0
  187. data/projects/domain/src/organization.rb +52 -0
  188. data/projects/domain/src/organization_module_extension.rb +50 -0
  189. data/projects/entity/lib/foobara/entity.rb +27 -0
  190. data/projects/entity/src/concerns/associations.rb +241 -0
  191. data/projects/entity/src/concerns/attributes.rb +170 -0
  192. data/projects/entity/src/concerns/callbacks.rb +97 -0
  193. data/projects/entity/src/concerns/initialization.rb +127 -0
  194. data/projects/entity/src/concerns/persistence.rb +142 -0
  195. data/projects/entity/src/concerns/primary_key.rb +43 -0
  196. data/projects/entity/src/concerns/queries.rb +96 -0
  197. data/projects/entity/src/concerns/reflection.rb +51 -0
  198. data/projects/entity/src/concerns/transactions.rb +31 -0
  199. data/projects/entity/src/concerns/types.rb +31 -0
  200. data/projects/entity/src/entity.rb +61 -0
  201. data/projects/entity/src/extensions/builtin_types/entity/casters/hash.rb +33 -0
  202. data/projects/entity/src/extensions/builtin_types/entity/validators/attributes_declaration.rb +32 -0
  203. data/projects/entity/src/extensions/builtin_types/entity.rb +6 -0
  204. data/projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration/attributes_handler_desugarizer.rb +14 -0
  205. data/projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration/hash_desugarizer.rb +43 -0
  206. data/projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration/model_class_desugarizer.rb +21 -0
  207. data/projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration/primary_key_desugarizer.rb +19 -0
  208. data/projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration/to_type_transformer.rb +64 -0
  209. data/projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration/validate_primary_key_is_symbol.rb +35 -0
  210. data/projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration/validate_primary_key_present.rb +27 -0
  211. data/projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration/validate_primary_key_references_attribute.rb +36 -0
  212. data/projects/entity/src/extensions/type_declarations/handlers/extend_entity_type_declaration.rb +11 -0
  213. data/projects/entity/src/new_prepend.rb +21 -0
  214. data/projects/entity/src/not_found_error.rb +72 -0
  215. data/projects/enumerated/lib/foobara/enumerated.rb +1 -0
  216. data/projects/enumerated/src/accessors.rb +61 -0
  217. data/projects/enumerated/src/values.rb +121 -0
  218. data/projects/foobara/lib/foobara/all.rb +44 -0
  219. data/projects/in_memory_crud_driver/lib/foobara/in_memory_crud_driver.rb +3 -0
  220. data/projects/in_memory_crud_driver/src/in_memory.rb +10 -0
  221. data/projects/in_memory_crud_driver_minimal/lib/foobara/in_memory_crud_driver_minimal.rb +1 -0
  222. data/projects/in_memory_crud_driver_minimal/src/in_memory_minimal.rb +113 -0
  223. data/projects/manifest/lib/foobara/manifest.rb +4 -0
  224. data/projects/manifest/src/foobara/manifest/array.rb +13 -0
  225. data/projects/manifest/src/foobara/manifest/attributes.rb +40 -0
  226. data/projects/manifest/src/foobara/manifest/base_manifest.rb +161 -0
  227. data/projects/manifest/src/foobara/manifest/command.rb +59 -0
  228. data/projects/manifest/src/foobara/manifest/domain.rb +43 -0
  229. data/projects/manifest/src/foobara/manifest/entity.rb +35 -0
  230. data/projects/manifest/src/foobara/manifest/error.rb +33 -0
  231. data/projects/manifest/src/foobara/manifest/model.rb +43 -0
  232. data/projects/manifest/src/foobara/manifest/organization.rb +45 -0
  233. data/projects/manifest/src/foobara/manifest/possible_error.rb +30 -0
  234. data/projects/manifest/src/foobara/manifest/processor.rb +11 -0
  235. data/projects/manifest/src/foobara/manifest/processor_class.rb +11 -0
  236. data/projects/manifest/src/foobara/manifest/root_manifest.rb +112 -0
  237. data/projects/manifest/src/foobara/manifest/type.rb +86 -0
  238. data/projects/manifest/src/foobara/manifest/type_declaration.rb +117 -0
  239. data/projects/model/lib/foobara/model.rb +23 -0
  240. data/projects/model/src/concerns/reflection.rb +22 -0
  241. data/projects/model/src/concerns/types.rb +104 -0
  242. data/projects/model/src/extensions/builtin_types/model/casters/hash.rb +23 -0
  243. data/projects/model/src/extensions/builtin_types/model/transformers/mutable.rb +26 -0
  244. data/projects/model/src/extensions/builtin_types/model/validators/attributes_declaration.rb +33 -0
  245. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/attributes_handler_desugarizer.rb +24 -0
  246. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/hash_desugarizer.rb +32 -0
  247. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/model_class_desugarizer.rb +119 -0
  248. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/to_type_transformer.rb +57 -0
  249. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration.rb +21 -0
  250. data/projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration/hash_desugarizer.rb +37 -0
  251. data/projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration/model_class_type_desugarizer.rb +25 -0
  252. data/projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration/mutable_validator.rb +46 -0
  253. data/projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration/normalize_mutable_attributes_desugarizer.rb +28 -0
  254. data/projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration/to_type_transformer.rb +27 -0
  255. data/projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration.rb +31 -0
  256. data/projects/model/src/extensions/type_declarations/handlers/registered_type_declaration/model_class_desugarizer.rb +23 -0
  257. data/projects/model/src/model.rb +320 -0
  258. data/projects/monorepo/lib/foobara/monorepo/project.rb +52 -0
  259. data/projects/monorepo/lib/foobara/monorepo.rb +63 -0
  260. data/projects/namespace/lib/foobara/namespace.rb +4 -0
  261. data/projects/namespace/src/ambiguous_registry.rb +104 -0
  262. data/projects/namespace/src/base_registry.rb +66 -0
  263. data/projects/namespace/src/extensions/module.rb +5 -0
  264. data/projects/namespace/src/is_namespace.rb +352 -0
  265. data/projects/namespace/src/namespace/lookup_mode.rb +41 -0
  266. data/projects/namespace/src/namespace.rb +61 -0
  267. data/projects/namespace/src/namespace_helpers.rb +273 -0
  268. data/projects/namespace/src/prefixless_registry.rb +54 -0
  269. data/projects/namespace/src/scoped.rb +113 -0
  270. data/projects/namespace/src/unambiguous_registry.rb +65 -0
  271. data/projects/persistence/lib/foobara/persistence.rb +22 -0
  272. data/projects/persistence/src/entity_attributes_crud_driver.rb +241 -0
  273. data/projects/persistence/src/entity_base/table.rb +14 -0
  274. data/projects/persistence/src/entity_base/transaction/concerns/entity_callback_handling.rb +157 -0
  275. data/projects/persistence/src/entity_base/transaction/concerns/state_transitions.rb +83 -0
  276. data/projects/persistence/src/entity_base/transaction/concerns/transaction_tracking.rb +53 -0
  277. data/projects/persistence/src/entity_base/transaction/state_machine.rb +27 -0
  278. data/projects/persistence/src/entity_base/transaction.rb +163 -0
  279. data/projects/persistence/src/entity_base/transaction_table/concerns/queries.rb +42 -0
  280. data/projects/persistence/src/entity_base/transaction_table/concerns/record_tracking.rb +134 -0
  281. data/projects/persistence/src/entity_base/transaction_table.rb +620 -0
  282. data/projects/persistence/src/entity_base.rb +114 -0
  283. data/projects/persistence/src/persistence.rb +172 -0
  284. data/projects/state_machine/lib/foobara/state_machine.rb +1 -0
  285. data/projects/state_machine/src/callbacks.rb +158 -0
  286. data/projects/state_machine/src/log_entry.rb +13 -0
  287. data/projects/state_machine/src/state_machine.rb +91 -0
  288. data/projects/state_machine/src/sugar.rb +125 -0
  289. data/projects/state_machine/src/transition_log.rb +19 -0
  290. data/projects/state_machine/src/validations.rb +69 -0
  291. data/projects/thread_parent/lib/foobara/thread_parent.rb +1 -0
  292. data/projects/thread_parent/src/thread_parent.rb +38 -0
  293. data/projects/type_declarations/lib/foobara/type_declarations.rb +131 -0
  294. data/projects/type_declarations/src/attributes.rb +34 -0
  295. data/projects/type_declarations/src/caster.rb +7 -0
  296. data/projects/type_declarations/src/desugarizer.rb +25 -0
  297. data/projects/type_declarations/src/dsl/attributes.rb +199 -0
  298. data/projects/type_declarations/src/element_processor.rb +7 -0
  299. data/projects/type_declarations/src/error_extension.rb +73 -0
  300. data/projects/type_declarations/src/handlers/extend_array_type_declaration/array_desugarizer.rb +31 -0
  301. data/projects/type_declarations/src/handlers/extend_array_type_declaration/element_type_declaration_desugarizer.rb +37 -0
  302. data/projects/type_declarations/src/handlers/extend_array_type_declaration/to_type_transformer.rb +22 -0
  303. data/projects/type_declarations/src/handlers/extend_array_type_declaration/type_set_to_array_desugarizer.rb +36 -0
  304. data/projects/type_declarations/src/handlers/extend_array_type_declaration.rb +14 -0
  305. data/projects/type_declarations/src/handlers/extend_associative_array_type_declaration/to_type_transformer.rb +28 -0
  306. data/projects/type_declarations/src/handlers/extend_associative_array_type_declaration.rb +20 -0
  307. data/projects/type_declarations/src/handlers/extend_attributes_type_declaration/dsl_desugarizer.rb +25 -0
  308. data/projects/type_declarations/src/handlers/extend_attributes_type_declaration/element_type_declarations_desugarizer.rb +34 -0
  309. data/projects/type_declarations/src/handlers/extend_attributes_type_declaration/hash_desugarizer.rb +60 -0
  310. data/projects/type_declarations/src/handlers/extend_attributes_type_declaration/to_type_transformer.rb +21 -0
  311. data/projects/type_declarations/src/handlers/extend_attributes_type_declaration.rb +16 -0
  312. data/projects/type_declarations/src/handlers/extend_registered_type_declaration/to_type_transformer.rb +75 -0
  313. data/projects/type_declarations/src/handlers/extend_registered_type_declaration.rb +23 -0
  314. data/projects/type_declarations/src/handlers/extend_tuple_type_declaration/array_desugarizer.rb +30 -0
  315. data/projects/type_declarations/src/handlers/extend_tuple_type_declaration/to_type_transformer.rb +24 -0
  316. data/projects/type_declarations/src/handlers/extend_tuple_type_declaration.rb +13 -0
  317. data/projects/type_declarations/src/handlers/registered_type_declaration/desugarizer_metadata_cleanup_desugarizer.rb +29 -0
  318. data/projects/type_declarations/src/handlers/registered_type_declaration/short_type_name_desugarizer.rb +65 -0
  319. data/projects/type_declarations/src/handlers/registered_type_declaration/strict_desugarizer.rb +32 -0
  320. data/projects/type_declarations/src/handlers/registered_type_declaration/strict_stringified_desugarizer.rb +39 -0
  321. data/projects/type_declarations/src/handlers/registered_type_declaration/symbol_desugarizer.rb +26 -0
  322. data/projects/type_declarations/src/handlers/registered_type_declaration/to_type_transformer.rb +28 -0
  323. data/projects/type_declarations/src/handlers/registered_type_declaration/type_desugarizer.rb +24 -0
  324. data/projects/type_declarations/src/handlers/registered_type_declaration.rb +26 -0
  325. data/projects/type_declarations/src/processor.rb +7 -0
  326. data/projects/type_declarations/src/to_type_transformer.rb +11 -0
  327. data/projects/type_declarations/src/transformer.rb +7 -0
  328. data/projects/type_declarations/src/type_builder.rb +112 -0
  329. data/projects/type_declarations/src/type_declaration_error.rb +9 -0
  330. data/projects/type_declarations/src/type_declaration_handler.rb +120 -0
  331. data/projects/type_declarations/src/type_declaration_handler_registry.rb +27 -0
  332. data/projects/type_declarations/src/type_declaration_validator.rb +19 -0
  333. data/projects/type_declarations/src/type_declarations.rb +128 -0
  334. data/projects/type_declarations/src/typed_transformer.rb +89 -0
  335. data/projects/type_declarations/src/validator.rb +7 -0
  336. data/projects/type_declarations/src/with_registries.rb +41 -0
  337. data/projects/types/lib/foobara/types.rb +11 -0
  338. data/projects/types/src/element_processor.rb +7 -0
  339. data/projects/types/src/extensions/error.rb +32 -0
  340. data/projects/types/src/type/concerns/reflection.rb +79 -0
  341. data/projects/types/src/type/concerns/supported_processor_registration.rb +56 -0
  342. data/projects/types/src/type.rb +375 -0
  343. data/projects/types/src/types.rb +4 -0
  344. data/projects/value/lib/foobara/value.rb +7 -0
  345. data/projects/value/src/caster.rb +84 -0
  346. data/projects/value/src/data_error.rb +27 -0
  347. data/projects/value/src/processor/casting.rb +123 -0
  348. data/projects/value/src/processor/multi.rb +63 -0
  349. data/projects/value/src/processor/pipeline.rb +27 -0
  350. data/projects/value/src/processor/runner.rb +38 -0
  351. data/projects/value/src/processor/selection.rb +90 -0
  352. data/projects/value/src/processor.rb +358 -0
  353. data/projects/value/src/transformer.rb +84 -0
  354. data/projects/value/src/validator.rb +53 -0
  355. data/projects/version/lib/foobara/version.rb +4 -0
  356. data/projects/version/src/version.rb +5 -0
  357. data/projects/weak_object_set/lib/foobara/weak_object_set.rb +3 -0
  358. data/projects/weak_object_set/src/weak_object_set.rb +163 -0
  359. metadata +445 -0
@@ -0,0 +1,102 @@
1
+ module Foobara
2
+ class Command
3
+ module Concerns
4
+ module Subcommands
5
+ include Concern
6
+
7
+ class AlreadyRegisteredSubcommand < StandardError; end
8
+ class SubcommandNotRegistered < StandardError; end
9
+ class CannotAccessDomain < StandardError; end
10
+
11
+ attr_accessor :is_subcommand
12
+
13
+ foobara_delegate :verify_depends_on!, to: :class
14
+
15
+ def subcommand?
16
+ is_subcommand
17
+ end
18
+
19
+ def run_subcommand!(subcommand_class, inputs = {})
20
+ domain = self.class.domain
21
+ sub_domain = subcommand_class.domain
22
+
23
+ unless domain.foobara_depends_on?(sub_domain)
24
+ raise CannotAccessDomain,
25
+ "Cannot access #{sub_domain} or its commands because #{domain} does not depend on it"
26
+ end
27
+
28
+ verify_depends_on!(subcommand_class)
29
+
30
+ subcommand = subcommand_class.new(inputs)
31
+ subcommand.is_subcommand = true
32
+ outcome = subcommand.run
33
+
34
+ if outcome.success?
35
+ outcome.result
36
+ else
37
+ outcome.errors.each do |error|
38
+ # problem... inner command could have a different category but we want this to be a runtime error...
39
+ # So I guess we should use our error class anyways but override its methods...
40
+ # Or do we want to let the inner category reign? Issue with that is the subcommand could have the same
41
+ # name as an input and collide (unlikely but possible.)
42
+ # So what to do? Wrapper error? Maybe introduce a sub command category for the wrapper?
43
+ # other solution instead.... add a runtime_path to Error
44
+ add_subcommand_error(subcommand, error)
45
+ end
46
+ end
47
+ end
48
+
49
+ module ClassMethods
50
+ def depends_on?(subcommand_name)
51
+ if subcommand_name.is_a?(Class)
52
+ subcommand_name = subcommand_name.scoped_full_name.to_sym
53
+ end
54
+
55
+ depends_on.include?(subcommand_name.to_sym)
56
+ end
57
+
58
+ def depends_on(*subcommand_classes)
59
+ return @depends_on ||= Set.new if subcommand_classes.empty?
60
+
61
+ if subcommand_classes.length == 1
62
+ subcommand_classes = Util.array(subcommand_classes.first)
63
+ end
64
+
65
+ subcommand_classes.each do |subcommand_class|
66
+ subcommand_name = subcommand_class.scoped_full_name.to_sym
67
+
68
+ if depends_on.include?(subcommand_name)
69
+ # :nocov:
70
+ raise AlreadyRegisteredSubcommand,
71
+ "Already registered #{subcommand_class} as a dependency of #{self}"
72
+ # :nocov:
73
+ end
74
+
75
+ depends_on << subcommand_name
76
+
77
+ register_possible_subcommand_errors(subcommand_class)
78
+ end
79
+ end
80
+
81
+ def verify_depends_on!(subcommand_class)
82
+ unless depends_on?(subcommand_class)
83
+ # :nocov:
84
+ raise SubcommandNotRegistered, "Need to declare #{subcommand_class} on #{self} with .depends_on"
85
+ # :nocov:
86
+ end
87
+ end
88
+
89
+ private
90
+
91
+ def register_possible_subcommand_errors(subcommand_class)
92
+ subcommand_class.possible_errors.each do |possible_error|
93
+ possible_error = possible_error.dup
94
+ possible_error.prepend_runtime_path!(subcommand_class.full_command_symbol)
95
+ register_possible_error_class(possible_error)
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,81 @@
1
+ module Foobara
2
+ class Command
3
+ module Concerns
4
+ module Transactions
5
+ include Concern
6
+
7
+ def transactions
8
+ @transactions ||= []
9
+ end
10
+
11
+ def opened_transactions
12
+ @opened_transactions ||= []
13
+ end
14
+
15
+ def auto_detect_current_transactions
16
+ bases = relevant_entity_classes.map(&:entity_base).uniq
17
+
18
+ bases.each do |base|
19
+ tx = base.current_transaction
20
+ transactions << tx if tx
21
+ end
22
+ end
23
+
24
+ def relevant_entity_classes
25
+ @relevant_entity_classes ||= begin
26
+ entity_classes = if inputs_type
27
+ Entity.construct_associations(
28
+ inputs_type
29
+ ).values.uniq.map(&:target_class)
30
+ else
31
+ []
32
+ end
33
+
34
+ if result_type
35
+ entity_classes += Entity.construct_associations(
36
+ result_type
37
+ ).values.uniq.map(&:target_class)
38
+ end
39
+
40
+ entity_classes += entity_classes.uniq.map do |entity_class|
41
+ entity_class.deep_associations.values
42
+ end.flatten.uniq.map(&:target_class)
43
+
44
+ [*entity_classes, *self.class.depends_on_entities].uniq
45
+ end
46
+ end
47
+
48
+ def open_transaction
49
+ auto_detect_current_transactions
50
+
51
+ bases_not_needing_transaction = transactions.map(&:entity_base)
52
+
53
+ bases_needing_transaction = relevant_entity_classes.map(&:entity_base).uniq - bases_not_needing_transaction
54
+
55
+ bases_needing_transaction.each do |entity_base|
56
+ transaction = entity_base.transaction
57
+ transaction.open!
58
+ opened_transactions << transaction
59
+ transactions << transaction
60
+ end
61
+ end
62
+
63
+ def rollback_transaction
64
+ opened_transactions.reverse.each do |transaction|
65
+ if transaction.currently_open?
66
+ # Hard to test this because halting and other exceptions rollback the transactions via
67
+ # block form but to be safe keeping this
68
+ # :nocov:
69
+ transaction.rollback!
70
+ # :nocov:
71
+ end
72
+ end
73
+ end
74
+
75
+ def commit_transaction
76
+ opened_transactions.reverse.each(&:commit!)
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,57 @@
1
+ module Foobara
2
+ class Command
3
+ class StateMachine < Foobara::StateMachine
4
+ transitions = %i[
5
+ open_transaction
6
+ cast_and_validate_inputs
7
+ load_records
8
+ validate_records
9
+ validate
10
+ run_execute
11
+ commit_transaction
12
+ succeed
13
+ error
14
+ fail
15
+ reset
16
+ ]
17
+
18
+ terminal_states = %i[succeeded errored failed]
19
+
20
+ states = %i[
21
+ initialized
22
+ transaction_opened
23
+ inputs_casted_and_validated
24
+ loaded_records
25
+ validated_records
26
+ validated_execution
27
+ executing
28
+ transaction_committed
29
+ ] + terminal_states
30
+
31
+ can_fail_states = states - terminal_states
32
+
33
+ transition_map = {
34
+ initialized: { open_transaction: :transaction_opened },
35
+ transaction_opened: { cast_and_validate_inputs: :inputs_casted_and_validated },
36
+ inputs_casted_and_validated: { load_records: :loaded_records },
37
+ loaded_records: { validate_records: :validated_records },
38
+ validated_records: { validate: :validated_execution },
39
+ validated_execution: { run_execute: :executing },
40
+ executing: { commit_transaction: :transaction_committed },
41
+ transaction_committed: { succeed: :succeeded },
42
+ terminal_states => { reset: :initialized },
43
+ can_fail_states => {
44
+ error: :errored,
45
+ fail: :failed
46
+ }
47
+ }
48
+
49
+ set_transition_map(
50
+ transition_map,
51
+ states:,
52
+ terminal_states:,
53
+ transitions:
54
+ )
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,459 @@
1
+ module Foobara
2
+ # TODO: feels so strange that this doesn't inherit from command
3
+ # TODO: move this to command connectors project
4
+ class TransformedCommand
5
+ class << self
6
+ attr_accessor :command_class,
7
+ :command_name,
8
+ :full_command_name,
9
+ :capture_unknown_error,
10
+ :inputs_transformers,
11
+ :result_transformers,
12
+ :errors_transformers,
13
+ :pre_commit_transformers,
14
+ # TODO: get at least these serializers out of here...
15
+ :serializers,
16
+ :allowed_rule,
17
+ :requires_authentication,
18
+ :authenticator
19
+
20
+ def subclass(
21
+ command_class,
22
+ full_command_name:,
23
+ command_name:,
24
+ inputs_transformers:,
25
+ result_transformers:,
26
+ errors_transformers:,
27
+ pre_commit_transformers:,
28
+ serializers:,
29
+ allowed_rule:,
30
+ requires_authentication:,
31
+ authenticator:,
32
+ suffix: nil,
33
+ capture_unknown_error: false
34
+ )
35
+ Class.new(self).tap do |klass|
36
+ klass.command_class = command_class
37
+ klass.command_name = command_name
38
+ klass.full_command_name = full_command_name
39
+ klass.capture_unknown_error = capture_unknown_error
40
+ klass.inputs_transformers = Util.array(inputs_transformers)
41
+ klass.result_transformers = Util.array(result_transformers)
42
+ klass.errors_transformers = Util.array(errors_transformers)
43
+ klass.pre_commit_transformers = Util.array(pre_commit_transformers)
44
+ klass.serializers = Util.array(serializers)
45
+ klass.allowed_rule = allowed_rule
46
+ klass.requires_authentication = requires_authentication
47
+ klass.authenticator = authenticator
48
+ end
49
+ end
50
+
51
+ foobara_delegate :description,
52
+ :domain,
53
+ :organization,
54
+ to: :command_class
55
+
56
+ def inputs_type
57
+ type = command_class.inputs_type
58
+
59
+ inputs_transformers.reverse.each do |transformer|
60
+ if transformer.is_a?(Class) && transformer < TypeDeclarations::TypedTransformer
61
+ new_type = transformer.type(type)
62
+
63
+ type = new_type if new_type
64
+ end
65
+ end
66
+
67
+ type
68
+ end
69
+
70
+ def result_type
71
+ type = command_class.result_type
72
+
73
+ result_transformers.each do |transformer|
74
+ if transformer.is_a?(Class) && transformer < TypeDeclarations::TypedTransformer
75
+ new_type = transformer.type(type)
76
+
77
+ type = new_type if new_type
78
+ end
79
+ end
80
+
81
+ type
82
+ end
83
+
84
+ def error_context_type_map
85
+ @error_context_type_map ||= begin
86
+ set = {}
87
+
88
+ command_class.possible_errors.each do |possible_error|
89
+ # For now, we get the input errors off the transformed inputs_type.
90
+ # This way if an inputs transformer changes the path of an input, we don't wind up with the old path
91
+ # in the errors.
92
+ if possible_error.error_class < Foobara::RuntimeError
93
+ set[possible_error.key.to_s] = possible_error
94
+ end
95
+ end
96
+
97
+ command_class.manually_added_possible_input_errors.each do |possible_error|
98
+ set[possible_error.key.to_s] = possible_error
99
+ end
100
+
101
+ inputs_type&.possible_errors&.each do |possible_error|
102
+ set[possible_error.key.to_s] = possible_error
103
+ end
104
+
105
+ errors_transformers.each do |transformer|
106
+ set = transformer.transform_error_context_type_map(self, set)
107
+ end
108
+
109
+ set
110
+ end
111
+ end
112
+
113
+ def possible_errors
114
+ @possible_errors ||= error_context_type_map.values
115
+ end
116
+
117
+ def possible_errors_manifest(to_include:)
118
+ possible_errors.map do |possible_error|
119
+ [possible_error.key.to_s, possible_error.foobara_manifest(to_include:)]
120
+ end.sort.to_h
121
+ end
122
+
123
+ def types_depended_on
124
+ # TODO: memoize this
125
+ # TODO: this should not delegate to command since transformers are in play
126
+ types = command_class.types_depended_on
127
+
128
+ type = inputs_type
129
+
130
+ if type != command_class.inputs_type
131
+ types |= if type.registered?
132
+ # TODO: if we ever change from attributes-only inputs type
133
+ # then this will be handy
134
+ # :nocov:
135
+ [type]
136
+ # :nocov:
137
+ else
138
+ type.types_depended_on
139
+ end
140
+ end
141
+
142
+ type = result_type
143
+
144
+ if type != command_class.result_type
145
+ types |= if type.registered?
146
+ # TODO: if we ever change from attributes-only inputs type
147
+ # then this will be handy
148
+ # :nocov:
149
+ [type]
150
+ # :nocov:
151
+ else
152
+ type.types_depended_on
153
+ end
154
+ end
155
+
156
+ types
157
+ end
158
+
159
+ def foobara_manifest(to_include:)
160
+ types = types_depended_on.select(&:registered?).map do |t|
161
+ to_include << t
162
+ t.foobara_manifest_reference
163
+ end.sort
164
+
165
+ inputs_transformers = self.inputs_transformers.map { |t| t.foobara_manifest(to_include:) }
166
+ result_transformers = self.result_transformers.map { |t| t.foobara_manifest(to_include:) }
167
+ errors_transformers = self.errors_transformers.map { |t| t.foobara_manifest(to_include:) }
168
+ pre_commit_transformers = self.pre_commit_transformers.map { |t| t.foobara_manifest(to_include:) }
169
+ serializers = self.serializers.map do |s|
170
+ if s.respond_to?(:foobara_manifest)
171
+ to_include << s
172
+ s.foobara_manifest_reference
173
+ else
174
+ { proc: s.to_s }
175
+ end
176
+ end
177
+
178
+ command_class.foobara_manifest(to_include:).merge(
179
+ Util.remove_blank(
180
+ types_depended_on: types,
181
+ inputs_type: inputs_type&.reference_or_declaration_data,
182
+ result_type: result_type&.reference_or_declaration_data,
183
+ possible_errors: possible_errors_manifest(to_include:),
184
+ capture_unknown_error:,
185
+ inputs_transformers:,
186
+ result_transformers:,
187
+ errors_transformers:,
188
+ pre_commit_transformers:,
189
+ serializers:,
190
+ requires_authentication:,
191
+ authenticator: authenticator&.manifest
192
+ )
193
+ )
194
+ end
195
+ end
196
+
197
+ attr_accessor :command, :untransformed_inputs, :transformed_inputs, :outcome, :authenticated_user
198
+
199
+ def initialize(untransformed_inputs = {})
200
+ self.untransformed_inputs = untransformed_inputs || {}
201
+
202
+ transform_inputs
203
+ construct_command
204
+ end
205
+
206
+ foobara_delegate :description, to: :command_class
207
+ foobara_delegate :full_command_name,
208
+ :command_name,
209
+ :command_class,
210
+ :capture_unknown_error,
211
+ :inputs_transformers,
212
+ :result_transformers,
213
+ :errors_transformers,
214
+ :pre_commit_transformers,
215
+ :serializers,
216
+ :requires_authentication,
217
+ :allowed_rule,
218
+ :authenticator,
219
+ to: :class
220
+
221
+ def run
222
+ authenticate if requires_authentication?
223
+ apply_allowed_rule
224
+ apply_pre_commit_transformers
225
+ run_command
226
+ # TODO: do this within the transaction!!!
227
+ transform_outcome
228
+
229
+ outcome
230
+ end
231
+
232
+ def requires_authentication?
233
+ !!requires_authentication
234
+ end
235
+
236
+ def transform_inputs
237
+ self.transformed_inputs = if inputs_transformer
238
+ inputs_transformer.process_value!(untransformed_inputs)
239
+ else
240
+ untransformed_inputs
241
+ end
242
+ end
243
+
244
+ def transform_result
245
+ if result_transformer
246
+ self.outcome = Outcome.success(result_transformer.process_value!(result))
247
+ end
248
+ end
249
+
250
+ def transform_errors
251
+ if errors_transformer
252
+ self.outcome = Outcome.errors(errors_transformer.process_value!(errors))
253
+ end
254
+ end
255
+
256
+ def inputs_transformer
257
+ return nil if inputs_transformers.empty?
258
+
259
+ transformers = transformers_to_processors(inputs_transformers, command_class.inputs_type)
260
+
261
+ if transformers.size == 1
262
+ transformers.first
263
+ else
264
+ Value::Processor::Pipeline.new(processors: transformers)
265
+ end
266
+ end
267
+
268
+ def result_transformer
269
+ return nil if result_transformers.empty?
270
+
271
+ transformers = transformers_to_processors(result_transformers, command_class.result_type)
272
+
273
+ if transformers.size == 1
274
+ transformers.first
275
+ else
276
+ Value::Processor::Pipeline.new(processors: transformers)
277
+ end
278
+ end
279
+
280
+ # TODO: let's get this out of here...
281
+ # we might want to have different serializers for different command instances of the same class.
282
+ # but currently serializers is set on the class. Since this class should not be concerned with serialization, we
283
+ # should just try to relocate this to the Request which could delegate to the registry for defaults.
284
+ def serializer
285
+ return nil if serializers.empty?
286
+
287
+ transformers = transformers_to_processors(serializers, nil)
288
+
289
+ if transformers.size == 1
290
+ transformers.first
291
+ else
292
+ Value::Processor::Pipeline.new(processors: transformers)
293
+ end
294
+ end
295
+
296
+ def errors_transformer
297
+ return nil if errors_transformers.empty?
298
+
299
+ transformers = transformers_to_processors(errors_transformers, nil)
300
+
301
+ if transformers.size == 1
302
+ transformers.first
303
+ else
304
+ Value::Processor::Pipeline.new(processors: transformers)
305
+ end
306
+ end
307
+
308
+ # TODO: memoize
309
+ def pre_commit_transformer
310
+ return nil if pre_commit_transformers.empty?
311
+
312
+ transformers = transformers_to_processors(pre_commit_transformers, nil)
313
+
314
+ if transformers.size == 1
315
+ transformers.first
316
+ else
317
+ Value::Processor::Pipeline.new(processors: transformers)
318
+ end
319
+ end
320
+
321
+ def transformers_to_processors(transformers, from_type)
322
+ transformers.map do |transformer|
323
+ if transformer.is_a?(Class)
324
+ if transformer < TypeDeclarations::TypedTransformer
325
+ transformer.new(from_type).tap do |tx|
326
+ new_type = tx.type
327
+ from_type = new_type if new_type
328
+ end
329
+ else
330
+ transformer.new(self)
331
+ end
332
+ elsif transformer.is_a?(Value::Processor)
333
+ transformer
334
+ elsif transformer.respond_to?(:call)
335
+ Value::Transformer.create(transform: transformer)
336
+ else
337
+ # :nocov:
338
+ raise "Not sure how to apply #{inputs_transformer}"
339
+ # :nocov:
340
+ end
341
+ end
342
+ end
343
+
344
+ def construct_command
345
+ self.command = command_class.new(transformed_inputs)
346
+ end
347
+
348
+ def authenticate
349
+ command.after_load_records do |command:, **|
350
+ self.authenticated_user = instance_eval(&:authenticator)
351
+
352
+ unless authenticated_user
353
+ self.outcome = Outcome.error(CommandConnector::UnauthenticatedError.new)
354
+
355
+ command.state_machine.error!
356
+ command.halt!
357
+ end
358
+ end
359
+ end
360
+
361
+ def apply_allowed_rule
362
+ rule = allowed_rule
363
+
364
+ if rule
365
+ command.after_load_records do |command:, **|
366
+ # NOTE: apparently no way to convert a lambda to a proc but lambda's won't work here...
367
+ # TODO: raise exception here if rule.lambda? is true, if this starts becoming a common error
368
+ is_allowed = instance_eval(&rule)
369
+
370
+ unless is_allowed
371
+ explanation = allowed_rule.explanation
372
+
373
+ if explanation.is_a?(Proc)
374
+ explanation = instance_eval(&explanation)
375
+ end
376
+
377
+ if explanation.nil?
378
+ explanation = allowed_rule.block.source || "No explanation."
379
+ end
380
+
381
+ error = CommandConnector::NotAllowedError.new(rule_symbol: rule.symbol, explanation:)
382
+ self.outcome = Outcome.error(error)
383
+
384
+ command.state_machine.error!
385
+ command.halt!
386
+ end
387
+ end
388
+ end
389
+ end
390
+
391
+ def apply_pre_commit_transformers
392
+ if pre_commit_transformer
393
+ command.before_commit_transaction do |**|
394
+ pre_commit_transformer.process_value!(self)
395
+ end
396
+ end
397
+ end
398
+
399
+ def run_command
400
+ outcome = command.run
401
+ self.outcome = outcome if outcome
402
+ rescue => e
403
+ if capture_unknown_error
404
+ # TODO: move to superclass?
405
+ self.outcome = Outcome.error(CommandConnector::UnknownError.new(e))
406
+ else
407
+ # :nocov:
408
+ raise
409
+ # :nocov:
410
+ end
411
+ end
412
+
413
+ def result
414
+ outcome.result
415
+ end
416
+
417
+ def errors
418
+ outcome.errors
419
+ end
420
+
421
+ def transform_outcome
422
+ if outcome.success?
423
+ # can we do this while still in the transaction of the command???
424
+ transform_result
425
+ else
426
+ transform_errors
427
+ end
428
+ end
429
+
430
+ # TODO: kill this
431
+ def serialize_result
432
+ body = if outcome.success?
433
+ outcome.result
434
+ else
435
+ outcome.errors
436
+ end
437
+
438
+ if serializer
439
+ serializer.process_value!(body)
440
+ else
441
+ body
442
+ end
443
+ end
444
+
445
+ def method_missing(method_name, *, **, &)
446
+ if command.respond_to?(method_name)
447
+ command.send(method_name, *, **, &)
448
+ else
449
+ # :nocov:
450
+ super
451
+ # :nocov:
452
+ end
453
+ end
454
+
455
+ def respond_to_missing?(method_name, private = false)
456
+ command.respond_to?(method_name, private) || super
457
+ end
458
+ end
459
+ end
@@ -0,0 +1,12 @@
1
+ # TODO: get this into its own project or at least move it to http
2
+ require "cgi"
3
+ # TODO: get this out of here and into its own project or at least move it to http
4
+ require "json"
5
+
6
+ module Foobara
7
+ module CommandConnectors
8
+ foobara_domain!
9
+ end
10
+
11
+ Monorepo.project :command_connectors
12
+ end