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.
- checksums.yaml +4 -4
- data/.github/workflows/docs.yml +98 -0
- data/.github/workflows/links.yml +100 -0
- data/.github/workflows/rake.yml +4 -0
- data/.github/workflows/release.yml +5 -0
- data/.github/workflows/validate_schemas.yml +1 -1
- data/.gitignore +3 -0
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +244 -39
- data/Gemfile +2 -1
- data/README.adoc +621 -54
- data/docs/Gemfile +12 -0
- data/docs/_config.yml +141 -0
- data/docs/_guides/changes/changes-format.adoc +778 -0
- data/docs/_guides/changes/importing-eengine.adoc +898 -0
- data/docs/_guides/changes/index.adoc +396 -0
- data/docs/_guides/changes/programmatic-usage.adoc +1038 -0
- data/docs/_guides/changes/validating-changes.adoc +681 -0
- data/docs/_guides/cli/benchmark-performance.adoc +834 -0
- data/docs/_guides/cli/coverage-analysis.adoc +921 -0
- data/docs/_guides/cli/format-schemas.adoc +547 -0
- data/docs/_guides/cli/index.adoc +8 -0
- data/docs/_guides/cli/managing-changes.adoc +927 -0
- data/docs/_guides/cli/validate-ascii.adoc +645 -0
- data/docs/_guides/cli/validate-schemas.adoc +534 -0
- data/docs/_guides/index.adoc +165 -0
- data/docs/_guides/ler/creating-packages.adoc +664 -0
- data/docs/_guides/ler/index.adoc +305 -0
- data/docs/_guides/ler/loading-packages.adoc +707 -0
- data/docs/_guides/ler/package-formats.adoc +748 -0
- data/docs/_guides/ler/querying-packages.adoc +826 -0
- data/docs/_guides/ler/validating-packages.adoc +750 -0
- data/docs/_guides/liquid/basic-templates.adoc +813 -0
- data/docs/_guides/liquid/documentation-generation.adoc +1042 -0
- data/docs/_guides/liquid/drops-reference.adoc +829 -0
- data/docs/_guides/liquid/filters-and-tags.adoc +912 -0
- data/docs/_guides/liquid/index.adoc +468 -0
- data/docs/_guides/manifests/creating-manifests.adoc +483 -0
- data/docs/_guides/manifests/index.adoc +307 -0
- data/docs/_guides/manifests/resolving-manifests.adoc +557 -0
- data/docs/_guides/manifests/validating-manifests.adoc +713 -0
- data/docs/_guides/ruby-api/formatting-schemas.adoc +605 -0
- data/docs/_guides/ruby-api/index.adoc +257 -0
- data/docs/_guides/ruby-api/parsing-files.adoc +421 -0
- data/docs/_guides/ruby-api/search-engine.adoc +609 -0
- data/docs/_guides/ruby-api/working-with-repository.adoc +577 -0
- data/docs/_pages/data-model.adoc +665 -0
- data/docs/_pages/express-language.adoc +506 -0
- data/docs/_pages/getting-started.adoc +414 -0
- data/docs/_pages/index.adoc +116 -0
- data/docs/_pages/introduction.adoc +256 -0
- data/docs/_pages/ler-packages.adoc +837 -0
- data/docs/_pages/parsers.adoc +683 -0
- data/docs/_pages/schema-manifests.adoc +431 -0
- data/docs/_references/index.adoc +228 -0
- data/docs/_tutorials/creating-ler-package.adoc +735 -0
- data/docs/_tutorials/documentation-coverage.adoc +795 -0
- data/docs/_tutorials/index.adoc +221 -0
- data/docs/_tutorials/liquid-templates.adoc +806 -0
- data/docs/_tutorials/parsing-your-first-schema.adoc +522 -0
- data/docs/_tutorials/querying-schemas.adoc +751 -0
- data/docs/_tutorials/working-with-multiple-schemas.adoc +676 -0
- data/docs/index.adoc +242 -0
- data/docs/lychee.toml +84 -0
- data/examples/demo_ler_usage.sh +86 -0
- data/examples/ler/README.md +111 -0
- data/examples/ler/simple_example.ler +0 -0
- data/examples/ler/simple_schema.exp +33 -0
- data/examples/ler_build.rb +75 -0
- data/examples/ler_cli.rb +79 -0
- data/examples/ler_demo_complete.rb +276 -0
- data/examples/ler_query.rb +91 -0
- data/examples/ler_query_examples.rb +305 -0
- data/examples/ler_stats.rb +81 -0
- data/examples/phase3_demo.rb +159 -0
- data/examples/query_demo_simple.rb +131 -0
- data/expressir.gemspec +2 -0
- data/lib/expressir/cli.rb +12 -4
- data/lib/expressir/commands/manifest.rb +427 -0
- data/lib/expressir/commands/package.rb +1274 -0
- data/lib/expressir/commands/validate.rb +70 -37
- data/lib/expressir/commands/validate_ascii.rb +607 -0
- data/lib/expressir/commands/validate_load.rb +88 -0
- data/lib/expressir/express/formatter.rb +5 -1
- data/lib/expressir/express/formatters/remark_item_formatter.rb +25 -0
- data/lib/expressir/express/parser.rb +33 -0
- data/lib/expressir/manifest/resolver.rb +213 -0
- data/lib/expressir/manifest/validator.rb +195 -0
- data/lib/expressir/model/declarations/entity.rb +6 -0
- data/lib/expressir/model/dependency_resolver.rb +270 -0
- data/lib/expressir/model/indexes/entity_index.rb +103 -0
- data/lib/expressir/model/indexes/reference_index.rb +148 -0
- data/lib/expressir/model/indexes/type_index.rb +149 -0
- data/lib/expressir/model/interface_validator.rb +384 -0
- data/lib/expressir/model/repository.rb +400 -5
- data/lib/expressir/model/repository_validator.rb +295 -0
- data/lib/expressir/model/search_engine.rb +525 -0
- data/lib/expressir/model.rb +4 -94
- data/lib/expressir/package/builder.rb +200 -0
- data/lib/expressir/package/metadata.rb +81 -0
- data/lib/expressir/package/reader.rb +165 -0
- data/lib/expressir/schema_manifest.rb +11 -1
- data/lib/expressir/version.rb +1 -1
- data/lib/expressir.rb +15 -2
- metadata +114 -4
- data/docs/benchmarking.adoc +0 -107
- data/docs/liquid_drops.adoc +0 -1547
|
@@ -0,0 +1,735 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Creating LER Packages
|
|
3
|
+
nav_order: 4
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
== Creating LER Packages
|
|
7
|
+
|
|
8
|
+
=== Prerequisites
|
|
9
|
+
|
|
10
|
+
Before starting this tutorial, ensure you have:
|
|
11
|
+
|
|
12
|
+
* Completed link:working-with-multiple-schemas.html[Working with Multiple Schemas]
|
|
13
|
+
* Understanding of EXPRESS schema dependencies
|
|
14
|
+
* Multiple EXPRESS schema files to package
|
|
15
|
+
* Expressir installed with CLI access
|
|
16
|
+
|
|
17
|
+
=== Learning Objectives
|
|
18
|
+
|
|
19
|
+
By the end of this tutorial, you will be able to:
|
|
20
|
+
|
|
21
|
+
* Understand what LER packages are and their benefits
|
|
22
|
+
* Create LER packages from EXPRESS schemas
|
|
23
|
+
* Configure packaging options for different use cases
|
|
24
|
+
* Load and query LER packages
|
|
25
|
+
* Validate package integrity
|
|
26
|
+
* Optimize packages for performance
|
|
27
|
+
|
|
28
|
+
=== What You'll Build
|
|
29
|
+
|
|
30
|
+
You'll create a distributable LER package from the multi-schema product catalog system, making it easy to share and use without re-parsing.
|
|
31
|
+
|
|
32
|
+
=== Step 1: Understanding LER Packages
|
|
33
|
+
|
|
34
|
+
==== What is a LER Package?
|
|
35
|
+
|
|
36
|
+
LutaML EXPRESS Repository (LER) is a distributable package format that:
|
|
37
|
+
|
|
38
|
+
* **Bundles all schemas** into a single `.ler` file
|
|
39
|
+
* **Pre-builds indexes** for fast entity/type lookups
|
|
40
|
+
* **Resolves references** so they're ready to use
|
|
41
|
+
* **Loads instantly** (<500ms vs 10+ seconds parsing)
|
|
42
|
+
|
|
43
|
+
==== Why Use LER Packages?
|
|
44
|
+
|
|
45
|
+
**Performance**::
|
|
46
|
+
Loading a pre-parsed package is 20-50x faster than parsing
|
|
47
|
+
|
|
48
|
+
**Distribution**::
|
|
49
|
+
One file contains everything needed
|
|
50
|
+
|
|
51
|
+
**Consistency**::
|
|
52
|
+
Everyone uses the same parsed result
|
|
53
|
+
|
|
54
|
+
**Production-ready**::
|
|
55
|
+
No parsing overhead in production
|
|
56
|
+
|
|
57
|
+
==== LER Package Structure
|
|
58
|
+
|
|
59
|
+
[source]
|
|
60
|
+
----
|
|
61
|
+
activity.ler (ZIP archive)
|
|
62
|
+
├── metadata.yaml # Package info
|
|
63
|
+
├── repository.marshal # Serialized schemas
|
|
64
|
+
├── entity_index.marshal # Fast entity lookups
|
|
65
|
+
├── type_index.marshal # Fast type lookups
|
|
66
|
+
├── reference_index.marshal # Reference mappings
|
|
67
|
+
├── manifest.yaml # Schema list
|
|
68
|
+
└── express_files/ # Original EXPRESS files
|
|
69
|
+
├── schema1.exp
|
|
70
|
+
└── schema2.exp
|
|
71
|
+
----
|
|
72
|
+
|
|
73
|
+
=== Step 2: Create Sample Schemas
|
|
74
|
+
|
|
75
|
+
First, let's create schemas to package.
|
|
76
|
+
|
|
77
|
+
==== Create `base_schema.exp`
|
|
78
|
+
|
|
79
|
+
[source,express]
|
|
80
|
+
----
|
|
81
|
+
SCHEMA base_schema;
|
|
82
|
+
|
|
83
|
+
TYPE identifier = STRING;
|
|
84
|
+
END_TYPE;
|
|
85
|
+
|
|
86
|
+
TYPE label = STRING;
|
|
87
|
+
END_TYPE;
|
|
88
|
+
|
|
89
|
+
ENTITY person;
|
|
90
|
+
name : label;
|
|
91
|
+
email : OPTIONAL STRING;
|
|
92
|
+
END_ENTITY;
|
|
93
|
+
|
|
94
|
+
ENTITY organization;
|
|
95
|
+
org_name : label;
|
|
96
|
+
employees : SET [0:?] OF person;
|
|
97
|
+
END_ENTITY;
|
|
98
|
+
|
|
99
|
+
END_SCHEMA;
|
|
100
|
+
----
|
|
101
|
+
|
|
102
|
+
==== Create `product_schema.exp`
|
|
103
|
+
|
|
104
|
+
[source,express]
|
|
105
|
+
----
|
|
106
|
+
SCHEMA product_schema;
|
|
107
|
+
|
|
108
|
+
REFERENCE FROM base_schema (identifier, label, person, organization);
|
|
109
|
+
|
|
110
|
+
ENTITY product;
|
|
111
|
+
id : identifier;
|
|
112
|
+
name : label;
|
|
113
|
+
price : REAL;
|
|
114
|
+
manufacturer : organization;
|
|
115
|
+
END_ENTITY;
|
|
116
|
+
|
|
117
|
+
ENTITY product_category;
|
|
118
|
+
category_name : label;
|
|
119
|
+
products : SET [0:?] OF product;
|
|
120
|
+
END_ENTITY;
|
|
121
|
+
|
|
122
|
+
END_SCHEMA;
|
|
123
|
+
----
|
|
124
|
+
|
|
125
|
+
=== Step 3: Create Your First Package
|
|
126
|
+
|
|
127
|
+
==== Using the CLI
|
|
128
|
+
|
|
129
|
+
The simplest way to create a package:
|
|
130
|
+
|
|
131
|
+
[source,bash]
|
|
132
|
+
----
|
|
133
|
+
# Create package from schema files
|
|
134
|
+
expressir package build base_schema.exp product_schema.exp catalog.ler
|
|
135
|
+
|
|
136
|
+
# With metadata
|
|
137
|
+
expressir package build base_schema.exp product_schema.exp catalog.ler \
|
|
138
|
+
--name "Product Catalog" \
|
|
139
|
+
--version "1.0.0" \
|
|
140
|
+
--description "Sample product catalog schemas"
|
|
141
|
+
----
|
|
142
|
+
|
|
143
|
+
**Expected output**:
|
|
144
|
+
[source]
|
|
145
|
+
----
|
|
146
|
+
✓ Parsing base_schema.exp
|
|
147
|
+
✓ Parsing product_schema.exp
|
|
148
|
+
✓ Resolving references
|
|
149
|
+
✓ Building indexes
|
|
150
|
+
✓ Creating package catalog.ler
|
|
151
|
+
|
|
152
|
+
Package created successfully!
|
|
153
|
+
Size: 45 KB
|
|
154
|
+
Schemas: 2
|
|
155
|
+
Entities: 4
|
|
156
|
+
Types: 2
|
|
157
|
+
----
|
|
158
|
+
|
|
159
|
+
==== Verify the Package
|
|
160
|
+
|
|
161
|
+
[source,bash]
|
|
162
|
+
----
|
|
163
|
+
# Show package information
|
|
164
|
+
expressir package info catalog.ler
|
|
165
|
+
----
|
|
166
|
+
|
|
167
|
+
**Output**:
|
|
168
|
+
[source]
|
|
169
|
+
----
|
|
170
|
+
Package Information
|
|
171
|
+
==================================================
|
|
172
|
+
Name: Product Catalog
|
|
173
|
+
Version: 1.0.0
|
|
174
|
+
Description: Sample product catalog schemas
|
|
175
|
+
Created: 2025-11-28T03:00:00Z
|
|
176
|
+
|
|
177
|
+
Configuration
|
|
178
|
+
--------------------------------------------------
|
|
179
|
+
Express mode: include_all
|
|
180
|
+
Resolution mode: resolved
|
|
181
|
+
Serialization format: marshal
|
|
182
|
+
|
|
183
|
+
Statistics
|
|
184
|
+
--------------------------------------------------
|
|
185
|
+
Total schemas: 2
|
|
186
|
+
Total entities: 4
|
|
187
|
+
Total types: 2
|
|
188
|
+
Total functions: 0
|
|
189
|
+
Total rules: 0
|
|
190
|
+
Total procedures: 0
|
|
191
|
+
----
|
|
192
|
+
|
|
193
|
+
=== Step 4: Package Configuration Options
|
|
194
|
+
|
|
195
|
+
==== Express Mode
|
|
196
|
+
|
|
197
|
+
Controls how EXPRESS files are bundled:
|
|
198
|
+
|
|
199
|
+
**include_all** (default)::
|
|
200
|
+
Includes original EXPRESS files in package
|
|
201
|
+
+
|
|
202
|
+
[source,bash]
|
|
203
|
+
----
|
|
204
|
+
expressir package build schema.exp output.ler --express-mode include_all
|
|
205
|
+
----
|
|
206
|
+
|
|
207
|
+
**allow_external**::
|
|
208
|
+
References external EXPRESS files (smaller package)
|
|
209
|
+
+
|
|
210
|
+
[source,bash]
|
|
211
|
+
----
|
|
212
|
+
expressir package build schema.exp output.ler --express-mode allow_external
|
|
213
|
+
----
|
|
214
|
+
|
|
215
|
+
==== Resolution Mode
|
|
216
|
+
|
|
217
|
+
Controls reference resolution:
|
|
218
|
+
|
|
219
|
+
**resolved** (default)::
|
|
220
|
+
Pre-resolves all references for faster loading
|
|
221
|
+
+
|
|
222
|
+
[source,bash]
|
|
223
|
+
----
|
|
224
|
+
expressir package build schema.exp output.ler --resolution-mode resolved
|
|
225
|
+
----
|
|
226
|
+
|
|
227
|
+
**bare**::
|
|
228
|
+
Does not pre-resolve (smaller but slower to load)
|
|
229
|
+
+
|
|
230
|
+
[source,bash]
|
|
231
|
+
----
|
|
232
|
+
expressir package build schema.exp output.ler --resolution-mode bare
|
|
233
|
+
----
|
|
234
|
+
|
|
235
|
+
==== Serialization Format
|
|
236
|
+
|
|
237
|
+
Controls internal data format:
|
|
238
|
+
|
|
239
|
+
**marshal** (default)::
|
|
240
|
+
Ruby's native format, fastest
|
|
241
|
+
+
|
|
242
|
+
[source,bash]
|
|
243
|
+
----
|
|
244
|
+
expressir package build schema.exp output.ler --serialization-format marshal
|
|
245
|
+
----
|
|
246
|
+
|
|
247
|
+
**yaml**::
|
|
248
|
+
Human-readable, cross-platform
|
|
249
|
+
+
|
|
250
|
+
[source,bash]
|
|
251
|
+
----
|
|
252
|
+
expressir package build schema.exp output.ler --serialization-format yaml
|
|
253
|
+
----
|
|
254
|
+
|
|
255
|
+
**json**::
|
|
256
|
+
Standard format, good compatibility
|
|
257
|
+
+
|
|
258
|
+
[source,bash]
|
|
259
|
+
----
|
|
260
|
+
expressir package build schema.exp output.ler --serialization-format json
|
|
261
|
+
----
|
|
262
|
+
|
|
263
|
+
=== Step 5: Build Optimized Packages
|
|
264
|
+
|
|
265
|
+
==== Production Package (Fastest)
|
|
266
|
+
|
|
267
|
+
[source,bash]
|
|
268
|
+
----
|
|
269
|
+
expressir package build base_schema.exp product_schema.exp production.ler \
|
|
270
|
+
--name "Production Catalog" \
|
|
271
|
+
--version "1.0.0" \
|
|
272
|
+
--express-mode include_all \
|
|
273
|
+
--resolution-mode resolved \
|
|
274
|
+
--serialization-format marshal \
|
|
275
|
+
--validate
|
|
276
|
+
----
|
|
277
|
+
|
|
278
|
+
**When to use**: Production deployments where speed is critical
|
|
279
|
+
|
|
280
|
+
==== Portable Package (Cross-Platform)
|
|
281
|
+
|
|
282
|
+
[source,bash]
|
|
283
|
+
----
|
|
284
|
+
expressir package build base_schema.exp product_schema.exp portable.ler \
|
|
285
|
+
--name "Portable Catalog" \
|
|
286
|
+
--version "1.0.0" \
|
|
287
|
+
--serialization-format json \
|
|
288
|
+
--validate
|
|
289
|
+
----
|
|
290
|
+
|
|
291
|
+
**When to use**: Sharing across different Ruby versions or platforms
|
|
292
|
+
|
|
293
|
+
==== Debug Package (Human-Readable)
|
|
294
|
+
|
|
295
|
+
[source,bash]
|
|
296
|
+
----
|
|
297
|
+
expressir package build base_schema.exp product_schema.exp debug.ler \
|
|
298
|
+
--name "Debug Catalog" \
|
|
299
|
+
--version "1.0.0" \
|
|
300
|
+
--serialization-format yaml \
|
|
301
|
+
--validate
|
|
302
|
+
----
|
|
303
|
+
|
|
304
|
+
**When to use**: Development and debugging
|
|
305
|
+
|
|
306
|
+
=== Step 6: Load and Use Packages
|
|
307
|
+
|
|
308
|
+
==== Load with CLI
|
|
309
|
+
|
|
310
|
+
[source,bash]
|
|
311
|
+
----
|
|
312
|
+
# List all entities
|
|
313
|
+
expressir package list catalog.ler
|
|
314
|
+
|
|
315
|
+
# List entities in specific schema
|
|
316
|
+
expressir package list catalog.ler --schema product_schema
|
|
317
|
+
|
|
318
|
+
# Search for entities
|
|
319
|
+
expressir package search catalog.ler "product"
|
|
320
|
+
----
|
|
321
|
+
|
|
322
|
+
==== Load with Ruby API
|
|
323
|
+
|
|
324
|
+
Create `use_package.rb`:
|
|
325
|
+
|
|
326
|
+
[source,ruby]
|
|
327
|
+
----
|
|
328
|
+
require 'expressir'
|
|
329
|
+
|
|
330
|
+
# Load package
|
|
331
|
+
repo = Expressir::Model::Repository.from_package('catalog.ler')
|
|
332
|
+
|
|
333
|
+
puts "Loaded package:"
|
|
334
|
+
puts " Schemas: #{repo.schemas.size}"
|
|
335
|
+
puts " Total entities: #{repo.schemas.sum { |s| s.entities.size }}"
|
|
336
|
+
|
|
337
|
+
# Access schemas
|
|
338
|
+
repo.schemas.each do |schema|
|
|
339
|
+
puts "\n#{schema.id}:"
|
|
340
|
+
schema.entities.each do |entity|
|
|
341
|
+
puts " - #{entity.id}"
|
|
342
|
+
end
|
|
343
|
+
end
|
|
344
|
+
----
|
|
345
|
+
|
|
346
|
+
Run it:
|
|
347
|
+
|
|
348
|
+
[source,bash]
|
|
349
|
+
----
|
|
350
|
+
ruby use_package.rb
|
|
351
|
+
----
|
|
352
|
+
|
|
353
|
+
**Output**:
|
|
354
|
+
[source]
|
|
355
|
+
----
|
|
356
|
+
Loaded package:
|
|
357
|
+
Schemas: 2
|
|
358
|
+
Total entities: 4
|
|
359
|
+
|
|
360
|
+
base_schema:
|
|
361
|
+
- person
|
|
362
|
+
- organization
|
|
363
|
+
|
|
364
|
+
product_schema:
|
|
365
|
+
- product
|
|
366
|
+
- product_category
|
|
367
|
+
----
|
|
368
|
+
|
|
369
|
+
=== Step 7: Query Package Contents
|
|
370
|
+
|
|
371
|
+
==== Using the Search Engine
|
|
372
|
+
|
|
373
|
+
Create `query_package.rb`:
|
|
374
|
+
|
|
375
|
+
[source,ruby]
|
|
376
|
+
----
|
|
377
|
+
require 'expressir'
|
|
378
|
+
|
|
379
|
+
# Load package
|
|
380
|
+
repo = Expressir::Model::Repository.from_package('catalog.ler')
|
|
381
|
+
|
|
382
|
+
# Create search engine
|
|
383
|
+
search = Expressir::Model::SearchEngine.new(repo)
|
|
384
|
+
|
|
385
|
+
# List all entities
|
|
386
|
+
puts "All entities:"
|
|
387
|
+
entities = search.list(type: 'entity')
|
|
388
|
+
entities.each do |e|
|
|
389
|
+
puts " #{e[:schema]}.#{e[:id]}"
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
# Search by pattern
|
|
393
|
+
puts "\nEntities starting with 'product':"
|
|
394
|
+
results = search.search(pattern: 'product*', type: 'entity')
|
|
395
|
+
results.each do |r|
|
|
396
|
+
puts " #{r[:path]}"
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
# Find specific entity
|
|
400
|
+
puts "\nFinding 'product_category':"
|
|
401
|
+
result = search.search(pattern: 'product_category', type: 'entity', exact: true)
|
|
402
|
+
if result.any?
|
|
403
|
+
entity = result.first[:object]
|
|
404
|
+
puts " Found in: #{result.first[:schema]}"
|
|
405
|
+
puts " Attributes: #{entity.attributes.map(&:id).join(', ')}"
|
|
406
|
+
end
|
|
407
|
+
----
|
|
408
|
+
|
|
409
|
+
**Output**:
|
|
410
|
+
[source]
|
|
411
|
+
----
|
|
412
|
+
All entities:
|
|
413
|
+
base_schema.person
|
|
414
|
+
base_schema.organization
|
|
415
|
+
product_schema.product
|
|
416
|
+
product_schema.product_category
|
|
417
|
+
|
|
418
|
+
Entities starting with 'product':
|
|
419
|
+
product_schema.product
|
|
420
|
+
product_schema.product_category
|
|
421
|
+
|
|
422
|
+
Finding 'product_category':
|
|
423
|
+
Found in: product_schema
|
|
424
|
+
Attributes: category_name, products
|
|
425
|
+
----
|
|
426
|
+
|
|
427
|
+
=== Step 8: Validate Packages
|
|
428
|
+
|
|
429
|
+
==== Validation with CLI
|
|
430
|
+
|
|
431
|
+
[source,bash]
|
|
432
|
+
----
|
|
433
|
+
# Basic validation
|
|
434
|
+
expressir package validate catalog.ler
|
|
435
|
+
|
|
436
|
+
# Strict validation with checks
|
|
437
|
+
expressir package validate catalog.ler --strict --check-interfaces --detailed
|
|
438
|
+
----
|
|
439
|
+
|
|
440
|
+
==== Validation with Ruby API
|
|
441
|
+
|
|
442
|
+
Create `validate_package.rb`:
|
|
443
|
+
|
|
444
|
+
[source,ruby]
|
|
445
|
+
----
|
|
446
|
+
require 'expressir'
|
|
447
|
+
|
|
448
|
+
# Load package
|
|
449
|
+
repo = Expressir::Model::Repository.from_package('catalog.ler')
|
|
450
|
+
|
|
451
|
+
# Validate
|
|
452
|
+
validation = repo.validate(strict: false)
|
|
453
|
+
|
|
454
|
+
if validation[:valid?]
|
|
455
|
+
puts "✓ Package is valid"
|
|
456
|
+
puts " Total schemas: #{validation[:total_schemas]}"
|
|
457
|
+
puts " Valid schemas: #{validation[:valid_schemas]}"
|
|
458
|
+
else
|
|
459
|
+
puts "✗ Validation failed"
|
|
460
|
+
validation[:errors].each do |error|
|
|
461
|
+
puts " Error: #{error[:message]}"
|
|
462
|
+
end
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
# Check warnings
|
|
466
|
+
if validation[:warnings]&.any?
|
|
467
|
+
puts "\nWarnings:"
|
|
468
|
+
validation[:warnings].each do |warning|
|
|
469
|
+
puts " - #{warning[:message]}"
|
|
470
|
+
end
|
|
471
|
+
end
|
|
472
|
+
----
|
|
473
|
+
|
|
474
|
+
=== Step 9: Package Statistics
|
|
475
|
+
|
|
476
|
+
==== Get Detailed Statistics
|
|
477
|
+
|
|
478
|
+
Create `package_stats.rb`:
|
|
479
|
+
|
|
480
|
+
[source,ruby]
|
|
481
|
+
----
|
|
482
|
+
require 'expressir'
|
|
483
|
+
|
|
484
|
+
repo = Expressir::Model::Repository.from_package('catalog.ler')
|
|
485
|
+
stats = repo.statistics
|
|
486
|
+
|
|
487
|
+
puts "Package Statistics"
|
|
488
|
+
puts "=" * 60
|
|
489
|
+
|
|
490
|
+
puts "\nElement counts:"
|
|
491
|
+
puts " Schemas: #{stats[:total_schemas]}"
|
|
492
|
+
puts " Entities: #{stats[:total_entities]}"
|
|
493
|
+
puts " Types: #{stats[:total_types]}"
|
|
494
|
+
puts " Functions: #{stats[:total_functions]}"
|
|
495
|
+
puts " Rules: #{stats[:total_rules]}"
|
|
496
|
+
puts " Procedures: #{stats[:total_procedures]}"
|
|
497
|
+
|
|
498
|
+
if stats[:types_by_category]
|
|
499
|
+
puts "\nTypes by category:"
|
|
500
|
+
stats[:types_by_category].each do |category, count|
|
|
501
|
+
puts " #{category}: #{count}"
|
|
502
|
+
end
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
if stats[:entities_by_schema]
|
|
506
|
+
puts "\nEntities per schema:"
|
|
507
|
+
stats[:entities_by_schema].each do |schema, count|
|
|
508
|
+
puts " #{schema}: #{count} entities"
|
|
509
|
+
end
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
if stats[:interfaces]
|
|
513
|
+
puts "\nInterface usage:"
|
|
514
|
+
puts " USE FROM: #{stats[:interfaces][:use_from]}"
|
|
515
|
+
puts " REFERENCE FROM: #{stats[:interfaces][:reference_from]}"
|
|
516
|
+
end
|
|
517
|
+
----
|
|
518
|
+
|
|
519
|
+
=== Step 10: Build from Schema Manifest
|
|
520
|
+
|
|
521
|
+
==== Create Schema Manifest
|
|
522
|
+
|
|
523
|
+
Create `schemas.yml`:
|
|
524
|
+
|
|
525
|
+
[source,yaml]
|
|
526
|
+
----
|
|
527
|
+
schemas:
|
|
528
|
+
- path: base_schema.exp
|
|
529
|
+
id: base_schema
|
|
530
|
+
- path: product_schema.exp
|
|
531
|
+
id: product_schema
|
|
532
|
+
----
|
|
533
|
+
|
|
534
|
+
==== Build Package from Manifest
|
|
535
|
+
|
|
536
|
+
[source,bash]
|
|
537
|
+
----
|
|
538
|
+
# Build from manifest
|
|
539
|
+
expressir package build-from-manifest schemas.yml manifest_catalog.ler \
|
|
540
|
+
--name "Manifest Catalog" \
|
|
541
|
+
--version "1.0.0" \
|
|
542
|
+
--validate
|
|
543
|
+
----
|
|
544
|
+
|
|
545
|
+
==== Programmatic Build from Manifest
|
|
546
|
+
|
|
547
|
+
Create `build_from_manifest.rb`:
|
|
548
|
+
|
|
549
|
+
[source,ruby]
|
|
550
|
+
----
|
|
551
|
+
require 'expressir'
|
|
552
|
+
|
|
553
|
+
# Load manifest
|
|
554
|
+
manifest = Expressir::SchemaManifest.from_file('schemas.yml')
|
|
555
|
+
|
|
556
|
+
# Get file paths
|
|
557
|
+
files = manifest.schemas.map(&:path)
|
|
558
|
+
|
|
559
|
+
puts "Building package from #{files.size} schemas..."
|
|
560
|
+
|
|
561
|
+
# Parse all files
|
|
562
|
+
repo = Expressir::Express::Parser.from_files(files) do |filename, schemas, error|
|
|
563
|
+
if error
|
|
564
|
+
puts " ✗ Error: #{filename}"
|
|
565
|
+
else
|
|
566
|
+
puts " ✓ Loaded: #{filename}"
|
|
567
|
+
end
|
|
568
|
+
end
|
|
569
|
+
|
|
570
|
+
# Export to package
|
|
571
|
+
repo.export_to_package(
|
|
572
|
+
'programmatic.ler',
|
|
573
|
+
name: 'Programmatic Catalog',
|
|
574
|
+
version: '1.0.0',
|
|
575
|
+
express_mode: 'include_all',
|
|
576
|
+
resolution_mode: 'resolved',
|
|
577
|
+
serialization_format: 'marshal'
|
|
578
|
+
)
|
|
579
|
+
|
|
580
|
+
puts "\n✓ Package created: programmatic.ler"
|
|
581
|
+
----
|
|
582
|
+
|
|
583
|
+
=== Step 11: Package Version Comparison
|
|
584
|
+
|
|
585
|
+
Compare different package configurations.
|
|
586
|
+
|
|
587
|
+
==== Benchmark Package Performance
|
|
588
|
+
|
|
589
|
+
Create `benchmark_packages.rb`:
|
|
590
|
+
|
|
591
|
+
[source,ruby]
|
|
592
|
+
----
|
|
593
|
+
require 'expressir'
|
|
594
|
+
require 'benchmark'
|
|
595
|
+
|
|
596
|
+
formats = {
|
|
597
|
+
'marshal' => 'marshal_catalog.ler',
|
|
598
|
+
'yaml' => 'yaml_catalog.ler',
|
|
599
|
+
'json' => 'json_catalog.ler'
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
puts "Package Loading Benchmark"
|
|
603
|
+
puts "=" * 60
|
|
604
|
+
|
|
605
|
+
formats.each do |format, file|
|
|
606
|
+
next unless File.exist?(file)
|
|
607
|
+
|
|
608
|
+
time = Benchmark.realtime do
|
|
609
|
+
repo = Expressir::Model::Repository.from_package(file)
|
|
610
|
+
end
|
|
611
|
+
|
|
612
|
+
size = File.size(file) / 1024.0 # KB
|
|
613
|
+
|
|
614
|
+
puts "\n#{format.upcase} format:"
|
|
615
|
+
puts " Load time: #{(time * 1000).round(2)}ms"
|
|
616
|
+
puts " File size: #{size.round(2)} KB"
|
|
617
|
+
end
|
|
618
|
+
----
|
|
619
|
+
|
|
620
|
+
=== Step 12: Practice Exercises
|
|
621
|
+
|
|
622
|
+
==== Exercise 1: Multi-Format Packages
|
|
623
|
+
|
|
624
|
+
Create three versions of the same package:
|
|
625
|
+
* Production (marshal, resolved)
|
|
626
|
+
* Development (yaml, resolved)
|
|
627
|
+
* Minimal (json, bare)
|
|
628
|
+
|
|
629
|
+
Compare file sizes and loading times.
|
|
630
|
+
|
|
631
|
+
==== Exercise 2: Large Package
|
|
632
|
+
|
|
633
|
+
Create a package with at least 10 schemas and 50+ entities.
|
|
634
|
+
Measure:
|
|
635
|
+
* Parsing time
|
|
636
|
+
* Package creation time
|
|
637
|
+
* Package loading time
|
|
638
|
+
* Query performance
|
|
639
|
+
|
|
640
|
+
==== Exercise 3: Package Distribution
|
|
641
|
+
|
|
642
|
+
Create a package that:
|
|
643
|
+
* Includes metadata (name, version, description)
|
|
644
|
+
* Uses portable format (JSON)
|
|
645
|
+
* Validates successfully
|
|
646
|
+
* Can be loaded on different systems
|
|
647
|
+
|
|
648
|
+
=== Common Issues and Solutions
|
|
649
|
+
|
|
650
|
+
==== "Package file not found"
|
|
651
|
+
|
|
652
|
+
**Problem**: Can't load package
|
|
653
|
+
|
|
654
|
+
**Solution**:
|
|
655
|
+
[source,ruby]
|
|
656
|
+
----
|
|
657
|
+
# Check file exists
|
|
658
|
+
unless File.exist?('catalog.ler')
|
|
659
|
+
puts "Error: Package file not found"
|
|
660
|
+
exit 1
|
|
661
|
+
end
|
|
662
|
+
|
|
663
|
+
repo = Expressir::Model::Repository.from_package('catalog.ler')
|
|
664
|
+
----
|
|
665
|
+
|
|
666
|
+
==== "Invalid package format"
|
|
667
|
+
|
|
668
|
+
**Problem**: Corrupted or incompatible package
|
|
669
|
+
|
|
670
|
+
**Solution**:
|
|
671
|
+
[source,bash]
|
|
672
|
+
----
|
|
673
|
+
# Rebuild package with validation
|
|
674
|
+
expressir package build schema.exp output.ler --validate
|
|
675
|
+
----
|
|
676
|
+
|
|
677
|
+
==== Large Package Performance
|
|
678
|
+
|
|
679
|
+
**Problem**: Package too large or slow to load
|
|
680
|
+
|
|
681
|
+
**Solutions**:
|
|
682
|
+
* Use marshal format (fastest)
|
|
683
|
+
* Enable compression
|
|
684
|
+
* Split into multiple packages
|
|
685
|
+
* Use bare resolution mode for less critical packages
|
|
686
|
+
|
|
687
|
+
=== Best Practices
|
|
688
|
+
|
|
689
|
+
**Development**::
|
|
690
|
+
* Use YAML format for readability
|
|
691
|
+
* Include original EXPRESS files
|
|
692
|
+
* Enable validation
|
|
693
|
+
* Keep packages small for iteration
|
|
694
|
+
|
|
695
|
+
**Production**::
|
|
696
|
+
* Use marshal format for speed
|
|
697
|
+
* Pre-resolve all references
|
|
698
|
+
* Validate before deployment
|
|
699
|
+
* Version your packages
|
|
700
|
+
|
|
701
|
+
**Distribution**::
|
|
702
|
+
* Use JSON format for compatibility
|
|
703
|
+
* Include comprehensive metadata
|
|
704
|
+
* Document dependencies
|
|
705
|
+
* Provide examples
|
|
706
|
+
|
|
707
|
+
=== Next Steps
|
|
708
|
+
|
|
709
|
+
Congratulations! You can now create and use LER packages.
|
|
710
|
+
|
|
711
|
+
**Continue learning**:
|
|
712
|
+
|
|
713
|
+
* link:querying-schemas.html[Querying Schemas] - Advanced search techniques
|
|
714
|
+
* link:liquid-templates.html[Liquid Templates] - Generate documentation
|
|
715
|
+
* link:../pages/ler-packages.html[LER Packages] - Complete reference
|
|
716
|
+
|
|
717
|
+
**Read more**:
|
|
718
|
+
|
|
719
|
+
* link:../guides/ler/[LER Guides] - Advanced LER usage
|
|
720
|
+
* link:../guides/ruby-api/[Ruby API Guides] - Programmatic access
|
|
721
|
+
* link:../guides/cli/[CLI Guides] - Command-line tools
|
|
722
|
+
|
|
723
|
+
=== Summary
|
|
724
|
+
|
|
725
|
+
In this tutorial, you learned to:
|
|
726
|
+
|
|
727
|
+
* ✅ Understand LER package benefits
|
|
728
|
+
* ✅ Create packages with different configurations
|
|
729
|
+
* ✅ Optimize packages for various use cases
|
|
730
|
+
* ✅ Load and use packages efficiently
|
|
731
|
+
* ✅ Validate package integrity
|
|
732
|
+
* ✅ Query package contents
|
|
733
|
+
* ✅ Compare package formats
|
|
734
|
+
|
|
735
|
+
You're now ready to distribute EXPRESS schemas efficiently with LER packages!
|