lutaml-store 0.2.0 → 0.2.2

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 (102) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +13 -177
  3. data/CLAUDE.md +22 -9
  4. data/README.adoc +326 -1103
  5. data/lib/lutaml/store/adapter/base.rb +4 -0
  6. data/lib/lutaml/store/adapter/memory.rb +8 -0
  7. data/lib/lutaml/store/adapter.rb +17 -0
  8. data/lib/lutaml/store/basic_store.rb +1 -10
  9. data/lib/lutaml/store/cache_store.rb +11 -16
  10. data/lib/lutaml/store/database_store.rb +19 -9
  11. data/lib/lutaml/store/format/base.rb +4 -0
  12. data/lib/lutaml/store/format/marshal_format.rb +4 -0
  13. data/lib/lutaml/store/format/xml.rb +37 -0
  14. data/lib/lutaml/store/format/yamls.rb +1 -1
  15. data/lib/lutaml/store/format.rb +22 -1
  16. data/lib/lutaml/store/format_serializer.rb +44 -0
  17. data/lib/lutaml/store/http_cache.rb +3 -13
  18. data/lib/lutaml/store/model_registration.rb +5 -2
  19. data/lib/lutaml/store/model_registry.rb +22 -20
  20. data/lib/lutaml/store/package_store.rb +2 -18
  21. data/lib/lutaml/store/package_transport/base.rb +60 -0
  22. data/lib/lutaml/store/package_transport/directory_transport.rb +196 -0
  23. data/lib/lutaml/store/package_transport/zip_transport.rb +183 -0
  24. data/lib/lutaml/store/package_transport.rb +11 -438
  25. data/lib/lutaml/store/storage_key.rb +1 -1
  26. data/lib/lutaml/store/version.rb +1 -1
  27. data/lib/lutaml/store.rb +1 -0
  28. metadata +14 -77
  29. data/.github/workflows/main.yml +0 -27
  30. data/.gitignore +0 -12
  31. data/CORRECTED_HTTP_CACHE_IMPLEMENTATION.md +0 -209
  32. data/CORRECTED_HTTP_CACHE_PLAN.md +0 -164
  33. data/Gemfile +0 -15
  34. data/Gemfile.lock +0 -227
  35. data/TODO.impl/0-lutaml-store-self-quality.md +0 -112
  36. data/TODO.impl/1-lutaml-hal-migration.md +0 -96
  37. data/TODO.impl/2-glossarist-migration.md +0 -359
  38. data/TODO.impl/3-lutaml-jsonschema-migration.md +0 -273
  39. data/bin/console +0 -11
  40. data/bin/setup +0 -8
  41. data/demo/Gemfile +0 -15
  42. data/demo/Gemfile.lock +0 -61
  43. data/demo/README.adoc +0 -301
  44. data/demo/data/vcards/co/contact_10_thompson.data +0 -1
  45. data/demo/data/vcards/co/contact_10_thompson.meta +0 -1
  46. data/demo/data/vcards/co/contact_1_doe.data +0 -1
  47. data/demo/data/vcards/co/contact_1_doe.meta +0 -1
  48. data/demo/data/vcards/co/contact_2_smith.data +0 -1
  49. data/demo/data/vcards/co/contact_2_smith.meta +0 -1
  50. data/demo/data/vcards/co/contact_3_johnson.data +0 -1
  51. data/demo/data/vcards/co/contact_3_johnson.meta +0 -1
  52. data/demo/data/vcards/co/contact_4_garcia.data +0 -1
  53. data/demo/data/vcards/co/contact_4_garcia.meta +0 -1
  54. data/demo/data/vcards/co/contact_5_wilson.data +0 -1
  55. data/demo/data/vcards/co/contact_5_wilson.meta +0 -1
  56. data/demo/data/vcards/co/contact_6_brown.data +0 -1
  57. data/demo/data/vcards/co/contact_6_brown.meta +0 -1
  58. data/demo/data/vcards/co/contact_7_davis.data +0 -1
  59. data/demo/data/vcards/co/contact_7_davis.meta +0 -1
  60. data/demo/data/vcards/co/contact_8_anderson.data +0 -1
  61. data/demo/data/vcards/co/contact_8_anderson.meta +0 -1
  62. data/demo/data/vcards/co/contact_9_taylor.data +0 -1
  63. data/demo/data/vcards/co/contact_9_taylor.meta +0 -1
  64. data/demo/data/vcards.db +0 -0
  65. data/demo/pottery_class_demo.rb +0 -164
  66. data/demo/vcard_models.rb +0 -140
  67. data/demo/vcard_store_demo.rb +0 -526
  68. data/lutaml-store.gemspec +0 -36
  69. data/plan.adoc +0 -606
  70. data/spec/lutaml/store/adapter_interface_spec.rb +0 -89
  71. data/spec/lutaml/store/anti_pattern_guard_spec.rb +0 -35
  72. data/spec/lutaml/store/anti_pattern_spec.rb +0 -78
  73. data/spec/lutaml/store/autoload_spec.rb +0 -34
  74. data/spec/lutaml/store/cache_store_spec.rb +0 -271
  75. data/spec/lutaml/store/compression_spec.rb +0 -78
  76. data/spec/lutaml/store/config_enhanced_spec.rb +0 -158
  77. data/spec/lutaml/store/corrected_http_cache_integration_spec.rb +0 -336
  78. data/spec/lutaml/store/custom_serializer_spec.rb +0 -108
  79. data/spec/lutaml/store/database_store_spec.rb +0 -279
  80. data/spec/lutaml/store/file_io_spec.rb +0 -220
  81. data/spec/lutaml/store/format/yamls_spec.rb +0 -80
  82. data/spec/lutaml/store/format_round_trip_spec.rb +0 -110
  83. data/spec/lutaml/store/format_spec.rb +0 -70
  84. data/spec/lutaml/store/http_cache_entry_spec.rb +0 -203
  85. data/spec/lutaml/store/http_cache_hal_integration_spec.rb +0 -404
  86. data/spec/lutaml/store/http_cache_spec.rb +0 -422
  87. data/spec/lutaml/store/http_header_processor_spec.rb +0 -290
  88. data/spec/lutaml/store/import_spec.rb +0 -90
  89. data/spec/lutaml/store/integrity_spec.rb +0 -157
  90. data/spec/lutaml/store/key_collision_serializer_spec.rb +0 -98
  91. data/spec/lutaml/store/load_save_spec.rb +0 -107
  92. data/spec/lutaml/store/lutaml_model_integration_spec.rb +0 -291
  93. data/spec/lutaml/store/model_serializer_spec.rb +0 -140
  94. data/spec/lutaml/store/package_definition_spec.rb +0 -89
  95. data/spec/lutaml/store/package_store_spec.rb +0 -153
  96. data/spec/lutaml/store/package_transport/directory_transport_spec.rb +0 -139
  97. data/spec/lutaml/store/package_transport/zip_transport_spec.rb +0 -85
  98. data/spec/lutaml/store/store_spec.rb +0 -182
  99. data/spec/lutaml/store_spec.rb +0 -21
  100. data/spec/spec_helper.rb +0 -16
  101. data/spec/support/simple_test_model.rb +0 -15
  102. data/spec/support/yamls_test_model.rb +0 -35
@@ -1,526 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require "bundler/setup"
5
- require "lutaml/store"
6
- require "securerandom"
7
- require "date"
8
- require "paint"
9
- require "table_tennis"
10
- require_relative "vcard_models"
11
-
12
- # VCard Store Demo
13
- # This demo showcases the lutaml-store functionality using vCard models
14
- class VCardStoreDemo
15
- include VCardDemo
16
-
17
- def initialize
18
- @stores = {}
19
- setup_stores
20
- puts "šŸŽÆ VCard Store Demo Initialized"
21
- puts "=" * 50
22
- end
23
-
24
- def run
25
- puts "\nšŸ“‹ Running VCard Store Demo..."
26
-
27
- # Create sample vCards
28
- create_sample_vcards
29
-
30
- # Demonstrate different storage backends
31
- demonstrate_memory_store
32
- demonstrate_filesystem_store
33
- demonstrate_sqlite_store
34
- demonstrate_cache_store
35
-
36
- # Demonstrate search and retrieval
37
- demonstrate_search_capabilities
38
-
39
- # Demonstrate data integrity
40
- demonstrate_integrity_features
41
-
42
- puts "\nāœ… Demo completed successfully!"
43
- puts "Check the demo/data/ directory for persisted files."
44
- end
45
-
46
- private
47
-
48
- def setup_stores
49
- # Memory store for fast operations
50
- @stores[:memory] = Lutaml::Store::Store.new(
51
- adapter: { type: :memory }
52
- )
53
-
54
- # Filesystem store for persistence
55
- @stores[:filesystem] = Lutaml::Store::Store.new(
56
- adapter: {
57
- type: :filesystem,
58
- options: { path: "demo/data/vcards" }
59
- }
60
- )
61
-
62
- # SQLite store for structured queries
63
- @stores[:sqlite] = Lutaml::Store::Store.new(
64
- adapter: {
65
- type: :sqlite,
66
- options: { path: "demo/data/vcards.db" }
67
- }
68
- )
69
-
70
- # Cache store for performance
71
- @stores[:cache] = Lutaml::Store::CacheStore.new(
72
- adapter: { type: :memory },
73
- default_ttl: 300, # 5 minutes
74
- max_size: 100
75
- )
76
- end
77
-
78
- def create_sample_vcards
79
- puts "\nšŸ“ Creating 10 sample vCards..."
80
-
81
- @sample_vcards = [
82
- create_vcard(
83
- fn: "John Doe",
84
- given: "John", family: "Doe",
85
- email: ["john.doe@example.com", "j.doe@work.com"],
86
- phone: ["+1-555-0101", "work"],
87
- org: "Tech Corp",
88
- birthday: "1985-03-15"
89
- ),
90
- create_vcard(
91
- fn: "Jane Smith",
92
- given: "Jane", family: "Smith",
93
- email: ["jane.smith@example.com"],
94
- phone: ["+1-555-0102", "mobile"],
95
- org: "Design Studio",
96
- birthday: "1990-07-22"
97
- ),
98
- create_vcard(
99
- fn: "Dr. Robert Johnson",
100
- prefix: "Dr.", given: "Robert", family: "Johnson",
101
- email: ["r.johnson@hospital.com", "robert@personal.com"],
102
- phone: ["+1-555-0103", "work"],
103
- org: "City Hospital",
104
- birthday: "1975-11-08"
105
- ),
106
- create_vcard(
107
- fn: "Maria Garcia",
108
- given: "Maria", family: "Garcia",
109
- email: ["maria.garcia@startup.com"],
110
- phone: ["+1-555-0104", "mobile"],
111
- org: "Innovation Labs",
112
- birthday: "1988-02-14"
113
- ),
114
- create_vcard(
115
- fn: "David Wilson",
116
- given: "David", family: "Wilson",
117
- email: ["david.wilson@consulting.com"],
118
- phone: ["+1-555-0105", "work"],
119
- org: "Wilson Consulting",
120
- birthday: "1982-09-30"
121
- ),
122
- create_vcard(
123
- fn: "Sarah Brown",
124
- given: "Sarah", family: "Brown",
125
- email: ["sarah.brown@university.edu", "s.brown@research.org"],
126
- phone: ["+1-555-0106", "work"],
127
- org: "State University",
128
- birthday: "1979-12-03"
129
- ),
130
- create_vcard(
131
- fn: "Michael Davis",
132
- given: "Michael", family: "Davis",
133
- email: ["mike.davis@agency.com"],
134
- phone: ["+1-555-0107", "mobile"],
135
- org: "Creative Agency",
136
- birthday: "1992-05-18"
137
- ),
138
- create_vcard(
139
- fn: "Lisa Anderson",
140
- given: "Lisa", family: "Anderson",
141
- email: ["lisa.anderson@finance.com"],
142
- phone: ["+1-555-0108", "work"],
143
- org: "Financial Services Inc",
144
- birthday: "1986-08-25"
145
- ),
146
- create_vcard(
147
- fn: "James Taylor",
148
- given: "James", family: "Taylor",
149
- email: ["james.taylor@music.com", "jtaylor@personal.net"],
150
- phone: ["+1-555-0109", "mobile"],
151
- org: "Music Production",
152
- birthday: "1983-01-12"
153
- ),
154
- create_vcard(
155
- fn: "Emma Thompson",
156
- given: "Emma", family: "Thompson",
157
- email: ["emma.thompson@law.com"],
158
- phone: ["+1-555-0110", "work"],
159
- org: "Thompson & Associates",
160
- birthday: "1977-04-07"
161
- )
162
- ]
163
-
164
- puts "āœ… Created #{@sample_vcards.length} vCards"
165
- end
166
-
167
- def create_vcard(fn:, given:, family:, email:, phone:, org:, birthday:, prefix: nil)
168
- name = VcardName.new(
169
- given: given,
170
- family: family,
171
- prefix: prefix
172
- )
173
-
174
- tel = VcardTel.new(
175
- value: phone[0],
176
- type: phone[1]
177
- )
178
-
179
- bday = VcardBday.new(
180
- value: birthday
181
- )
182
-
183
- Vcard.new(
184
- fn: fn,
185
- n: name,
186
- email: email,
187
- tel: [tel],
188
- org: org,
189
- bday: bday
190
- )
191
- end
192
-
193
- def demonstrate_memory_store
194
- puts "\n🧠 Memory Store Demo"
195
- puts "-" * 30
196
-
197
- store = @stores[:memory]
198
-
199
- # Store all vCards
200
- @sample_vcards.each do |vcard|
201
- store.set(vcard.uid, vcard.to_h)
202
- puts "šŸ’¾ Stored: #{vcard.fn}"
203
- end
204
-
205
- puts "šŸ“Š Total stored: #{store.size} vCards"
206
-
207
- # Retrieve a specific vCard
208
- first_uid = @sample_vcards.first.uid
209
- retrieved = store.get(first_uid)
210
- puts "šŸ” Retrieved: #{retrieved["fn"]} by UID"
211
-
212
- # List all keys
213
- puts "šŸ—‚ļø All UIDs: #{store.keys.length} entries"
214
- end
215
-
216
- def demonstrate_filesystem_store
217
- puts "\nšŸ’¾ Filesystem Store Demo"
218
- puts "-" * 30
219
-
220
- store = @stores[:filesystem]
221
-
222
- # Store vCards with organized keys
223
- @sample_vcards.each_with_index do |vcard, index|
224
- key = "contact_#{index + 1}_#{vcard.n.family.downcase}"
225
- store.set(key, vcard.to_h)
226
- puts "šŸ“ Saved to file: #{key}"
227
- end
228
-
229
- puts "šŸ“Š Total files: #{store.size}"
230
-
231
- # Demonstrate file persistence
232
- puts "šŸ’½ Files are persisted in: demo/data/vcards/"
233
-
234
- # Retrieve by organized key
235
- key = "contact_1_doe"
236
- return unless store.exists?(key)
237
-
238
- retrieved = store.get(key)
239
- puts "šŸ” Retrieved from file: #{retrieved["fn"]}"
240
- end
241
-
242
- def demonstrate_sqlite_store
243
- puts "\nšŸ—„ļø SQLite Store Demo"
244
- puts "-" * 30
245
-
246
- store = @stores[:sqlite]
247
-
248
- # Store with email-based keys for easy lookup
249
- @sample_vcards.each do |vcard|
250
- email_key = vcard.primary_email.split("@").first
251
- store.set(email_key, vcard.to_h)
252
- puts "šŸ—ƒļø Stored in DB: #{email_key} -> #{vcard.fn}"
253
- end
254
-
255
- puts "šŸ“Š Total DB records: #{store.size}"
256
-
257
- # Demonstrate database persistence
258
- puts "šŸ’¾ Data persisted in: demo/data/vcards.db"
259
-
260
- # Retrieve by email key
261
- retrieved = store.get("john.doe")
262
- puts "šŸ” Retrieved from DB: #{retrieved["fn"]}" if retrieved
263
- end
264
-
265
- def demonstrate_cache_store
266
- puts "\n⚔ Cache Store Demo"
267
- puts "-" * 30
268
-
269
- cache = @stores[:cache]
270
-
271
- # Cache frequently accessed vCards
272
- @sample_vcards.first(5).each do |vcard|
273
- cache.set(vcard.uid, vcard.to_h, ttl: 60) # 1 minute TTL
274
- puts "⚔ Cached: #{vcard.fn} (TTL: 60s)"
275
- end
276
-
277
- # Demonstrate cache operations
278
- first_uid = @sample_vcards.first.uid
279
- puts "šŸ” Cache hit: #{cache.get(first_uid)["fn"]}"
280
- puts "ā±ļø TTL remaining: #{cache.ttl(first_uid).round(2)}s"
281
-
282
- # Cache statistics
283
- info = cache.cache_info
284
- puts "šŸ“Š Cache stats: #{info[:valid_entries]} valid, #{info[:expired_entries]} expired"
285
- end
286
-
287
- def demonstrate_search_capabilities
288
- puts "\nšŸ” Search & Retrieval Demo"
289
- puts "-" * 30
290
-
291
- # Search across different stores
292
- puts "šŸ¢ Finding contacts by organization:"
293
- find_by_organization("Tech Corp")
294
-
295
- puts "\nšŸ“§ Finding contacts by email domain:"
296
- find_by_email_domain("example.com")
297
-
298
- puts "\nšŸŽ‚ Finding contacts by birth year:"
299
- find_by_birth_year(1985)
300
-
301
- # Display contacts in a formatted table
302
- puts "\nšŸ“‹ Contact Directory (Table View)"
303
- puts "-" * 40
304
- display_contacts_table
305
-
306
- # Demonstrate ID-based search
307
- puts "\nšŸ†” Search by ID Demo"
308
- puts "-" * 25
309
- first_uid = @sample_vcards.first.uid
310
- colored_search_by_id(first_uid)
311
- end
312
-
313
- def find_by_organization(org_name)
314
- found = 0
315
- @stores[:memory].each_key do |key|
316
- vcard_data = @stores[:memory].get(key)
317
- if vcard_data["org"] == org_name
318
- puts " šŸ‘¤ #{vcard_data["fn"]} - #{vcard_data["org"]}"
319
- found += 1
320
- end
321
- end
322
- puts " šŸ“Š Found #{found} contacts in #{org_name}" if found.positive?
323
- end
324
-
325
- def find_by_email_domain(domain)
326
- @stores[:filesystem].each_key do |key|
327
- vcard_data = @stores[:filesystem].get(key)
328
- emails = vcard_data["email"] || []
329
- puts " šŸ“§ #{vcard_data["fn"]} - #{emails.first}" if emails.any? { |email| email.include?(domain) }
330
- end
331
- end
332
-
333
- def find_by_birth_year(year)
334
- @stores[:sqlite].each_key do |key|
335
- vcard_data = @stores[:sqlite].get(key)
336
- puts " šŸŽ‚ #{vcard_data["fn"]} - born in #{year}" if vcard_data.dig("bday", "value")&.start_with?(year.to_s)
337
- end
338
- end
339
-
340
- def demonstrate_integrity_features
341
- puts "\nšŸ”’ Data Integrity Demo"
342
- puts "-" * 30
343
-
344
- # Create a store with integrity checking
345
- integrity_store = Lutaml::Store::Store.new(
346
- adapter: { type: :memory },
347
- integrity: { enabled: true, algorithm: :sha256 }
348
- )
349
-
350
- # Store a vCard with integrity checking
351
- vcard = @sample_vcards.first
352
- integrity_store.set(vcard.uid, vcard.to_h)
353
- puts "šŸ” Stored with integrity check: #{vcard.fn}"
354
-
355
- # Verify integrity
356
- puts "āœ… Integrity verified for: #{vcard.fn}" if integrity_store.exists?(vcard.uid)
357
-
358
- # Demonstrate compression
359
- compressed_store = Lutaml::Store::Store.new(
360
- adapter: { type: :memory },
361
- compression: { enabled: true, algorithm: :gzip }
362
- )
363
-
364
- compressed_store.set(vcard.uid, vcard.to_h)
365
- puts "šŸ—œļø Stored with compression: #{vcard.fn}"
366
- end
367
-
368
- # Display contacts in a formatted table using table_tennis
369
- def display_contacts_table
370
- # Prepare data for the table (without colors for table_tennis)
371
- table_data = []
372
-
373
- # Header row (plain text for table_tennis)
374
- table_data << %w[Name Organization Email Phone Birthday]
375
-
376
- # Data rows from memory store
377
- @stores[:memory].keys.first(5).each do |key|
378
- vcard_data = @stores[:memory].get(key)
379
- emails = vcard_data["email"] || []
380
- tel_data = vcard_data["tel"] || []
381
- phone = tel_data.first&.dig("value") || "N/A"
382
- birthday = vcard_data.dig("bday", "value") || "N/A"
383
-
384
- table_data << [
385
- vcard_data["fn"],
386
- vcard_data["org"] || "N/A",
387
- emails.first || "N/A",
388
- phone,
389
- birthday
390
- ]
391
- end
392
-
393
- # Create and display the table
394
- table = TableTennis::Table.new(table_data)
395
- puts table
396
-
397
- # Show the saved files
398
- puts "\nšŸ“ Saved Files in Filesystem Store"
399
- puts "-" * 40
400
- show_saved_files
401
-
402
- # Display individual contact cards
403
- puts "\nšŸŽØ Individual Contact Cards"
404
- puts "-" * 40
405
- @sample_vcards.first(3).each do |vcard|
406
- display_colored_vcard(vcard)
407
- puts
408
- end
409
- end
410
-
411
- # Show the actual saved files and their contents
412
- def show_saved_files
413
- data_dir = "demo/data/vcards"
414
- puts "šŸ“‚ Directory: #{File.expand_path(data_dir)}"
415
-
416
- if Dir.exist?(data_dir)
417
- # Look for .data files specifically
418
- files = Dir.glob("#{data_dir}/**/*.data").first(3)
419
- files.each do |file|
420
- puts "\nšŸ“„ File: #{File.basename(file)}"
421
- puts " Path: #{file}"
422
- puts " Content preview:"
423
- if File.file?(file)
424
- content = File.read(file)
425
- # Show first few lines of YAML content
426
- lines = content.lines.first(8)
427
- lines.each { |line| puts " #{line.chomp}" }
428
- puts " ..." if content.lines.length > 8
429
- else
430
- puts " āŒ Not a regular file"
431
- end
432
- end
433
-
434
- # Also show directory structure
435
- puts "\nšŸ“ Directory Structure:"
436
- Dir.glob("#{data_dir}/**/*").first(10).each do |path|
437
- relative_path = path.sub("#{data_dir}/", "")
438
- if File.directory?(path)
439
- puts " šŸ“ #{relative_path}/"
440
- else
441
- puts " šŸ“„ #{relative_path}"
442
- end
443
- end
444
- else
445
- puts "āŒ Directory not found: #{data_dir}"
446
- end
447
- end
448
-
449
- # Display a single vCard with colors and formatting
450
- def display_colored_vcard(vcard)
451
- puts Paint["ā•”#{"═" * 50}ā•—", :blue, :bold]
452
- puts Paint["ā•‘", :blue, :bold] + Paint[" #{vcard.fn.center(48)} ", :white, :bold] + Paint["ā•‘", :blue, :bold]
453
- puts Paint["ā• #{"═" * 50}ā•£", :blue, :bold]
454
-
455
- # Name details
456
- if vcard.n.prefix
457
- puts Paint["ā•‘", :blue,
458
- :bold] + Paint[" Title: ", :cyan,
459
- :bold] + Paint["#{vcard.n.prefix.ljust(41)} ", :white] + Paint["ā•‘", :blue, :bold]
460
- end
461
-
462
- puts Paint["ā•‘", :blue,
463
- :bold] + Paint[" Given: ", :cyan,
464
- :bold] + Paint["#{vcard.n.given.ljust(40)} ", :white] + Paint["ā•‘", :blue, :bold]
465
- puts Paint["ā•‘", :blue,
466
- :bold] + Paint[" Family: ", :cyan,
467
- :bold] + Paint["#{vcard.n.family.ljust(39)} ", :white] + Paint["ā•‘", :blue, :bold]
468
-
469
- # Organization
470
- puts Paint["ā•‘", :blue,
471
- :bold] + Paint[" Organization: ", :green,
472
- :bold] + Paint["#{vcard.org.ljust(33)} ", :green] + Paint["ā•‘", :blue, :bold]
473
-
474
- # Contact info
475
- puts Paint["ā•‘", :blue,
476
- :bold] + Paint[" Email: ", :yellow,
477
- :bold] + Paint["#{vcard.primary_email.ljust(39)} ",
478
- :yellow] + Paint["ā•‘", :blue, :bold]
479
-
480
- if vcard.tel && !vcard.tel.empty?
481
- tel = vcard.tel.first
482
- phone_info = "#{tel.value} (#{tel.type})"
483
- puts Paint["ā•‘", :blue,
484
- :bold] + Paint[" Phone: ", :magenta,
485
- :bold] + Paint["#{phone_info.ljust(39)} ", :magenta] + Paint["ā•‘", :blue, :bold]
486
- end
487
-
488
- # Birthday
489
- if vcard.bday
490
- puts Paint["ā•‘", :blue,
491
- :bold] + Paint[" Birthday: ", :cyan,
492
- :bold] + Paint["#{vcard.bday.value.ljust(37)} ", :cyan] + Paint["ā•‘", :blue, :bold]
493
- end
494
-
495
- # UID
496
- puts Paint["ā•‘", :blue,
497
- :bold] + Paint[" UID: ", :red,
498
- :bold] + Paint["#{vcard.uid[0..41]}... ", :red] + Paint["ā•‘", :blue, :bold]
499
-
500
- puts Paint["ā•š#{"═" * 50}ā•", :blue, :bold]
501
- end
502
-
503
- # Enhanced search with colored output
504
- def colored_search_by_id(uid)
505
- puts Paint["\nšŸ” Searching for UID: #{uid}", :yellow, :bold]
506
-
507
- @stores.each do |store_name, store|
508
- next unless store.exists?(uid)
509
-
510
- vcard_data = store.get(uid)
511
- puts Paint["āœ… Found in #{store_name} store:", :green, :bold]
512
- puts Paint[" Name: #{vcard_data["fn"]}", :white]
513
- puts Paint[" Organization: #{vcard_data["org"]}", :green]
514
- return vcard_data
515
- end
516
-
517
- puts Paint["āŒ Not found in any store", :red, :bold]
518
- nil
519
- end
520
- end
521
-
522
- # Run the demo
523
- if __FILE__ == $PROGRAM_NAME
524
- demo = VCardStoreDemo.new
525
- demo.run
526
- end
data/lutaml-store.gemspec DELETED
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "lib/lutaml/store/version"
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = "lutaml-store"
7
- spec.version = Lutaml::Store::VERSION
8
- spec.authors = ["Ronald Tse"]
9
- spec.email = ["ronald.tse@ribose.com"]
10
-
11
- spec.summary = "Store-centric database-style API for Lutaml::Model with multi-backend persistence."
12
- spec.description = <<~DESCRIPTION
13
- Provides a unified store interface for Lutaml::Model objects with model registry,
14
- polymorphic support, composite relationships, and multiple storage backends
15
- (memory, filesystem, SQLite).
16
- DESCRIPTION
17
-
18
- spec.homepage = "https://github.com/lutaml/lutaml-store"
19
- spec.license = "BSD-2-Clause"
20
-
21
- spec.bindir = "exe"
22
- spec.require_paths = ["lib"]
23
- spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
24
-
25
- spec.files = Dir.chdir(File.expand_path(__dir__)) do
26
- `git ls-files -z`.split("\x0").reject do |f|
27
- f.match(%r{^(test|features)/})
28
- end
29
- end
30
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
-
32
- spec.add_dependency "lutaml-model", "~> 0.8.15"
33
- spec.add_dependency "rubyzip", "~> 2.3"
34
-
35
- spec.metadata["rubygems_mfa_required"] = "true"
36
- end