|
16 | 16 | EndpointCreateResponse, |
17 | 17 | EndpointDetailResponse, |
18 | 18 | EndpointListItem, |
| 19 | + MarketplaceAvailabilityResult, |
19 | 20 | MessageResponse, |
20 | 21 | ProviderInfo, |
21 | 22 | PublishEndpointResponse, |
22 | 23 | PublishResult, |
23 | 24 | QueryEndpointResponse, |
24 | 25 | ReferencesResponse, |
| 26 | + SlugAvailabilityResponse, |
25 | 27 | SummaryResponse, |
26 | 28 | TokenUsage, |
27 | 29 | ) |
@@ -607,7 +609,7 @@ def _publish_to_marketplace( |
607 | 609 | } |
608 | 610 | ], |
609 | 611 | } |
610 | | - client.publish_endpoint(payload) |
| 612 | + client.publish_endpoint(payload, overwrite=True) |
611 | 613 |
|
612 | 614 | except SyftHubError as e: |
613 | 615 | return PublishResult( |
@@ -636,3 +638,132 @@ def _publish_to_marketplace( |
636 | 638 | success=False, |
637 | 639 | error=str(e), |
638 | 640 | ) |
| 641 | + |
| 642 | + def check_slug_availability( |
| 643 | + self, |
| 644 | + slug: str, |
| 645 | + marketplace_ids: list[UUID] | None, |
| 646 | + check_all_marketplaces: bool, |
| 647 | + tenant: Tenant, |
| 648 | + ) -> SlugAvailabilityResponse: |
| 649 | + """Check if a slug is available locally and optionally on marketplaces. |
| 650 | +
|
| 651 | + Args: |
| 652 | + slug: Slug to check |
| 653 | + marketplace_ids: Optional list of marketplace IDs to check |
| 654 | + check_all_marketplaces: If True, check all active marketplaces (takes precedence) |
| 655 | + tenant: Tenant context |
| 656 | +
|
| 657 | + Returns: |
| 658 | + Availability status for local and each requested marketplace |
| 659 | + """ |
| 660 | + # Check local availability |
| 661 | + existing_endpoint = self.endpoint_repository.get_by_slug(slug, tenant.id) |
| 662 | + local_available = existing_endpoint is None |
| 663 | + |
| 664 | + # Determine if we need to check marketplaces |
| 665 | + should_check_marketplaces = check_all_marketplaces or marketplace_ids |
| 666 | + |
| 667 | + # If no marketplace check needed, return local-only result |
| 668 | + if not should_check_marketplaces: |
| 669 | + return SlugAvailabilityResponse( |
| 670 | + slug=slug, |
| 671 | + local_available=local_available, |
| 672 | + marketplaces=None, |
| 673 | + ) |
| 674 | + |
| 675 | + # Check marketplace availability |
| 676 | + if not self.marketplace_repository: |
| 677 | + raise HTTPException( |
| 678 | + status_code=500, |
| 679 | + detail="Marketplace checking is not configured", |
| 680 | + ) |
| 681 | + |
| 682 | + # Get marketplaces to check |
| 683 | + if check_all_marketplaces: |
| 684 | + # Get all active marketplaces (flag takes precedence) |
| 685 | + marketplaces = self.marketplace_repository.get_active(tenant.id) |
| 686 | + missing_ids: set[UUID] = set() |
| 687 | + else: |
| 688 | + # Get specific marketplaces by IDs |
| 689 | + marketplaces = self.marketplace_repository.get_by_ids( |
| 690 | + marketplace_ids, tenant.id |
| 691 | + ) |
| 692 | + found_ids = {m.id for m in marketplaces} |
| 693 | + missing_ids = set(marketplace_ids) - found_ids |
| 694 | + |
| 695 | + # Build results for each requested marketplace |
| 696 | + marketplace_results: list[MarketplaceAvailabilityResult] = [] |
| 697 | + |
| 698 | + # Add results for missing marketplaces (only when using marketplace_ids) |
| 699 | + for missing_id in missing_ids: |
| 700 | + marketplace_results.append( |
| 701 | + MarketplaceAvailabilityResult( |
| 702 | + marketplace_id=missing_id, |
| 703 | + available=None, |
| 704 | + error="Marketplace not found", |
| 705 | + ) |
| 706 | + ) |
| 707 | + |
| 708 | + # Check each found marketplace |
| 709 | + for marketplace in marketplaces: |
| 710 | + result = self._check_marketplace_availability(slug, marketplace) |
| 711 | + marketplace_results.append(result) |
| 712 | + |
| 713 | + return SlugAvailabilityResponse( |
| 714 | + slug=slug, |
| 715 | + local_available=local_available, |
| 716 | + marketplaces=marketplace_results, |
| 717 | + ) |
| 718 | + |
| 719 | + def _check_marketplace_availability( |
| 720 | + self, |
| 721 | + slug: str, |
| 722 | + marketplace: Marketplace, |
| 723 | + ) -> MarketplaceAvailabilityResult: |
| 724 | + """Check if a slug is available on a specific marketplace. |
| 725 | +
|
| 726 | + Args: |
| 727 | + slug: Slug to check |
| 728 | + marketplace: Marketplace to check on |
| 729 | +
|
| 730 | + Returns: |
| 731 | + Availability result for the marketplace |
| 732 | + """ |
| 733 | + # Validate marketplace is active |
| 734 | + if not marketplace.is_active: |
| 735 | + return MarketplaceAvailabilityResult( |
| 736 | + marketplace_id=marketplace.id, |
| 737 | + available=None, |
| 738 | + error="Marketplace is not active", |
| 739 | + ) |
| 740 | + |
| 741 | + # Validate marketplace has credentials |
| 742 | + if not marketplace.email or not marketplace.password: |
| 743 | + return MarketplaceAvailabilityResult( |
| 744 | + marketplace_id=marketplace.id, |
| 745 | + available=None, |
| 746 | + error="Marketplace credentials not configured", |
| 747 | + ) |
| 748 | + |
| 749 | + try: |
| 750 | + with SyftHubClient(base_url=marketplace.url) as client: |
| 751 | + client.login(username=marketplace.email, password=marketplace.password) |
| 752 | + exists = client.endpoint_exists(slug) |
| 753 | + return MarketplaceAvailabilityResult( |
| 754 | + marketplace_id=marketplace.id, |
| 755 | + available=not exists, |
| 756 | + error=None, |
| 757 | + ) |
| 758 | + except SyftHubError as e: |
| 759 | + return MarketplaceAvailabilityResult( |
| 760 | + marketplace_id=marketplace.id, |
| 761 | + available=None, |
| 762 | + error=e.message, |
| 763 | + ) |
| 764 | + except Exception as e: |
| 765 | + return MarketplaceAvailabilityResult( |
| 766 | + marketplace_id=marketplace.id, |
| 767 | + available=None, |
| 768 | + error=str(e), |
| 769 | + ) |
0 commit comments