operandi 5.0.0

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 (107) hide show
  1. checksums.yaml +7 -0
  2. data/.cursor/rules/services/RULE.md +269 -0
  3. data/.cursor/rules/services-rspec/RULE.md +354 -0
  4. data/.github/dependabot.yml +11 -0
  5. data/.github/workflows/ci.yml +77 -0
  6. data/.gitignore +25 -0
  7. data/.rspec +3 -0
  8. data/.rubocop.yml +134 -0
  9. data/.ruby-version +1 -0
  10. data/.vscode/cspell.json +18 -0
  11. data/.vscode/project-words.txt +12 -0
  12. data/AGENTS.md +139 -0
  13. data/CHANGELOG.md +111 -0
  14. data/CLAUDE.md +139 -0
  15. data/CODE_OF_CONDUCT.md +74 -0
  16. data/Gemfile +28 -0
  17. data/Gemfile.lock +149 -0
  18. data/LICENSE.txt +21 -0
  19. data/README.md +172 -0
  20. data/Rakefile +8 -0
  21. data/bin/console +15 -0
  22. data/bin/setup +8 -0
  23. data/config/default.yml +57 -0
  24. data/docs/README.md +105 -0
  25. data/docs/SUMMARY.md +31 -0
  26. data/docs/arguments.md +275 -0
  27. data/docs/best-practices.md +153 -0
  28. data/docs/callbacks.md +475 -0
  29. data/docs/concepts.md +79 -0
  30. data/docs/configuration.md +218 -0
  31. data/docs/context.md +128 -0
  32. data/docs/crud.md +525 -0
  33. data/docs/errors.md +331 -0
  34. data/docs/generators.md +250 -0
  35. data/docs/outputs.md +150 -0
  36. data/docs/pundit-authorization.md +320 -0
  37. data/docs/quickstart.md +133 -0
  38. data/docs/recipes.md +14 -0
  39. data/docs/rubocop.md +430 -0
  40. data/docs/ruby-lsp.md +121 -0
  41. data/docs/service-rendering.md +222 -0
  42. data/docs/sorbet-runtime.md +283 -0
  43. data/docs/steps.md +438 -0
  44. data/docs/tapioca.md +188 -0
  45. data/docs/testing.md +548 -0
  46. data/lib/generators/operandi/install/USAGE +15 -0
  47. data/lib/generators/operandi/install/install_generator.rb +45 -0
  48. data/lib/generators/operandi/install/templates/application_service.rb.tt +8 -0
  49. data/lib/generators/operandi/install/templates/application_service_spec.rb.tt +7 -0
  50. data/lib/generators/operandi/install/templates/initializer.rb.tt +30 -0
  51. data/lib/generators/operandi/service/USAGE +21 -0
  52. data/lib/generators/operandi/service/service_generator.rb +80 -0
  53. data/lib/generators/operandi/service/templates/service.rb.tt +48 -0
  54. data/lib/generators/operandi/service/templates/service_spec.rb.tt +40 -0
  55. data/lib/operandi/base.rb +230 -0
  56. data/lib/operandi/base_with_context.rb +57 -0
  57. data/lib/operandi/callbacks.rb +353 -0
  58. data/lib/operandi/collection.rb +166 -0
  59. data/lib/operandi/concerns/execution.rb +80 -0
  60. data/lib/operandi/concerns/parent_service.rb +32 -0
  61. data/lib/operandi/concerns/state_management.rb +34 -0
  62. data/lib/operandi/config.rb +142 -0
  63. data/lib/operandi/constants.rb +96 -0
  64. data/lib/operandi/dsl/arguments_dsl.rb +83 -0
  65. data/lib/operandi/dsl/outputs_dsl.rb +79 -0
  66. data/lib/operandi/dsl/steps_dsl.rb +206 -0
  67. data/lib/operandi/dsl/validation.rb +171 -0
  68. data/lib/operandi/exceptions.rb +66 -0
  69. data/lib/operandi/message.rb +52 -0
  70. data/lib/operandi/messages.rb +185 -0
  71. data/lib/operandi/rspec/matchers/define_argument.rb +172 -0
  72. data/lib/operandi/rspec/matchers/define_output.rb +145 -0
  73. data/lib/operandi/rspec/matchers/define_step.rb +223 -0
  74. data/lib/operandi/rspec/matchers/execute_step.rb +228 -0
  75. data/lib/operandi/rspec/matchers/have_error_on.rb +144 -0
  76. data/lib/operandi/rspec/matchers/have_warning_on.rb +146 -0
  77. data/lib/operandi/rspec/matchers/trigger_callback.rb +136 -0
  78. data/lib/operandi/rspec.rb +15 -0
  79. data/lib/operandi/rubocop/cop/operandi/argument_type_required.rb +52 -0
  80. data/lib/operandi/rubocop/cop/operandi/condition_method_exists.rb +173 -0
  81. data/lib/operandi/rubocop/cop/operandi/deprecated_accessors.rb +113 -0
  82. data/lib/operandi/rubocop/cop/operandi/deprecated_methods.rb +113 -0
  83. data/lib/operandi/rubocop/cop/operandi/dsl_order.rb +181 -0
  84. data/lib/operandi/rubocop/cop/operandi/missing_private_keyword.rb +102 -0
  85. data/lib/operandi/rubocop/cop/operandi/no_direct_instantiation.rb +66 -0
  86. data/lib/operandi/rubocop/cop/operandi/no_hash_argument.rb +101 -0
  87. data/lib/operandi/rubocop/cop/operandi/output_type_required.rb +52 -0
  88. data/lib/operandi/rubocop/cop/operandi/prefer_fail_method.rb +112 -0
  89. data/lib/operandi/rubocop/cop/operandi/prefer_optional_over_default_nil.rb +124 -0
  90. data/lib/operandi/rubocop/cop/operandi/redundant_optional.rb +103 -0
  91. data/lib/operandi/rubocop/cop/operandi/reserved_name.rb +56 -0
  92. data/lib/operandi/rubocop/cop/operandi/step_method_exists.rb +134 -0
  93. data/lib/operandi/rubocop.rb +22 -0
  94. data/lib/operandi/settings/field.rb +147 -0
  95. data/lib/operandi/settings/step.rb +105 -0
  96. data/lib/operandi/utils.rb +36 -0
  97. data/lib/operandi/version.rb +5 -0
  98. data/lib/operandi.rb +11 -0
  99. data/lib/ruby_lsp/operandi/addon.rb +37 -0
  100. data/lib/ruby_lsp/operandi/definition.rb +134 -0
  101. data/lib/ruby_lsp/operandi/indexing_enhancement.rb +224 -0
  102. data/lib/tapioca/dsl/compilers/operandi.rb +378 -0
  103. data/operandi.gemspec +33 -0
  104. data/rbi/operandi.rbi +197 -0
  105. data/sorbet/cache/data.mdb +0 -0
  106. data/sorbet/cache/lock.mdb +0 -0
  107. metadata +151 -0
data/rbi/operandi.rbi ADDED
@@ -0,0 +1,197 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ # RBI signatures for Operandi gem.
5
+ # These signatures provide Sorbet type checking without requiring sorbet-runtime as a dependency.
6
+
7
+ module Operandi
8
+ class Error < StandardError; end
9
+
10
+ class RuntimeError < Error
11
+ sig { params(message: T.nilable(String), service: Operandi::Base).void }
12
+ def initialize(message = nil, service:); end
13
+
14
+ sig { returns(Operandi::Base) }
15
+ def service; end
16
+ end
17
+
18
+ class ArgTypeError < Error
19
+ sig { params(message: T.nilable(String), service_class: T.class_of(Operandi::Base)).void }
20
+ def initialize(message = nil, service_class:); end
21
+
22
+ sig { returns(T.class_of(Operandi::Base)) }
23
+ def service_class; end
24
+ end
25
+
26
+ class Base
27
+ # Attributes
28
+ sig { returns(Operandi::Messages) }
29
+ def errors; end
30
+
31
+ sig { returns(Operandi::Messages) }
32
+ def warnings; end
33
+
34
+ # Instance methods
35
+ sig { returns(T::Boolean) }
36
+ def success?; end
37
+
38
+ sig { returns(T::Boolean) }
39
+ def successful?; end
40
+
41
+ sig { returns(T::Boolean) }
42
+ def failed?; end
43
+
44
+ sig { returns(T::Boolean) }
45
+ def errors?; end
46
+
47
+ sig { returns(T::Boolean) }
48
+ def warnings?; end
49
+
50
+ sig { void }
51
+ def stop!; end
52
+
53
+ sig { returns(T::Boolean) }
54
+ def stopped?; end
55
+
56
+ sig { returns(T.noreturn) }
57
+ def stop_immediately!; end
58
+
59
+ sig { params(message: String).void }
60
+ def fail!(message); end
61
+
62
+ sig { params(message: String).returns(T.noreturn) }
63
+ def fail_immediately!(message); end
64
+
65
+ sig { void }
66
+ def call; end
67
+
68
+ # Class methods
69
+ class << self
70
+ sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
71
+ def class_config; end
72
+
73
+ sig { params(class_config: T.nilable(T::Hash[Symbol, T.untyped])).returns(T.nilable(T::Hash[Symbol, T.untyped])) }
74
+ def class_config=(class_config); end
75
+
76
+ sig { params(config: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
77
+ def config(config = {}); end
78
+
79
+ sig { params(kwargs: T.untyped).returns(T.attached_class) }
80
+ def run(**kwargs); end
81
+
82
+ sig { params(kwargs: T.untyped).returns(T.attached_class) }
83
+ def run!(**kwargs); end
84
+
85
+ sig {
86
+ params(
87
+ service_or_config: T.any(Operandi::Base, T::Hash[Symbol, T.untyped]),
88
+ config: T::Hash[Symbol, T.untyped],
89
+ ).returns(Operandi::BaseWithContext)
90
+ }
91
+ def with(service_or_config, config = {}); end
92
+ end
93
+ end
94
+
95
+ class BaseWithContext
96
+ sig {
97
+ params(
98
+ service_class: T.class_of(Operandi::Base),
99
+ parent_service: T.nilable(Operandi::Base),
100
+ config: T::Hash[Symbol, T.untyped],
101
+ ).void
102
+ }
103
+ def initialize(service_class, parent_service, config); end
104
+
105
+ sig { params(kwargs: T.untyped).returns(Operandi::Base) }
106
+ def run(**kwargs); end
107
+
108
+ sig { params(kwargs: T.untyped).returns(Operandi::Base) }
109
+ def run!(**kwargs); end
110
+ end
111
+
112
+ class Messages
113
+ sig {
114
+ params(
115
+ config: T::Hash[Symbol, T.untyped],
116
+ service: Operandi::Base,
117
+ ).void
118
+ }
119
+ def initialize(config = {}, service:); end
120
+
121
+ sig { params(key: Symbol).returns(T.nilable(T::Array[Operandi::Message])) }
122
+ def [](key); end
123
+
124
+ sig { returns(T::Boolean) }
125
+ def any?; end
126
+
127
+ sig { returns(T::Boolean) }
128
+ def empty?; end
129
+
130
+ sig { returns(Integer) }
131
+ def size; end
132
+
133
+ sig { returns(Integer) }
134
+ def count; end
135
+
136
+ sig { returns(T::Array[Symbol]) }
137
+ def keys; end
138
+
139
+ sig { params(key: Symbol).returns(T::Boolean) }
140
+ def key?(key); end
141
+
142
+ sig { params(key: Symbol).returns(T::Boolean) }
143
+ def has_key?(key); end
144
+
145
+ sig {
146
+ params(
147
+ key: Symbol,
148
+ texts: T.any(String, T::Array[String], Operandi::Message),
149
+ opts: T::Hash[Symbol, T.untyped],
150
+ ).void
151
+ }
152
+ def add(key, texts, opts = {}); end
153
+
154
+ sig { returns(T::Boolean) }
155
+ def break?; end
156
+
157
+ sig { params(entity: T.untyped, opts: T::Hash[Symbol, T.untyped]).void }
158
+ def copy_from(entity, opts = {}); end
159
+
160
+ sig { params(entity: T.untyped, opts: T::Hash[Symbol, T.untyped]).void }
161
+ def from_record(entity, opts = {}); end
162
+
163
+ sig { returns(T::Hash[Symbol, T::Array[String]]) }
164
+ def to_h; end
165
+ end
166
+
167
+ module Collection
168
+ class Base
169
+ sig { params(key: Symbol).returns(T::Boolean) }
170
+ def key?(key); end
171
+
172
+ sig { returns(T::Hash[Symbol, T.untyped]) }
173
+ def to_h; end
174
+
175
+ sig { params(key: Symbol, value: T.untyped).returns(T.untyped) }
176
+ def set(key, value); end
177
+
178
+ sig { params(key: Symbol).returns(T.untyped) }
179
+ def get(key); end
180
+
181
+ sig { params(key: Symbol).returns(T.untyped) }
182
+ def [](key); end
183
+
184
+ sig { params(key: Symbol, value: T.untyped).returns(T.untyped) }
185
+ def []=(key, value); end
186
+
187
+ sig { void }
188
+ def load_defaults; end
189
+
190
+ sig { void }
191
+ def validate!; end
192
+
193
+ sig { params(args: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
194
+ def extend_with_context(args); end
195
+ end
196
+ end
197
+ end
Binary file
Binary file
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: operandi
3
+ version: !ruby/object:Gem::Version
4
+ version: 5.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Kodkod
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: Operandi is a simple yet powerful way to organize business logic in Ruby
13
+ applications. Build services that are easy to test, maintain, and understand.
14
+ email:
15
+ - andrew@kodkod.me
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".cursor/rules/services-rspec/RULE.md"
21
+ - ".cursor/rules/services/RULE.md"
22
+ - ".github/dependabot.yml"
23
+ - ".github/workflows/ci.yml"
24
+ - ".gitignore"
25
+ - ".rspec"
26
+ - ".rubocop.yml"
27
+ - ".ruby-version"
28
+ - ".vscode/cspell.json"
29
+ - ".vscode/project-words.txt"
30
+ - AGENTS.md
31
+ - CHANGELOG.md
32
+ - CLAUDE.md
33
+ - CODE_OF_CONDUCT.md
34
+ - Gemfile
35
+ - Gemfile.lock
36
+ - LICENSE.txt
37
+ - README.md
38
+ - Rakefile
39
+ - bin/console
40
+ - bin/setup
41
+ - config/default.yml
42
+ - docs/README.md
43
+ - docs/SUMMARY.md
44
+ - docs/arguments.md
45
+ - docs/best-practices.md
46
+ - docs/callbacks.md
47
+ - docs/concepts.md
48
+ - docs/configuration.md
49
+ - docs/context.md
50
+ - docs/crud.md
51
+ - docs/errors.md
52
+ - docs/generators.md
53
+ - docs/outputs.md
54
+ - docs/pundit-authorization.md
55
+ - docs/quickstart.md
56
+ - docs/recipes.md
57
+ - docs/rubocop.md
58
+ - docs/ruby-lsp.md
59
+ - docs/service-rendering.md
60
+ - docs/sorbet-runtime.md
61
+ - docs/steps.md
62
+ - docs/tapioca.md
63
+ - docs/testing.md
64
+ - lib/generators/operandi/install/USAGE
65
+ - lib/generators/operandi/install/install_generator.rb
66
+ - lib/generators/operandi/install/templates/application_service.rb.tt
67
+ - lib/generators/operandi/install/templates/application_service_spec.rb.tt
68
+ - lib/generators/operandi/install/templates/initializer.rb.tt
69
+ - lib/generators/operandi/service/USAGE
70
+ - lib/generators/operandi/service/service_generator.rb
71
+ - lib/generators/operandi/service/templates/service.rb.tt
72
+ - lib/generators/operandi/service/templates/service_spec.rb.tt
73
+ - lib/operandi.rb
74
+ - lib/operandi/base.rb
75
+ - lib/operandi/base_with_context.rb
76
+ - lib/operandi/callbacks.rb
77
+ - lib/operandi/collection.rb
78
+ - lib/operandi/concerns/execution.rb
79
+ - lib/operandi/concerns/parent_service.rb
80
+ - lib/operandi/concerns/state_management.rb
81
+ - lib/operandi/config.rb
82
+ - lib/operandi/constants.rb
83
+ - lib/operandi/dsl/arguments_dsl.rb
84
+ - lib/operandi/dsl/outputs_dsl.rb
85
+ - lib/operandi/dsl/steps_dsl.rb
86
+ - lib/operandi/dsl/validation.rb
87
+ - lib/operandi/exceptions.rb
88
+ - lib/operandi/message.rb
89
+ - lib/operandi/messages.rb
90
+ - lib/operandi/rspec.rb
91
+ - lib/operandi/rspec/matchers/define_argument.rb
92
+ - lib/operandi/rspec/matchers/define_output.rb
93
+ - lib/operandi/rspec/matchers/define_step.rb
94
+ - lib/operandi/rspec/matchers/execute_step.rb
95
+ - lib/operandi/rspec/matchers/have_error_on.rb
96
+ - lib/operandi/rspec/matchers/have_warning_on.rb
97
+ - lib/operandi/rspec/matchers/trigger_callback.rb
98
+ - lib/operandi/rubocop.rb
99
+ - lib/operandi/rubocop/cop/operandi/argument_type_required.rb
100
+ - lib/operandi/rubocop/cop/operandi/condition_method_exists.rb
101
+ - lib/operandi/rubocop/cop/operandi/deprecated_accessors.rb
102
+ - lib/operandi/rubocop/cop/operandi/deprecated_methods.rb
103
+ - lib/operandi/rubocop/cop/operandi/dsl_order.rb
104
+ - lib/operandi/rubocop/cop/operandi/missing_private_keyword.rb
105
+ - lib/operandi/rubocop/cop/operandi/no_direct_instantiation.rb
106
+ - lib/operandi/rubocop/cop/operandi/no_hash_argument.rb
107
+ - lib/operandi/rubocop/cop/operandi/output_type_required.rb
108
+ - lib/operandi/rubocop/cop/operandi/prefer_fail_method.rb
109
+ - lib/operandi/rubocop/cop/operandi/prefer_optional_over_default_nil.rb
110
+ - lib/operandi/rubocop/cop/operandi/redundant_optional.rb
111
+ - lib/operandi/rubocop/cop/operandi/reserved_name.rb
112
+ - lib/operandi/rubocop/cop/operandi/step_method_exists.rb
113
+ - lib/operandi/settings/field.rb
114
+ - lib/operandi/settings/step.rb
115
+ - lib/operandi/utils.rb
116
+ - lib/operandi/version.rb
117
+ - lib/ruby_lsp/operandi/addon.rb
118
+ - lib/ruby_lsp/operandi/definition.rb
119
+ - lib/ruby_lsp/operandi/indexing_enhancement.rb
120
+ - lib/tapioca/dsl/compilers/operandi.rb
121
+ - operandi.gemspec
122
+ - rbi/operandi.rbi
123
+ - sorbet/cache/data.mdb
124
+ - sorbet/cache/lock.mdb
125
+ homepage: https://operandi-docs.vercel.app/
126
+ licenses:
127
+ - MIT
128
+ metadata:
129
+ allowed_push_host: https://rubygems.org
130
+ homepage_uri: https://operandi-docs.vercel.app/
131
+ source_code_uri: https://github.com/akodkod/operandi
132
+ changelog_uri: https://github.com/akodkod/operandi/blob/master/CHANGELOG.md
133
+ rubygems_mfa_required: 'true'
134
+ rdoc_options: []
135
+ require_paths:
136
+ - lib
137
+ required_ruby_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: 3.1.0
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ requirements: []
148
+ rubygems_version: 4.0.6
149
+ specification_version: 4
150
+ summary: Robust service architecture for Ruby/Rails applications
151
+ test_files: []