dexkit 0.6.0 → 0.7.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.
data/lib/dex/operation.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  # Wrapper modules (loaded before class body so `include`/`use` can find them)
4
4
  require_relative "operation/result_wrapper"
5
+ require_relative "operation/once_wrapper"
5
6
  require_relative "operation/record_wrapper"
6
7
  require_relative "operation/transaction_wrapper"
7
8
  require_relative "operation/lock_wrapper"
@@ -9,6 +10,7 @@ require_relative "operation/async_wrapper"
9
10
  require_relative "operation/safe_wrapper"
10
11
  require_relative "operation/rescue_wrapper"
11
12
  require_relative "operation/callback_wrapper"
13
+ require_relative "operation/guard_wrapper"
12
14
 
13
15
  module Dex
14
16
  class Operation
@@ -40,20 +42,22 @@ module Dex
40
42
  end
41
43
  end
42
44
 
43
- RESERVED_PROP_NAMES = %i[call perform async safe initialize].to_set.freeze
45
+ RESERVED_PROP_NAMES = %i[call perform async safe once initialize].to_set.freeze
44
46
 
45
47
  include Executable
46
48
  include PropsSetup
47
49
  include TypeCoercion
50
+ include ContextSetup
48
51
 
49
- Contract = Data.define(:params, :success, :errors)
52
+ Contract = Data.define(:params, :success, :errors, :guards)
50
53
 
51
54
  class << self
52
55
  def contract
53
56
  Contract.new(
54
57
  params: _contract_params,
55
58
  success: _success_type,
56
- errors: _declared_errors
59
+ errors: _declared_errors,
60
+ guards: _contract_guards
57
61
  )
58
62
  end
59
63
 
@@ -66,6 +70,14 @@ module Dex
66
70
  hash[prop.name] = prop.type
67
71
  end
68
72
  end
73
+
74
+ def _contract_guards
75
+ return [] unless respond_to?(:_guard_list)
76
+
77
+ _guard_list.map do |g|
78
+ { name: g.name, message: g.message, requires: g.requires }
79
+ end
80
+ end
69
81
  end
70
82
 
71
83
  def perform(*, **)
@@ -88,9 +100,11 @@ module Dex
88
100
  include SafeWrapper
89
101
 
90
102
  use ResultWrapper
103
+ use GuardWrapper
104
+ use OnceWrapper
91
105
  use LockWrapper
92
- use TransactionWrapper
93
106
  use RecordWrapper
107
+ use TransactionWrapper
94
108
  use RescueWrapper
95
109
  use CallbackWrapper
96
110
  end
@@ -214,6 +214,29 @@ module Dex
214
214
  "Expected #{model_class.name} count to increase, but it stayed at #{count_before}"
215
215
  end
216
216
 
217
+ # --- Guard assertions ---
218
+
219
+ def assert_callable(*args, **params)
220
+ klass = _dex_resolve_subject(args)
221
+ result = klass.callable(**params)
222
+ assert result.ok?, "Expected operation to be callable, but guards failed:\n#{_dex_format_err(result)}"
223
+ result
224
+ end
225
+
226
+ def refute_callable(*args, **params)
227
+ klass_args, codes = _dex_split_class_and_symbols(args)
228
+ klass = _dex_resolve_subject(klass_args)
229
+ code = codes.first
230
+ result = klass.callable(**params)
231
+ refute result.ok?, "Expected operation to NOT be callable, but all guards passed"
232
+ if code
233
+ failed_codes = result.details.map { |f| f[:guard] }
234
+ assert_includes failed_codes, code,
235
+ "Expected guard :#{code} to fail, but it didn't.\n Failed guards: #{failed_codes.inspect}"
236
+ end
237
+ result
238
+ end
239
+
217
240
  # --- Batch assertions ---
218
241
 
219
242
  def assert_all_succeed(*args, params_list:)
data/lib/dex/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dex
4
- VERSION = "0.6.0"
4
+ VERSION = "0.7.0"
5
5
  end
data/lib/dexkit.rb CHANGED
@@ -14,6 +14,7 @@ require_relative "dex/concern"
14
14
  require_relative "dex/ref_type"
15
15
  require_relative "dex/type_coercion"
16
16
  require_relative "dex/props_setup"
17
+ require_relative "dex/context_setup"
17
18
  require_relative "dex/error"
18
19
  require_relative "dex/settings"
19
20
  require_relative "dex/pipeline"
@@ -71,5 +72,20 @@ module Dex
71
72
  def transaction_adapter=(adapter)
72
73
  configuration.transaction_adapter = adapter
73
74
  end
75
+
76
+ CONTEXT_KEY = :_dex_context
77
+ EMPTY_CONTEXT = {}.freeze
78
+
79
+ def context
80
+ Fiber[CONTEXT_KEY] || EMPTY_CONTEXT
81
+ end
82
+
83
+ def with_context(**values)
84
+ previous = Fiber[CONTEXT_KEY]
85
+ Fiber[CONTEXT_KEY] = (previous || {}).merge(values)
86
+ yield
87
+ ensure
88
+ Fiber[CONTEXT_KEY] = previous
89
+ end
74
90
  end
75
91
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dexkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jacek Galanciak
@@ -166,6 +166,7 @@ files:
166
166
  - guides/llm/OPERATION.md
167
167
  - guides/llm/QUERY.md
168
168
  - lib/dex/concern.rb
169
+ - lib/dex/context_setup.rb
169
170
  - lib/dex/error.rb
170
171
  - lib/dex/event.rb
171
172
  - lib/dex/event/bus.rb
@@ -186,8 +187,10 @@ files:
186
187
  - lib/dex/operation/async_proxy.rb
187
188
  - lib/dex/operation/async_wrapper.rb
188
189
  - lib/dex/operation/callback_wrapper.rb
190
+ - lib/dex/operation/guard_wrapper.rb
189
191
  - lib/dex/operation/jobs.rb
190
192
  - lib/dex/operation/lock_wrapper.rb
193
+ - lib/dex/operation/once_wrapper.rb
191
194
  - lib/dex/operation/outcome.rb
192
195
  - lib/dex/operation/record_backend.rb
193
196
  - lib/dex/operation/record_wrapper.rb