expressir 2.1.25 → 2.1.27

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f52eda5e0d80dd80576d784a17159f1f70151d1040d493e2f70408a86a269f9f
4
- data.tar.gz: a5bfdc154ad38933894545b193ead0f616e07e86aa316284d86fbf3f1556f673
3
+ metadata.gz: 79f9083d84c90911c68536e3f07c4a2ebeb7675bca18d445b7af90d9ece6e7ee
4
+ data.tar.gz: 69e648f694b883906a32fc316219db79dbaa053c2633a4543cd4b62673a9f88d
5
5
  SHA512:
6
- metadata.gz: 9ada0d27c2df4a16595cde9973f48e224d4a46691bad332500af178b43898f4a721bc19876ba383dc41a694ee405796495996999eb3008220aca53e978c9d3e3
7
- data.tar.gz: ebdb14b2bd307482f39c8c682c68081324bfb012bf9b4cc68f511739b65f26b361e40f65fba2ae6fc50b782a04661836849c6ecd827e95f318e828221b951de3
6
+ metadata.gz: d9cc037357c9803c739a486089fc69b4799b1ba02f5f9de51216175447765f0e650dc02f8c525d2c4be8a3ea38e2ac953c5ef22e530ce4fea1f42f902eead456
7
+ data.tar.gz: aca50dfe25f95e07453607f76df4ca532a3c3e97f8d95af08442c5a5ff402434a80e3fa6b2f8147992b72fefbaa1c3b9487f001095960b605abd5a3cfecd2bf1
data/.rubocop_todo.yml CHANGED
@@ -1,18 +1,116 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2025-07-04 10:39:56 UTC using RuboCop version 1.77.0.
3
+ # on 2025-10-12 15:55:59 UTC using RuboCop version 1.81.1.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 550
9
+ # Offense count: 9
10
+ # This cop supports safe autocorrection (--autocorrect).
11
+ # Configuration parameters: EnforcedStyle, IndentationWidth.
12
+ # SupportedStyles: with_first_argument, with_fixed_indentation
13
+ Layout/ArgumentAlignment:
14
+ Exclude:
15
+ - 'lib/expressir/commands/changes.rb'
16
+ - 'spec/expressir/changes/schema_change_spec.rb'
17
+ - 'spec/expressir/commands/changes_import_eengine_spec.rb'
18
+ - 'spec/expressir/commands/changes_validate_spec.rb'
19
+
20
+ # Offense count: 1
21
+ # This cop supports safe autocorrection (--autocorrect).
22
+ # Configuration parameters: EnforcedStyleAlignWith.
23
+ # SupportedStylesAlignWith: either, start_of_block, start_of_line
24
+ Layout/BlockAlignment:
25
+ Exclude:
26
+ - 'lib/expressir/changes/schema_change.rb'
27
+
28
+ # Offense count: 1
29
+ # This cop supports safe autocorrection (--autocorrect).
30
+ Layout/BlockEndNewline:
31
+ Exclude:
32
+ - 'lib/expressir/changes/schema_change.rb'
33
+
34
+ # Offense count: 1
35
+ # This cop supports safe autocorrection (--autocorrect).
36
+ # Configuration parameters: AllowForAlignment.
37
+ Layout/CommentIndentation:
38
+ Exclude:
39
+ - 'lib/expressir/commands/changes_validate.rb'
40
+
41
+ # Offense count: 2
42
+ # This cop supports safe autocorrection (--autocorrect).
43
+ Layout/ElseAlignment:
44
+ Exclude:
45
+ - 'lib/expressir/commands/changes_validate.rb'
46
+
47
+ # Offense count: 2
48
+ # This cop supports safe autocorrection (--autocorrect).
49
+ # Configuration parameters: EnforcedStyle.
50
+ # SupportedStyles: empty_lines, no_empty_lines
51
+ Layout/EmptyLinesAroundBlockBody:
52
+ Exclude:
53
+ - 'bin/validate_all_changes'
54
+
55
+ # Offense count: 1
56
+ # This cop supports safe autocorrection (--autocorrect).
57
+ # Configuration parameters: EnforcedStyleAlignWith, Severity.
58
+ # SupportedStylesAlignWith: keyword, variable, start_of_line
59
+ Layout/EndAlignment:
60
+ Exclude:
61
+ - 'lib/expressir/commands/changes_validate.rb'
62
+
63
+ # Offense count: 12
64
+ # This cop supports safe autocorrection (--autocorrect).
65
+ # Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
66
+ # SupportedHashRocketStyles: key, separator, table
67
+ # SupportedColonStyles: key, separator, table
68
+ # SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
69
+ Layout/HashAlignment:
70
+ Exclude:
71
+ - 'lib/expressir/commands/changes.rb'
72
+ - 'spec/expressir/changes/schema_change_spec.rb'
73
+ - 'spec/expressir/commands/changes_validate_spec.rb'
74
+
75
+ # Offense count: 6
76
+ # This cop supports safe autocorrection (--autocorrect).
77
+ # Configuration parameters: Width, AllowedPatterns.
78
+ Layout/IndentationWidth:
79
+ Exclude:
80
+ - 'bin/validate_all_changes'
81
+ - 'lib/expressir/changes/schema_change.rb'
82
+ - 'lib/expressir/commands/changes_validate.rb'
83
+
84
+ # Offense count: 574
10
85
  # This cop supports safe autocorrection (--autocorrect).
11
86
  # Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
12
87
  # URISchemes: http, https
13
88
  Layout/LineLength:
14
89
  Enabled: false
15
90
 
91
+ # Offense count: 1
92
+ # This cop supports safe autocorrection (--autocorrect).
93
+ Layout/RescueEnsureAlignment:
94
+ Exclude:
95
+ - 'bin/validate_all_changes'
96
+
97
+ # Offense count: 8
98
+ # This cop supports safe autocorrection (--autocorrect).
99
+ # Configuration parameters: AllowInHeredoc.
100
+ Layout/TrailingWhitespace:
101
+ Exclude:
102
+ - 'bin/validate_all_changes'
103
+ - 'lib/expressir/commands/changes.rb'
104
+ - 'spec/expressir/changes/schema_change_spec.rb'
105
+ - 'spec/expressir/commands/changes_import_eengine_spec.rb'
106
+ - 'spec/expressir/commands/changes_validate_spec.rb'
107
+
108
+ # Offense count: 4
109
+ # This cop supports safe autocorrection (--autocorrect).
110
+ Lint/AmbiguousOperatorPrecedence:
111
+ Exclude:
112
+ - 'bin/validate_all_changes'
113
+
16
114
  # Offense count: 1
17
115
  # Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
18
116
  Lint/DuplicateBranch:
@@ -21,43 +119,32 @@ Lint/DuplicateBranch:
21
119
 
22
120
  # Offense count: 2
23
121
  # This cop supports safe autocorrection (--autocorrect).
24
- # Configuration parameters: AutoCorrect, AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions.
122
+ # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions.
25
123
  # NotImplementedExceptions: NotImplementedError
26
124
  Lint/UnusedMethodArgument:
27
125
  Exclude:
28
126
  - 'lib/expressir/express/cache.rb'
29
127
  - 'lib/expressir/express/parser.rb'
30
128
 
31
- # Offense count: 79
129
+ # Offense count: 83
32
130
  # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
33
131
  Metrics/AbcSize:
34
- Exclude:
35
- - 'lib/expressir/benchmark.rb'
36
- - 'lib/expressir/commands/benchmark.rb'
37
- - 'lib/expressir/commands/benchmark_cache.rb'
38
- - 'lib/expressir/commands/coverage.rb'
39
- - 'lib/expressir/commands/validate.rb'
40
- - 'lib/expressir/config.rb'
41
- - 'lib/expressir/coverage.rb'
42
- - 'lib/expressir/express/formatter.rb'
43
- - 'lib/expressir/express/hyperlink_formatter.rb'
44
- - 'lib/expressir/express/parser.rb'
45
- - 'lib/expressir/express/resolve_references_model_visitor.rb'
46
- - 'lib/expressir/express/visitor.rb'
47
- - 'lib/expressir/model/declarations/schema.rb'
48
- - 'lib/expressir/model/model_element.rb'
132
+ Enabled: false
49
133
 
50
- # Offense count: 1
134
+ # Offense count: 2
51
135
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
52
136
  # AllowedMethods: refine
53
137
  Metrics/BlockLength:
54
- Max: 46
138
+ Max: 72
55
139
 
56
- # Offense count: 56
140
+ # Offense count: 59
57
141
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
58
142
  Metrics/CyclomaticComplexity:
59
143
  Exclude:
60
144
  - 'lib/expressir/benchmark.rb'
145
+ - 'lib/expressir/changes/schema_change.rb'
146
+ - 'lib/expressir/commands/changes_import_eengine.rb'
147
+ - 'lib/expressir/commands/changes_validate.rb'
61
148
  - 'lib/expressir/commands/coverage.rb'
62
149
  - 'lib/expressir/coverage.rb'
63
150
  - 'lib/expressir/express/formatter.rb'
@@ -68,16 +155,19 @@ Metrics/CyclomaticComplexity:
68
155
  - 'lib/expressir/model/model_element.rb'
69
156
  - 'spec/support/model_element_helper.rb'
70
157
 
71
- # Offense count: 105
158
+ # Offense count: 109
72
159
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
73
160
  Metrics/MethodLength:
74
161
  Max: 106
75
162
 
76
- # Offense count: 44
163
+ # Offense count: 47
77
164
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
78
165
  Metrics/PerceivedComplexity:
79
166
  Exclude:
80
167
  - 'lib/expressir/benchmark.rb'
168
+ - 'lib/expressir/changes/schema_change.rb'
169
+ - 'lib/expressir/commands/changes_import_eengine.rb'
170
+ - 'lib/expressir/commands/changes_validate.rb'
81
171
  - 'lib/expressir/commands/coverage.rb'
82
172
  - 'lib/expressir/coverage.rb'
83
173
  - 'lib/expressir/express/formatter.rb'
@@ -104,7 +194,7 @@ Performance/MapMethodChain:
104
194
  - 'spec/expressir/commands/coverage_ignore_files_spec.rb'
105
195
  - 'spec/expressir/coverage_spec.rb'
106
196
 
107
- # Offense count: 102
197
+ # Offense count: 122
108
198
  # Configuration parameters: CountAsOne.
109
199
  RSpec/ExampleLength:
110
200
  Max: 123
@@ -121,11 +211,12 @@ RSpec/IndexedLet:
121
211
  - 'spec/expressir/model/data_types/string_spec.rb'
122
212
 
123
213
  # Offense count: 1
214
+ # This cop supports safe autocorrection (--autocorrect).
124
215
  RSpec/IteratedExpectation:
125
216
  Exclude:
126
217
  - 'spec/expressir/schema_manifest_spec.rb'
127
218
 
128
- # Offense count: 235
219
+ # Offense count: 254
129
220
  RSpec/MultipleExpectations:
130
221
  Max: 114
131
222
 
@@ -146,7 +237,89 @@ RSpec/RepeatedExample:
146
237
  Exclude:
147
238
  - 'spec/expressir/model/data_types/logical_spec.rb'
148
239
 
240
+ # Offense count: 2
241
+ # This cop supports unsafe autocorrection (--autocorrect-all).
242
+ Security/YAMLLoad:
243
+ Exclude:
244
+ - 'bin/validate_all_changes'
245
+
246
+ # Offense count: 1
247
+ # This cop supports safe autocorrection (--autocorrect).
248
+ # Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods.
249
+ # SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces
250
+ # ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
251
+ # FunctionalMethods: let, let!, subject, watch
252
+ # AllowedMethods: lambda, proc, it
253
+ Style/BlockDelimiters:
254
+ Exclude:
255
+ - 'lib/expressir/changes/schema_change.rb'
256
+
257
+ # Offense count: 1
258
+ # This cop supports safe autocorrection (--autocorrect).
259
+ # Configuration parameters: EnforcedStyle, AllowComments.
260
+ # SupportedStyles: empty, nil, both
261
+ Style/EmptyElse:
262
+ Exclude:
263
+ - 'lib/expressir/commands/changes_validate.rb'
264
+
149
265
  # Offense count: 1
150
266
  Style/MissingRespondToMissing:
151
267
  Exclude:
152
268
  - 'lib/expressir/express/visitor.rb'
269
+
270
+ # Offense count: 1
271
+ # This cop supports unsafe autocorrection (--autocorrect-all).
272
+ # Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns.
273
+ # SupportedStyles: predicate, comparison
274
+ Style/NumericPredicate:
275
+ Exclude:
276
+ - 'spec/**/*'
277
+ - 'lib/expressir/commands/changes_import_eengine.rb'
278
+
279
+ # Offense count: 1
280
+ # This cop supports safe autocorrection (--autocorrect).
281
+ Style/RedundantBegin:
282
+ Exclude:
283
+ - 'bin/validate_all_changes'
284
+
285
+ # Offense count: 4
286
+ # This cop supports unsafe autocorrection (--autocorrect-all).
287
+ # Configuration parameters: Mode.
288
+ Style/StringConcatenation:
289
+ Exclude:
290
+ - 'bin/validate_all_changes'
291
+
292
+ # Offense count: 4
293
+ # This cop supports safe autocorrection (--autocorrect).
294
+ # Configuration parameters: EnforcedStyle.
295
+ # SupportedStyles: single_quotes, double_quotes
296
+ Style/StringLiteralsInInterpolation:
297
+ Exclude:
298
+ - 'bin/validate_all_changes'
299
+
300
+ # Offense count: 4
301
+ # This cop supports safe autocorrection (--autocorrect).
302
+ # Configuration parameters: EnforcedStyleForMultiline.
303
+ # SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
304
+ Style/TrailingCommaInArguments:
305
+ Exclude:
306
+ - 'lib/expressir/changes/schema_change.rb'
307
+ - 'lib/expressir/commands/changes_import_eengine.rb'
308
+
309
+ # Offense count: 5
310
+ # This cop supports safe autocorrection (--autocorrect).
311
+ # Configuration parameters: EnforcedStyleForMultiline.
312
+ # SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
313
+ Style/TrailingCommaInArrayLiteral:
314
+ Exclude:
315
+ - 'spec/expressir/changes/schema_change_spec.rb'
316
+
317
+ # Offense count: 10
318
+ # This cop supports safe autocorrection (--autocorrect).
319
+ # Configuration parameters: EnforcedStyleForMultiline.
320
+ # SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
321
+ Style/TrailingCommaInHashLiteral:
322
+ Exclude:
323
+ - 'bin/validate_all_changes'
324
+ - 'lib/expressir/commands/changes_import_eengine.rb'
325
+ - 'spec/expressir/changes/schema_change_spec.rb'
data/Gemfile CHANGED
@@ -5,6 +5,7 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in reeper.gemspec
6
6
  gemspec
7
7
 
8
+ gem "canon"
8
9
  gem "pry"
9
10
  gem "rake"
10
11
  gem "rspec"
data/README.adoc CHANGED
@@ -76,6 +76,7 @@ $ expressir
76
76
  Commands:
77
77
  expressir benchmark FILE_OR_YAML # Benchmark schema loading performance for a file or list of files from YAML
78
78
  expressir benchmark-cache FILE_OR_YAML # Benchmark schema loading with caching
79
+ expressir changes SUBCOMMAND # Commands for EXPRESS Changes files
79
80
  expressir clean PATH # Strip remarks and prettify EXPRESS schema at PATH
80
81
  expressir format PATH # pretty print EXPRESS schema located at PATH
81
82
  expressir help [COMMAND] # Describe available commands or one specific command
@@ -667,6 +668,103 @@ The default text output displays:
667
668
  This helps identify areas of your EXPRESS schemas that need documentation
668
669
  improvement.
669
670
 
671
+ === EXPRESS Changes files
672
+
673
+ Expressir provides commands for working with EXPRESS Changes files that track
674
+ schema modifications across versions.
675
+
676
+ ==== Validating change files
677
+
678
+ The `changes validate` command validates EXPRESS Changes YAML files and
679
+ optionally normalizes them through round-trip serialization.
680
+
681
+ [source, sh]
682
+ ----
683
+ # Validate a changes file
684
+ expressir changes validate schema.changes.yaml
685
+
686
+ # Validate with verbose output
687
+ expressir changes validate schema.changes.yaml --verbose
688
+
689
+ # Validate and normalize (outputs to stdout)
690
+ expressir changes validate schema.changes.yaml --normalize
691
+
692
+ # Validate and normalize in-place
693
+ expressir changes validate schema.changes.yaml --normalize --in-place
694
+
695
+ # Validate and save normalized output to a new file
696
+ expressir changes validate schema.changes.yaml --normalize --output normalized.yaml
697
+ ----
698
+
699
+ [options="header"]
700
+ |===
701
+ | Option | Description
702
+ | `--normalize` | Normalize file through round-trip serialization
703
+ | `--in-place` | Update file in place (requires `--normalize`)
704
+ | `--output PATH` | Output file path for normalized output
705
+ | `--verbose` | Show verbose output with validation details
706
+ |===
707
+
708
+ The validate command performs the following checks:
709
+
710
+ . Verifies the YAML file can be parsed
711
+ . Validates against the SchemaChange model structure
712
+ . Ensures all required fields are present
713
+ . Checks that change items have valid types
714
+
715
+ When using `--normalize`, the command:
716
+
717
+ . Loads the file and validates it
718
+ . Serializes it back to YAML with consistent formatting
719
+ . Either outputs to stdout, saves in-place, or writes to a new file
720
+
721
+ This is useful for:
722
+
723
+ * **Standardizing formatting**: Ensures consistent YAML structure
724
+ * **Catching errors early**: Validates before committing changes
725
+ * **Cleaning up files**: Removes inconsistencies in formatting
726
+
727
+ ==== Importing from eengine XML
728
+
729
+ The `changes import-eengine` command converts eengine comparison XML files to
730
+ EXPRESS Changes YAML format.
731
+
732
+ [source, sh]
733
+ ----
734
+ # Import and output to stdout
735
+ expressir changes import-eengine comparison.xml schema_name "2"
736
+
737
+ # Import and save to file
738
+ expressir changes import-eengine comparison.xml schema_name "2" -o output.yaml
739
+
740
+ # Import with verbose output
741
+ expressir changes import-eengine comparison.xml schema_name "2" -o output.yaml --verbose
742
+
743
+ # Append to existing changes file
744
+ expressir changes import-eengine comparison.xml schema_name "3" -o existing.yaml
745
+ ----
746
+
747
+ [options="header"]
748
+ |===
749
+ | Option | Description
750
+ | `-o, --output PATH` | Output YAML file path (stdout if not specified)
751
+ | `--verbose` | Show verbose output
752
+ |===
753
+
754
+ The import command:
755
+
756
+ . Parses the eengine XML comparison file
757
+ . Extracts additions, modifications, and removals
758
+ . Creates or updates an EXPRESS Changes YAML file
759
+ . Supports appending new versions to existing files
760
+
761
+ When the output file already exists:
762
+
763
+ * **Same version**: Replaces the existing edition with that version
764
+ * **New version**: Adds a new edition to the file
765
+
766
+ This allows you to build up a complete change history incrementally.
767
+
670
768
 
671
769
  == Usage: Ruby
672
770
 
@@ -1063,6 +1161,196 @@ expressir coverage schemas.yml --format json --exclude=TYPE:SELECT
1063
1161
 
1064
1162
 
1065
1163
 
1164
+ == Working with EXPRESS Changes
1165
+
1166
+ === General
1167
+
1168
+ Expressir provides the `Changes` module for managing and tracking changes to
1169
+ EXPRESS schemas across versions. This module implements the EXPRESS Changes YAML
1170
+ format defined by ELF (Express Language Foundation).
1171
+
1172
+ The Changes module enables:
1173
+
1174
+ * Loading and saving schema change records from/to YAML files
1175
+ * Programmatic creation and manipulation of change records
1176
+ * Smart edition handling (replace same version, add new version)
1177
+ * Support for all change types: additions, modifications, removals, deletions
1178
+ * Support for mapping changes in ARM/MIM schemas
1179
+
1180
+ === Reading change files
1181
+
1182
+ Load an existing schema change file:
1183
+
1184
+ [source,ruby]
1185
+ ----
1186
+ require "expressir/changes"
1187
+
1188
+ # Load from file
1189
+ change_schema = Expressir::Changes::SchemaChange.from_file("schema.changes.yaml")
1190
+
1191
+ # Access schema name
1192
+ puts "Schema: #{change_schema.schema}"
1193
+
1194
+ # Iterate through change editions
1195
+ change_schema.edition_change.each do |edition|
1196
+ puts "Version #{edition.version}: #{edition.description}"
1197
+
1198
+ # Access changes by type
1199
+ puts " Additions: #{edition.additions.size}" if edition.additions
1200
+ puts " Modifications: #{edition.modifications.size}" if edition.modifications
1201
+ puts " Deletions: #{edition.deletions.size}" if edition.deletions
1202
+ puts " Removals: #{edition.removals.size}" if edition.removals
1203
+ end
1204
+ ----
1205
+
1206
+ === Creating change records
1207
+
1208
+ Create a new change schema programmatically:
1209
+
1210
+ [source,ruby]
1211
+ ----
1212
+ # Create a new empty change schema
1213
+ change_schema = Expressir::Changes::SchemaChange.create_new("my_schema")
1214
+
1215
+ # Create change items
1216
+ new_entity = Expressir::Changes::ItemChange.new(
1217
+ type: "ENTITY",
1218
+ name: "new_entity_name"
1219
+ )
1220
+
1221
+ modified_function = Expressir::Changes::ItemChange.new(
1222
+ type: "FUNCTION",
1223
+ name: "modified_function",
1224
+ description: "Updated parameters"
1225
+ )
1226
+
1227
+ # Add a change edition
1228
+ changes = {
1229
+ additions: [new_entity],
1230
+ modifications: [modified_function],
1231
+ removals: []
1232
+ }
1233
+
1234
+ change_schema.add_or_update_edition(
1235
+ "2",
1236
+ "Added new entity and modified function",
1237
+ changes
1238
+ )
1239
+
1240
+ # Save to file
1241
+ change_schema.to_file("my_schema.changes.yaml")
1242
+ ----
1243
+
1244
+ === Updating existing change files
1245
+
1246
+ The `add_or_update_edition` method provides smart handling:
1247
+
1248
+ * **Same version**: Replaces the existing edition
1249
+ * **Different version**: Adds a new edition
1250
+
1251
+ [source,ruby]
1252
+ ----
1253
+ # Load existing change file
1254
+ change_schema = Expressir::Changes::SchemaChange.from_file("schema.changes.yaml")
1255
+
1256
+ # Add a new version
1257
+ changes = {
1258
+ modifications: [
1259
+ Expressir::Changes::ItemChange.new(type: "TYPE", name: "updated_type")
1260
+ ]
1261
+ }
1262
+ change_schema.add_or_update_edition("3", "Modified type definition", changes)
1263
+
1264
+ # Or replace existing version
1265
+ change_schema.add_or_update_edition("2", "Revised description", changes)
1266
+
1267
+ # Save changes
1268
+ change_schema.to_file("schema.changes.yaml")
1269
+ ----
1270
+
1271
+ === Change item fields
1272
+
1273
+ Change items support the following fields:
1274
+
1275
+ `type`:: (Required) The EXPRESS construct type (ENTITY, TYPE, FUNCTION, etc.)
1276
+ `name`:: (Required) The name of the construct
1277
+ `description`:: (Optional) Additional details about the change
1278
+ `interfaced_items`:: (Optional) For REFERENCE_FROM items
1279
+
1280
+ [source,ruby]
1281
+ ----
1282
+ item = Expressir::Changes::ItemChange.new(
1283
+ type: "REFERENCE_FROM",
1284
+ name: "measure_schema",
1285
+ interfaced_items: "length_measure"
1286
+ )
1287
+ ----
1288
+
1289
+ === Change edition fields
1290
+
1291
+ Change editions support categorizing changes into:
1292
+
1293
+ `additions`:: New elements added to the schema
1294
+ `modifications`:: Existing elements that were modified
1295
+ `removals`:: Elements removed from the schema
1296
+ `deletions`:: Alternative term for removals (both supported)
1297
+ `mapping`:: Mapping-related changes (for ARM/MIM modules)
1298
+ `changes`:: General changes (alternative to mapping)
1299
+
1300
+ [source,ruby]
1301
+ ----
1302
+ edition = Expressir::Changes::EditionChange.new(
1303
+ version: "2",
1304
+ description: "Added support for new functionality",
1305
+ additions: [item1, item2],
1306
+ modifications: [item3],
1307
+ deletions: [item4],
1308
+ mapping: [mapping_change]
1309
+ )
1310
+ ----
1311
+
1312
+ === Mapping changes
1313
+
1314
+ For ARM/MIM schema mappings, use `MappingChange`:
1315
+
1316
+ [source,ruby]
1317
+ ----
1318
+ mapping_change = Expressir::Changes::MappingChange.new(
1319
+ change: "Entity_name ENTITY mapping updated"
1320
+ )
1321
+ ----
1322
+
1323
+ === Example change file format
1324
+
1325
+ [source,yaml]
1326
+ ----
1327
+ ---
1328
+ schema: support_resource_schema
1329
+ edition_change:
1330
+ - version: '2'
1331
+ description: |-
1332
+ The definitions of the following EXPRESS entity data types were modified:
1333
+
1334
+ * action;
1335
+ * action_directive;
1336
+ * action_method.
1337
+ additions:
1338
+ - type: FUNCTION
1339
+ name: type_check_function
1340
+ modifications:
1341
+ - type: FUNCTION
1342
+ name: bag_to_set
1343
+ - version: '4'
1344
+ description: |-
1345
+ Added support for external element references.
1346
+ additions:
1347
+ - type: ENTITY
1348
+ name: component_path_shape_aspect
1349
+ modifications:
1350
+ - type: FUNCTION
1351
+ name: type_check_function
1352
+ ----
1353
+
1066
1354
  == Contributing
1067
1355
 
1068
1356
  First, thank you for contributing! We love pull requests from everyone. By
data/expressir.gemspec CHANGED
@@ -38,6 +38,6 @@ Gem::Specification.new do |spec|
38
38
  spec.add_dependency "lutaml-model"
39
39
  spec.add_dependency "parslet", "~> 2.0"
40
40
  spec.add_dependency "ruby-progressbar", "~> 1.11"
41
- spec.add_dependency "terminal-table", "~> 3.0"
41
+ spec.add_dependency "table_tennis"
42
42
  spec.add_dependency "thor", "~> 1.0"
43
43
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+ require_relative "item_change"
5
+ require_relative "mapping_change"
6
+
7
+ module Expressir
8
+ module Changes
9
+ # Represents a version edition of schema changes
10
+ class EditionChange < Lutaml::Model::Serializable
11
+ attribute :version, :string
12
+ attribute :description, :string
13
+ attribute :additions, ItemChange, collection: true
14
+ attribute :modifications, ItemChange, collection: true
15
+ attribute :removals, ItemChange, collection: true
16
+ attribute :deletions, ItemChange, collection: true
17
+ attribute :mapping, MappingChange, collection: true
18
+ attribute :changes, MappingChange, collection: true
19
+
20
+ yaml do
21
+ map "version", to: :version
22
+ map "description", to: :description
23
+ map "additions", to: :additions
24
+ map "modifications", to: :modifications
25
+ map "removals", to: :removals
26
+ map "deletions", to: :deletions
27
+ map "mapping", to: :mapping
28
+ map "changes", to: :changes
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Expressir
6
+ module Changes
7
+ # Represents a single change to an EXPRESS construct
8
+ class ItemChange < Lutaml::Model::Serializable
9
+ attribute :type, :string
10
+ attribute :name, :string
11
+ attribute :description, :string
12
+ attribute :interfaced_items, :string
13
+
14
+ yaml do
15
+ map "type", to: :type
16
+ map "name", to: :name
17
+ map "description", to: :description
18
+ map "interfaced_items", to: :interfaced_items
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Expressir
6
+ module Changes
7
+ # Represents a mapping change entry
8
+ class MappingChange < Lutaml::Model::Serializable
9
+ attribute :change, :string
10
+ attribute :description, :string
11
+
12
+ yaml do
13
+ map "change", to: :change
14
+ map "description", to: :description
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+ require_relative "edition_change"
5
+
6
+ module Expressir
7
+ module Changes
8
+ # Represents changes to an EXPRESS schema across multiple versions
9
+ class SchemaChange < Lutaml::Model::Serializable
10
+ attribute :schema, :string
11
+ attribute :edition_change, EditionChange, collection: true
12
+
13
+ yaml do
14
+ map "schema", to: :schema
15
+ map "edition_change", to: :edition_change
16
+ end
17
+
18
+ class << self
19
+ # Load a SchemaChange from a YAML file
20
+ #
21
+ # @param path [String] Path to the YAML file
22
+ # @return [SchemaChange] The loaded schema changes
23
+ def from_file(path)
24
+ content = File.read(path)
25
+ # Handle empty or minimal YAML files
26
+ return new(schema: "", edition_change: []) if content.strip == "---"
27
+
28
+ from_yaml(content)
29
+ end
30
+
31
+ # Create a new empty SchemaChange
32
+ #
33
+ # @param schema_name [String] Name of the schema
34
+ # @return [SchemaChange] New instance with empty change editions
35
+ def create_new(schema_name)
36
+ new(schema: schema_name, edition_change: [])
37
+ end
38
+ end
39
+
40
+ # Add or update a change edition in this schema
41
+ #
42
+ # @param version [String] Version number
43
+ # @param description [String] Description of changes
44
+ # @param changes [Hash] Hash with :additions, :modifications, :removals
45
+ # @return [EditionChange] The added or updated edition
46
+ def add_or_update_edition(version, description, changes)
47
+ version_str = version.to_s
48
+
49
+ # Find existing edition with this version
50
+ existing_index = edition_change.find_index do |ed|
51
+ ed.version == version_str
52
+ end
53
+
54
+ # Create new edition
55
+ edition = EditionChange.new(
56
+ version: version_str,
57
+ description: description,
58
+ additions: changes[:additions] || [],
59
+ modifications: changes[:modifications] || [],
60
+ removals: changes[:removals] || [],
61
+ deletions: changes[:deletions] || [],
62
+ )
63
+
64
+ if existing_index
65
+ # Replace existing edition with same version
66
+ edition_change[existing_index] = edition
67
+ else
68
+ # Add new edition
69
+ edition_change << edition
70
+ end
71
+
72
+ edition
73
+ end
74
+
75
+ # Save this SchemaChange to a YAML file
76
+ #
77
+ # @param path [String] Path where to save the file
78
+ # @return [Integer] Number of bytes written
79
+ def to_file(path)
80
+ File.write(path, to_yaml)
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "changes/schema_change"
4
+ require_relative "changes/edition_change"
5
+ require_relative "changes/item_change"
6
+ require_relative "changes/mapping_change"
7
+
8
+ module Expressir
9
+ # Module for EXPRESS schema change tracking and management
10
+ module Changes
11
+ end
12
+ end
data/lib/expressir/cli.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require "thor"
2
2
  require "yaml"
3
- require "terminal-table"
4
3
 
5
4
  require_relative "commands/base"
6
5
  require_relative "commands/format"
@@ -9,6 +8,7 @@ require_relative "commands/benchmark"
9
8
  require_relative "commands/benchmark_cache"
10
9
  require_relative "commands/validate"
11
10
  require_relative "commands/coverage"
11
+ require_relative "commands/changes"
12
12
  require_relative "commands/version"
13
13
 
14
14
  module Expressir
@@ -74,6 +74,9 @@ module Expressir
74
74
  Commands::Coverage.new(options).run(paths)
75
75
  end
76
76
 
77
+ desc "changes SUBCOMMAND", "Commands for EXPRESS Changes files"
78
+ subcommand "changes", Commands::Changes
79
+
77
80
  desc "version", "Expressir Version"
78
81
  def version
79
82
  Commands::Version.new(options).run
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+
5
+ module Expressir
6
+ module Commands
7
+ # Thor subcommand for EXPRESS Changes file operations
8
+ class Changes < Thor
9
+ desc "validate PATH", "Validate EXPRESS Changes YAML file"
10
+ method_option :normalize, type: :boolean,
11
+ desc: "Normalize file through round-trip serialization"
12
+ method_option :in_place, type: :boolean,
13
+ desc: "Update file in place (requires --normalize)"
14
+ method_option :output, type: :string,
15
+ desc: "Output file path (for normalized output)"
16
+ method_option :verbose, type: :boolean,
17
+ desc: "Show verbose output"
18
+ def validate(path)
19
+ require_relative "changes_validate"
20
+ ChangesValidate.new(options).run(path)
21
+ end
22
+
23
+ desc "import-eengine INPUT_XML SCHEMA_NAME VERSION",
24
+ "Import eengine comparison XML to EXPRESS Changes YAML"
25
+ method_option :output, type: :string, aliases: "-o",
26
+ desc: "Output YAML file path (stdout if not specified)"
27
+ method_option :verbose, type: :boolean,
28
+ desc: "Show verbose output"
29
+ def import_eengine(input_xml, schema_name, version)
30
+ require_relative "changes_import_eengine"
31
+ ChangesImportEengine.call(input_xml, options[:output], schema_name,
32
+ version, **options)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require "nokogiri"
5
+
6
+ module Expressir
7
+ module Commands
8
+ # Command to import eengine comparison XML to EXPRESS Changes YAML
9
+ class ChangesImportEengine < Base
10
+ def self.call(input_file, output_file, schema_name, version, **options)
11
+ new.call(input_file, output_file, schema_name, version, **options)
12
+ end
13
+
14
+ def call(input_file, output_file, schema_name, version, **options)
15
+ require "expressir/changes"
16
+
17
+ # Parse the eengine XML
18
+ xml_doc = File.open(input_file) { |f| Nokogiri::XML(f) }
19
+
20
+ # Extract changes from XML
21
+ changes = extract_changes(xml_doc)
22
+ description = generate_description(xml_doc)
23
+
24
+ # Load or create change schema
25
+ change_schema = if output_file && File.exist?(output_file) && File.size(output_file).positive?
26
+ Expressir::Changes::SchemaChange.from_file(output_file)
27
+ else
28
+ Expressir::Changes::SchemaChange.create_new(schema_name)
29
+ end
30
+
31
+ # Add or update edition
32
+ change_schema.add_or_update_edition(version, description, changes)
33
+
34
+ # Save to file
35
+ if output_file
36
+ change_schema.to_file(output_file)
37
+ puts "Change YAML file written to: #{output_file}" if options[:verbose]
38
+ else
39
+ puts change_schema.to_yaml
40
+ end
41
+
42
+ change_schema
43
+ end
44
+
45
+ private
46
+
47
+ def extract_changes(xml_doc)
48
+ {
49
+ additions: extract_added_objects(xml_doc),
50
+ modifications: extract_modified_objects(xml_doc),
51
+ removals: extract_removed_objects(xml_doc),
52
+ }
53
+ end
54
+
55
+ def extract_modified_objects(xml_doc)
56
+ xml_doc.xpath("//schema.modifications/modified.object").map do |node|
57
+ Expressir::Changes::ItemChange.new(
58
+ type: node["type"],
59
+ name: node["name"],
60
+ )
61
+ end
62
+ end
63
+
64
+ def extract_added_objects(xml_doc)
65
+ xml_doc.xpath("//schema.additions/added.object").map do |node|
66
+ Expressir::Changes::ItemChange.new(
67
+ type: node["type"],
68
+ name: node["name"],
69
+ )
70
+ end
71
+ end
72
+
73
+ def extract_removed_objects(xml_doc)
74
+ xml_doc.xpath("//schema.removals/removed.object").map do |node|
75
+ Expressir::Changes::ItemChange.new(
76
+ type: node["type"],
77
+ name: node["name"],
78
+ )
79
+ end
80
+ end
81
+
82
+ def generate_description(xml_doc)
83
+ parts = []
84
+
85
+ # Get descriptions from modifications
86
+ xml_doc.xpath("//schema.modifications/modified.object/description").each do |desc|
87
+ text = desc.text.strip
88
+ parts << text unless text.empty?
89
+ end
90
+
91
+ # Get descriptions from additions
92
+ xml_doc.xpath("//schema.additions/added.object/description").each do |desc|
93
+ text = desc.text.strip
94
+ parts << text unless text.empty?
95
+ end
96
+
97
+ # Get descriptions from removals
98
+ xml_doc.xpath("//schema.removals/removed.object/description").each do |desc|
99
+ text = desc.text.strip
100
+ parts << text unless text.empty?
101
+ end
102
+
103
+ parts.join("\n\n")
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module Expressir
6
+ module Commands
7
+ # Command to validate and normalize EXPRESS Changes YAML files
8
+ class ChangesValidate < Base
9
+ def run(path)
10
+ require "expressir/changes"
11
+
12
+ # Check if file exists
13
+ unless File.exist?(path)
14
+ exit_with_error("File not found: #{path}")
15
+ end
16
+
17
+ # Validate --in-place requires --normalize
18
+ if options[:in_place] && !options[:normalize]
19
+ exit_with_error("--in-place requires --normalize flag")
20
+ end
21
+
22
+ # Validate --in-place and --output are mutually exclusive
23
+ if options[:in_place] && options[:output]
24
+ exit_with_error("Cannot use both --in-place and --output")
25
+ end
26
+
27
+ begin
28
+ # Load and validate the file
29
+ say "Validating #{path}..." if options[:verbose]
30
+ schema_change = Expressir::Changes::SchemaChange.from_file(path)
31
+
32
+ say "✓ File is valid" if options[:verbose]
33
+ say " Schema: #{schema_change.schema}" if options[:verbose]
34
+ say " Editions: #{schema_change.edition_change.length}" if options[:verbose]
35
+
36
+ # Normalize if requested
37
+ if options[:normalize]
38
+ say "Normalizing through round-trip serialization..." if options[:verbose]
39
+
40
+ output_path = if options[:in_place]
41
+ path
42
+ elsif options[:output]
43
+ options[:output]
44
+ else
45
+ # Output to stdout
46
+ nil
47
+ end
48
+
49
+ if output_path
50
+ schema_change.to_file(output_path)
51
+ say "✓ Normalized file written to: #{output_path}"
52
+ else
53
+ # Output to stdout
54
+ puts schema_change.to_yaml
55
+ end
56
+ else
57
+ say "✓ File is valid"
58
+ end
59
+ rescue Psych::SyntaxError => e
60
+ exit_with_error("Invalid YAML syntax: #{e.message}")
61
+ rescue StandardError => e
62
+ exit_with_error("Validation failed: #{e.message}")
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -1,4 +1,4 @@
1
- require "terminal-table"
1
+ require "table_tennis"
2
2
  require "json"
3
3
  require "yaml"
4
4
  require "ruby-progressbar"
@@ -173,55 +173,79 @@ module Expressir
173
173
  end
174
174
  end
175
175
 
176
- # Create table
177
- table = Terminal::Table.new(
178
- title: "Directory Coverage",
179
- headings: ["Directory", "Total", "Documented", "Coverage %"],
180
- style: {
181
- border_x: "-",
182
- border_y: "|",
183
- border_i: "+",
184
- },
185
- )
186
-
187
- # Add rows
176
+ table_data = []
188
177
  dirs.each do |dir, stats|
189
178
  coverage = stats["total"].positive? ? (stats["documented"].to_f / stats["total"] * 100).round(2) : 100.0
190
- table.add_row [dir, stats["total"], stats["documented"],
191
- "#{coverage}%"]
179
+ table_data << {
180
+ directory: dir,
181
+ total: stats["total"].to_s,
182
+ documented: stats["documented"].to_s,
183
+ coverage_percentage: "#{coverage}%",
184
+ }
192
185
  end
193
186
 
187
+ table = TableTennis.new(
188
+ table_data,
189
+ {
190
+ title: "Entity coverage per directory",
191
+ headers: {
192
+ file: "Directory",
193
+ total: "Total Entities",
194
+ documented: "Documented Entities",
195
+ coverage_percentage: "Coverage %",
196
+ },
197
+ titleize: true,
198
+ layout: true,
199
+ },
200
+ )
201
+
194
202
  say table
195
203
  end
196
204
 
197
205
  def display_file_coverage(reports)
198
- say "\nFile Coverage:"
199
-
200
- # Create table
201
- table = Terminal::Table.new(
202
- title: "File Coverage",
203
- headings: ["File", "Undocumented Entities", "Coverage %"],
204
- style: {
205
- border_x: "-",
206
- border_y: "|",
207
- border_i: "+",
208
- },
209
- )
210
-
206
+ # Prepare data for table_tennis
207
+ table_data = []
211
208
  reports.each do |report|
212
209
  report.file_reports.each do |file_report|
213
210
  file_path = file_report["file"]
214
211
 
215
212
  # Format undocumented entities as "TYPE name, TYPE name, ..."
216
- undocumented_formatted = file_report["undocumented"].map do |entity_info|
213
+ undocumented = file_report["undocumented"].map do |entity_info|
217
214
  "#{entity_info['type']} #{entity_info['name']}"
218
215
  end.join(", ")
219
216
 
220
217
  coverage = file_report["coverage"].round(2)
221
- table.add_row [file_path, undocumented_formatted, "#{coverage}%"]
218
+
219
+ table_data << {
220
+ filename: File.basename(file_path),
221
+ undocumented_entities: if undocumented.empty?
222
+ "None"
223
+ else
224
+ undocumented
225
+ end,
226
+ coverage_percentage: "#{coverage}%",
227
+ }
222
228
  end
223
229
  end
224
230
 
231
+ table = TableTennis.new(
232
+ table_data,
233
+ {
234
+ title: "Entity coverage in file",
235
+ headers: {
236
+ filename: "Filename",
237
+ undocumented_entities: "Undocumented Entities",
238
+ coverage_percentage: "Coverage %",
239
+ },
240
+ titleize: true,
241
+ layout: {
242
+ filename: 30,
243
+ undocumented_entities: 50,
244
+ coverage_percentage: 20,
245
+ },
246
+ },
247
+ )
248
+
225
249
  say table
226
250
  end
227
251
 
@@ -229,22 +253,35 @@ module Expressir
229
253
  # Get structured report for overall statistics
230
254
  overall = build_structured_report(reports)["overall"]
231
255
 
232
- table = Terminal::Table.new(
233
- title: "Overall Documentation Coverage",
234
- style: {
235
- border_x: "-",
236
- border_y: "|",
237
- border_i: "+",
256
+ coverage_percentage = overall["coverage_percentage"]
257
+ table_data = [
258
+ {
259
+ metric: "Coverage Percentage",
260
+ value: "#{coverage_percentage}%",
261
+ },
262
+ {
263
+ metric: "Total Entities",
264
+ value: overall["total_entities"].to_s,
265
+ },
266
+ {
267
+ metric: "Documented Entities",
268
+ value: overall["documented_entities"].to_s,
269
+ },
270
+ {
271
+ metric: "Undocumented Entities",
272
+ value: overall["undocumented_entities"].to_s,
273
+ },
274
+ ]
275
+
276
+ table = TableTennis.new(
277
+ table_data,
278
+ {
279
+ title: "Entity overall coverage",
280
+ titleize: true,
281
+ layout: true,
238
282
  },
239
283
  )
240
284
 
241
- table.add_row ["Coverage Percentage",
242
- "#{overall['coverage_percentage']}%"]
243
- table.add_row ["Total Entities", overall["total_entities"]]
244
- table.add_row ["Documented Entities", overall["documented_entities"]]
245
- table.add_row ["Undocumented Entities",
246
- overall["undocumented_entities"]]
247
-
248
285
  say table
249
286
  end
250
287
 
@@ -253,6 +290,15 @@ module Expressir
253
290
  ignored_files = reports.flat_map(&:ignored_file_reports)
254
291
  ignored_entities_count = ignored_files.sum { |f| f["total"] }
255
292
 
293
+ total = reports.sum { |r| r.total_entities.size }
294
+ documented = reports.sum { |r| r.documented_entities.size }
295
+
296
+ coverage_per = if total.positive?
297
+ (documented.to_f / total * 100).round(2)
298
+ else
299
+ 100.0
300
+ end
301
+
256
302
  overall_stats = {
257
303
  "total_entities" => reports.sum { |r| r.total_entities.size },
258
304
  "documented_entities" => reports.sum do |r|
@@ -261,17 +307,7 @@ module Expressir
261
307
  "undocumented_entities" => reports.sum do |r|
262
308
  r.undocumented_entities.size
263
309
  end,
264
- "coverage_percentage" => if reports.sum do |r|
265
- r.total_entities.size
266
- end.positive?
267
- (reports.sum do |r|
268
- r.documented_entities.size
269
- end.to_f / reports.sum do |r|
270
- r.total_entities.size
271
- end * 100).round(2)
272
- else
273
- 100.0
274
- end,
310
+ "coverage_percentage" => coverage_per,
275
311
  }
276
312
 
277
313
  # Add ignored file information if there are any
@@ -28,7 +28,8 @@ module Expressir
28
28
  x.set_initial_path(path)
29
29
  end
30
30
  rescue StandardError => e
31
- raise InvalidSchemaManifestError, "Invalid schema manifest format: #{e.message}"
31
+ raise InvalidSchemaManifestError,
32
+ "Invalid schema manifest format: #{e.message}"
32
33
  end
33
34
 
34
35
  def to_file(to_path = path)
@@ -1,3 +1,3 @@
1
1
  module Expressir
2
- VERSION = "2.1.25".freeze
2
+ VERSION = "2.1.27".freeze
3
3
  end
data/lib/expressir.rb CHANGED
@@ -170,11 +170,20 @@ module Expressir
170
170
  autoload :Benchmark, "expressir/commands/benchmark"
171
171
  autoload :BenchmarkCache, "expressir/commands/benchmark_cache"
172
172
  autoload :Clean, "expressir/commands/clean"
173
+ autoload :ImportComparison, "expressir/commands/import_comparison"
173
174
  autoload :Coverage, "expressir/commands/coverage"
174
175
  autoload :Format, "expressir/commands/format"
175
176
  autoload :Validate, "expressir/commands/validate"
176
177
  autoload :Version, "expressir/commands/version"
177
178
  end
179
+
180
+ # Autoload for Changes module classes
181
+ module Changes
182
+ autoload :SchemaChange, "expressir/changes/schema_change"
183
+ autoload :EditionChange, "expressir/changes/edition_change"
184
+ autoload :ItemChange, "expressir/changes/item_change"
185
+ autoload :MappingChange, "expressir/changes/mapping_change"
186
+ end
178
187
  end
179
188
 
180
189
  require_relative "expressir/model"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: expressir
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.25
4
+ version: 2.1.27
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-08-15 00:00:00.000000000 Z
11
+ date: 2025-10-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -109,19 +109,19 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '1.11'
111
111
  - !ruby/object:Gem::Dependency
112
- name: terminal-table
112
+ name: table_tennis
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - "~>"
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
- version: '3.0'
117
+ version: '0'
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - "~>"
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
- version: '3.0'
124
+ version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: thor
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -169,10 +169,18 @@ files:
169
169
  - expressir.gemspec
170
170
  - lib/expressir.rb
171
171
  - lib/expressir/benchmark.rb
172
+ - lib/expressir/changes.rb
173
+ - lib/expressir/changes/edition_change.rb
174
+ - lib/expressir/changes/item_change.rb
175
+ - lib/expressir/changes/mapping_change.rb
176
+ - lib/expressir/changes/schema_change.rb
172
177
  - lib/expressir/cli.rb
173
178
  - lib/expressir/commands/base.rb
174
179
  - lib/expressir/commands/benchmark.rb
175
180
  - lib/expressir/commands/benchmark_cache.rb
181
+ - lib/expressir/commands/changes.rb
182
+ - lib/expressir/commands/changes_import_eengine.rb
183
+ - lib/expressir/commands/changes_validate.rb
176
184
  - lib/expressir/commands/clean.rb
177
185
  - lib/expressir/commands/coverage.rb
178
186
  - lib/expressir/commands/format.rb