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,707 @@
1
+ ---
2
+ title: Loading Packages
3
+ parent: LER Packages
4
+ grand_parent: Guides
5
+ nav_order: 2
6
+ ---
7
+
8
+ = Loading Packages
9
+
10
+ == Purpose
11
+
12
+ This guide explains how to load LER packages into your applications using both
13
+ the Ruby API and CLI commands. Loading pre-built packages is significantly
14
+ faster than parsing raw EXPRESS files.
15
+
16
+ == References
17
+
18
+ * link:index.html[LER Packages Overview]
19
+ * link:creating-packages.html[Creating Packages]
20
+ * link:querying-packages.html[Querying Packages]
21
+ * link:../ruby-api/working-with-repository.html[Working with Repository]
22
+
23
+ == Concepts
24
+
25
+ Package loading:: The process of reading a LER package file and deserializing
26
+ its contents into a [`Repository`](../../lib/expressir/model/repository.rb)
27
+ instance.
28
+
29
+ Package reader:: The [`Expressir::Package::Reader`](../../lib/expressir/package/reader.rb)
30
+ class responsible for loading LER packages.
31
+
32
+ Deserialization:: Converting serialized data (Marshal, YAML, or JSON) back
33
+ into Ruby objects.
34
+
35
+ Pre-built indexes:: Entity, type, and reference indexes stored in the package
36
+ that are loaded directly without rebuilding.
37
+
38
+ == Loading packages via Ruby API
39
+
40
+ === Basic package loading
41
+
42
+ Use [`Repository.from_package`](../../lib/expressir/model/repository.rb:256)
43
+ to load a LER package:
44
+
45
+ [source,ruby]
46
+ ----
47
+ require "expressir"
48
+
49
+ # Load package
50
+ repo = Expressir::Model::Repository.from_package("schemas.ler")
51
+
52
+ # Package is ready to use
53
+ puts "Loaded #{repo.schemas.size} schemas"
54
+ ----
55
+
56
+ The repository is fully initialized with:
57
+
58
+ * All schemas loaded and resolved
59
+ * Pre-built indexes ready for queries
60
+ * All references resolved
61
+
62
+ === Using Package::Reader directly
63
+
64
+ For more control, use the [`Package::Reader`](../../lib/expressir/package/reader.rb:10)
65
+ class:
66
+
67
+ [source,ruby]
68
+ ----
69
+ require "expressir/package/reader"
70
+
71
+ # Load using reader
72
+ reader = Expressir::Package::Reader.new
73
+ repo = reader.load("schemas.ler")
74
+
75
+ # Or use class method
76
+ repo = Expressir::Package::Reader.load("schemas.ler")
77
+ ----
78
+
79
+ === Accessing loaded data
80
+
81
+ Once loaded, use the repository normally:
82
+
83
+ [source,ruby]
84
+ ----
85
+ # Load package
86
+ repo = Expressir::Model::Repository.from_package("schemas.ler")
87
+
88
+ # Access schemas
89
+ repo.schemas.each do |schema|
90
+ puts "Schema: #{schema.id}"
91
+ puts " Entities: #{schema.entities&.size || 0}"
92
+ puts " Types: #{schema.types&.size || 0}"
93
+ end
94
+
95
+ # Use pre-built indexes
96
+ entity = repo.find_entity(qualified_name: "action_schema.action")
97
+ puts "Found entity: #{entity.id}" if entity
98
+
99
+ # List entities
100
+ entities = repo.list_entities
101
+ puts "Total entities: #{entities.size}"
102
+ ----
103
+
104
+ === Loading with error handling
105
+
106
+ Handle loading errors gracefully:
107
+
108
+ [source,ruby]
109
+ ----
110
+ begin
111
+ repo = Expressir::Model::Repository.from_package("schemas.ler")
112
+ puts "✓ Package loaded successfully"
113
+ rescue ArgumentError => e
114
+ puts "Error: #{e.message}"
115
+ # Package file not found
116
+ rescue StandardError => e
117
+ puts "Loading error: #{e.message}"
118
+ # Corrupted package or incompatible format
119
+ end
120
+ ----
121
+
122
+ === Measuring load time
123
+
124
+ Track loading performance:
125
+
126
+ [source,ruby]
127
+ ----
128
+ require "benchmark"
129
+
130
+ load_time = Benchmark.realtime do
131
+ @repo = Expressir::Model::Repository.from_package("large_schemas.ler")
132
+ end
133
+
134
+ puts "Load time: #{(load_time * 1000).round(2)} ms"
135
+ puts "Schemas: #{@repo.schemas.size}"
136
+ puts "Entities: #{@repo.list_entities.size}"
137
+ ----
138
+
139
+ == Loading packages via CLI
140
+
141
+ === Package information
142
+
143
+ View package contents without full loading:
144
+
145
+ [source,bash]
146
+ ----
147
+ # Show package metadata and statistics
148
+ expressir package info schemas.ler
149
+
150
+ # Output in JSON format
151
+ expressir package info schemas.ler --format json
152
+
153
+ # Output in YAML format
154
+ expressir package info schemas.ler --format yaml
155
+ ----
156
+
157
+ .Example output
158
+ [example]
159
+ ====
160
+ [source]
161
+ ----
162
+ Package Information
163
+ ==================================================
164
+ Name: Production Schemas
165
+ Version: 2.1.0
166
+ Description: Schema set for production deployment
167
+ Created: 2024-01-15T10:30:00Z
168
+
169
+ Configuration
170
+ --------------------------------------------------
171
+ Express mode: include_all
172
+ Resolution mode: resolved
173
+ Serialization format: marshal
174
+
175
+ Statistics
176
+ --------------------------------------------------
177
+ Total schemas: 45
178
+ Total entities: 892
179
+ Total types: 456
180
+ Total functions: 123
181
+ Total rules: 67
182
+ Total procedures: 34
183
+ ----
184
+ ====
185
+
186
+ === Listing package contents
187
+
188
+ List elements in the package:
189
+
190
+ [source,bash]
191
+ ----
192
+ # List all entities
193
+ expressir package list schemas.ler --type entity
194
+
195
+ # List types
196
+ expressir package list schemas.ler --type type
197
+
198
+ # List entities from specific schema
199
+ expressir package list schemas.ler --type entity --schema action_schema
200
+
201
+ # List SELECT types only
202
+ expressir package list schemas.ler --type type --category select
203
+
204
+ # Show counts only
205
+ expressir package list schemas.ler --type entity --count-only
206
+ ----
207
+
208
+ === Extracting package contents
209
+
210
+ Extract package contents to directory:
211
+
212
+ [source,bash]
213
+ ----
214
+ # Extract to directory
215
+ expressir package extract schemas.ler --output extracted/
216
+
217
+ # View extracted structure
218
+ ls -R extracted/
219
+ ----
220
+
221
+ Extracted contents include:
222
+
223
+ * `metadata.yaml` - Package metadata
224
+ * `manifest.yaml` - Schema manifest
225
+ * `repository.marshal` (or `.yaml`, `.json`) - Serialized repository
226
+ * `entity_index.marshal` - Entity index
227
+ * `type_index.marshal` - Type index
228
+ * `reference_index.marshal` - Reference index
229
+ * `express_files/` - Original EXPRESS files (if included)
230
+
231
+ == Performance comparison
232
+
233
+ === Load time comparison
234
+
235
+ LER packages load significantly faster than parsing EXPRESS files:
236
+
237
+ .Performance comparison example
238
+ [example]
239
+ ====
240
+ [source,ruby]
241
+ ----
242
+ require "benchmark"
243
+
244
+ # Scenario: 100 EXPRESS schema files
245
+ # Total size: 15 MB of EXPRESS source
246
+
247
+ # Method 1: Parse from EXPRESS files
248
+ parse_time = Benchmark.realtime do
249
+ files = Dir.glob("schemas/**/*.exp")
250
+ @repo1 = Expressir::Express::Parser.from_files(files)
251
+ end
252
+ puts "Parse time: #{parse_time.round(2)}s" # ~45 seconds
253
+
254
+ # Method 2: Load from LER package
255
+ load_time = Benchmark.realtime do
256
+ @repo2 = Expressir::Model::Repository.from_package("schemas.ler")
257
+ end
258
+ puts "Load time: #{load_time.round(2)}s" # ~2 seconds
259
+
260
+ # Speed improvement
261
+ speedup = parse_time / load_time
262
+ puts "Speed improvement: #{speedup.round(1)}x faster" # ~22x faster
263
+ ----
264
+ ====
265
+
266
+ === Real-world performance data
267
+
268
+ Typical performance improvements:
269
+
270
+ [options="header"]
271
+ |===
272
+ | Schema Set Size | Parse Time | Load Time | Improvement
273
+
274
+ | Small (10 files)
275
+ | 5s
276
+ | 0.3s
277
+ | 16x faster
278
+
279
+ | Medium (50 files)
280
+ | 22s
281
+ | 1.2s
282
+ | 18x faster
283
+
284
+ | Large (100 files)
285
+ | 45s
286
+ | 2.0s
287
+ | 22x faster
288
+
289
+ | Very Large (200 files)
290
+ | 95s
291
+ | 4.5s
292
+ | 21x faster
293
+ |===
294
+
295
+ === Performance factors
296
+
297
+ Factors affecting load performance:
298
+
299
+ Serialization format:: Marshal is fastest, YAML is slowest
300
+ +
301
+ [source]
302
+ ----
303
+ Marshal: 1.0x (baseline)
304
+ JSON: 3.2x slower
305
+ YAML: 4.1x slower
306
+ ----
307
+
308
+ Package size:: Linear relationship with schema count
309
+
310
+ Disk I/O speed:: SSD vs HDD can differ by 2-3x
311
+
312
+ Pre-built indexes:: No rebuild time needed (saves 0.5-2s)
313
+
314
+ == Memory considerations
315
+
316
+ === Memory usage patterns
317
+
318
+ LER packages load entire repository into memory:
319
+
320
+ [options="header"]
321
+ |===
322
+ | Schema Count | Repository Size | Memory Usage | Load Time
323
+
324
+ | 10-50
325
+ | Small
326
+ | 10-50 MB
327
+ | <1 second
328
+
329
+ | 50-100
330
+ | Medium
331
+ | 50-200 MB
332
+ | 1-2 seconds
333
+
334
+ | 100-500
335
+ | Large
336
+ | 200-500 MB
337
+ | 2-5 seconds
338
+
339
+ | 500+
340
+ | Very Large
341
+ | 500+ MB
342
+ | 5+ seconds
343
+ |===
344
+
345
+ === Managing memory usage
346
+
347
+ For large packages, consider:
348
+
349
+ .Memory optimization strategies
350
+ [example]
351
+ ====
352
+ 1. Use selective loading (load only needed schemas)
353
+ 2. Clear repository when done: `repo = nil; GC.start`
354
+ 3. Use streaming for one-time queries
355
+ 4. Split into multiple smaller packages
356
+ ====
357
+
358
+ === Monitoring memory usage
359
+
360
+ Track memory consumption:
361
+
362
+ [source,ruby]
363
+ ----
364
+ require "get_process_mem"
365
+
366
+ # Measure memory before
367
+ mem_before = GetProcessMem.new.mb
368
+
369
+ # Load package
370
+ repo = Expressir::Model::Repository.from_package("large.ler")
371
+
372
+ # Measure memory after
373
+ mem_after = GetProcessMem.new.mb
374
+ mem_used = mem_after - mem_before
375
+
376
+ puts "Memory used: #{mem_used.round(2)} MB"
377
+ puts "Schemas: #{repo.schemas.size}"
378
+ puts "Per schema: #{(mem_used / repo.schemas.size).round(2)} MB"
379
+ ----
380
+
381
+ == Cache strategies
382
+
383
+ === When to use caching
384
+
385
+ Use LER packages as a cache layer:
386
+
387
+ Development:: Keep EXPRESS files, build packages for testing
388
+
389
+ Production:: Deploy pre-built packages, no parsing needed
390
+
391
+ CI/CD:: Build once, deploy everywhere
392
+
393
+ === Cache invalidation
394
+
395
+ Rebuild packages when:
396
+
397
+ * EXPRESS schemas change
398
+ * Schema versions are updated
399
+ * Dependencies are modified
400
+ * Validation rules change
401
+
402
+ === Hybrid approach
403
+
404
+ Combine EXPRESS files and LER packages:
405
+
406
+ [source,ruby]
407
+ ----
408
+ class SchemaLoader
409
+ def initialize(package_path, schemas_dir)
410
+ @package_path = package_path
411
+ @schemas_dir = schemas_dir
412
+ end
413
+
414
+ def load
415
+ # Check if package exists and is recent
416
+ if package_fresh?
417
+ load_from_package
418
+ else
419
+ load_from_express_and_rebuild
420
+ end
421
+ end
422
+
423
+ private
424
+
425
+ def package_fresh?
426
+ return false unless File.exist?(@package_path)
427
+
428
+ package_mtime = File.mtime(@package_path)
429
+ schemas_mtime = Dir.glob("#{@schemas_dir}/**/*.exp")
430
+ .map { |f| File.mtime(f) }
431
+ .max
432
+
433
+ package_mtime > schemas_mtime
434
+ end
435
+
436
+ def load_from_package
437
+ puts "Loading from package (cached)..."
438
+ Expressir::Model::Repository.from_package(@package_path)
439
+ end
440
+
441
+ def load_from_express_and_rebuild
442
+ puts "Loading from EXPRESS (cache stale)..."
443
+ files = Dir.glob("#{@schemas_dir}/**/*.exp")
444
+ repo = Expressir::Express::Parser.from_files(files)
445
+
446
+ puts "Rebuilding package cache..."
447
+ repo.export_to_package(@package_path)
448
+
449
+ repo
450
+ end
451
+ end
452
+
453
+ # Usage
454
+ loader = SchemaLoader.new("cache/schemas.ler", "schemas/")
455
+ repo = loader.load
456
+ ----
457
+
458
+ == Error handling
459
+
460
+ === Common loading errors
461
+
462
+ ==== Package file not found
463
+
464
+ .Error
465
+ [example]
466
+ ====
467
+ [source]
468
+ ----
469
+ ArgumentError: Package file not found: schemas.ler
470
+ ----
471
+ ====
472
+
473
+ .Solution
474
+ [example]
475
+ ====
476
+ [source,ruby]
477
+ ----
478
+ unless File.exist?("schemas.ler")
479
+ abort "Package file not found. Build with: expressir package build ..."
480
+ end
481
+
482
+ repo = Expressir::Model::Repository.from_package("schemas.ler")
483
+ ----
484
+ ====
485
+
486
+ ==== Corrupted package
487
+
488
+ .Error
489
+ [example]
490
+ ====
491
+ [source]
492
+ ----
493
+ Error: Metadata not found in package
494
+ ----
495
+ ====
496
+
497
+ .Solution
498
+ [example]
499
+ ====
500
+ 1. Verify package is a valid ZIP file: `unzip -t schemas.ler`
501
+ 2. Rebuild package from source
502
+ 3. Check disk space and file permissions
503
+ ====
504
+
505
+ ==== Incompatible format
506
+
507
+ .Error
508
+ [example]
509
+ ====
510
+ [source]
511
+ ----
512
+ Error: Unknown serialization format: custom
513
+ ----
514
+ ====
515
+
516
+ .Solution
517
+ [example]
518
+ ====
519
+ Package was built with unsupported format. Rebuild with:
520
+ * `marshal` (recommended)
521
+ * `yaml`
522
+ * `json`
523
+ ====
524
+
525
+ ==== Version mismatch
526
+
527
+ .Error
528
+ [example]
529
+ ====
530
+ [source]
531
+ ----
532
+ Error: Package built with expressir 0.6.0, current version is 0.7.0
533
+ ----
534
+ ====
535
+
536
+ .Solution
537
+ [example]
538
+ ====
539
+ Rebuild package with current Expressir version:
540
+ [source,bash]
541
+ ----
542
+ expressir package build schemas/ new_package.ler
543
+ ----
544
+ ====
545
+
546
+ === Robust error handling
547
+
548
+ Implement comprehensive error handling:
549
+
550
+ [source,ruby]
551
+ ----
552
+ def load_package_safely(path, fallback_dir = nil)
553
+ begin
554
+ # Try loading package
555
+ repo = Expressir::Model::Repository.from_package(path)
556
+ puts "✓ Loaded package: #{path}"
557
+ return repo
558
+
559
+ rescue ArgumentError => e
560
+ puts "Package not found: #{path}"
561
+
562
+ if fallback_dir && Dir.exist?(fallback_dir)
563
+ puts "Falling back to EXPRESS files..."
564
+ return load_from_express(fallback_dir)
565
+ else
566
+ raise "No package or fallback available"
567
+ end
568
+
569
+ rescue StandardError => e
570
+ puts "Error loading package: #{e.message}"
571
+
572
+ if fallback_dir && Dir.exist?(fallback_dir)
573
+ puts "Attempting recovery from EXPRESS files..."
574
+ return load_from_express(fallback_dir)
575
+ else
576
+ raise
577
+ end
578
+ end
579
+ end
580
+
581
+ def load_from_express(dir)
582
+ files = Dir.glob("#{dir}/**/*.exp")
583
+ Expressir::Express::Parser.from_files(files)
584
+ end
585
+
586
+ # Usage with fallback
587
+ repo = load_package_safely(
588
+ "cache/schemas.ler",
589
+ "schemas/" # fallback directory
590
+ )
591
+ ----
592
+
593
+ == Verification after loading
594
+
595
+ === Verify package integrity
596
+
597
+ Check loaded repository:
598
+
599
+ [source,ruby]
600
+ ----
601
+ repo = Expressir::Model::Repository.from_package("schemas.ler")
602
+
603
+ # Verify schemas loaded
604
+ if repo.schemas.empty?
605
+ abort "Error: No schemas loaded from package"
606
+ end
607
+
608
+ puts "Loaded schemas:"
609
+ repo.schemas.each { |s| puts " - #{s.id}" }
610
+
611
+ # Verify indexes built
612
+ if repo.entity_index.nil?
613
+ puts "Warning: Entity index not loaded"
614
+ repo.build_indexes
615
+ end
616
+
617
+ # Test entity lookup
618
+ test_entity = repo.find_entity(qualified_name: "action_schema.action")
619
+ if test_entity
620
+ puts "✓ Entity lookup working"
621
+ else
622
+ puts "⚠ Entity lookup failed"
623
+ end
624
+ ----
625
+
626
+ === Validate repository
627
+
628
+ Run validation after loading:
629
+
630
+ [source,ruby]
631
+ ----
632
+ repo = Expressir::Model::Repository.from_package("schemas.ler")
633
+
634
+ # Validate repository
635
+ validation = repo.validate
636
+
637
+ if validation[:valid?]
638
+ puts "✓ Repository is valid"
639
+ else
640
+ puts "⚠ Validation errors found:"
641
+ validation[:errors].each do |error|
642
+ puts " - #{error[:message]}"
643
+ end
644
+ end
645
+ ----
646
+
647
+ === Statistics check
648
+
649
+ Verify expected schema contents:
650
+
651
+ [source,ruby]
652
+ ----
653
+ repo = Expressir::Model::Repository.from_package("schemas.ler")
654
+ stats = repo.statistics
655
+
656
+ puts "Package Statistics:"
657
+ puts " Schemas: #{stats[:total_schemas]}"
658
+ puts " Entities: #{stats[:total_entities]}"
659
+ puts " Types: #{stats[:total_types]}"
660
+ puts " Functions: #{stats[:total_functions]}"
661
+
662
+ # Compare with expected values
663
+ expected = { schemas: 45, entities: 892 }
664
+
665
+ if stats[:total_schemas] != expected[:schemas]
666
+ puts "⚠ Schema count mismatch"
667
+ end
668
+
669
+ if stats[:total_entities] != expected[:entities]
670
+ puts "⚠ Entity count mismatch"
671
+ end
672
+ ----
673
+
674
+ == Next steps
675
+
676
+ * link:querying-packages.html[Querying Packages] - Search and filter package
677
+ contents
678
+ * link:validating-packages.html[Validating Packages] - Comprehensive package
679
+ validation
680
+ * link:package-formats.html[Package Formats] - Understanding serialization
681
+ formats
682
+ * link:creating-packages.html[Creating Packages] - Build your own packages
683
+
684
+ == Summary
685
+
686
+ Key takeaways for loading LER packages:
687
+
688
+ * Use `Repository.from_package()` for simplest loading
689
+ * Loading is 20-30x faster than parsing EXPRESS files
690
+ * Packages are fully ready after loading (indexes included)
691
+ * Memory usage scales linearly with package size
692
+ * Use packages as cache layer for best performance
693
+ * Implement error handling with fallback to EXPRESS files
694
+ * Validate repository after loading critical packages
695
+ * Marshal format provides fastest loading
696
+ * Extract packages to debug contents
697
+
698
+ Best practices:
699
+
700
+ * Always check package exists before loading
701
+ * Use try-catch for robust applications
702
+ * Verify loaded content with statistics
703
+ * Consider memory constraints for large packages
704
+ * Implement cache invalidation strategy
705
+ * Keep original EXPRESS files as source of truth
706
+ * Monitor load times in production
707
+ * Use fallback to EXPRESS files when needed