cmdx 1.1.1 → 1.5.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 (193) hide show
  1. checksums.yaml +4 -4
  2. data/.DS_Store +0 -0
  3. data/.cursor/prompts/docs.md +4 -1
  4. data/.cursor/prompts/llms.md +20 -0
  5. data/.cursor/prompts/rspec.md +4 -1
  6. data/.cursor/prompts/yardoc.md +3 -2
  7. data/.cursor/rules/cursor-instructions.mdc +56 -1
  8. data/.irbrc +6 -0
  9. data/.rubocop.yml +29 -18
  10. data/.ruby-version +1 -1
  11. data/CHANGELOG.md +6 -128
  12. data/LLM.md +3317 -0
  13. data/README.md +68 -44
  14. data/docs/attributes/coercions.md +162 -0
  15. data/docs/attributes/defaults.md +90 -0
  16. data/docs/attributes/definitions.md +281 -0
  17. data/docs/attributes/naming.md +78 -0
  18. data/docs/attributes/validations.md +309 -0
  19. data/docs/basics/chain.md +56 -249
  20. data/docs/basics/context.md +56 -289
  21. data/docs/basics/execution.md +114 -0
  22. data/docs/basics/setup.md +37 -334
  23. data/docs/callbacks.md +89 -467
  24. data/docs/deprecation.md +91 -174
  25. data/docs/getting_started.md +212 -202
  26. data/docs/internationalization.md +11 -647
  27. data/docs/interruptions/exceptions.md +23 -198
  28. data/docs/interruptions/faults.md +71 -151
  29. data/docs/interruptions/halt.md +109 -186
  30. data/docs/logging.md +44 -256
  31. data/docs/middlewares.md +113 -426
  32. data/docs/outcomes/result.md +81 -228
  33. data/docs/outcomes/states.md +33 -221
  34. data/docs/outcomes/statuses.md +21 -311
  35. data/docs/tips_and_tricks.md +120 -70
  36. data/docs/workflows.md +99 -283
  37. data/lib/cmdx/.DS_Store +0 -0
  38. data/lib/cmdx/attribute.rb +229 -0
  39. data/lib/cmdx/attribute_registry.rb +94 -0
  40. data/lib/cmdx/attribute_value.rb +193 -0
  41. data/lib/cmdx/callback_registry.rb +69 -77
  42. data/lib/cmdx/chain.rb +56 -73
  43. data/lib/cmdx/coercion_registry.rb +52 -68
  44. data/lib/cmdx/coercions/array.rb +19 -18
  45. data/lib/cmdx/coercions/big_decimal.rb +20 -24
  46. data/lib/cmdx/coercions/boolean.rb +26 -25
  47. data/lib/cmdx/coercions/complex.rb +21 -22
  48. data/lib/cmdx/coercions/date.rb +25 -23
  49. data/lib/cmdx/coercions/date_time.rb +24 -25
  50. data/lib/cmdx/coercions/float.rb +25 -22
  51. data/lib/cmdx/coercions/hash.rb +31 -32
  52. data/lib/cmdx/coercions/integer.rb +30 -24
  53. data/lib/cmdx/coercions/rational.rb +29 -24
  54. data/lib/cmdx/coercions/string.rb +19 -22
  55. data/lib/cmdx/coercions/symbol.rb +37 -0
  56. data/lib/cmdx/coercions/time.rb +26 -25
  57. data/lib/cmdx/configuration.rb +49 -108
  58. data/lib/cmdx/context.rb +222 -44
  59. data/lib/cmdx/deprecator.rb +61 -0
  60. data/lib/cmdx/errors.rb +42 -252
  61. data/lib/cmdx/exceptions.rb +39 -0
  62. data/lib/cmdx/faults.rb +78 -39
  63. data/lib/cmdx/freezer.rb +51 -0
  64. data/lib/cmdx/identifier.rb +30 -0
  65. data/lib/cmdx/locale.rb +52 -0
  66. data/lib/cmdx/log_formatters/json.rb +21 -22
  67. data/lib/cmdx/log_formatters/key_value.rb +20 -22
  68. data/lib/cmdx/log_formatters/line.rb +15 -22
  69. data/lib/cmdx/log_formatters/logstash.rb +22 -23
  70. data/lib/cmdx/log_formatters/raw.rb +16 -22
  71. data/lib/cmdx/middleware_registry.rb +70 -74
  72. data/lib/cmdx/middlewares/correlate.rb +90 -54
  73. data/lib/cmdx/middlewares/runtime.rb +58 -0
  74. data/lib/cmdx/middlewares/timeout.rb +48 -68
  75. data/lib/cmdx/railtie.rb +12 -45
  76. data/lib/cmdx/result.rb +229 -314
  77. data/lib/cmdx/task.rb +194 -366
  78. data/lib/cmdx/utils/call.rb +49 -0
  79. data/lib/cmdx/utils/condition.rb +71 -0
  80. data/lib/cmdx/utils/format.rb +61 -0
  81. data/lib/cmdx/validator_registry.rb +63 -72
  82. data/lib/cmdx/validators/exclusion.rb +38 -67
  83. data/lib/cmdx/validators/format.rb +48 -49
  84. data/lib/cmdx/validators/inclusion.rb +43 -74
  85. data/lib/cmdx/validators/length.rb +91 -154
  86. data/lib/cmdx/validators/numeric.rb +87 -162
  87. data/lib/cmdx/validators/presence.rb +37 -50
  88. data/lib/cmdx/version.rb +1 -1
  89. data/lib/cmdx/worker.rb +178 -0
  90. data/lib/cmdx/workflow.rb +85 -81
  91. data/lib/cmdx.rb +19 -13
  92. data/lib/generators/cmdx/install_generator.rb +14 -13
  93. data/lib/generators/cmdx/task_generator.rb +25 -50
  94. data/lib/generators/cmdx/templates/install.rb +11 -46
  95. data/lib/generators/cmdx/templates/task.rb.tt +3 -2
  96. data/lib/locales/en.yml +18 -4
  97. data/src/cmdx-logo.png +0 -0
  98. metadata +32 -116
  99. data/docs/ai_prompts.md +0 -393
  100. data/docs/basics/call.md +0 -317
  101. data/docs/configuration.md +0 -344
  102. data/docs/parameters/coercions.md +0 -396
  103. data/docs/parameters/defaults.md +0 -335
  104. data/docs/parameters/definitions.md +0 -446
  105. data/docs/parameters/namespacing.md +0 -378
  106. data/docs/parameters/validations.md +0 -405
  107. data/docs/testing.md +0 -553
  108. data/lib/cmdx/callback.rb +0 -53
  109. data/lib/cmdx/chain_inspector.rb +0 -56
  110. data/lib/cmdx/chain_serializer.rb +0 -63
  111. data/lib/cmdx/coercion.rb +0 -57
  112. data/lib/cmdx/coercions/virtual.rb +0 -29
  113. data/lib/cmdx/core_ext/hash.rb +0 -83
  114. data/lib/cmdx/core_ext/module.rb +0 -98
  115. data/lib/cmdx/core_ext/object.rb +0 -125
  116. data/lib/cmdx/correlator.rb +0 -122
  117. data/lib/cmdx/error.rb +0 -60
  118. data/lib/cmdx/fault.rb +0 -140
  119. data/lib/cmdx/immutator.rb +0 -52
  120. data/lib/cmdx/lazy_struct.rb +0 -246
  121. data/lib/cmdx/log_formatters/pretty_json.rb +0 -40
  122. data/lib/cmdx/log_formatters/pretty_key_value.rb +0 -38
  123. data/lib/cmdx/log_formatters/pretty_line.rb +0 -41
  124. data/lib/cmdx/logger.rb +0 -49
  125. data/lib/cmdx/logger_ansi.rb +0 -68
  126. data/lib/cmdx/logger_serializer.rb +0 -116
  127. data/lib/cmdx/middleware.rb +0 -70
  128. data/lib/cmdx/parameter.rb +0 -312
  129. data/lib/cmdx/parameter_evaluator.rb +0 -231
  130. data/lib/cmdx/parameter_inspector.rb +0 -66
  131. data/lib/cmdx/parameter_registry.rb +0 -106
  132. data/lib/cmdx/parameter_serializer.rb +0 -59
  133. data/lib/cmdx/result_ansi.rb +0 -71
  134. data/lib/cmdx/result_inspector.rb +0 -71
  135. data/lib/cmdx/result_logger.rb +0 -59
  136. data/lib/cmdx/result_serializer.rb +0 -104
  137. data/lib/cmdx/rspec/matchers.rb +0 -28
  138. data/lib/cmdx/rspec/result_matchers/be_executed.rb +0 -42
  139. data/lib/cmdx/rspec/result_matchers/be_failed_task.rb +0 -94
  140. data/lib/cmdx/rspec/result_matchers/be_skipped_task.rb +0 -94
  141. data/lib/cmdx/rspec/result_matchers/be_state_matchers.rb +0 -59
  142. data/lib/cmdx/rspec/result_matchers/be_status_matchers.rb +0 -57
  143. data/lib/cmdx/rspec/result_matchers/be_successful_task.rb +0 -87
  144. data/lib/cmdx/rspec/result_matchers/have_bad_outcome.rb +0 -51
  145. data/lib/cmdx/rspec/result_matchers/have_caused_failure.rb +0 -58
  146. data/lib/cmdx/rspec/result_matchers/have_chain_index.rb +0 -59
  147. data/lib/cmdx/rspec/result_matchers/have_context.rb +0 -86
  148. data/lib/cmdx/rspec/result_matchers/have_empty_metadata.rb +0 -54
  149. data/lib/cmdx/rspec/result_matchers/have_good_outcome.rb +0 -52
  150. data/lib/cmdx/rspec/result_matchers/have_metadata.rb +0 -114
  151. data/lib/cmdx/rspec/result_matchers/have_preserved_context.rb +0 -66
  152. data/lib/cmdx/rspec/result_matchers/have_received_thrown_failure.rb +0 -64
  153. data/lib/cmdx/rspec/result_matchers/have_runtime.rb +0 -78
  154. data/lib/cmdx/rspec/result_matchers/have_thrown_failure.rb +0 -76
  155. data/lib/cmdx/rspec/task_matchers/be_well_formed_task.rb +0 -62
  156. data/lib/cmdx/rspec/task_matchers/have_callback.rb +0 -85
  157. data/lib/cmdx/rspec/task_matchers/have_cmd_setting.rb +0 -68
  158. data/lib/cmdx/rspec/task_matchers/have_executed_callbacks.rb +0 -92
  159. data/lib/cmdx/rspec/task_matchers/have_middleware.rb +0 -46
  160. data/lib/cmdx/rspec/task_matchers/have_parameter.rb +0 -181
  161. data/lib/cmdx/task_deprecator.rb +0 -52
  162. data/lib/cmdx/task_processor.rb +0 -246
  163. data/lib/cmdx/task_serializer.rb +0 -57
  164. data/lib/cmdx/utils/ansi_color.rb +0 -73
  165. data/lib/cmdx/utils/log_timestamp.rb +0 -36
  166. data/lib/cmdx/utils/monotonic_runtime.rb +0 -34
  167. data/lib/cmdx/utils/name_affix.rb +0 -52
  168. data/lib/cmdx/validator.rb +0 -57
  169. data/lib/generators/cmdx/templates/workflow.rb.tt +0 -7
  170. data/lib/generators/cmdx/workflow_generator.rb +0 -84
  171. data/lib/locales/ar.yml +0 -35
  172. data/lib/locales/cs.yml +0 -35
  173. data/lib/locales/da.yml +0 -35
  174. data/lib/locales/de.yml +0 -35
  175. data/lib/locales/el.yml +0 -35
  176. data/lib/locales/es.yml +0 -35
  177. data/lib/locales/fi.yml +0 -35
  178. data/lib/locales/fr.yml +0 -35
  179. data/lib/locales/he.yml +0 -35
  180. data/lib/locales/hi.yml +0 -35
  181. data/lib/locales/it.yml +0 -35
  182. data/lib/locales/ja.yml +0 -35
  183. data/lib/locales/ko.yml +0 -35
  184. data/lib/locales/nl.yml +0 -35
  185. data/lib/locales/no.yml +0 -35
  186. data/lib/locales/pl.yml +0 -35
  187. data/lib/locales/pt.yml +0 -35
  188. data/lib/locales/ru.yml +0 -35
  189. data/lib/locales/sv.yml +0 -35
  190. data/lib/locales/th.yml +0 -35
  191. data/lib/locales/tr.yml +0 -35
  192. data/lib/locales/vi.yml +0 -35
  193. data/lib/locales/zh.yml +0 -35
@@ -1,335 +0,0 @@
1
- # Parameters - Defaults
2
-
3
- Parameter defaults provide fallback values when arguments are not provided or resolve to `nil`. Defaults ensure tasks have sensible values for optional parameters while maintaining flexibility for callers to override when needed.
4
-
5
- ## Table of Contents
6
-
7
- - [TLDR](#tldr)
8
- - [Default Fundamentals](#default-fundamentals)
9
- - [Dynamic Defaults](#dynamic-defaults)
10
- - [Defaults with Coercion and Validation](#defaults-with-coercion-and-validation)
11
- - [Nested Parameter Defaults](#nested-parameter-defaults)
12
- - [Error Handling](#error-handling)
13
-
14
- ## TLDR
15
-
16
- ```ruby
17
- # Fixed defaults
18
- optional :priority, default: "normal"
19
- optional :retries, type: :integer, default: 3
20
- optional :tags, type: :array, default: []
21
-
22
- # Dynamic defaults
23
- optional :created_at, default: -> { Time.now }
24
- optional :template, default: :determine_template
25
-
26
- # With coercion - defaults are coerced too
27
- optional :max_items, type: :integer, default: "50" # → 50
28
-
29
- # Nested defaults
30
- optional :config, type: :hash, default: {} do
31
- optional :timeout, default: 30
32
- end
33
- ```
34
-
35
- ## Default Fundamentals
36
-
37
- > [!NOTE]
38
- > Defaults apply when parameters are not provided or resolve to `nil`. They work seamlessly with coercion, validation, and nested parameters.
39
-
40
- ```ruby
41
- class ProcessOrderTask < CMDx::Task
42
- required :order_id, type: :integer
43
-
44
- # Fixed value defaults
45
- optional :priority, default: "standard"
46
- optional :send_email, type: :boolean, default: true
47
- optional :max_retries, type: :integer, default: 3
48
- optional :tags, type: :array, default: []
49
- optional :metadata, type: :hash, default: {}
50
-
51
- def call
52
- # Defaults used when parameters not provided
53
- process_order_with_priority(priority) # "standard"
54
- send_notification if send_email # true
55
- retry_failed_steps(max_retries) # 3
56
- end
57
- end
58
-
59
- # Using defaults
60
- ProcessOrderTask.call(order_id: 123)
61
- # priority: "standard", send_email: true, max_retries: 3
62
-
63
- # Overriding defaults
64
- ProcessOrderTask.call(
65
- order_id: 123,
66
- priority: "urgent",
67
- send_email: false,
68
- tags: ["rush"]
69
- )
70
- ```
71
-
72
- ## Dynamic Defaults
73
-
74
- > [!TIP]
75
- > Use procs, lambdas, or method symbols for dynamic defaults evaluated at runtime. Essential for timestamps, UUIDs, and context-dependent values.
76
-
77
- ```ruby
78
- class SendNotificationTask < CMDx::Task
79
- required :user_id, type: :integer
80
- required :message, type: :string
81
-
82
- # Proc defaults - evaluated when accessed
83
- optional :sent_at, type: :datetime, default: -> { Time.now }
84
- optional :tracking_id, default: -> { SecureRandom.uuid }
85
-
86
- # Environment-aware defaults
87
- optional :service, default: -> { Rails.env.production? ? "sendgrid" : "test" }
88
-
89
- # Method symbol defaults
90
- optional :template, default: :default_template
91
- optional :priority, default: :calculate_priority
92
-
93
- def call
94
- notification = {
95
- message: message,
96
- sent_at: sent_at, # Current time when accessed
97
- tracking_id: tracking_id, # Unique UUID when accessed
98
- template: template, # Result of default_template method
99
- priority: priority # Result of calculate_priority method
100
- }
101
-
102
- NotificationService.send(notification, service: service)
103
- end
104
-
105
- private
106
-
107
- def default_template
108
- user.premium? ? "premium_notification" : "standard_notification"
109
- end
110
-
111
- def calculate_priority
112
- user.vip? ? "high" : "normal"
113
- end
114
-
115
- def user
116
- @user ||= User.find(user_id)
117
- end
118
- end
119
- ```
120
-
121
- ## Defaults with Coercion and Validation
122
-
123
- > [!IMPORTANT]
124
- > Defaults are subject to the same coercion and validation rules as provided values, ensuring consistency and catching configuration errors early.
125
-
126
- ### Coercion with Defaults
127
-
128
- ```ruby
129
- class ConfigureServiceTask < CMDx::Task
130
- # String defaults coerced to target types
131
- optional :max_connections, type: :integer, default: "100"
132
- optional :config, type: :hash, default: '{"timeout": 30}'
133
- optional :allowed_hosts, type: :array, default: '["localhost"]'
134
- optional :debug_mode, type: :boolean, default: "false"
135
-
136
- # Dynamic defaults with coercion
137
- optional :session_id, type: :string, default: -> { Time.now.to_i }
138
-
139
- def call
140
- max_connections # → 100 (Integer from "100")
141
- config # → {"timeout" => 30} (Hash from JSON)
142
- allowed_hosts # → ["localhost"] (Array from JSON)
143
- debug_mode # → false (Boolean from "false")
144
- session_id # → "1640995200" (String from Integer)
145
- end
146
- end
147
- ```
148
-
149
- ### Validation with Defaults
150
-
151
- ```ruby
152
- class ScheduleTaskTask < CMDx::Task
153
- required :task_name, type: :string
154
-
155
- # Default must pass validation rules
156
- optional :priority, default: "medium",
157
- inclusion: { in: %w[low medium high urgent] }
158
-
159
- optional :timeout, type: :integer, default: 300,
160
- numeric: { min: 60, max: 3600 }
161
-
162
- optional :retry_count, type: :integer, default: 3,
163
- numeric: { min: 0, max: 10 }
164
-
165
- def call
166
- # All defaults validated against their rules
167
- schedule_task(task_name, priority: priority, timeout: timeout)
168
- end
169
- end
170
-
171
- # Invalid default would cause validation error
172
- # optional :priority, default: "invalid", inclusion: { in: %w[low medium high] }
173
- # → CMDx::ValidationError: priority invalid is not included in the list
174
- ```
175
-
176
- ## Nested Parameter Defaults
177
-
178
- ```ruby
179
- class ProcessPaymentTask < CMDx::Task
180
- required :amount, type: :float
181
- required :user_id, type: :integer
182
-
183
- # Nested structure with defaults at multiple levels
184
- optional :payment_config, type: :hash, default: {} do
185
- optional :method, default: "credit_card"
186
- optional :currency, default: "USD"
187
- optional :require_cvv, type: :boolean, default: true
188
-
189
- optional :billing_address, type: :hash, default: -> { user_default_address } do
190
- optional :country, default: "US"
191
- optional :state, default: -> { user_default_state }
192
- end
193
-
194
- optional :notification_settings, type: :hash, default: {} do
195
- optional :send_receipt, type: :boolean, default: true
196
- optional :send_sms, type: :boolean, default: false
197
- end
198
- end
199
-
200
- def call
201
- # Process payment with defaults applied at each level
202
- PaymentProcessor.charge(
203
- amount: amount,
204
- method: payment_config[:method], # "credit_card"
205
- currency: payment_config[:currency], # "USD"
206
- billing_address: payment_config[:billing_address],
207
- notifications: payment_config[:notification_settings]
208
- )
209
- end
210
-
211
- private
212
-
213
- def user
214
- @user ||= User.find(user_id)
215
- end
216
-
217
- def user_default_address
218
- user.billing_address&.to_hash || {}
219
- end
220
-
221
- def user_default_state
222
- user.billing_address&.state || "CA"
223
- end
224
- end
225
-
226
- # Usage with nested defaults
227
- ProcessPaymentTask.call(amount: 99.99, user_id: 123)
228
- # payment_config automatically gets:
229
- # {
230
- # method: "credit_card",
231
- # currency: "USD",
232
- # require_cvv: true,
233
- # billing_address: { country: "US", state: "CA" },
234
- # notification_settings: { send_receipt: true, send_sms: false }
235
- # }
236
- ```
237
-
238
- ## Error Handling
239
-
240
- > [!WARNING]
241
- > Default values that fail coercion or validation will cause task execution to fail with detailed error information.
242
-
243
- ### Validation Errors with Defaults
244
-
245
- ```ruby
246
- class BadDefaultsTask < CMDx::Task
247
- # This default will fail validation
248
- optional :priority, default: "invalid",
249
- inclusion: { in: %w[low medium high] }
250
-
251
- # This default will fail coercion
252
- optional :count, type: :integer, default: "not-a-number"
253
-
254
- def call
255
- # Won't reach here due to validation/coercion failures
256
- end
257
- end
258
-
259
- result = BadDefaultsTask.call
260
- result.failed? # → true
261
- result.metadata
262
- # {
263
- # reason: "priority invalid is not included in the list. count could not coerce into an integer.",
264
- # messages: {
265
- # priority: ["invalid is not included in the list"],
266
- # count: ["could not coerce into an integer"]
267
- # }
268
- # }
269
- ```
270
-
271
- ### Dynamic Default Errors
272
-
273
- ```ruby
274
- class ProblematicDefaultsTask < CMDx::Task
275
- # Method that might raise an error
276
- optional :config, default: :load_external_config
277
-
278
- # Proc that might fail
279
- optional :api_key, default: -> { fetch_api_key_from_vault }
280
-
281
- def call
282
- # Task logic
283
- end
284
-
285
- private
286
-
287
- def load_external_config
288
- # This might raise if external service is down
289
- ExternalConfigService.fetch_config
290
- rescue => e
291
- raise CMDx::Error, "Failed to load default config: #{e.message}"
292
- end
293
-
294
- def fetch_api_key_from_vault
295
- # This might raise if vault is unavailable
296
- VaultService.get_secret("api_key")
297
- rescue => e
298
- raise CMDx::Error, "Failed to fetch default API key: #{e.message}"
299
- end
300
- end
301
- ```
302
-
303
- ### Nil vs Missing Parameters
304
-
305
- ```ruby
306
- class NilHandlingTask < CMDx::Task
307
- optional :status, default: "active"
308
- optional :tags, type: :array, default: []
309
-
310
- def call
311
- status # Default applied based on input
312
- tags # Default applied based on input
313
- end
314
- end
315
-
316
- # Missing parameters use defaults
317
- NilHandlingTask.call
318
- # status: "active", tags: []
319
-
320
- # Explicitly nil parameters also use defaults
321
- NilHandlingTask.call(status: nil, tags: nil)
322
- # status: "active", tags: []
323
-
324
- # Empty string is NOT nil - no default applied
325
- NilHandlingTask.call(status: "", tags: "")
326
- # status: "", tags: "" (string, not array - may cause coercion error)
327
- ```
328
-
329
- > [!TIP]
330
- > Defaults only apply to `nil` values. Empty strings, empty arrays, or false values are considered valid inputs and won't trigger defaults.
331
-
332
- ---
333
-
334
- - **Prev:** [Parameters - Validations](validations.md)
335
- - **Next:** [Callbacks](../callbacks.md)