dexkit 0.8.0 → 0.10.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +36 -0
  3. data/README.md +50 -18
  4. data/gemfiles/mongoid_no_ar.gemfile +10 -0
  5. data/gemfiles/mongoid_no_ar.gemfile.lock +232 -0
  6. data/guides/llm/EVENT.md +41 -23
  7. data/guides/llm/FORM.md +202 -61
  8. data/guides/llm/OPERATION.md +49 -20
  9. data/guides/llm/QUERY.md +52 -2
  10. data/lib/dex/context_dsl.rb +56 -0
  11. data/lib/dex/context_setup.rb +2 -33
  12. data/lib/dex/event/bus.rb +85 -8
  13. data/lib/dex/event/handler.rb +18 -0
  14. data/lib/dex/event/metadata.rb +16 -9
  15. data/lib/dex/event/processor.rb +1 -1
  16. data/lib/dex/event/test_helpers.rb +88 -0
  17. data/lib/dex/event/trace.rb +14 -27
  18. data/lib/dex/event.rb +2 -7
  19. data/lib/dex/event_test_helpers.rb +1 -86
  20. data/lib/dex/form/context.rb +27 -0
  21. data/lib/dex/form/export.rb +128 -0
  22. data/lib/dex/form/nesting.rb +2 -0
  23. data/lib/dex/form/uniqueness_validator.rb +17 -1
  24. data/lib/dex/form.rb +119 -3
  25. data/lib/dex/id.rb +38 -0
  26. data/lib/dex/operation/async_proxy.rb +13 -2
  27. data/lib/dex/operation/explain.rb +11 -7
  28. data/lib/dex/operation/jobs.rb +5 -4
  29. data/lib/dex/operation/lock_wrapper.rb +15 -2
  30. data/lib/dex/operation/once_wrapper.rb +24 -15
  31. data/lib/dex/operation/record_backend.rb +15 -1
  32. data/lib/dex/operation/record_wrapper.rb +43 -8
  33. data/lib/dex/operation/test_helpers/assertions.rb +359 -0
  34. data/lib/dex/operation/test_helpers/execution.rb +30 -0
  35. data/lib/dex/operation/test_helpers/stubbing.rb +61 -0
  36. data/lib/dex/operation/test_helpers.rb +160 -0
  37. data/lib/dex/operation/trace_wrapper.rb +20 -0
  38. data/lib/dex/operation/transaction_adapter.rb +29 -68
  39. data/lib/dex/operation/transaction_wrapper.rb +10 -16
  40. data/lib/dex/operation.rb +2 -0
  41. data/lib/dex/query/backend.rb +13 -0
  42. data/lib/dex/query/export.rb +64 -0
  43. data/lib/dex/query.rb +50 -5
  44. data/lib/dex/ref_type.rb +4 -0
  45. data/lib/dex/test_helpers.rb +4 -139
  46. data/lib/dex/test_log.rb +62 -4
  47. data/lib/dex/trace.rb +291 -0
  48. data/lib/dex/type_coercion.rb +4 -1
  49. data/lib/dex/version.rb +1 -1
  50. data/lib/dexkit.rb +9 -5
  51. metadata +16 -5
  52. data/lib/dex/test_helpers/assertions.rb +0 -333
  53. data/lib/dex/test_helpers/execution.rb +0 -28
  54. data/lib/dex/test_helpers/stubbing.rb +0 -59
  55. /data/lib/dex/{event_test_helpers → event/test_helpers}/assertions.rb +0 -0
@@ -1,148 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "test_log"
3
+ require_relative "operation/test_helpers"
4
+ require_relative "event/test_helpers"
4
5
 
5
6
  module Dex
6
- module TestWrapper
7
- @_installed = false
8
-
9
- class << self
10
- def install!
11
- return if @_installed
12
-
13
- Dex::Operation.prepend(self)
14
- @_installed = true
15
- end
16
-
17
- def installed?
18
- @_installed
19
- end
20
-
21
- # Stub registry
22
-
23
- def stubs
24
- @_stubs ||= {}
25
- end
26
-
27
- def find_stub(klass)
28
- stubs[klass]
29
- end
30
-
31
- def register_stub(klass, **options)
32
- stubs[klass] = options
33
- end
34
-
35
- def clear_stub(klass)
36
- stubs.delete(klass)
37
- end
38
-
39
- def clear_all_stubs!
40
- stubs.clear
41
- end
42
- end
43
-
44
- def call
45
- stub = Dex::TestWrapper.find_stub(self.class)
46
- return _test_apply_stub(stub) if stub
47
-
48
- started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
49
- result = nil
50
- err = nil
51
-
52
- begin
53
- result = super
54
- rescue Exception => e # rubocop:disable Lint/RescueException
55
- err = e
56
- raise
57
- ensure
58
- duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - started_at
59
- _test_record_to_log(result, err, duration)
60
- end
61
-
62
- result
63
- end
64
-
65
- private
66
-
67
- def _test_apply_stub(stub)
68
- if stub[:error]
69
- err_opts = stub[:error]
70
- case err_opts
71
- when Symbol
72
- raise Dex::Error.new(err_opts)
73
- when Hash
74
- raise Dex::Error.new(err_opts[:code], err_opts[:message], details: err_opts[:details])
75
- end
76
- else
77
- stub[:returns]
78
- end
79
- end
80
-
81
- def _test_safe_params
82
- respond_to?(:to_h) ? to_h : {}
83
- rescue
84
- {}
85
- end
86
-
87
- def _test_record_to_log(result, err, duration)
88
- safe_result = if err
89
- dex_err = if err.is_a?(Dex::Error)
90
- err
91
- else
92
- Dex::Error.new(:exception, err.message, details: { exception_class: err.class.name })
93
- end
94
- Dex::Operation::Err.new(dex_err)
95
- else
96
- Dex::Operation::Ok.new(result)
97
- end
98
-
99
- entry = Dex::TestLog::Entry.new(
100
- type: "Operation",
101
- name: self.class.name || self.class.to_s,
102
- operation_class: self.class,
103
- params: _test_safe_params,
104
- result: safe_result,
105
- duration: duration,
106
- caller_location: caller_locations(4, 1)&.first
107
- )
108
- Dex::TestLog.record(entry)
109
- end
110
- end
111
-
112
7
  module TestHelpers
113
- extend Dex::Concern
114
-
115
8
  def self.included(base)
116
- Dex::TestWrapper.install!
117
- super
118
- end
119
-
120
- def setup
121
- super
122
- Dex::TestLog.clear!
123
- Dex::TestWrapper.clear_all_stubs!
124
- end
125
-
126
- module ClassMethods
127
- def testing(klass)
128
- @_dex_test_subject = klass
129
- end
130
-
131
- def _dex_test_subject
132
- return @_dex_test_subject if defined?(@_dex_test_subject) && @_dex_test_subject
133
-
134
- superclass._dex_test_subject if superclass.respond_to?(:_dex_test_subject)
135
- end
136
- end
137
-
138
- private
139
-
140
- def _dex_test_subject
141
- self.class._dex_test_subject
9
+ base.include(Dex::Operation::TestHelpers)
10
+ base.include(Dex::Event::TestHelpers)
142
11
  end
143
12
  end
144
13
  end
145
-
146
- require_relative "test_helpers/execution"
147
- require_relative "test_helpers/assertions"
148
- require_relative "test_helpers/stubbing"
data/lib/dex/test_log.rb CHANGED
@@ -2,7 +2,18 @@
2
2
 
3
3
  module Dex
4
4
  module TestLog
5
- Entry = Data.define(:type, :name, :operation_class, :params, :result, :duration, :caller_location)
5
+ Entry = Data.define(
6
+ :type,
7
+ :name,
8
+ :operation_class,
9
+ :params,
10
+ :result,
11
+ :duration,
12
+ :caller_location,
13
+ :execution_id,
14
+ :trace_id,
15
+ :trace
16
+ )
6
17
 
7
18
  @_entries = []
8
19
  @_mutex = Mutex.new
@@ -42,14 +53,61 @@ module Dex
42
53
  return "No operations called." if entries.empty?
43
54
 
44
55
  lines = ["Operations called (#{entries.size}):"]
45
- entries.each_with_index do |entry, i|
56
+ nodes = entries.each_with_index.map { |entry, index| { entry: entry, index: index } }
57
+ by_id = nodes.to_h { |node| [node[:entry].execution_id, node] }
58
+ children = Hash.new { |hash, key| hash[key] = [] }
59
+ roots = []
60
+
61
+ nodes.each do |node|
62
+ parent_id = _parent_operation_id(node[:entry])
63
+ if parent_id && by_id[parent_id]
64
+ children[parent_id] << node
65
+ else
66
+ roots << node
67
+ end
68
+ end
69
+
70
+ counter = 0
71
+ render = lambda do |node, depth|
72
+ counter += 1
73
+ entry = node[:entry]
46
74
  status = entry.result.ok? ? "OK" : "ERR(#{entry.result.code})"
47
75
  duration_ms = entry.duration ? format("%.1fms", entry.duration * 1000) : "n/a"
48
- lines << " #{i + 1}. #{entry.name} [#{status}] #{duration_ms}"
49
- lines << " params: #{entry.params.inspect}" unless entry.params.nil? || entry.params.empty?
76
+ indent = " " * depth
77
+ id = entry.execution_id ? " (#{_display_id(entry.execution_id)})" : ""
78
+
79
+ lines << " #{indent}#{counter}. #{entry.name}#{id} [#{status}] #{duration_ms}"
80
+ lines << " #{indent} params: #{entry.params.inspect}" unless entry.params.nil? || entry.params.empty?
81
+
82
+ children.fetch(entry.execution_id, []).sort_by { |child| child[:index] }.each do |child|
83
+ render.call(child, depth + 1)
84
+ end
50
85
  end
86
+
87
+ roots.sort_by { |node| node[:index] }.each { |node| render.call(node, 0) }
51
88
  lines.join("\n")
52
89
  end
90
+
91
+ private
92
+
93
+ def _frame_type(frame)
94
+ return unless frame
95
+
96
+ (frame[:type] || frame["type"])&.to_sym
97
+ end
98
+
99
+ def _display_id(id)
100
+ prefix, suffix = id.to_s.split("_", 2)
101
+ return id.to_s unless suffix
102
+
103
+ "#{prefix}_#{suffix[0, 7]}"
104
+ end
105
+
106
+ def _parent_operation_id(entry)
107
+ frames = Array(entry.trace)[0...-1]
108
+ parent = frames.reverse.find { |frame| _frame_type(frame) == :operation }
109
+ parent && (parent[:id] || parent["id"])
110
+ end
53
111
  end
54
112
  end
55
113
  end
data/lib/dex/trace.rb ADDED
@@ -0,0 +1,291 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dex
4
+ module Trace
5
+ FIBER_KEY = :_dex_trace
6
+ FRAME_TYPES = %i[actor operation handler].freeze
7
+
8
+ class << self
9
+ def start(actor: nil, trace_id: nil)
10
+ previous = _dump_state
11
+ _set_state(trace_id: (trace_id || Dex::Id.generate("tr_")).to_s, frames: [], event_context: nil)
12
+ _state[:frames] << _normalize_actor(actor) if actor
13
+ yield
14
+ ensure
15
+ _restore_state(previous)
16
+ end
17
+
18
+ def ensure_started!(trace_id: nil)
19
+ return false if active?
20
+
21
+ _state[:trace_id] = (trace_id || Dex::Id.generate("tr_")).to_s
22
+ true
23
+ end
24
+
25
+ def active?
26
+ !trace_id.nil?
27
+ end
28
+
29
+ def with_frame(frame)
30
+ auto_started = ensure_started!
31
+ pushed = false
32
+ push(frame)
33
+ pushed = true
34
+ yield
35
+ ensure
36
+ pop if pushed
37
+ stop! if auto_started
38
+ end
39
+
40
+ def with_event_context(event)
41
+ auto_started = ensure_started!(trace_id: event.trace_id)
42
+ previous = _state[:event_context]
43
+ _state[:event_context] = _build_event_context(event)
44
+ yield
45
+ ensure
46
+ _state[:event_context] = previous
47
+ stop! if auto_started
48
+ end
49
+
50
+ def restore_event_context(event_id:, trace_id:, event_class: nil, event_ancestry: [])
51
+ previous = _dump_state
52
+ effective_trace_id = trace_id&.to_s || _state[:trace_id]
53
+ _set_state(
54
+ trace_id: effective_trace_id,
55
+ frames: _normalize_frames(_state[:frames]),
56
+ event_context: {
57
+ id: event_id&.to_s,
58
+ trace_id: effective_trace_id,
59
+ event_class: event_class,
60
+ event_ancestry: Array(event_ancestry).compact.map(&:to_s)
61
+ }
62
+ )
63
+ yield
64
+ ensure
65
+ _restore_state(previous)
66
+ end
67
+
68
+ def push(frame)
69
+ _state[:frames] << _normalize_frame(frame)
70
+ end
71
+
72
+ def pop
73
+ _state[:frames].pop
74
+ end
75
+
76
+ def current
77
+ _deep_copy(_state[:frames])
78
+ end
79
+
80
+ def trace_id
81
+ _state[:trace_id]
82
+ end
83
+
84
+ def current_id
85
+ _state[:frames].last&.dig(:id)
86
+ end
87
+
88
+ def actor
89
+ frame = _state[:frames].find { |entry| entry[:type] == :actor }
90
+ frame ? _deep_copy(frame) : nil
91
+ end
92
+
93
+ def current_event_id
94
+ current_event_context&.dig(:id)
95
+ end
96
+
97
+ def current_event_context
98
+ context = _state[:event_context]
99
+ return _deep_copy(context) if context
100
+
101
+ handler = _state[:frames].reverse.find { |frame| frame[:type] == :handler && frame[:event_id] }
102
+ return nil unless handler
103
+
104
+ {
105
+ id: handler[:event_id],
106
+ trace_id: trace_id,
107
+ event_class: handler[:event_class],
108
+ event_ancestry: _deep_copy(Array(handler[:event_ancestry]))
109
+ }
110
+ end
111
+
112
+ def dump
113
+ return nil unless active?
114
+
115
+ data = {
116
+ trace_id: trace_id,
117
+ frames: current
118
+ }
119
+ data[:event_context] = _deep_copy(_state[:event_context]) if _state[:event_context]
120
+ data
121
+ end
122
+
123
+ def restore(data)
124
+ return yield unless data
125
+
126
+ previous = _dump_state
127
+ _set_state(
128
+ trace_id: _fetch(data, :trace_id)&.to_s,
129
+ frames: _normalize_frames(_fetch(data, :frames)),
130
+ event_context: _normalize_event_context(_fetch(data, :event_context))
131
+ )
132
+ yield
133
+ ensure
134
+ _restore_state(previous)
135
+ end
136
+
137
+ def to_s
138
+ current.filter_map { |frame| _format_frame(frame) }.join(" > ")
139
+ end
140
+
141
+ def clear!
142
+ Fiber[FIBER_KEY] = nil
143
+ end
144
+ alias_method :stop!, :clear!
145
+
146
+ private
147
+
148
+ def _state
149
+ Fiber[FIBER_KEY] ||= { trace_id: nil, frames: [], event_context: nil }
150
+ end
151
+
152
+ def _set_state(trace_id:, frames:, event_context:)
153
+ Fiber[FIBER_KEY] = {
154
+ trace_id: trace_id,
155
+ frames: frames,
156
+ event_context: event_context
157
+ }
158
+ end
159
+
160
+ def _dump_state
161
+ state = _state
162
+ return nil unless state[:trace_id] || !state[:frames].empty? || state[:event_context]
163
+
164
+ {
165
+ trace_id: state[:trace_id],
166
+ frames: _deep_copy(state[:frames]),
167
+ event_context: _deep_copy(state[:event_context])
168
+ }
169
+ end
170
+
171
+ def _restore_state(state)
172
+ if state
173
+ _set_state(
174
+ trace_id: state[:trace_id],
175
+ frames: _normalize_frames(state[:frames]),
176
+ event_context: _normalize_event_context(state[:event_context])
177
+ )
178
+ else
179
+ clear!
180
+ end
181
+ end
182
+
183
+ def _normalize_frames(frames)
184
+ Array(frames).map { |frame| _normalize_frame(frame) }
185
+ end
186
+
187
+ def _normalize_actor(actor)
188
+ raise ArgumentError, "actor must be a Hash" unless actor.is_a?(Hash)
189
+
190
+ normalized = _symbolize(actor)
191
+ actor_type = normalized[:type]
192
+ raise ArgumentError, "actor must include :type" if actor_type.nil? || actor_type.to_s.strip.empty?
193
+
194
+ frame = { type: :actor, actor_type: actor_type.to_s }
195
+ frame[:id] = normalized[:id].to_s if normalized.key?(:id) && !normalized[:id].nil?
196
+
197
+ normalized.each do |key, value|
198
+ next if %i[type id].include?(key)
199
+
200
+ frame[key] = _deep_copy(value)
201
+ end
202
+
203
+ frame
204
+ end
205
+
206
+ def _normalize_frame(frame)
207
+ raise ArgumentError, "trace frame must be a Hash" unless frame.is_a?(Hash)
208
+
209
+ normalized = _symbolize(frame)
210
+ type = normalized[:type]&.to_sym
211
+ raise ArgumentError, "trace frame type is required" unless type
212
+ raise ArgumentError, "unknown trace frame type: #{type.inspect}" unless FRAME_TYPES.include?(type)
213
+
214
+ normalized[:type] = type
215
+ normalized[:id] = normalized[:id].to_s if normalized.key?(:id) && !normalized[:id].nil?
216
+ normalized[:actor_type] = normalized[:actor_type].to_s if normalized.key?(:actor_type) && !normalized[:actor_type].nil?
217
+ normalized[:event_id] = normalized[:event_id].to_s if normalized.key?(:event_id) && !normalized[:event_id].nil?
218
+ normalized[:event_ancestry] = Array(normalized[:event_ancestry]).compact.map(&:to_s) if normalized.key?(:event_ancestry)
219
+ normalized
220
+ end
221
+
222
+ def _normalize_event_context(context)
223
+ return nil unless context
224
+
225
+ {
226
+ id: _fetch(context, :id)&.to_s,
227
+ trace_id: _fetch(context, :trace_id)&.to_s,
228
+ event_class: _fetch(context, :event_class),
229
+ event_ancestry: Array(_fetch(context, :event_ancestry)).compact.map(&:to_s)
230
+ }
231
+ end
232
+
233
+ def _build_event_context(event)
234
+ {
235
+ id: event.id.to_s,
236
+ trace_id: event.trace_id.to_s,
237
+ event_class: event.class.name,
238
+ event_ancestry: Array(event.metadata.event_ancestry).compact.map(&:to_s)
239
+ }
240
+ end
241
+
242
+ def _symbolize(hash)
243
+ hash.each_with_object({}) do |(key, value), result|
244
+ result[key.respond_to?(:to_sym) ? key.to_sym : key] = _deep_copy(value)
245
+ end
246
+ end
247
+
248
+ def _deep_copy(value)
249
+ case value
250
+ when Hash
251
+ value.each_with_object({}) { |(key, nested), result| result[key] = _deep_copy(nested) }
252
+ when Array
253
+ value.map { |nested| _deep_copy(nested) }
254
+ else
255
+ value
256
+ end
257
+ end
258
+
259
+ def _fetch(hash, key)
260
+ hash[key] || hash[key.to_s]
261
+ end
262
+
263
+ def _format_frame(frame)
264
+ case frame[:type]
265
+ when :actor
266
+ return nil unless frame[:actor_type]
267
+
268
+ frame[:id] ? "#{frame[:actor_type]}:#{frame[:id]}" : frame[:actor_type]
269
+ when :operation
270
+ name = frame[:class] || "Operation"
271
+ id = _display_id(frame[:id])
272
+ id ? "#{name}(#{id})" : name
273
+ when :handler
274
+ event_class = frame[:event_class] || "Event"
275
+ handler_name = frame[:class] || "Handler"
276
+ id = _display_id(frame[:id])
277
+ id ? "[#{event_class}] #{handler_name}(#{id})" : "[#{event_class}] #{handler_name}"
278
+ end
279
+ end
280
+
281
+ def _display_id(id)
282
+ return nil unless id
283
+
284
+ prefix, suffix = id.split("_", 2)
285
+ return id[0, 10] unless suffix
286
+
287
+ "#{prefix}_#{suffix[0, 7]}"
288
+ end
289
+ end
290
+ end
291
+ end
@@ -64,7 +64,10 @@ module Dex
64
64
  return _serialize_value(type.type, value) if type.is_a?(Literal::Types::NilableType)
65
65
 
66
66
  ref = _find_ref_type(type)
67
- return value.id if ref
67
+ if ref
68
+ serialized_id = value.id
69
+ return serialized_id.respond_to?(:as_json) ? serialized_id.as_json : serialized_id
70
+ end
68
71
 
69
72
  value.respond_to?(:as_json) ? value.as_json : value
70
73
  end
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.8.0"
4
+ VERSION = "0.10.0"
5
5
  end
data/lib/dexkit.rb CHANGED
@@ -5,15 +5,12 @@ require "zeitwerk"
5
5
  require "literal"
6
6
  require "time"
7
7
 
8
- loader = Zeitwerk::Loader.for_gem
9
- loader.ignore("#{__dir__}/dex")
10
- loader.setup
11
-
12
8
  require_relative "dex/version"
13
9
  require_relative "dex/concern"
14
10
  require_relative "dex/ref_type"
15
11
  require_relative "dex/type_coercion"
16
12
  require_relative "dex/props_setup"
13
+ require_relative "dex/context_dsl"
17
14
  require_relative "dex/context_setup"
18
15
  require_relative "dex/error"
19
16
  require_relative "dex/settings"
@@ -21,6 +18,8 @@ require_relative "dex/pipeline"
21
18
  require_relative "dex/executable"
22
19
  require_relative "dex/registry"
23
20
  require_relative "dex/type_serializer"
21
+ require_relative "dex/id"
22
+ require_relative "dex/trace"
24
23
  require_relative "dex/operation"
25
24
  require_relative "dex/event"
26
25
  require_relative "dex/tool"
@@ -29,7 +28,8 @@ require_relative "dex/query"
29
28
 
30
29
  module Dex
31
30
  class Configuration
32
- attr_accessor :record_class, :transaction_adapter, :event_store, :event_context, :restore_event_context
31
+ attr_accessor :record_class, :event_store, :event_context, :restore_event_context
32
+ attr_reader :transaction_adapter
33
33
 
34
34
  def initialize
35
35
  @record_class = nil
@@ -38,6 +38,10 @@ module Dex
38
38
  @event_context = nil
39
39
  @restore_event_context = nil
40
40
  end
41
+
42
+ def transaction_adapter=(adapter)
43
+ @transaction_adapter = Operation::TransactionAdapter.normalize_name(adapter)
44
+ end
41
45
  end
42
46
 
43
47
  class << self
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.8.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jacek Galanciak
@@ -161,11 +161,14 @@ files:
161
161
  - LICENSE.txt
162
162
  - README.md
163
163
  - Untitled
164
+ - gemfiles/mongoid_no_ar.gemfile
165
+ - gemfiles/mongoid_no_ar.gemfile.lock
164
166
  - guides/llm/EVENT.md
165
167
  - guides/llm/FORM.md
166
168
  - guides/llm/OPERATION.md
167
169
  - guides/llm/QUERY.md
168
170
  - lib/dex/concern.rb
171
+ - lib/dex/context_dsl.rb
169
172
  - lib/dex/context_setup.rb
170
173
  - lib/dex/error.rb
171
174
  - lib/dex/event.rb
@@ -176,13 +179,17 @@ files:
176
179
  - lib/dex/event/metadata.rb
177
180
  - lib/dex/event/processor.rb
178
181
  - lib/dex/event/suppression.rb
182
+ - lib/dex/event/test_helpers.rb
183
+ - lib/dex/event/test_helpers/assertions.rb
179
184
  - lib/dex/event/trace.rb
180
185
  - lib/dex/event_test_helpers.rb
181
- - lib/dex/event_test_helpers/assertions.rb
182
186
  - lib/dex/executable.rb
183
187
  - lib/dex/form.rb
188
+ - lib/dex/form/context.rb
189
+ - lib/dex/form/export.rb
184
190
  - lib/dex/form/nesting.rb
185
191
  - lib/dex/form/uniqueness_validator.rb
192
+ - lib/dex/id.rb
186
193
  - lib/dex/match.rb
187
194
  - lib/dex/operation.rb
188
195
  - lib/dex/operation/async_proxy.rb
@@ -200,12 +207,18 @@ files:
200
207
  - lib/dex/operation/rescue_wrapper.rb
201
208
  - lib/dex/operation/result_wrapper.rb
202
209
  - lib/dex/operation/safe_wrapper.rb
210
+ - lib/dex/operation/test_helpers.rb
211
+ - lib/dex/operation/test_helpers/assertions.rb
212
+ - lib/dex/operation/test_helpers/execution.rb
213
+ - lib/dex/operation/test_helpers/stubbing.rb
214
+ - lib/dex/operation/trace_wrapper.rb
203
215
  - lib/dex/operation/transaction_adapter.rb
204
216
  - lib/dex/operation/transaction_wrapper.rb
205
217
  - lib/dex/pipeline.rb
206
218
  - lib/dex/props_setup.rb
207
219
  - lib/dex/query.rb
208
220
  - lib/dex/query/backend.rb
221
+ - lib/dex/query/export.rb
209
222
  - lib/dex/query/filtering.rb
210
223
  - lib/dex/query/sorting.rb
211
224
  - lib/dex/railtie.rb
@@ -213,11 +226,9 @@ files:
213
226
  - lib/dex/registry.rb
214
227
  - lib/dex/settings.rb
215
228
  - lib/dex/test_helpers.rb
216
- - lib/dex/test_helpers/assertions.rb
217
- - lib/dex/test_helpers/execution.rb
218
- - lib/dex/test_helpers/stubbing.rb
219
229
  - lib/dex/test_log.rb
220
230
  - lib/dex/tool.rb
231
+ - lib/dex/trace.rb
221
232
  - lib/dex/type_coercion.rb
222
233
  - lib/dex/type_serializer.rb
223
234
  - lib/dex/version.rb