unitysvc-services 0.1.1__py3-none-any.whl → 0.2.0__py3-none-any.whl
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.
- unitysvc_services/format_data.py +2 -7
- unitysvc_services/list.py +14 -43
- unitysvc_services/models/base.py +34 -102
- unitysvc_services/models/listing_v1.py +3 -9
- unitysvc_services/models/provider_v1.py +2 -6
- unitysvc_services/models/seller_v1.py +2 -6
- unitysvc_services/populate.py +2 -6
- unitysvc_services/publisher.py +237 -162
- unitysvc_services/query.py +22 -120
- unitysvc_services/update.py +4 -13
- unitysvc_services/utils.py +2 -6
- unitysvc_services/validator.py +19 -56
- {unitysvc_services-0.1.1.dist-info → unitysvc_services-0.2.0.dist-info}/METADATA +37 -38
- unitysvc_services-0.2.0.dist-info/RECORD +23 -0
- unitysvc_services-0.1.1.dist-info/RECORD +0 -23
- {unitysvc_services-0.1.1.dist-info → unitysvc_services-0.2.0.dist-info}/WHEEL +0 -0
- {unitysvc_services-0.1.1.dist-info → unitysvc_services-0.2.0.dist-info}/entry_points.txt +0 -0
- {unitysvc_services-0.1.1.dist-info → unitysvc_services-0.2.0.dist-info}/licenses/LICENSE +0 -0
- {unitysvc_services-0.1.1.dist-info → unitysvc_services-0.2.0.dist-info}/top_level.txt +0 -0
unitysvc_services/publisher.py
CHANGED
@@ -57,9 +57,7 @@ class ServiceDataPublisher:
|
|
57
57
|
with open(full_path, "rb") as f:
|
58
58
|
return base64.b64encode(f.read()).decode("ascii")
|
59
59
|
|
60
|
-
def resolve_file_references(
|
61
|
-
self, data: dict[str, Any], base_path: Path
|
62
|
-
) -> dict[str, Any]:
|
60
|
+
def resolve_file_references(self, data: dict[str, Any], base_path: Path) -> dict[str, Any]:
|
63
61
|
"""Recursively resolve file references and include content in data."""
|
64
62
|
result: dict[str, Any] = {}
|
65
63
|
|
@@ -70,11 +68,7 @@ class ServiceDataPublisher:
|
|
70
68
|
elif isinstance(value, list):
|
71
69
|
# Process lists
|
72
70
|
result[key] = [
|
73
|
-
(
|
74
|
-
self.resolve_file_references(item, base_path)
|
75
|
-
if isinstance(item, dict)
|
76
|
-
else item
|
77
|
-
)
|
71
|
+
(self.resolve_file_references(item, base_path) if isinstance(item, dict) else item)
|
78
72
|
for item in value
|
79
73
|
]
|
80
74
|
elif key == "file_path" and isinstance(value, str):
|
@@ -87,9 +81,7 @@ class ServiceDataPublisher:
|
|
87
81
|
content = self.load_file_content(Path(value), base_path)
|
88
82
|
result["file_content"] = content
|
89
83
|
except Exception as e:
|
90
|
-
raise ValueError(
|
91
|
-
f"Failed to load file content from '{value}': {e}"
|
92
|
-
)
|
84
|
+
raise ValueError(f"Failed to load file content from '{value}': {e}")
|
93
85
|
else:
|
94
86
|
result[key] = value
|
95
87
|
|
@@ -172,10 +164,7 @@ class ServiceDataPublisher:
|
|
172
164
|
)
|
173
165
|
|
174
166
|
# If service_name is not in listing data, find it from service files in the same directory
|
175
|
-
if
|
176
|
-
"service_name" not in data_with_content
|
177
|
-
or not data_with_content["service_name"]
|
178
|
-
):
|
167
|
+
if "service_name" not in data_with_content or not data_with_content["service_name"]:
|
179
168
|
# Find all service files in the same directory
|
180
169
|
service_files = find_files_by_schema(data_file.parent, "service_v1")
|
181
170
|
|
@@ -185,9 +174,7 @@ class ServiceDataPublisher:
|
|
185
174
|
f"Listing files must be in the same directory as a service definition."
|
186
175
|
)
|
187
176
|
elif len(service_files) > 1:
|
188
|
-
service_names = [
|
189
|
-
data.get("name", "unknown") for _, _, data in service_files
|
190
|
-
]
|
177
|
+
service_names = [data.get("name", "unknown") for _, _, data in service_files]
|
191
178
|
raise ValueError(
|
192
179
|
f"Multiple services found in {data_file.parent}: {', '.join(service_names)}. "
|
193
180
|
f"Please add 'service_name' field to {data_file.name} to specify which "
|
@@ -201,9 +188,7 @@ class ServiceDataPublisher:
|
|
201
188
|
else:
|
202
189
|
# service_name is provided in listing data, find the matching service to get version
|
203
190
|
service_name = data_with_content["service_name"]
|
204
|
-
service_files = find_files_by_schema(
|
205
|
-
data_file.parent, "service_v1", field_filter=(("name", service_name),)
|
206
|
-
)
|
191
|
+
service_files = find_files_by_schema(data_file.parent, "service_v1", field_filter=(("name", service_name),))
|
207
192
|
|
208
193
|
if not service_files:
|
209
194
|
raise ValueError(
|
@@ -320,9 +305,7 @@ class ServiceDataPublisher:
|
|
320
305
|
|
321
306
|
# Convert convenience fields (logo only for sellers, no terms_of_service)
|
322
307
|
base_path = data_file.parent
|
323
|
-
data = convert_convenience_fields_to_documents(
|
324
|
-
data, base_path, logo_field="logo", terms_field=None
|
325
|
-
)
|
308
|
+
data = convert_convenience_fields_to_documents(data, base_path, logo_field="logo", terms_field=None)
|
326
309
|
|
327
310
|
# Resolve file references and include content
|
328
311
|
data_with_content = self.resolve_file_references(data, base_path)
|
@@ -376,10 +359,7 @@ class ServiceDataPublisher:
|
|
376
359
|
"total": 0,
|
377
360
|
"success": 0,
|
378
361
|
"failed": 0,
|
379
|
-
"errors": [
|
380
|
-
{"file": "validation", "error": error}
|
381
|
-
for error in validation_errors
|
382
|
-
],
|
362
|
+
"errors": [{"file": "validation", "error": error} for error in validation_errors],
|
383
363
|
}
|
384
364
|
|
385
365
|
offering_files = self.find_offering_files(data_dir)
|
@@ -415,10 +395,7 @@ class ServiceDataPublisher:
|
|
415
395
|
"total": 0,
|
416
396
|
"success": 0,
|
417
397
|
"failed": 0,
|
418
|
-
"errors": [
|
419
|
-
{"file": "validation", "error": error}
|
420
|
-
for error in validation_errors
|
421
|
-
],
|
398
|
+
"errors": [{"file": "validation", "error": error} for error in validation_errors],
|
422
399
|
}
|
423
400
|
|
424
401
|
listing_files = self.find_listing_files(data_dir)
|
@@ -487,6 +464,55 @@ class ServiceDataPublisher:
|
|
487
464
|
|
488
465
|
return results
|
489
466
|
|
467
|
+
def publish_all_models(self, data_dir: Path) -> dict[str, Any]:
|
468
|
+
"""
|
469
|
+
Publish all data types in the correct order.
|
470
|
+
|
471
|
+
Publishing order:
|
472
|
+
1. Sellers - Must exist before listings
|
473
|
+
2. Providers - Must exist before offerings
|
474
|
+
3. Service Offerings - Must exist before listings
|
475
|
+
4. Service Listings - Depends on sellers, providers, and offerings
|
476
|
+
|
477
|
+
Returns a dict with results for each data type and overall summary.
|
478
|
+
"""
|
479
|
+
all_results: dict[str, Any] = {
|
480
|
+
"sellers": {},
|
481
|
+
"providers": {},
|
482
|
+
"offerings": {},
|
483
|
+
"listings": {},
|
484
|
+
"total_success": 0,
|
485
|
+
"total_failed": 0,
|
486
|
+
"total_found": 0,
|
487
|
+
}
|
488
|
+
|
489
|
+
# Publish in order: sellers -> providers -> offerings -> listings
|
490
|
+
publish_order = [
|
491
|
+
("sellers", self.publish_all_sellers),
|
492
|
+
("providers", self.publish_all_providers),
|
493
|
+
("offerings", self.publish_all_offerings),
|
494
|
+
("listings", self.publish_all_listings),
|
495
|
+
]
|
496
|
+
|
497
|
+
for data_type, publish_method in publish_order:
|
498
|
+
try:
|
499
|
+
results = publish_method(data_dir)
|
500
|
+
all_results[data_type] = results
|
501
|
+
all_results["total_success"] += results["success"]
|
502
|
+
all_results["total_failed"] += results["failed"]
|
503
|
+
all_results["total_found"] += results["total"]
|
504
|
+
except Exception as e:
|
505
|
+
# If a publish method fails catastrophically, record the error
|
506
|
+
all_results[data_type] = {
|
507
|
+
"total": 0,
|
508
|
+
"success": 0,
|
509
|
+
"failed": 1,
|
510
|
+
"errors": [{"file": "N/A", "error": str(e)}],
|
511
|
+
}
|
512
|
+
all_results["total_failed"] += 1
|
513
|
+
|
514
|
+
return all_results
|
515
|
+
|
490
516
|
def close(self):
|
491
517
|
"""Close the HTTP client."""
|
492
518
|
self.client.close()
|
@@ -505,34 +531,145 @@ app = typer.Typer(help="Publish data to backend")
|
|
505
531
|
console = Console()
|
506
532
|
|
507
533
|
|
508
|
-
@app.
|
509
|
-
def
|
510
|
-
|
511
|
-
|
512
|
-
help="Path to provider file or directory (default: ./data or UNITYSVC_DATA_DIR env var)",
|
513
|
-
),
|
514
|
-
backend_url: str | None = typer.Option(
|
534
|
+
@app.callback(invoke_without_command=True)
|
535
|
+
def publish_callback(
|
536
|
+
ctx: typer.Context,
|
537
|
+
data_path: Path | None = typer.Option(
|
515
538
|
None,
|
516
|
-
"--
|
517
|
-
"-
|
518
|
-
help="
|
539
|
+
"--data-path",
|
540
|
+
"-d",
|
541
|
+
help="Path to data directory (default: current directory)",
|
519
542
|
),
|
520
|
-
|
543
|
+
):
|
544
|
+
"""
|
545
|
+
Publish data to backend.
|
546
|
+
|
547
|
+
When called without a subcommand, publishes all data types in order:
|
548
|
+
sellers → providers → offerings → listings.
|
549
|
+
|
550
|
+
Use subcommands to publish specific data types:
|
551
|
+
- providers: Publish only providers
|
552
|
+
- sellers: Publish only sellers
|
553
|
+
- offerings: Publish only service offerings
|
554
|
+
- listings: Publish only service listings
|
555
|
+
|
556
|
+
Required environment variables:
|
557
|
+
- UNITYSVC_BASE_URL: Backend API URL
|
558
|
+
- UNITYSVC_API_KEY: API key for authentication
|
559
|
+
"""
|
560
|
+
# If a subcommand was invoked, skip this callback logic
|
561
|
+
if ctx.invoked_subcommand is not None:
|
562
|
+
return
|
563
|
+
|
564
|
+
# No subcommand - publish all
|
565
|
+
# Set data path
|
566
|
+
if data_path is None:
|
567
|
+
data_path = Path.cwd()
|
568
|
+
|
569
|
+
if not data_path.is_absolute():
|
570
|
+
data_path = Path.cwd() / data_path
|
571
|
+
|
572
|
+
if not data_path.exists():
|
573
|
+
console.print(f"[red]✗[/red] Path not found: {data_path}", style="bold red")
|
574
|
+
raise typer.Exit(code=1)
|
575
|
+
|
576
|
+
# Get backend URL from environment
|
577
|
+
backend_url = os.getenv("UNITYSVC_BASE_URL")
|
578
|
+
if not backend_url:
|
579
|
+
console.print(
|
580
|
+
"[red]✗[/red] UNITYSVC_BASE_URL environment variable not set.",
|
581
|
+
style="bold red",
|
582
|
+
)
|
583
|
+
raise typer.Exit(code=1)
|
584
|
+
|
585
|
+
# Get API key from environment
|
586
|
+
api_key = os.getenv("UNITYSVC_API_KEY")
|
587
|
+
if not api_key:
|
588
|
+
console.print(
|
589
|
+
"[red]✗[/red] UNITYSVC_API_KEY environment variable not set.",
|
590
|
+
style="bold red",
|
591
|
+
)
|
592
|
+
raise typer.Exit(code=1)
|
593
|
+
|
594
|
+
console.print(f"[bold blue]Publishing all data from:[/bold blue] {data_path}")
|
595
|
+
console.print(f"[bold blue]Backend URL:[/bold blue] {backend_url}\n")
|
596
|
+
|
597
|
+
try:
|
598
|
+
with ServiceDataPublisher(backend_url, api_key) as publisher:
|
599
|
+
# Call the publish_all_models method
|
600
|
+
all_results = publisher.publish_all_models(data_path)
|
601
|
+
|
602
|
+
# Display results for each data type
|
603
|
+
data_type_display_names = {
|
604
|
+
"sellers": "Sellers",
|
605
|
+
"providers": "Providers",
|
606
|
+
"offerings": "Service Offerings",
|
607
|
+
"listings": "Service Listings",
|
608
|
+
}
|
609
|
+
|
610
|
+
for data_type in ["sellers", "providers", "offerings", "listings"]:
|
611
|
+
display_name = data_type_display_names[data_type]
|
612
|
+
results = all_results[data_type]
|
613
|
+
|
614
|
+
console.print(f"\n[bold cyan]{'=' * 60}[/bold cyan]")
|
615
|
+
console.print(f"[bold cyan]{display_name}[/bold cyan]")
|
616
|
+
console.print(f"[bold cyan]{'=' * 60}[/bold cyan]\n")
|
617
|
+
|
618
|
+
console.print(f" Total found: {results['total']}")
|
619
|
+
console.print(f" [green]✓ Success:[/green] {results['success']}")
|
620
|
+
console.print(f" [red]✗ Failed:[/red] {results['failed']}")
|
621
|
+
|
622
|
+
# Display errors if any
|
623
|
+
if results.get("errors"):
|
624
|
+
console.print(f"\n[bold red]Errors in {display_name}:[/bold red]")
|
625
|
+
for error in results["errors"]:
|
626
|
+
# Check if this is a skipped item
|
627
|
+
if isinstance(error, dict) and error.get("error", "").startswith("skipped"):
|
628
|
+
continue
|
629
|
+
console.print(f" [red]✗[/red] {error.get('file', 'unknown')}")
|
630
|
+
console.print(f" {error.get('error', 'unknown error')}")
|
631
|
+
|
632
|
+
# Final summary
|
633
|
+
console.print(f"\n[bold cyan]{'=' * 60}[/bold cyan]")
|
634
|
+
console.print("[bold]Final Publishing Summary[/bold]")
|
635
|
+
console.print(f"[bold cyan]{'=' * 60}[/bold cyan]\n")
|
636
|
+
console.print(f" Total found: {all_results['total_found']}")
|
637
|
+
console.print(f" [green]✓ Success:[/green] {all_results['total_success']}")
|
638
|
+
console.print(f" [red]✗ Failed:[/red] {all_results['total_failed']}")
|
639
|
+
|
640
|
+
if all_results["total_failed"] > 0:
|
641
|
+
console.print(
|
642
|
+
f"\n[yellow]⚠[/yellow] Completed with {all_results['total_failed']} failure(s)",
|
643
|
+
style="bold yellow",
|
644
|
+
)
|
645
|
+
raise typer.Exit(code=1)
|
646
|
+
else:
|
647
|
+
console.print(
|
648
|
+
"\n[green]✓[/green] All data published successfully!",
|
649
|
+
style="bold green",
|
650
|
+
)
|
651
|
+
|
652
|
+
except typer.Exit:
|
653
|
+
raise
|
654
|
+
except Exception as e:
|
655
|
+
console.print(f"[red]✗[/red] Failed to publish all data: {e}", style="bold red")
|
656
|
+
raise typer.Exit(code=1)
|
657
|
+
|
658
|
+
|
659
|
+
@app.command("providers")
|
660
|
+
def publish_providers(
|
661
|
+
data_path: Path | None = typer.Option(
|
521
662
|
None,
|
522
|
-
"--
|
523
|
-
"-
|
524
|
-
help="
|
663
|
+
"--data-path",
|
664
|
+
"-d",
|
665
|
+
help="Path to provider file or directory (default: current directory)",
|
525
666
|
),
|
526
667
|
):
|
527
668
|
"""Publish provider(s) from a file or directory."""
|
528
669
|
|
529
670
|
# Set data path
|
530
671
|
if data_path is None:
|
531
|
-
|
532
|
-
if data_path_str:
|
533
|
-
data_path = Path(data_path_str)
|
534
|
-
else:
|
535
|
-
data_path = Path.cwd() / "data"
|
672
|
+
data_path = Path.cwd()
|
536
673
|
|
537
674
|
if not data_path.is_absolute():
|
538
675
|
data_path = Path.cwd() / data_path
|
@@ -541,20 +678,20 @@ def publish_providers(
|
|
541
678
|
console.print(f"[red]✗[/red] Path not found: {data_path}", style="bold red")
|
542
679
|
raise typer.Exit(code=1)
|
543
680
|
|
544
|
-
# Get backend URL from
|
545
|
-
backend_url =
|
681
|
+
# Get backend URL from environment
|
682
|
+
backend_url = os.getenv("UNITYSVC_BASE_URL")
|
546
683
|
if not backend_url:
|
547
684
|
console.print(
|
548
|
-
"[red]✗[/red]
|
685
|
+
"[red]✗[/red] UNITYSVC_BASE_URL environment variable not set.",
|
549
686
|
style="bold red",
|
550
687
|
)
|
551
688
|
raise typer.Exit(code=1)
|
552
689
|
|
553
|
-
# Get API key from
|
554
|
-
api_key =
|
690
|
+
# Get API key from environment
|
691
|
+
api_key = os.getenv("UNITYSVC_API_KEY")
|
555
692
|
if not api_key:
|
556
693
|
console.print(
|
557
|
-
"[red]✗[/red]
|
694
|
+
"[red]✗[/red] UNITYSVC_API_KEY environment variable not set.",
|
558
695
|
style="bold red",
|
559
696
|
)
|
560
697
|
raise typer.Exit(code=1)
|
@@ -593,39 +730,23 @@ def publish_providers(
|
|
593
730
|
except typer.Exit:
|
594
731
|
raise
|
595
732
|
except Exception as e:
|
596
|
-
console.print(
|
597
|
-
f"[red]✗[/red] Failed to publish providers: {e}", style="bold red"
|
598
|
-
)
|
733
|
+
console.print(f"[red]✗[/red] Failed to publish providers: {e}", style="bold red")
|
599
734
|
raise typer.Exit(code=1)
|
600
735
|
|
601
736
|
|
602
737
|
@app.command("sellers")
|
603
738
|
def publish_sellers(
|
604
|
-
data_path: Path | None = typer.
|
605
|
-
None,
|
606
|
-
help="Path to seller file or directory (default: ./data or UNITYSVC_DATA_DIR env var)",
|
607
|
-
),
|
608
|
-
backend_url: str | None = typer.Option(
|
739
|
+
data_path: Path | None = typer.Option(
|
609
740
|
None,
|
610
|
-
"--
|
611
|
-
"-
|
612
|
-
help="
|
613
|
-
),
|
614
|
-
api_key: str | None = typer.Option(
|
615
|
-
None,
|
616
|
-
"--api-key",
|
617
|
-
"-k",
|
618
|
-
help="API key for authentication (default: from UNITYSVC_API_KEY env var)",
|
741
|
+
"--data-path",
|
742
|
+
"-d",
|
743
|
+
help="Path to seller file or directory (default: current directory)",
|
619
744
|
),
|
620
745
|
):
|
621
746
|
"""Publish seller(s) from a file or directory."""
|
622
747
|
# Set data path
|
623
748
|
if data_path is None:
|
624
|
-
|
625
|
-
if data_path_str:
|
626
|
-
data_path = Path(data_path_str)
|
627
|
-
else:
|
628
|
-
data_path = Path.cwd() / "data"
|
749
|
+
data_path = Path.cwd()
|
629
750
|
|
630
751
|
if not data_path.is_absolute():
|
631
752
|
data_path = Path.cwd() / data_path
|
@@ -634,20 +755,20 @@ def publish_sellers(
|
|
634
755
|
console.print(f"[red]✗[/red] Path not found: {data_path}", style="bold red")
|
635
756
|
raise typer.Exit(code=1)
|
636
757
|
|
637
|
-
# Get backend URL
|
638
|
-
backend_url =
|
758
|
+
# Get backend URL from environment
|
759
|
+
backend_url = os.getenv("UNITYSVC_BASE_URL")
|
639
760
|
if not backend_url:
|
640
761
|
console.print(
|
641
|
-
"[red]✗[/red]
|
762
|
+
"[red]✗[/red] UNITYSVC_BASE_URL environment variable not set.",
|
642
763
|
style="bold red",
|
643
764
|
)
|
644
765
|
raise typer.Exit(code=1)
|
645
766
|
|
646
|
-
# Get API key
|
647
|
-
api_key =
|
767
|
+
# Get API key from environment
|
768
|
+
api_key = os.getenv("UNITYSVC_API_KEY")
|
648
769
|
if not api_key:
|
649
770
|
console.print(
|
650
|
-
"[red]✗[/red]
|
771
|
+
"[red]✗[/red] UNITYSVC_API_KEY environment variable not set.",
|
651
772
|
style="bold red",
|
652
773
|
)
|
653
774
|
raise typer.Exit(code=1)
|
@@ -679,9 +800,7 @@ def publish_sellers(
|
|
679
800
|
console.print(f" {error['error']}")
|
680
801
|
raise typer.Exit(code=1)
|
681
802
|
else:
|
682
|
-
console.print(
|
683
|
-
"\n[green]✓[/green] All sellers published successfully!"
|
684
|
-
)
|
803
|
+
console.print("\n[green]✓[/green] All sellers published successfully!")
|
685
804
|
|
686
805
|
except typer.Exit:
|
687
806
|
raise
|
@@ -692,31 +811,17 @@ def publish_sellers(
|
|
692
811
|
|
693
812
|
@app.command("offerings")
|
694
813
|
def publish_offerings(
|
695
|
-
data_path: Path | None = typer.
|
696
|
-
None,
|
697
|
-
help="Path to service offering file or directory (default: ./data or UNITYSVC_DATA_DIR env var)",
|
698
|
-
),
|
699
|
-
backend_url: str | None = typer.Option(
|
700
|
-
None,
|
701
|
-
"--backend-url",
|
702
|
-
"-u",
|
703
|
-
help="UnitySVC backend URL (default: from UNITYSVC_BACKEND_URL env var)",
|
704
|
-
),
|
705
|
-
api_key: str | None = typer.Option(
|
814
|
+
data_path: Path | None = typer.Option(
|
706
815
|
None,
|
707
|
-
"--
|
708
|
-
"-
|
709
|
-
help="
|
816
|
+
"--data-path",
|
817
|
+
"-d",
|
818
|
+
help="Path to service offering file or directory (default: current directory)",
|
710
819
|
),
|
711
820
|
):
|
712
821
|
"""Publish service offering(s) from a file or directory."""
|
713
822
|
# Set data path
|
714
823
|
if data_path is None:
|
715
|
-
|
716
|
-
if data_path_str:
|
717
|
-
data_path = Path(data_path_str)
|
718
|
-
else:
|
719
|
-
data_path = Path.cwd() / "data"
|
824
|
+
data_path = Path.cwd()
|
720
825
|
|
721
826
|
if not data_path.is_absolute():
|
722
827
|
data_path = Path.cwd() / data_path
|
@@ -725,20 +830,20 @@ def publish_offerings(
|
|
725
830
|
console.print(f"[red]✗[/red] Path not found: {data_path}", style="bold red")
|
726
831
|
raise typer.Exit(code=1)
|
727
832
|
|
728
|
-
# Get backend URL from
|
729
|
-
backend_url =
|
833
|
+
# Get backend URL from environment
|
834
|
+
backend_url = os.getenv("UNITYSVC_BASE_URL")
|
730
835
|
if not backend_url:
|
731
836
|
console.print(
|
732
|
-
"[red]✗[/red]
|
837
|
+
"[red]✗[/red] UNITYSVC_BASE_URL environment variable not set.",
|
733
838
|
style="bold red",
|
734
839
|
)
|
735
840
|
raise typer.Exit(code=1)
|
736
841
|
|
737
|
-
# Get API key from
|
738
|
-
api_key =
|
842
|
+
# Get API key from environment
|
843
|
+
api_key = os.getenv("UNITYSVC_API_KEY")
|
739
844
|
if not api_key:
|
740
845
|
console.print(
|
741
|
-
"[red]✗[/red]
|
846
|
+
"[red]✗[/red] UNITYSVC_API_KEY environment variable not set.",
|
742
847
|
style="bold red",
|
743
848
|
)
|
744
849
|
raise typer.Exit(code=1)
|
@@ -750,15 +855,11 @@ def publish_offerings(
|
|
750
855
|
console.print(f"[blue]Publishing service offering:[/blue] {data_path}")
|
751
856
|
console.print(f"[blue]Backend URL:[/blue] {backend_url}\n")
|
752
857
|
result = publisher.post_service_offering(data_path)
|
753
|
-
console.print(
|
754
|
-
"[green]✓[/green] Service offering published successfully!"
|
755
|
-
)
|
858
|
+
console.print("[green]✓[/green] Service offering published successfully!")
|
756
859
|
console.print(f"[cyan]Response:[/cyan] {json.dumps(result, indent=2)}")
|
757
860
|
# Handle directory
|
758
861
|
else:
|
759
|
-
console.print(
|
760
|
-
f"[blue]Scanning for service offerings in:[/blue] {data_path}"
|
761
|
-
)
|
862
|
+
console.print(f"[blue]Scanning for service offerings in:[/blue] {data_path}")
|
762
863
|
console.print(f"[blue]Backend URL:[/blue] {backend_url}\n")
|
763
864
|
results = publisher.publish_all_offerings(data_path)
|
764
865
|
|
@@ -774,47 +875,29 @@ def publish_offerings(
|
|
774
875
|
console.print(f" {error['error']}")
|
775
876
|
raise typer.Exit(code=1)
|
776
877
|
else:
|
777
|
-
console.print(
|
778
|
-
"\n[green]✓[/green] All service offerings published successfully!"
|
779
|
-
)
|
878
|
+
console.print("\n[green]✓[/green] All service offerings published successfully!")
|
780
879
|
|
781
880
|
except typer.Exit:
|
782
881
|
raise
|
783
882
|
except Exception as e:
|
784
|
-
console.print(
|
785
|
-
f"[red]✗[/red] Failed to publish service offerings: {e}", style="bold red"
|
786
|
-
)
|
883
|
+
console.print(f"[red]✗[/red] Failed to publish service offerings: {e}", style="bold red")
|
787
884
|
raise typer.Exit(code=1)
|
788
885
|
|
789
886
|
|
790
887
|
@app.command("listings")
|
791
888
|
def publish_listings(
|
792
|
-
data_path: Path | None = typer.
|
793
|
-
None,
|
794
|
-
help="Path to service listing file or directory (default: ./data or UNITYSVC_DATA_DIR env var)",
|
795
|
-
),
|
796
|
-
backend_url: str | None = typer.Option(
|
889
|
+
data_path: Path | None = typer.Option(
|
797
890
|
None,
|
798
|
-
"--
|
799
|
-
"-
|
800
|
-
help="
|
801
|
-
),
|
802
|
-
api_key: str | None = typer.Option(
|
803
|
-
None,
|
804
|
-
"--api-key",
|
805
|
-
"-k",
|
806
|
-
help="API key for authentication (default: from UNITYSVC_API_KEY env var)",
|
891
|
+
"--data-path",
|
892
|
+
"-d",
|
893
|
+
help="Path to service listing file or directory (default: current directory)",
|
807
894
|
),
|
808
895
|
):
|
809
896
|
"""Publish service listing(s) from a file or directory."""
|
810
897
|
|
811
898
|
# Set data path
|
812
899
|
if data_path is None:
|
813
|
-
|
814
|
-
if data_path_str:
|
815
|
-
data_path = Path(data_path_str)
|
816
|
-
else:
|
817
|
-
data_path = Path.cwd() / "data"
|
900
|
+
data_path = Path.cwd()
|
818
901
|
|
819
902
|
if not data_path.is_absolute():
|
820
903
|
data_path = Path.cwd() / data_path
|
@@ -823,20 +906,20 @@ def publish_listings(
|
|
823
906
|
console.print(f"[red]✗[/red] Path not found: {data_path}", style="bold red")
|
824
907
|
raise typer.Exit(code=1)
|
825
908
|
|
826
|
-
# Get backend URL from
|
827
|
-
backend_url =
|
909
|
+
# Get backend URL from environment
|
910
|
+
backend_url = os.getenv("UNITYSVC_BASE_URL")
|
828
911
|
if not backend_url:
|
829
912
|
console.print(
|
830
|
-
"[red]✗[/red]
|
913
|
+
"[red]✗[/red] UNITYSVC_BASE_URL environment variable not set.",
|
831
914
|
style="bold red",
|
832
915
|
)
|
833
916
|
raise typer.Exit(code=1)
|
834
917
|
|
835
|
-
# Get API key from
|
836
|
-
api_key =
|
918
|
+
# Get API key from environment
|
919
|
+
api_key = os.getenv("UNITYSVC_API_KEY")
|
837
920
|
if not api_key:
|
838
921
|
console.print(
|
839
|
-
"[red]✗[/red]
|
922
|
+
"[red]✗[/red] UNITYSVC_API_KEY environment variable not set.",
|
840
923
|
style="bold red",
|
841
924
|
)
|
842
925
|
raise typer.Exit(code=1)
|
@@ -848,15 +931,11 @@ def publish_listings(
|
|
848
931
|
console.print(f"[blue]Publishing service listing:[/blue] {data_path}")
|
849
932
|
console.print(f"[blue]Backend URL:[/blue] {backend_url}\n")
|
850
933
|
result = publisher.post_service_listing(data_path)
|
851
|
-
console.print(
|
852
|
-
"[green]✓[/green] Service listing published successfully!"
|
853
|
-
)
|
934
|
+
console.print("[green]✓[/green] Service listing published successfully!")
|
854
935
|
console.print(f"[cyan]Response:[/cyan] {json.dumps(result, indent=2)}")
|
855
936
|
# Handle directory
|
856
937
|
else:
|
857
|
-
console.print(
|
858
|
-
f"[blue]Scanning for service listings in:[/blue] {data_path}"
|
859
|
-
)
|
938
|
+
console.print(f"[blue]Scanning for service listings in:[/blue] {data_path}")
|
860
939
|
console.print(f"[blue]Backend URL:[/blue] {backend_url}\n")
|
861
940
|
results = publisher.publish_all_listings(data_path)
|
862
941
|
|
@@ -872,14 +951,10 @@ def publish_listings(
|
|
872
951
|
console.print(f" {error['error']}")
|
873
952
|
raise typer.Exit(code=1)
|
874
953
|
else:
|
875
|
-
console.print(
|
876
|
-
"\n[green]✓[/green] All service listings published successfully!"
|
877
|
-
)
|
954
|
+
console.print("\n[green]✓[/green] All service listings published successfully!")
|
878
955
|
|
879
956
|
except typer.Exit:
|
880
957
|
raise
|
881
958
|
except Exception as e:
|
882
|
-
console.print(
|
883
|
-
f"[red]✗[/red] Failed to publish service listings: {e}", style="bold red"
|
884
|
-
)
|
959
|
+
console.print(f"[red]✗[/red] Failed to publish service listings: {e}", style="bold red")
|
885
960
|
raise typer.Exit(code=1)
|