expressir 2.1.30 → 2.1.31

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 (107) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/docs.yml +98 -0
  3. data/.github/workflows/links.yml +100 -0
  4. data/.github/workflows/rake.yml +4 -0
  5. data/.github/workflows/release.yml +5 -0
  6. data/.github/workflows/validate_schemas.yml +1 -1
  7. data/.gitignore +3 -0
  8. data/.rubocop.yml +1 -1
  9. data/.rubocop_todo.yml +244 -39
  10. data/Gemfile +2 -1
  11. data/README.adoc +621 -54
  12. data/docs/Gemfile +12 -0
  13. data/docs/_config.yml +141 -0
  14. data/docs/_guides/changes/changes-format.adoc +778 -0
  15. data/docs/_guides/changes/importing-eengine.adoc +898 -0
  16. data/docs/_guides/changes/index.adoc +396 -0
  17. data/docs/_guides/changes/programmatic-usage.adoc +1038 -0
  18. data/docs/_guides/changes/validating-changes.adoc +681 -0
  19. data/docs/_guides/cli/benchmark-performance.adoc +834 -0
  20. data/docs/_guides/cli/coverage-analysis.adoc +921 -0
  21. data/docs/_guides/cli/format-schemas.adoc +547 -0
  22. data/docs/_guides/cli/index.adoc +8 -0
  23. data/docs/_guides/cli/managing-changes.adoc +927 -0
  24. data/docs/_guides/cli/validate-ascii.adoc +645 -0
  25. data/docs/_guides/cli/validate-schemas.adoc +534 -0
  26. data/docs/_guides/index.adoc +165 -0
  27. data/docs/_guides/ler/creating-packages.adoc +664 -0
  28. data/docs/_guides/ler/index.adoc +305 -0
  29. data/docs/_guides/ler/loading-packages.adoc +707 -0
  30. data/docs/_guides/ler/package-formats.adoc +748 -0
  31. data/docs/_guides/ler/querying-packages.adoc +826 -0
  32. data/docs/_guides/ler/validating-packages.adoc +750 -0
  33. data/docs/_guides/liquid/basic-templates.adoc +813 -0
  34. data/docs/_guides/liquid/documentation-generation.adoc +1042 -0
  35. data/docs/_guides/liquid/drops-reference.adoc +829 -0
  36. data/docs/_guides/liquid/filters-and-tags.adoc +912 -0
  37. data/docs/_guides/liquid/index.adoc +468 -0
  38. data/docs/_guides/manifests/creating-manifests.adoc +483 -0
  39. data/docs/_guides/manifests/index.adoc +307 -0
  40. data/docs/_guides/manifests/resolving-manifests.adoc +557 -0
  41. data/docs/_guides/manifests/validating-manifests.adoc +713 -0
  42. data/docs/_guides/ruby-api/formatting-schemas.adoc +605 -0
  43. data/docs/_guides/ruby-api/index.adoc +257 -0
  44. data/docs/_guides/ruby-api/parsing-files.adoc +421 -0
  45. data/docs/_guides/ruby-api/search-engine.adoc +609 -0
  46. data/docs/_guides/ruby-api/working-with-repository.adoc +577 -0
  47. data/docs/_pages/data-model.adoc +665 -0
  48. data/docs/_pages/express-language.adoc +506 -0
  49. data/docs/_pages/getting-started.adoc +414 -0
  50. data/docs/_pages/index.adoc +116 -0
  51. data/docs/_pages/introduction.adoc +256 -0
  52. data/docs/_pages/ler-packages.adoc +837 -0
  53. data/docs/_pages/parsers.adoc +683 -0
  54. data/docs/_pages/schema-manifests.adoc +431 -0
  55. data/docs/_references/index.adoc +228 -0
  56. data/docs/_tutorials/creating-ler-package.adoc +735 -0
  57. data/docs/_tutorials/documentation-coverage.adoc +795 -0
  58. data/docs/_tutorials/index.adoc +221 -0
  59. data/docs/_tutorials/liquid-templates.adoc +806 -0
  60. data/docs/_tutorials/parsing-your-first-schema.adoc +522 -0
  61. data/docs/_tutorials/querying-schemas.adoc +751 -0
  62. data/docs/_tutorials/working-with-multiple-schemas.adoc +676 -0
  63. data/docs/index.adoc +242 -0
  64. data/docs/lychee.toml +84 -0
  65. data/examples/demo_ler_usage.sh +86 -0
  66. data/examples/ler/README.md +111 -0
  67. data/examples/ler/simple_example.ler +0 -0
  68. data/examples/ler/simple_schema.exp +33 -0
  69. data/examples/ler_build.rb +75 -0
  70. data/examples/ler_cli.rb +79 -0
  71. data/examples/ler_demo_complete.rb +276 -0
  72. data/examples/ler_query.rb +91 -0
  73. data/examples/ler_query_examples.rb +305 -0
  74. data/examples/ler_stats.rb +81 -0
  75. data/examples/phase3_demo.rb +159 -0
  76. data/examples/query_demo_simple.rb +131 -0
  77. data/expressir.gemspec +2 -0
  78. data/lib/expressir/cli.rb +12 -4
  79. data/lib/expressir/commands/manifest.rb +427 -0
  80. data/lib/expressir/commands/package.rb +1274 -0
  81. data/lib/expressir/commands/validate.rb +70 -37
  82. data/lib/expressir/commands/validate_ascii.rb +607 -0
  83. data/lib/expressir/commands/validate_load.rb +88 -0
  84. data/lib/expressir/express/formatter.rb +5 -1
  85. data/lib/expressir/express/formatters/remark_item_formatter.rb +25 -0
  86. data/lib/expressir/express/parser.rb +33 -0
  87. data/lib/expressir/manifest/resolver.rb +213 -0
  88. data/lib/expressir/manifest/validator.rb +195 -0
  89. data/lib/expressir/model/declarations/entity.rb +6 -0
  90. data/lib/expressir/model/dependency_resolver.rb +270 -0
  91. data/lib/expressir/model/indexes/entity_index.rb +103 -0
  92. data/lib/expressir/model/indexes/reference_index.rb +148 -0
  93. data/lib/expressir/model/indexes/type_index.rb +149 -0
  94. data/lib/expressir/model/interface_validator.rb +384 -0
  95. data/lib/expressir/model/repository.rb +400 -5
  96. data/lib/expressir/model/repository_validator.rb +295 -0
  97. data/lib/expressir/model/search_engine.rb +525 -0
  98. data/lib/expressir/model.rb +4 -94
  99. data/lib/expressir/package/builder.rb +200 -0
  100. data/lib/expressir/package/metadata.rb +81 -0
  101. data/lib/expressir/package/reader.rb +165 -0
  102. data/lib/expressir/schema_manifest.rb +11 -1
  103. data/lib/expressir/version.rb +1 -1
  104. data/lib/expressir.rb +15 -2
  105. metadata +114 -4
  106. data/docs/benchmarking.adoc +0 -107
  107. data/docs/liquid_drops.adoc +0 -1547
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Example: Using LER via CLI commands
5
+ # This script demonstrates CLI usage for package operations
6
+
7
+ PACKAGE_FILE = File.expand_path("ler/simple_example.ler", __dir__)
8
+
9
+ unless File.exist?(PACKAGE_FILE)
10
+ puts "Error: Package not found: #{PACKAGE_FILE}"
11
+ puts "Run 'ruby examples/ler_build.rb' first to create the package."
12
+ exit 1
13
+ end
14
+
15
+ puts "LER CLI Commands Example"
16
+ puts "=" * 60
17
+ puts
18
+
19
+ # Example 1: Package info
20
+ puts "Example 1: Display package information"
21
+ puts "-" * 60
22
+ puts "Command: expressir package info #{PACKAGE_FILE}"
23
+ puts
24
+ system("bundle exec expressir package info #{PACKAGE_FILE}")
25
+ puts
26
+
27
+ # Example 2: Find entity
28
+ puts "\nExample 2: Find specific entity"
29
+ puts "-" * 60
30
+ puts "Command: expressir entity find \"simple_example.product\" --from #{PACKAGE_FILE}"
31
+ puts
32
+ system("bundle exec expressir entity find \"simple_example.product\" --from #{PACKAGE_FILE}")
33
+ puts
34
+
35
+ # Example 3: List entities
36
+ puts "\nExample 3: List all entities"
37
+ puts "-" * 60
38
+ puts "Command: expressir entity list --from #{PACKAGE_FILE}"
39
+ puts
40
+ system("bundle exec expressir entity list --from #{PACKAGE_FILE}")
41
+ puts
42
+
43
+ # Example 4: Find type
44
+ puts "\nExample 4: Find specific type"
45
+ puts "-" * 60
46
+ puts "Command: expressir type find \"simple_example.product_status\" --from #{PACKAGE_FILE}"
47
+ puts
48
+ system("bundle exec expressir type find \"simple_example.product_status\" --from #{PACKAGE_FILE}")
49
+ puts
50
+
51
+ # Example 5: List types by category
52
+ puts "\nExample 5: List types by category"
53
+ puts "-" * 60
54
+ puts "Command: expressir type list --from #{PACKAGE_FILE} --category enumeration"
55
+ puts
56
+ system("bundle exec expressir type list --from #{PACKAGE_FILE} --category enumeration")
57
+ puts
58
+
59
+ # Example 6: Show statistics
60
+ puts "\nExample 6: Show statistics"
61
+ puts "-" * 60
62
+ puts "Command: expressir stats show #{PACKAGE_FILE}"
63
+ puts
64
+ system("bundle exec expressir stats show #{PACKAGE_FILE}")
65
+ puts
66
+
67
+ puts "=" * 60
68
+ puts "CLI examples complete!"
69
+ puts
70
+ puts "All commands available:"
71
+ puts " expressir package build ROOT_SCHEMA OUTPUT [options]"
72
+ puts " expressir package info PACKAGE [options]"
73
+ puts " expressir package validate PACKAGE [options]"
74
+ puts " expressir entity find QUALIFIED_NAME --from PACKAGE"
75
+ puts " expressir entity list --from PACKAGE [--schema NAME]"
76
+ puts " expressir type find QUALIFIED_NAME --from PACKAGE"
77
+ puts " expressir type list --from PACKAGE [--category TYPE]"
78
+ puts " expressir stats show PACKAGE [--format FORMAT]"
79
+ puts
@@ -0,0 +1,276 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Complete LER Demonstration
5
+ # Shows package creation, searching, and querying with all advanced features
6
+
7
+ require_relative "../lib/expressir"
8
+
9
+ class LERDemo
10
+ SCHEMA_FILE = File.expand_path("ler/simple_schema.exp", __dir__)
11
+ PACKAGE_FILE = File.expand_path("ler/simple_example.ler", __dir__)
12
+
13
+ def run
14
+ print_header("LER Package Creation and Query Demonstration")
15
+
16
+ create_package
17
+ load_and_query_package
18
+ demonstrate_advanced_search
19
+ demonstrate_statistics
20
+ demonstrate_validation
21
+
22
+ print_header("Demo Complete!", "=")
23
+ puts "\nPackage saved at: #{PACKAGE_FILE}"
24
+ puts "You can now use CLI commands like:"
25
+ puts " expressir package info #{PACKAGE_FILE}"
26
+ puts " expressir package search #{PACKAGE_FILE} 'product'"
27
+ puts " expressir package tree #{PACKAGE_FILE}"
28
+ end
29
+
30
+ private
31
+
32
+ def create_package
33
+ print_section("Step 1: Creating LER Package")
34
+
35
+ unless File.exist?(SCHEMA_FILE)
36
+ puts "Error: Schema file not found: #{SCHEMA_FILE}"
37
+ exit 1
38
+ end
39
+
40
+ # Use CLI to build package (recommended approach)
41
+ puts "Building LER package from: #{File.basename(SCHEMA_FILE)}"
42
+ puts "Output: #{File.basename(PACKAGE_FILE)}"
43
+
44
+ cmd = "bundle exec expressir package build #{SCHEMA_FILE} #{PACKAGE_FILE} " \
45
+ "--name 'Simple Product Management Schema' " \
46
+ "--version '1.0.0' " \
47
+ "--description 'Demonstrates LER features with product entities' " \
48
+ "--express-mode include_all " \
49
+ "--resolution-mode resolved " \
50
+ "--serialization-format yaml"
51
+
52
+ system(cmd, out: File::NULL, err: File::NULL)
53
+
54
+ unless File.exist?(PACKAGE_FILE)
55
+ puts "Error: Failed to create package"
56
+ exit 1
57
+ end
58
+
59
+ file_size = File.size(PACKAGE_FILE)
60
+ puts " ✓ Package created: #{(file_size / 1024.0).round(2)} KB"
61
+ end
62
+
63
+ def load_and_query_package
64
+ print_section("Step 2: Loading and Basic Queries")
65
+
66
+ # Load package (force class load first)
67
+ puts "Loading package from: #{File.basename(PACKAGE_FILE)}"
68
+ require_relative "../lib/expressir/model/repository"
69
+ require_relative "../lib/expressir/package/reader"
70
+ @repo = Expressir::Package::Reader.load(PACKAGE_FILE)
71
+ require_relative "../lib/expressir/model/search_engine"
72
+ @search = Expressir::Model::SearchEngine.new(@repo)
73
+ puts " ✓ Package loaded"
74
+
75
+ # Basic statistics
76
+ stats = @repo.statistics
77
+ puts "\nPackage contains:"
78
+ puts " Schemas: #{stats[:total_schemas]}"
79
+ puts " Entities: #{stats[:total_entities]}"
80
+ puts " Types: #{stats[:total_types]}"
81
+
82
+ # List entities
83
+ puts "\nEntities:"
84
+ entities = @search.list(type: "entity")
85
+ entities.each do |e|
86
+ puts " - #{e[:id]} (#{e[:schema]})"
87
+ end
88
+
89
+ # List types by category
90
+ puts "\nTypes by category:"
91
+ stats[:types_by_category].each do |category, count|
92
+ next if count.zero?
93
+
94
+ puts " #{category}: #{count}"
95
+ types = @search.list(type: "type", category: category.to_s)
96
+ types.each do |t|
97
+ puts " - #{t[:id]}"
98
+ end
99
+ end
100
+ end
101
+
102
+ def demonstrate_advanced_search
103
+ print_section("Step 3: Advanced Search Features (Phase 3)")
104
+
105
+ # Pattern matching
106
+ puts "1. Wildcard pattern search:"
107
+ results = @search.search(pattern: "product*", type: "entity")
108
+ puts " Found #{results.size} entities starting with 'product':"
109
+ results.each { |r| puts " - #{r[:path]}" }
110
+
111
+ # Depth filtering
112
+ puts "\n2. Depth-filtered search (max_depth: 2):"
113
+ results = @search.search_with_depth(pattern: "product", max_depth: 2)
114
+ puts " Found #{results.size} results at depth ≤ 2:"
115
+ results.each do |r|
116
+ depth = r[:path]&.split(".")&.size || 0
117
+ puts " - #{r[:path]} (depth: #{depth})"
118
+ end
119
+
120
+ # Relevance ranking
121
+ puts "\n3. Relevance-ranked search:"
122
+ results = @search.search_ranked(pattern: "product")
123
+ puts " Results ranked by relevance:"
124
+ results.take(5).each do |r|
125
+ puts " - #{r[:path]} (score: #{r[:relevance_score]})"
126
+ end
127
+
128
+ # Advanced combined search
129
+ puts "\n4. Advanced search (depth + ranking):"
130
+ results = @search.search_advanced(
131
+ pattern: "product",
132
+ max_depth: 2,
133
+ ranked: true,
134
+ )
135
+ puts " Combined results:"
136
+ results.each do |r|
137
+ puts " - #{r[:path]} (score: #{r[:relevance_score]})"
138
+ end
139
+
140
+ # Regex search
141
+ puts "\n5. Regex search:"
142
+ results = @search.search(
143
+ pattern: "^product_.*",
144
+ regex: true,
145
+ )
146
+ puts " Regex matches: #{results.size} result(s)"
147
+ results.each { |r| puts " - #{r[:id]}" }
148
+
149
+ # Exact match
150
+ puts "\n6. Exact match:"
151
+ results = @search.search(
152
+ pattern: "simple_example.product",
153
+ exact: true,
154
+ )
155
+ puts " Exact matches: #{results.size} result(s)"
156
+ end
157
+
158
+ def demonstrate_statistics
159
+ print_section("Step 4: Repository Statistics (Phase 3)")
160
+
161
+ # Schema categorization
162
+ puts "1. Schemas by category:"
163
+ categories = @repo.schemas_by_category
164
+ categories.each do |category, schemas|
165
+ next if schemas.empty?
166
+
167
+ puts " #{category}: #{schemas.size} schema(s)"
168
+ schemas.each { |s| puts " - #{s.id}" }
169
+ end
170
+
171
+ # Largest schemas
172
+ puts "\n2. Largest schemas by element count:"
173
+ largest = @repo.largest_schemas(5)
174
+ largest.each do |item|
175
+ puts " - #{item[:schema].id}: #{item[:total_elements]} elements"
176
+ end
177
+
178
+ # Schema complexity
179
+ puts "\n3. Schema complexity scores:"
180
+ complex = @repo.schemas_by_complexity(5)
181
+ complex.each do |item|
182
+ puts " - #{item[:schema].id}: complexity #{item[:complexity]}"
183
+ schema = item[:schema]
184
+ details = []
185
+ details << "#{schema.entities&.size || 0} entities" if schema.entities&.any?
186
+ details << "#{schema.types&.size || 0} types" if schema.types&.any?
187
+ details << "#{schema.functions&.size || 0} functions" if schema.functions&.any?
188
+ puts " (#{details.join(', ')})" unless details.empty?
189
+ end
190
+
191
+ # Dependency statistics
192
+ puts "\n4. Dependency statistics:"
193
+ deps = @repo.dependency_statistics
194
+ puts " Total interfaces: #{deps[:total_interfaces]}"
195
+ puts " USE FROM: #{deps[:use_from_count]}"
196
+ puts " REFERENCE FROM: #{deps[:reference_from_count]}"
197
+
198
+ if deps[:most_referenced].any?
199
+ puts " Most referenced schemas:"
200
+ deps[:most_referenced].take(3).each do |schema_id, count|
201
+ puts " - #{schema_id}: #{count} references"
202
+ end
203
+ end
204
+ end
205
+
206
+ def demonstrate_validation
207
+ print_section("Step 5: Package Validation (Phase 2)")
208
+
209
+ # Basic validation
210
+ puts "1. Basic validation:"
211
+ validation = @repo.validate
212
+ if validation[:valid?]
213
+ puts " ✓ Package is valid"
214
+ else
215
+ puts " ✗ Validation failed:"
216
+ validation[:errors].each do |error|
217
+ puts " - #{error[:message]}"
218
+ end
219
+ end
220
+
221
+ # Strict validation
222
+ puts "\n2. Strict validation (with completeness checks):"
223
+ validation = @repo.validate(
224
+ strict: true,
225
+ check_completeness: true,
226
+ )
227
+
228
+ if validation[:valid?]
229
+ puts " ✓ Package passes strict validation"
230
+ end
231
+
232
+ if validation[:warnings]&.any?
233
+ puts " Warnings (#{validation[:warnings].size}):"
234
+ validation[:warnings].take(3).each do |warning|
235
+ puts " - #{warning[:message]}"
236
+ end
237
+ end
238
+
239
+ # Enhanced validation
240
+ puts "\n3. Enhanced validation (all checks):"
241
+ validation = @repo.validate(
242
+ strict: true,
243
+ check_interfaces: true,
244
+ check_completeness: true,
245
+ check_duplicates: true,
246
+ detailed: false,
247
+ )
248
+
249
+ puts " Validation result: #{validation[:valid?] ? '✓ Valid' : '✗ Invalid'}"
250
+ puts " Errors: #{validation[:errors]&.size || 0}"
251
+ puts " Warnings: #{validation[:warnings]&.size || 0}"
252
+ end
253
+
254
+ def print_header(text, char = "=")
255
+ line = char * 70
256
+ puts "\n#{line}"
257
+ puts text.center(70)
258
+ puts "#{line}\n"
259
+ end
260
+
261
+ def print_section(title)
262
+ puts "\n#{title}"
263
+ puts "-" * 70
264
+ end
265
+ end
266
+
267
+ # Run demo
268
+ if __FILE__ == $PROGRAM_NAME
269
+ begin
270
+ LERDemo.new.run
271
+ rescue StandardError => e
272
+ puts "\nError: #{e.message}"
273
+ puts e.backtrace.first(5)
274
+ exit 1
275
+ end
276
+ end
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Example: Query LER package for entities and types
5
+ # This script demonstrates querying an existing LER package
6
+
7
+ require_relative "../lib/expressir"
8
+
9
+ PACKAGE_FILE = File.expand_path("ler/simple_example.ler", __dir__)
10
+
11
+ unless File.exist?(PACKAGE_FILE)
12
+ puts "Error: Package not found: #{PACKAGE_FILE}"
13
+ puts "Run 'ruby examples/ler_build.rb' first to create the package."
14
+ exit 1
15
+ end
16
+
17
+ puts "LER Package Query Example"
18
+ puts "=" * 60
19
+ puts "Package: #{File.basename(PACKAGE_FILE)}"
20
+ puts
21
+
22
+ # Load package
23
+ puts "Loading package..."
24
+ start_time = Time.now
25
+ repo = Expressir::Model::Repository.from_package(PACKAGE_FILE)
26
+ load_time = ((Time.now - start_time) * 1000).round(2)
27
+ puts " ✓ Loaded in #{load_time}ms"
28
+ puts
29
+
30
+ # Query 1: Find specific entity
31
+ puts "Query 1: Find entity 'simple_example.product'"
32
+ puts "-" * 60
33
+ entity = repo.find_entity(qualified_name: "simple_example.product")
34
+ if entity
35
+ puts " ✓ Found: #{entity.id}"
36
+ puts " Schema: #{entity.parent.id}"
37
+ puts " Path: #{entity.path}"
38
+ if entity.attributes&.any?
39
+ puts " Attributes:"
40
+ entity.attributes.each do |attr|
41
+ puts " - #{attr.id}"
42
+ end
43
+ end
44
+ else
45
+ puts " ✗ Not found"
46
+ end
47
+ puts
48
+
49
+ # Query 2: List all entities
50
+ puts "Query 2: List all entities"
51
+ puts "-" * 60
52
+ entities = repo.list_entities(format: :hash)
53
+ puts " Total entities: #{entities.size}"
54
+ entities.each do |e|
55
+ puts " #{e[:schema]}.#{e[:id]}"
56
+ end
57
+ puts
58
+
59
+ # Query 3: Find specific type
60
+ puts "Query 3: Find type 'simple_example.product_status'"
61
+ puts "-" * 60
62
+ type = repo.find_type(qualified_name: "simple_example.product_status")
63
+ if type
64
+ puts " ✓ Found: #{type.id}"
65
+ puts " Schema: #{type.parent.id}"
66
+ end
67
+ puts
68
+
69
+ # Query 4: List types by category
70
+ puts "Query 4: List SELECT types"
71
+ puts "-" * 60
72
+ select_types = repo.list_types(category: "select", format: :hash)
73
+ puts " Total SELECT types: #{select_types.size}"
74
+ select_types.each do |t|
75
+ puts " #{t[:schema]}.#{t[:id]} [#{t[:category]}]"
76
+ end
77
+ puts
78
+
79
+ # Query 5: List ENUMERATION types
80
+ puts "Query 5: List ENUMERATION types"
81
+ puts "-" * 60
82
+ enum_types = repo.list_types(category: "enumeration", format: :hash)
83
+ puts " Total ENUMERATION types: #{enum_types.size}"
84
+ enum_types.each do |t|
85
+ puts " #{t[:schema]}.#{t[:id]} [#{t[:category]}]"
86
+ end
87
+ puts
88
+
89
+ puts "=" * 60
90
+ puts "Query examples complete!"
91
+ puts