cmdx 1.1.2 → 1.5.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 (192) 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 +55 -1
  8. data/.irbrc +6 -0
  9. data/.rubocop.yml +29 -18
  10. data/CHANGELOG.md +11 -132
  11. data/LLM.md +3317 -0
  12. data/README.md +68 -44
  13. data/docs/attributes/coercions.md +162 -0
  14. data/docs/attributes/defaults.md +90 -0
  15. data/docs/attributes/definitions.md +281 -0
  16. data/docs/attributes/naming.md +78 -0
  17. data/docs/attributes/validations.md +309 -0
  18. data/docs/basics/chain.md +56 -249
  19. data/docs/basics/context.md +56 -289
  20. data/docs/basics/execution.md +114 -0
  21. data/docs/basics/setup.md +37 -334
  22. data/docs/callbacks.md +89 -467
  23. data/docs/deprecation.md +91 -174
  24. data/docs/getting_started.md +212 -202
  25. data/docs/internationalization.md +11 -647
  26. data/docs/interruptions/exceptions.md +23 -198
  27. data/docs/interruptions/faults.md +71 -151
  28. data/docs/interruptions/halt.md +109 -186
  29. data/docs/logging.md +44 -256
  30. data/docs/middlewares.md +113 -426
  31. data/docs/outcomes/result.md +81 -228
  32. data/docs/outcomes/states.md +33 -221
  33. data/docs/outcomes/statuses.md +21 -311
  34. data/docs/tips_and_tricks.md +120 -70
  35. data/docs/workflows.md +99 -283
  36. data/lib/cmdx/.DS_Store +0 -0
  37. data/lib/cmdx/attribute.rb +229 -0
  38. data/lib/cmdx/attribute_registry.rb +94 -0
  39. data/lib/cmdx/attribute_value.rb +193 -0
  40. data/lib/cmdx/callback_registry.rb +69 -77
  41. data/lib/cmdx/chain.rb +56 -73
  42. data/lib/cmdx/coercion_registry.rb +52 -68
  43. data/lib/cmdx/coercions/array.rb +19 -18
  44. data/lib/cmdx/coercions/big_decimal.rb +20 -24
  45. data/lib/cmdx/coercions/boolean.rb +26 -25
  46. data/lib/cmdx/coercions/complex.rb +21 -22
  47. data/lib/cmdx/coercions/date.rb +25 -23
  48. data/lib/cmdx/coercions/date_time.rb +24 -25
  49. data/lib/cmdx/coercions/float.rb +25 -22
  50. data/lib/cmdx/coercions/hash.rb +31 -32
  51. data/lib/cmdx/coercions/integer.rb +30 -24
  52. data/lib/cmdx/coercions/rational.rb +29 -24
  53. data/lib/cmdx/coercions/string.rb +19 -22
  54. data/lib/cmdx/coercions/symbol.rb +37 -0
  55. data/lib/cmdx/coercions/time.rb +26 -25
  56. data/lib/cmdx/configuration.rb +49 -108
  57. data/lib/cmdx/context.rb +222 -44
  58. data/lib/cmdx/deprecator.rb +61 -0
  59. data/lib/cmdx/errors.rb +42 -252
  60. data/lib/cmdx/exceptions.rb +39 -0
  61. data/lib/cmdx/faults.rb +78 -39
  62. data/lib/cmdx/freezer.rb +51 -0
  63. data/lib/cmdx/identifier.rb +30 -0
  64. data/lib/cmdx/locale.rb +52 -0
  65. data/lib/cmdx/log_formatters/json.rb +21 -22
  66. data/lib/cmdx/log_formatters/key_value.rb +20 -22
  67. data/lib/cmdx/log_formatters/line.rb +15 -22
  68. data/lib/cmdx/log_formatters/logstash.rb +22 -23
  69. data/lib/cmdx/log_formatters/raw.rb +16 -22
  70. data/lib/cmdx/middleware_registry.rb +70 -74
  71. data/lib/cmdx/middlewares/correlate.rb +90 -54
  72. data/lib/cmdx/middlewares/runtime.rb +58 -0
  73. data/lib/cmdx/middlewares/timeout.rb +48 -68
  74. data/lib/cmdx/railtie.rb +12 -45
  75. data/lib/cmdx/result.rb +229 -314
  76. data/lib/cmdx/task.rb +194 -366
  77. data/lib/cmdx/utils/call.rb +49 -0
  78. data/lib/cmdx/utils/condition.rb +71 -0
  79. data/lib/cmdx/utils/format.rb +61 -0
  80. data/lib/cmdx/validator_registry.rb +63 -72
  81. data/lib/cmdx/validators/exclusion.rb +38 -67
  82. data/lib/cmdx/validators/format.rb +48 -49
  83. data/lib/cmdx/validators/inclusion.rb +43 -74
  84. data/lib/cmdx/validators/length.rb +101 -162
  85. data/lib/cmdx/validators/numeric.rb +95 -170
  86. data/lib/cmdx/validators/presence.rb +37 -50
  87. data/lib/cmdx/version.rb +1 -1
  88. data/lib/cmdx/worker.rb +178 -0
  89. data/lib/cmdx/workflow.rb +85 -81
  90. data/lib/cmdx.rb +19 -13
  91. data/lib/generators/cmdx/install_generator.rb +14 -13
  92. data/lib/generators/cmdx/task_generator.rb +25 -50
  93. data/lib/generators/cmdx/templates/install.rb +11 -46
  94. data/lib/generators/cmdx/templates/task.rb.tt +3 -2
  95. data/lib/locales/en.yml +18 -4
  96. data/src/cmdx-logo.png +0 -0
  97. metadata +32 -116
  98. data/docs/ai_prompts.md +0 -393
  99. data/docs/basics/call.md +0 -317
  100. data/docs/configuration.md +0 -344
  101. data/docs/parameters/coercions.md +0 -396
  102. data/docs/parameters/defaults.md +0 -335
  103. data/docs/parameters/definitions.md +0 -446
  104. data/docs/parameters/namespacing.md +0 -378
  105. data/docs/parameters/validations.md +0 -405
  106. data/docs/testing.md +0 -553
  107. data/lib/cmdx/callback.rb +0 -53
  108. data/lib/cmdx/chain_inspector.rb +0 -56
  109. data/lib/cmdx/chain_serializer.rb +0 -63
  110. data/lib/cmdx/coercion.rb +0 -57
  111. data/lib/cmdx/coercions/virtual.rb +0 -29
  112. data/lib/cmdx/core_ext/hash.rb +0 -83
  113. data/lib/cmdx/core_ext/module.rb +0 -98
  114. data/lib/cmdx/core_ext/object.rb +0 -125
  115. data/lib/cmdx/correlator.rb +0 -122
  116. data/lib/cmdx/error.rb +0 -67
  117. data/lib/cmdx/fault.rb +0 -140
  118. data/lib/cmdx/immutator.rb +0 -52
  119. data/lib/cmdx/lazy_struct.rb +0 -246
  120. data/lib/cmdx/log_formatters/pretty_json.rb +0 -40
  121. data/lib/cmdx/log_formatters/pretty_key_value.rb +0 -38
  122. data/lib/cmdx/log_formatters/pretty_line.rb +0 -41
  123. data/lib/cmdx/logger.rb +0 -49
  124. data/lib/cmdx/logger_ansi.rb +0 -68
  125. data/lib/cmdx/logger_serializer.rb +0 -116
  126. data/lib/cmdx/middleware.rb +0 -70
  127. data/lib/cmdx/parameter.rb +0 -312
  128. data/lib/cmdx/parameter_evaluator.rb +0 -231
  129. data/lib/cmdx/parameter_inspector.rb +0 -66
  130. data/lib/cmdx/parameter_registry.rb +0 -106
  131. data/lib/cmdx/parameter_serializer.rb +0 -59
  132. data/lib/cmdx/result_ansi.rb +0 -71
  133. data/lib/cmdx/result_inspector.rb +0 -71
  134. data/lib/cmdx/result_logger.rb +0 -59
  135. data/lib/cmdx/result_serializer.rb +0 -104
  136. data/lib/cmdx/rspec/matchers.rb +0 -28
  137. data/lib/cmdx/rspec/result_matchers/be_executed.rb +0 -42
  138. data/lib/cmdx/rspec/result_matchers/be_failed_task.rb +0 -94
  139. data/lib/cmdx/rspec/result_matchers/be_skipped_task.rb +0 -94
  140. data/lib/cmdx/rspec/result_matchers/be_state_matchers.rb +0 -59
  141. data/lib/cmdx/rspec/result_matchers/be_status_matchers.rb +0 -57
  142. data/lib/cmdx/rspec/result_matchers/be_successful_task.rb +0 -87
  143. data/lib/cmdx/rspec/result_matchers/have_bad_outcome.rb +0 -51
  144. data/lib/cmdx/rspec/result_matchers/have_caused_failure.rb +0 -58
  145. data/lib/cmdx/rspec/result_matchers/have_chain_index.rb +0 -59
  146. data/lib/cmdx/rspec/result_matchers/have_context.rb +0 -86
  147. data/lib/cmdx/rspec/result_matchers/have_empty_metadata.rb +0 -54
  148. data/lib/cmdx/rspec/result_matchers/have_good_outcome.rb +0 -52
  149. data/lib/cmdx/rspec/result_matchers/have_metadata.rb +0 -114
  150. data/lib/cmdx/rspec/result_matchers/have_preserved_context.rb +0 -66
  151. data/lib/cmdx/rspec/result_matchers/have_received_thrown_failure.rb +0 -64
  152. data/lib/cmdx/rspec/result_matchers/have_runtime.rb +0 -78
  153. data/lib/cmdx/rspec/result_matchers/have_thrown_failure.rb +0 -76
  154. data/lib/cmdx/rspec/task_matchers/be_well_formed_task.rb +0 -62
  155. data/lib/cmdx/rspec/task_matchers/have_callback.rb +0 -85
  156. data/lib/cmdx/rspec/task_matchers/have_cmd_setting.rb +0 -68
  157. data/lib/cmdx/rspec/task_matchers/have_executed_callbacks.rb +0 -92
  158. data/lib/cmdx/rspec/task_matchers/have_middleware.rb +0 -46
  159. data/lib/cmdx/rspec/task_matchers/have_parameter.rb +0 -181
  160. data/lib/cmdx/task_deprecator.rb +0 -58
  161. data/lib/cmdx/task_processor.rb +0 -246
  162. data/lib/cmdx/task_serializer.rb +0 -57
  163. data/lib/cmdx/utils/ansi_color.rb +0 -73
  164. data/lib/cmdx/utils/log_timestamp.rb +0 -36
  165. data/lib/cmdx/utils/monotonic_runtime.rb +0 -34
  166. data/lib/cmdx/utils/name_affix.rb +0 -52
  167. data/lib/cmdx/validator.rb +0 -57
  168. data/lib/generators/cmdx/templates/workflow.rb.tt +0 -7
  169. data/lib/generators/cmdx/workflow_generator.rb +0 -84
  170. data/lib/locales/ar.yml +0 -35
  171. data/lib/locales/cs.yml +0 -35
  172. data/lib/locales/da.yml +0 -35
  173. data/lib/locales/de.yml +0 -35
  174. data/lib/locales/el.yml +0 -35
  175. data/lib/locales/es.yml +0 -35
  176. data/lib/locales/fi.yml +0 -35
  177. data/lib/locales/fr.yml +0 -35
  178. data/lib/locales/he.yml +0 -35
  179. data/lib/locales/hi.yml +0 -35
  180. data/lib/locales/it.yml +0 -35
  181. data/lib/locales/ja.yml +0 -35
  182. data/lib/locales/ko.yml +0 -35
  183. data/lib/locales/nl.yml +0 -35
  184. data/lib/locales/no.yml +0 -35
  185. data/lib/locales/pl.yml +0 -35
  186. data/lib/locales/pt.yml +0 -35
  187. data/lib/locales/ru.yml +0 -35
  188. data/lib/locales/sv.yml +0 -35
  189. data/lib/locales/th.yml +0 -35
  190. data/lib/locales/tr.yml +0 -35
  191. data/lib/locales/vi.yml +0 -35
  192. 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)