paper_trail_diff 0.2.0 → 0.3.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 (94) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +62 -0
  3. data/QUICKSTART.md +44 -2
  4. data/README.md +188 -14
  5. data/lib/paper_trail_diff/activity_belongs_to_event_applier.rb +126 -0
  6. data/lib/paper_trail_diff/activity_child_candidate_loader.rb +73 -0
  7. data/lib/paper_trail_diff/activity_collection_event_applier.rb +137 -0
  8. data/lib/paper_trail_diff/activity_collection_record_updater.rb +67 -0
  9. data/lib/paper_trail_diff/activity_collection_route_change.rb +21 -0
  10. data/lib/paper_trail_diff/activity_collection_route_updater.rb +128 -0
  11. data/lib/paper_trail_diff/activity_event_record_normalizer.rb +42 -0
  12. data/lib/paper_trail_diff/activity_event_record_resolver.rb +120 -0
  13. data/lib/paper_trail_diff/activity_event_route_finder.rb +112 -0
  14. data/lib/paper_trail_diff/activity_event_snapshot_refresher.rb +59 -437
  15. data/lib/paper_trail_diff/activity_history.rb +136 -0
  16. data/lib/paper_trail_diff/activity_range.rb +28 -12
  17. data/lib/paper_trail_diff/activity_relationship.rb +55 -0
  18. data/lib/paper_trail_diff/activity_snapshot_delta.rb +64 -0
  19. data/lib/paper_trail_diff/activity_snapshot_sequence.rb +3 -3
  20. data/lib/paper_trail_diff/activity_timeline_builder.rb +54 -45
  21. data/lib/paper_trail_diff/activity_version_collector.rb +14 -17
  22. data/lib/paper_trail_diff/branch_snapshot_refresher.rb +7 -3
  23. data/lib/paper_trail_diff/collection_comparator.rb +155 -0
  24. data/lib/paper_trail_diff/collection_identity_index.rb +53 -0
  25. data/lib/paper_trail_diff/collection_transition.rb +25 -0
  26. data/lib/paper_trail_diff/comparison_batch.rb +151 -0
  27. data/lib/paper_trail_diff/engine.rb +5 -45
  28. data/lib/paper_trail_diff/errors.rb +9 -0
  29. data/lib/paper_trail_diff/historical_snapshot_store.rb +55 -3
  30. data/lib/paper_trail_diff/instrumentation.rb +30 -0
  31. data/lib/paper_trail_diff/live_endpoint_batch_loader.rb +133 -0
  32. data/lib/paper_trail_diff/live_endpoint_provider.rb +48 -0
  33. data/lib/paper_trail_diff/live_graph_collector.rb +52 -0
  34. data/lib/paper_trail_diff/paper_trail_adapter.rb +61 -34
  35. data/lib/paper_trail_diff/preloaded_endpoint_batch_loader.rb +48 -0
  36. data/lib/paper_trail_diff/prepared_edge_loader.rb +54 -17
  37. data/lib/paper_trail_diff/prepared_history.rb +14 -4
  38. data/lib/paper_trail_diff/prepared_history_loader.rb +17 -9
  39. data/lib/paper_trail_diff/prepared_record_index.rb +138 -10
  40. data/lib/paper_trail_diff/snapshot.rb +66 -3
  41. data/lib/paper_trail_diff/support.rb +18 -0
  42. data/lib/paper_trail_diff/time_activity_timeline_builder.rb +111 -0
  43. data/lib/paper_trail_diff/time_range.rb +85 -0
  44. data/lib/paper_trail_diff/time_version_range.rb +53 -0
  45. data/lib/paper_trail_diff/timeline_builder.rb +13 -7
  46. data/lib/paper_trail_diff/timeline_range.rb +72 -0
  47. data/lib/paper_trail_diff/version.rb +1 -1
  48. data/lib/paper_trail_diff/version_association_candidate_scope.rb +73 -0
  49. data/lib/paper_trail_diff.rb +83 -12
  50. data/sig/generated/paper_trail_diff/activity_belongs_to_event_applier.rbs +41 -0
  51. data/sig/generated/paper_trail_diff/activity_child_candidate_loader.rbs +40 -0
  52. data/sig/generated/paper_trail_diff/activity_collection_event_applier.rbs +46 -0
  53. data/sig/generated/paper_trail_diff/activity_collection_record_updater.rbs +25 -0
  54. data/sig/generated/paper_trail_diff/activity_collection_route_change.rbs +17 -0
  55. data/sig/generated/paper_trail_diff/activity_collection_route_updater.rbs +44 -0
  56. data/sig/generated/paper_trail_diff/activity_event_record_normalizer.rbs +19 -0
  57. data/sig/generated/paper_trail_diff/activity_event_record_resolver.rbs +44 -0
  58. data/sig/generated/paper_trail_diff/activity_event_route_finder.rbs +54 -0
  59. data/sig/generated/paper_trail_diff/activity_event_snapshot_refresher.rbs +20 -71
  60. data/sig/generated/paper_trail_diff/activity_history.rbs +79 -0
  61. data/sig/generated/paper_trail_diff/activity_range.rbs +14 -5
  62. data/sig/generated/paper_trail_diff/activity_relationship.rbs +23 -0
  63. data/sig/generated/paper_trail_diff/activity_snapshot_delta.rbs +33 -0
  64. data/sig/generated/paper_trail_diff/activity_snapshot_sequence.rbs +2 -2
  65. data/sig/generated/paper_trail_diff/activity_timeline_builder.rbs +15 -10
  66. data/sig/generated/paper_trail_diff/activity_version_collector.rbs +2 -5
  67. data/sig/generated/paper_trail_diff/branch_snapshot_refresher.rbs +2 -2
  68. data/sig/generated/paper_trail_diff/collection_comparator.rbs +59 -0
  69. data/sig/generated/paper_trail_diff/collection_identity_index.rbs +29 -0
  70. data/sig/generated/paper_trail_diff/collection_transition.rbs +18 -0
  71. data/sig/generated/paper_trail_diff/comparison_batch.rbs +65 -0
  72. data/sig/generated/paper_trail_diff/engine.rbs +0 -12
  73. data/sig/generated/paper_trail_diff/errors.rbs +12 -0
  74. data/sig/generated/paper_trail_diff/historical_snapshot_store.rbs +22 -2
  75. data/sig/generated/paper_trail_diff/instrumentation.rbs +12 -0
  76. data/sig/generated/paper_trail_diff/live_endpoint_batch_loader.rbs +52 -0
  77. data/sig/generated/paper_trail_diff/live_endpoint_provider.rbs +23 -0
  78. data/sig/generated/paper_trail_diff/live_graph_collector.rbs +27 -0
  79. data/sig/generated/paper_trail_diff/paper_trail_adapter.rbs +21 -10
  80. data/sig/generated/paper_trail_diff/preloaded_endpoint_batch_loader.rbs +24 -0
  81. data/sig/generated/paper_trail_diff/prepared_edge_loader.rbs +22 -8
  82. data/sig/generated/paper_trail_diff/prepared_history.rbs +6 -0
  83. data/sig/generated/paper_trail_diff/prepared_history_loader.rbs +4 -2
  84. data/sig/generated/paper_trail_diff/prepared_record_index.rbs +61 -6
  85. data/sig/generated/paper_trail_diff/snapshot.rbs +37 -2
  86. data/sig/generated/paper_trail_diff/support.rbs +6 -0
  87. data/sig/generated/paper_trail_diff/time_activity_timeline_builder.rbs +46 -0
  88. data/sig/generated/paper_trail_diff/time_range.rbs +41 -0
  89. data/sig/generated/paper_trail_diff/time_version_range.rbs +27 -0
  90. data/sig/generated/paper_trail_diff/timeline_builder.rbs +6 -5
  91. data/sig/generated/paper_trail_diff/timeline_range.rbs +41 -0
  92. data/sig/generated/paper_trail_diff/version_association_candidate_scope.rbs +32 -0
  93. data/sig/generated/paper_trail_diff.rbs +16 -8
  94. metadata +56 -4
@@ -0,0 +1,79 @@
1
+ # Generated from lib/paper_trail_diff/activity_history.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Immutable snapshots and steps produced by one activity-history pass.
5
+ class ActivityHistory
6
+ attr_reader steps: Array[ActivityStep]
7
+
8
+ attr_reader root_snapshots: Hash[Array[untyped], RecordSnapshot?]
9
+
10
+ attr_reader first_snapshot: RecordSnapshot?
11
+
12
+ attr_reader last_snapshot: RecordSnapshot?
13
+
14
+ # : (steps: Array[ActivityStep], root_snapshots: Hash[Array[untyped], RecordSnapshot?], first_snapshot: RecordSnapshot?, last_snapshot: RecordSnapshot?) -> void
15
+ def initialize: (steps: Array[ActivityStep], root_snapshots: Hash[Array[untyped], RecordSnapshot?], first_snapshot: RecordSnapshot?, last_snapshot: RecordSnapshot?) -> void
16
+
17
+ # : () -> ActivityHistory
18
+ def self.empty: () -> ActivityHistory
19
+ end
20
+
21
+ # Builds activity steps while retaining root snapshots for combined analysis.
22
+ class ActivityHistoryBuilder
23
+ # : (Array[untyped], Array[ActivityEvent], untyped, ?current: untyped, ?include_step: untyped) -> void
24
+ def initialize: (Array[untyped], Array[ActivityEvent], untyped, ?current: untyped, ?include_step: untyped) -> void
25
+
26
+ # : () -> ActivityHistory
27
+ def call: () -> ActivityHistory
28
+
29
+ private
30
+
31
+ @current: untyped
32
+
33
+ @events: Array[ActivityEvent]
34
+
35
+ @first_snapshot: RecordSnapshot?
36
+
37
+ @include_step: untyped
38
+
39
+ @previous_boundary: ActivityBoundary?
40
+
41
+ @previous_event: ActivityEvent?
42
+
43
+ @previous_snapshot: RecordSnapshot?
44
+
45
+ @root_snapshots: Hash[Array[untyped], RecordSnapshot?]
46
+
47
+ @root_versions: Array[untyped]
48
+
49
+ @selected_last_snapshot: RecordSnapshot?
50
+
51
+ @snapshotter: untyped
52
+
53
+ @steps: Array[ActivityStep]
54
+
55
+ # : () -> void
56
+ def reset: () -> void
57
+
58
+ # : () -> ActivitySnapshotSequence
59
+ def sequence: () -> ActivitySnapshotSequence
60
+
61
+ # : (ActivityEvent, RecordSnapshot?) -> void
62
+ def consume: (ActivityEvent, RecordSnapshot?) -> void
63
+
64
+ # : (RecordSnapshot?) -> void
65
+ def capture_first: (RecordSnapshot?) -> void
66
+
67
+ # : (ActivityBoundary, RecordSnapshot?) -> void
68
+ def append_step: (ActivityBoundary, RecordSnapshot?) -> void
69
+
70
+ # : () -> bool
71
+ def include_previous_step?: () -> bool
72
+
73
+ # : () -> RecordSnapshot?
74
+ def final_snapshot: () -> RecordSnapshot?
75
+
76
+ # : (untyped) -> Array[untyped]
77
+ def version_key: (untyped) -> Array[untyped]
78
+ end
79
+ end
@@ -3,6 +3,10 @@
3
3
  module PaperTrailDiff
4
4
  # Tests activity versions against a historical-version or wall-clock range end.
5
5
  class ActivityRange
6
+ attr_reader start_time: untyped
7
+
8
+ attr_reader end_time: untyped
9
+
6
10
  # : (untyped, untyped) -> void
7
11
  def initialize: (untyped, untyped) -> void
8
12
 
@@ -14,21 +18,26 @@ module PaperTrailDiff
14
18
  # : (untyped) -> untyped
15
19
  def scope: (untyped) -> untyped
16
20
 
21
+ # : () -> bool
22
+ def current_end?: () -> bool
23
+
17
24
  private
18
25
 
19
26
  @end_boundary: untyped
20
27
 
21
28
  @end_key: Array[untyped]?
22
29
 
23
- @start_key: Array[untyped]
30
+ @start_boundary: untyped
31
+
32
+ @start_key: Array[untyped]?
24
33
 
25
- @start_version: untyped
34
+ @start_time: untyped
26
35
 
27
36
  # : (untyped, Array[untyped]) -> bool
28
- def before_end?: (untyped, Array[untyped]) -> bool
37
+ def after_start?: (untyped, Array[untyped]) -> bool
29
38
 
30
- # : () -> untyped
31
- def end_time: () -> untyped
39
+ # : (untyped, Array[untyped]) -> bool
40
+ def before_end?: (untyped, Array[untyped]) -> bool
32
41
 
33
42
  # : (Array[untyped], Array[untyped]) -> bool
34
43
  def key_before_or_equal?: (Array[untyped], Array[untyped]) -> bool
@@ -0,0 +1,23 @@
1
+ # Generated from lib/paper_trail_diff/activity_relationship.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Reads event-side foreign keys and matches them to an immutable snapshot owner.
5
+ class ActivityRelationship
6
+ # : (untyped, untyped, RecordSnapshot, ?state: Symbol) -> bool
7
+ def member_of_owner?: (untyped, untyped, RecordSnapshot, ?state: Symbol) -> bool
8
+
9
+ # : (untyped, untyped, state: Symbol) -> untyped
10
+ def owner_id: (untyped, untyped, state: Symbol) -> untyped
11
+
12
+ private
13
+
14
+ # : (untyped, untyped, state: Symbol) -> Array[String]
15
+ def relationship_owner_values: (untyped, untyped, state: Symbol) -> Array[String]
16
+
17
+ # : (untyped, untyped, state: Symbol) -> untyped
18
+ def event_attribute: (untyped, untyped, state: Symbol) -> untyped
19
+
20
+ # : (untyped, RecordSnapshot) -> Array[String]
21
+ def owner_types: (untyped, RecordSnapshot) -> Array[String]
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ # Generated from lib/paper_trail_diff/activity_snapshot_delta.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Internal scalar transition for one isolated PaperTrail update event.
5
+ class ActivitySnapshotDelta
6
+ # : (before_attributes: Hash[untyped, untyped], after_attributes: Hash[untyped, untyped]) -> void
7
+ def initialize: (before_attributes: Hash[untyped, untyped], after_attributes: Hash[untyped, untyped]) -> void
8
+
9
+ # : (RecordSnapshot) -> RecordSnapshot
10
+ def apply: (RecordSnapshot) -> RecordSnapshot
11
+
12
+ # : (untyped) -> untyped
13
+ def before_value: (untyped) -> untyped
14
+
15
+ # : (untyped) -> untyped
16
+ def after_value: (untyped) -> untyped
17
+
18
+ # : (untyped) -> bool
19
+ def relationship_changed?: (untyped) -> bool
20
+
21
+ private
22
+
23
+ @after_attributes: Hash[String, untyped]
24
+
25
+ @before_attributes: Hash[String, untyped]
26
+
27
+ # : (Hash[untyped, untyped]) -> Hash[String, untyped]
28
+ def normalize_hash: (Hash[untyped, untyped]) -> Hash[String, untyped]
29
+
30
+ # : (untyped) -> Array[untyped]
31
+ def relationship_keys: (untyped) -> Array[untyped]
32
+ end
33
+ end
@@ -6,8 +6,8 @@ module PaperTrailDiff
6
6
  # : (snapshotter: untyped, refresher: untyped, preparer: untyped) -> void
7
7
  def initialize: (snapshotter: untyped, refresher: untyped, preparer: untyped) -> void
8
8
 
9
- # : (untyped, Array[untyped]) -> void
10
- def prepare: (untyped, Array[untyped]) -> void
9
+ # : (untyped, Array[untyped], ?start_at: untyped) -> void
10
+ def prepare: (untyped, Array[untyped], ?start_at: untyped) -> void
11
11
 
12
12
  # : (untyped, untyped) -> RecordSnapshot?
13
13
  def call: (untyped, untyped) -> RecordSnapshot?
@@ -3,8 +3,8 @@
3
3
  module PaperTrailDiff
4
4
  # Compares adjacent root and selected-descendant activity boundaries.
5
5
  class ActivityTimelineBuilder
6
- # : (untyped, from: untyped, to: untyped, tree: AssociationTree, snapshotter: untyped) -> void
7
- def initialize: (untyped, from: untyped, to: untyped, tree: AssociationTree, snapshotter: untyped) -> void
6
+ # : (untyped, range: TimelineRange, tree: AssociationTree, snapshotter: untyped) -> void
7
+ def initialize: (untyped, range: TimelineRange, tree: AssociationTree, snapshotter: untyped) -> void
8
8
 
9
9
  # : () -> Array[ActivityStep]
10
10
  def build: () -> Array[ActivityStep]
@@ -17,6 +17,8 @@ module PaperTrailDiff
17
17
 
18
18
  @from: untyped
19
19
 
20
+ @range: TimelineRange
21
+
20
22
  @record: untyped
21
23
 
22
24
  @snapshotter: untyped
@@ -37,25 +39,28 @@ module PaperTrailDiff
37
39
  # : () -> void
38
40
  def validate_current_range!: () -> void
39
41
 
40
- # : (Array[untyped], ?range_end: untyped) -> Array[ActivityEvent]
41
- def collect_events: (Array[untyped], ?range_end: untyped) -> Array[ActivityEvent]
42
+ # : (Array[untyped], ?range_start: untyped, ?range_end: untyped) -> Array[ActivityEvent]
43
+ def collect_events: (Array[untyped], ?range_start: untyped, ?range_end: untyped) -> Array[ActivityEvent]
42
44
 
43
- # : (Array[untyped]) -> void
44
- def prepare_history: (Array[untyped]) -> void
45
+ # : (Array[untyped], ?start_at: untyped) -> void
46
+ def prepare_history: (Array[untyped], ?start_at: untyped) -> void
45
47
 
46
48
  # : (Array[untyped], Array[ActivityEvent], ?current: untyped, ?final_boundary: ActivityBoundary?, ?final_snapshot: RecordSnapshot?) -> Array[ActivityStep]
47
49
  def build_event_steps: (Array[untyped], Array[ActivityEvent], ?current: untyped, ?final_boundary: ActivityBoundary?, ?final_snapshot: RecordSnapshot?) -> Array[ActivityStep]
48
50
 
49
- # : (Array[untyped], Array[ActivityEvent], ?current: untyped) -> [Array[ActivityStep], Hash[Array[untyped], RecordSnapshot?], RecordSnapshot?]
50
- def event_history: (Array[untyped], Array[ActivityEvent], ?current: untyped) -> [ Array[ActivityStep], Hash[Array[untyped], RecordSnapshot?], RecordSnapshot? ]
51
+ # : (Array[untyped], Array[ActivityEvent], ?current: untyped) -> ActivityHistory
52
+ def event_history: (Array[untyped], Array[ActivityEvent], ?current: untyped) -> ActivityHistory
51
53
 
52
- # : (Array[untyped], Hash[Array[untyped], RecordSnapshot?], Array[ActivityStep]) -> Analysis
53
- def build_analysis: (Array[untyped], Hash[Array[untyped], RecordSnapshot?], Array[ActivityStep]) -> Analysis
54
+ # : (Array[untyped], ActivityHistory) -> Analysis
55
+ def build_analysis: (Array[untyped], ActivityHistory) -> Analysis
54
56
 
55
57
  # : (Array[untyped], Array[RecordSnapshot?]) -> Array[Step]
56
58
  def build_root_steps: (Array[untyped], Array[RecordSnapshot?]) -> Array[Step]
57
59
 
58
60
  # : (untyped) -> Array[untyped]
59
61
  def version_key: (untyped) -> Array[untyped]
62
+
63
+ # : () -> TimeActivityTimelineBuilder
64
+ def time_builder: () -> TimeActivityTimelineBuilder
60
65
  end
61
66
  end
@@ -3,8 +3,8 @@
3
3
  module PaperTrailDiff
4
4
  # Collects root and selected-descendant versions relevant to one root history range.
5
5
  class ActivityVersionCollector
6
- # : (untyped, root_versions: Array[untyped], tree: AssociationTree, traversal: AssociationTraversal, ?range_end: untyped) -> void
7
- def initialize: (untyped, root_versions: Array[untyped], tree: AssociationTree, traversal: AssociationTraversal, ?range_end: untyped) -> void
6
+ # : (untyped, root_versions: Array[untyped], tree: AssociationTree, traversal: AssociationTraversal, ?range_start: untyped, ?range_end: untyped) -> void
7
+ def initialize: (untyped, root_versions: Array[untyped], tree: AssociationTree, traversal: AssociationTraversal, ?range_start: untyped, ?range_end: untyped) -> void
8
8
 
9
9
  # : () -> Array[ActivityEvent]
10
10
  def call: () -> Array[ActivityEvent]
@@ -59,9 +59,6 @@ module PaperTrailDiff
59
59
  # : (untyped, untyped) -> untyped
60
60
  def target_class: (untyped, untyped) -> untyped
61
61
 
62
- # : (untyped) -> Array[String?]
63
- def related_parent_types: (untyped) -> Array[String?]
64
-
65
62
  # : (untyped) -> bool
66
63
  def in_range?: (untyped) -> bool
67
64
 
@@ -3,8 +3,8 @@
3
3
  module PaperTrailDiff
4
4
  # Reconstructs selected root branches and merges them into a prior immutable snapshot.
5
5
  class BranchSnapshotRefresher
6
- # : (tree: AssociationTree, ignore_policy: IgnorePolicy, traversal: AssociationTraversal, pool: SnapshotPool, normalizer: SnapshotNormalizer, full_snapshotter: untyped, partial_snapshotter: untyped, association_reader: untyped) -> void
7
- def initialize: (tree: AssociationTree, ignore_policy: IgnorePolicy, traversal: AssociationTraversal, pool: SnapshotPool, normalizer: SnapshotNormalizer, full_snapshotter: untyped, partial_snapshotter: untyped, association_reader: untyped) -> void
6
+ # : (tree: AssociationTree, ignore_policy: IgnorePolicy, traversal: AssociationTraversal, pool: SnapshotPool, normalizer: SnapshotNormalizer, full_snapshotter: untyped, partial_snapshotter: untyped, association_reader: untyped, record_transition: untyped) -> void
7
+ def initialize: (tree: AssociationTree, ignore_policy: IgnorePolicy, traversal: AssociationTraversal, pool: SnapshotPool, normalizer: SnapshotNormalizer, full_snapshotter: untyped, partial_snapshotter: untyped, association_reader: untyped, record_transition: untyped) -> void
8
8
 
9
9
  # : (untyped, untyped, RecordSnapshot?, event: ActivityEvent) -> RecordSnapshot?
10
10
  def advance_root: (untyped, untyped, RecordSnapshot?, event: ActivityEvent) -> RecordSnapshot?
@@ -0,0 +1,59 @@
1
+ # Generated from lib/paper_trail_diff/collection_comparator.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Compares collection snapshots with a low-allocation path for stable membership.
5
+ class CollectionComparator
6
+ # : (AssociationSnapshot, AssociationSnapshot, record_comparer: untyped) -> void
7
+ def initialize: (AssociationSnapshot, AssociationSnapshot, record_comparer: untyped) -> void
8
+
9
+ # : () -> CollectionAssociationDiff
10
+ def call: () -> CollectionAssociationDiff
11
+
12
+ private
13
+
14
+ @from: AssociationSnapshot
15
+
16
+ @record_comparer: untyped
17
+
18
+ @to: AssociationSnapshot
19
+
20
+ # : (CollectionTransition) -> CollectionAssociationDiff
21
+ def transition_difference: (CollectionTransition) -> CollectionAssociationDiff
22
+
23
+ # : (RecordSnapshot?, RecordSnapshot?) -> RecordChange?
24
+ def compare_transition_records: (RecordSnapshot?, RecordSnapshot?) -> RecordChange?
25
+
26
+ # : () -> Array[RecordChange]?
27
+ def aligned_changes: () -> Array[RecordChange]?
28
+
29
+ # : () -> Array[[RecordSnapshot, RecordSnapshot]]?
30
+ def aligned_changed_pairs: () -> Array[[ RecordSnapshot, RecordSnapshot ]]?
31
+
32
+ # : (Array[RecordSnapshot], Array[RecordSnapshot]) -> Array[[RecordSnapshot, RecordSnapshot]]?
33
+ def collect_aligned_pairs: (Array[RecordSnapshot], Array[RecordSnapshot]) -> Array[[ RecordSnapshot, RecordSnapshot ]]?
34
+
35
+ # : () -> CollectionAssociationDiff
36
+ def indexed_difference: () -> CollectionAssociationDiff
37
+
38
+ # : (added: Array[RecordSnapshot], removed: Array[RecordSnapshot], changed: Array[RecordChange]) -> CollectionAssociationDiff
39
+ def difference: (added: Array[RecordSnapshot], removed: Array[RecordSnapshot], changed: Array[RecordChange]) -> CollectionAssociationDiff
40
+
41
+ # : (Hash[identity, RecordSnapshot], Hash[identity, RecordSnapshot]) -> Array[RecordSnapshot]
42
+ def records_missing_from: (Hash[identity, RecordSnapshot], Hash[identity, RecordSnapshot]) -> Array[RecordSnapshot]
43
+
44
+ # : (Hash[identity, RecordSnapshot], Hash[identity, RecordSnapshot]) -> Array[RecordChange]
45
+ def changed_records: (Hash[identity, RecordSnapshot], Hash[identity, RecordSnapshot]) -> Array[RecordChange]
46
+
47
+ # : (Array[RecordSnapshot]) -> Hash[identity, RecordSnapshot]
48
+ def index_records: (Array[RecordSnapshot]) -> Hash[identity, RecordSnapshot]
49
+
50
+ # : (Array[identity]) -> Array[identity]
51
+ def sorted_identities: (Array[identity]) -> Array[identity]
52
+
53
+ # : (identity) -> Array[untyped]
54
+ def sortable_identity: (identity) -> Array[untyped]
55
+
56
+ # : (identity) -> void
57
+ def raise_duplicate_identity!: (identity) -> void
58
+ end
59
+ end
@@ -0,0 +1,29 @@
1
+ # Generated from lib/paper_trail_diff/collection_identity_index.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Immutable positions for one collection membership and ordering.
5
+ class CollectionIdentityIndex
6
+ # : (Array[untyped]) -> void
7
+ def initialize: (Array[untyped]) -> void
8
+
9
+ # : (untyped, untyped) -> Integer?
10
+ def position: (untyped, untyped) -> Integer?
11
+
12
+ # : (untyped) -> Integer?
13
+ def position_for_id: (untyped) -> Integer?
14
+
15
+ private
16
+
17
+ @id_positions: Hash[String, Integer?]
18
+
19
+ @positions: Hash[Array[untyped], Integer]
20
+
21
+ @serialized_positions: Hash[Array[String], Integer]
22
+
23
+ # : (untyped, Integer) -> void
24
+ def register: (untyped, Integer) -> void
25
+
26
+ # : (untyped, Integer) -> void
27
+ def register_id: (untyped, Integer) -> void
28
+ end
29
+ end
@@ -0,0 +1,18 @@
1
+ # Generated from lib/paper_trail_diff/collection_transition.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # One collection mutation between structurally adjacent snapshots.
5
+ class CollectionTransition
6
+ attr_reader before: RecordSnapshot?
7
+
8
+ attr_reader after: RecordSnapshot?
9
+
10
+ # : (from: AssociationSnapshot, before: RecordSnapshot?, after: RecordSnapshot?) -> void
11
+ def initialize: (from: AssociationSnapshot, before: RecordSnapshot?, after: RecordSnapshot?) -> void
12
+
13
+ # : (AssociationSnapshot) -> bool
14
+ def from?: (AssociationSnapshot) -> bool
15
+
16
+ @from_object_id: Integer
17
+ end
18
+ end
@@ -0,0 +1,65 @@
1
+ # Generated from lib/paper_trail_diff/comparison_batch.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Validates and executes independent comparisons with shared live endpoint loading.
5
+ class ComparisonBatch
6
+ # : (Array[comparison_input], live_loader: untyped, preparer: untyped, history_preparer: untyped, historical_snapshotter: untyped, live_normalizer: untyped) -> void
7
+ def initialize: (Array[comparison_input], live_loader: untyped, preparer: untyped, history_preparer: untyped, historical_snapshotter: untyped, live_normalizer: untyped) -> void
8
+
9
+ # : () -> comparison_results
10
+ def call: () -> comparison_results
11
+
12
+ private
13
+
14
+ @comparisons: Array[comparison_input]
15
+
16
+ @historical_snapshotter: untyped
17
+
18
+ @history_preparer: untyped
19
+
20
+ @live_loader: untyped
21
+
22
+ @live_normalizer: untyped
23
+
24
+ @preparer: untyped
25
+
26
+ # : (untyped, untyped, Hash[identity, RecordSnapshot]) -> Diff
27
+ def compare: (untyped, untyped, Hash[identity, RecordSnapshot]) -> Diff
28
+
29
+ # : (untyped, Hash[identity, RecordSnapshot]) -> RecordSnapshot?
30
+ def snapshot: (untyped, Hash[identity, RecordSnapshot]) -> RecordSnapshot?
31
+
32
+ # : (Array[untyped]) -> Hash[identity, untyped]
33
+ def load_live_records: (Array[untyped]) -> Hash[identity, untyped]
34
+
35
+ # : (Hash[identity, untyped]) -> Hash[identity, RecordSnapshot]
36
+ def normalize_live_records: (Hash[identity, untyped]) -> Hash[identity, RecordSnapshot]
37
+
38
+ # : (Array[[untyped, untyped]], Hash[identity, untyped]) -> void
39
+ def prepare_historical_batches!: (Array[[ untyped, untyped ]], Hash[identity, untyped]) -> void
40
+
41
+ # : (Array[[untyped, untyped]], Hash[identity, untyped]) -> Array[untyped]
42
+ def historical_versions: (Array[[ untyped, untyped ]], Hash[identity, untyped]) -> Array[untyped]
43
+
44
+ # : () -> Array[[untyped, untyped]]
45
+ def comparison_pairs: () -> Array[[ untyped, untyped ]]
46
+
47
+ # : (untyped, Integer) -> [untyped, untyped]
48
+ def comparison_pair: (untyped, Integer) -> [ untyped, untyped ]
49
+
50
+ # : (untyped, Integer) -> void
51
+ def valid_comparison!: (untyped, Integer) -> void
52
+
53
+ # : (Hash[untyped, untyped], Symbol) -> untyped
54
+ def endpoint: (Hash[untyped, untyped], Symbol) -> untyped
55
+
56
+ # : (Array[[untyped, untyped]]) -> void
57
+ def ensure_unique_identities!: (Array[[ untyped, untyped ]]) -> void
58
+
59
+ # : (Array[[untyped, untyped]]) -> void
60
+ def prepare_endpoint_classes!: (Array[[ untyped, untyped ]]) -> void
61
+
62
+ # : (Array[[untyped, untyped]]) -> Hash[untyped, bool]
63
+ def endpoint_requirements: (Array[[ untyped, untyped ]]) -> Hash[untyped, bool]
64
+ end
65
+ end
@@ -36,18 +36,6 @@ module PaperTrailDiff
36
36
  # : (AssociationSnapshot, AssociationSnapshot) -> CollectionAssociationDiff
37
37
  private def self.compare_collection: (AssociationSnapshot, AssociationSnapshot) -> CollectionAssociationDiff
38
38
 
39
- # : (Hash[identity, RecordSnapshot], Hash[identity, RecordSnapshot]) -> Array[RecordSnapshot]
40
- private def self.records_missing_from: (Hash[identity, RecordSnapshot], Hash[identity, RecordSnapshot]) -> Array[RecordSnapshot]
41
-
42
- # : (Hash[identity, RecordSnapshot], Hash[identity, RecordSnapshot]) -> Array[RecordChange]
43
- private def self.changed_records: (Hash[identity, RecordSnapshot], Hash[identity, RecordSnapshot]) -> Array[RecordChange]
44
-
45
- # : (Array[RecordSnapshot]) -> Hash[Array[untyped], RecordSnapshot]
46
- private def self.index_records: (Array[RecordSnapshot]) -> Hash[Array[untyped], RecordSnapshot]
47
-
48
- # : (Array[Array[untyped]]) -> Array[Array[untyped]]
49
- private def self.sorted_identities: (Array[Array[untyped]]) -> Array[Array[untyped]]
50
-
51
39
  # : (RecordSnapshot?, RecordSnapshot?) -> bool
52
40
  private def self.same_identity?: (RecordSnapshot?, RecordSnapshot?) -> bool
53
41
  end
@@ -17,10 +17,22 @@ module PaperTrailDiff
17
17
  class InvalidEndpointError < Error
18
18
  end
19
19
 
20
+ # Raised when reload opt-out encounters an association that was not preloaded.
21
+ class UnloadedAssociationError < InvalidEndpointError
22
+ end
23
+
20
24
  # Raised when a timeline boundary is absent or the requested range is reversed.
21
25
  class InvalidTimelineRangeError < Error
22
26
  end
23
27
 
28
+ # Raised when `within` is not a finite, chronological range of time-like values.
29
+ class InvalidTimeRangeError < InvalidTimelineRangeError
30
+ end
31
+
32
+ # Raised when an in-range mutation has no later root boundary for reconstruction.
33
+ class IncompleteTimeRangeError < InvalidTimelineRangeError
34
+ end
35
+
24
36
  # Raised when a requested ActiveRecord association does not exist.
25
37
  class UnknownAssociationError < Error
26
38
  end
@@ -6,8 +6,12 @@ module PaperTrailDiff
6
6
  # : (tree: AssociationTree, traversal: AssociationTraversal, normalizer: SnapshotNormalizer, preparer: untyped) -> void
7
7
  def initialize: (tree: AssociationTree, traversal: AssociationTraversal, normalizer: SnapshotNormalizer, preparer: untyped) -> void
8
8
 
9
- # : (untyped, Array[untyped]) -> void
10
- def prepare: (untyped, Array[untyped]) -> void
9
+ # : (untyped, Array[untyped], ?start_at: untyped) -> void
10
+ def prepare: (untyped, Array[untyped], ?start_at: untyped) -> void
11
+
12
+ # Prepares selected history for several roots of the same model class.
13
+ # : (Array[untyped], Array[untyped]) -> void
14
+ def prepare_batch: (Array[untyped], Array[untyped]) -> void
11
15
 
12
16
  # : (untyped, untyped) -> RecordSnapshot?
13
17
  def call: (untyped, untyped) -> RecordSnapshot?
@@ -21,10 +25,17 @@ module PaperTrailDiff
21
25
  # : (untyped, habtm_version: untyped) -> untyped
22
26
  def association_reader: (untyped, habtm_version: untyped) -> untyped
23
27
 
28
+ # : (untyped) -> [Hash[untyped, untyped], Hash[untyped, untyped]]?
29
+ def record_transition: (untyped) -> [ Hash[untyped, untyped], Hash[untyped, untyped] ]?
30
+
24
31
  private
25
32
 
33
+ @live_graph_collector: LiveGraphCollector
34
+
26
35
  @normalizer: SnapshotNormalizer
27
36
 
37
+ @prepared_histories: Hash[Array[untyped], PreparedHistory]
38
+
28
39
  @prepared_history: PreparedHistory?
29
40
 
30
41
  @preparer: untyped
@@ -35,6 +46,15 @@ module PaperTrailDiff
35
46
 
36
47
  @tree: AssociationTree
37
48
 
49
+ # : (untyped) -> Array[untyped]
50
+ def context_key: (untyped) -> Array[untyped]
51
+
52
+ # : (Array[untyped], Array[untyped]) -> Hash[Symbol, untyped]
53
+ def batch_payload: (Array[untyped], Array[untyped]) -> Hash[Symbol, untyped]
54
+
55
+ # : (Array[untyped], Array[untyped]) -> void
56
+ def register_batch: (Array[untyped], Array[untyped]) -> void
57
+
38
58
  # : (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer) -> RecordSnapshot?
39
59
  def snapshot_from_version: (untyped, untyped, tree: AssociationTree, normalizer: SnapshotNormalizer) -> RecordSnapshot?
40
60
 
@@ -0,0 +1,12 @@
1
+ # Generated from lib/paper_trail_diff/instrumentation.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Emits quiet, namespaced runtime events for application-owned diagnostics.
5
+ module Instrumentation
6
+ # : (String | Symbol, Hash[Symbol, untyped]) { () -> untyped } -> untyped
7
+ def self?.instrument: (String | Symbol, Hash[Symbol, untyped]) { () -> untyped } -> untyped
8
+
9
+ # : (association_paths: Array[String], reload_live_endpoints: bool) -> Hash[Symbol, untyped]
10
+ def self?.comparison_payload: (association_paths: Array[String], reload_live_endpoints: bool) -> Hash[Symbol, untyped]
11
+ end
12
+ end
@@ -0,0 +1,52 @@
1
+ # Generated from lib/paper_trail_diff/live_endpoint_batch_loader.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Reloads current-record endpoints and their explicitly selected associations in batches.
5
+ class LiveEndpointBatchLoader
6
+ # : (tree: AssociationTree) -> void
7
+ def initialize: (tree: AssociationTree) -> void
8
+
9
+ # : (Array[untyped]) -> Hash[identity, untyped]
10
+ def call: (Array[untyped]) -> Hash[identity, untyped]
11
+
12
+ private
13
+
14
+ @tree: AssociationTree
15
+
16
+ # : (untyped, Array[untyped]) -> Array[untyped]
17
+ def load_group: (untyped, Array[untyped]) -> Array[untyped]
18
+
19
+ # : (Array[untyped], AssociationTree) -> void
20
+ def preload_tree: (Array[untyped], AssociationTree) -> void
21
+
22
+ # : (untyped, Array[untyped], AssociationTree) -> void
23
+ def preload_model_tree: (untyped, Array[untyped], AssociationTree) -> void
24
+
25
+ # : (untyped, AssociationTree) -> Array[[untyped, AssociationTree]]
26
+ def selected_reflections: (untyped, AssociationTree) -> Array[[ untyped, AssociationTree ]]
27
+
28
+ # : (Array[untyped], Array[[untyped, AssociationTree]], individually: bool) -> void
29
+ def preload_subtrees: (Array[untyped], Array[[ untyped, AssociationTree ]], individually: bool) -> void
30
+
31
+ # : (Array[untyped], Array[Symbol]) -> void
32
+ def preload_batch: (Array[untyped], Array[Symbol]) -> void
33
+
34
+ # : () -> untyped
35
+ def active_record_preloader: () -> untyped
36
+
37
+ # : (untyped, untyped) -> bool
38
+ def batch_safe?: (untyped, untyped) -> bool
39
+
40
+ # : (Array[untyped], untyped) -> Array[untyped]
41
+ def load_individually: (Array[untyped], untyped) -> Array[untyped]
42
+
43
+ # : (Array[untyped], untyped) -> Array[untyped]
44
+ def targets: (Array[untyped], untyped) -> Array[untyped]
45
+
46
+ # : (Array[untyped]) -> Array[untyped]
47
+ def unique_records: (Array[untyped]) -> Array[untyped]
48
+
49
+ # : (Array[untyped], Hash[identity, untyped]) -> void
50
+ def ensure_all_loaded!: (Array[untyped], Hash[identity, untyped]) -> void
51
+ end
52
+ end
@@ -0,0 +1,23 @@
1
+ # Generated from lib/paper_trail_diff/live_endpoint_provider.rb with RBS::Inline
2
+
3
+ module PaperTrailDiff
4
+ # Selects safe reload or validated caller-owned loading for current endpoints.
5
+ class LiveEndpointProvider
6
+ attr_reader reload: bool
7
+
8
+ attr_reader comparison_payload: Hash[Symbol, untyped]
9
+
10
+ # : (tree: AssociationTree, traversal: AssociationTraversal, reload: bool) -> void
11
+ def initialize: (tree: AssociationTree, traversal: AssociationTraversal, reload: bool) -> void
12
+
13
+ # : (Array[untyped]) -> Hash[identity, untyped]
14
+ def call: (Array[untyped]) -> Hash[identity, untyped]
15
+
16
+ private
17
+
18
+ @loader: untyped
19
+
20
+ # : (Array[untyped]) -> Hash[Symbol, untyped]
21
+ def payload: (Array[untyped]) -> Hash[Symbol, untyped]
22
+ end
23
+ end