Add the experience service with sites through analytics/AI hooks, migrations through 0011, and phase docs/manifests marking the track complete. Co-authored-by: Cursor <cursoragent@cursor.com>
323 lines
8.3 KiB
Python
323 lines
8.3 KiB
Python
"""Publishing / SEO / PWA DTOs — Phase 11.7."""
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
from uuid import UUID
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field
|
|
|
|
from app.models.types import (
|
|
DomainEdgeStatus,
|
|
PublishReleaseStatus,
|
|
PublishTarget,
|
|
PwaStatus,
|
|
RobotsStatus,
|
|
SeoStatus,
|
|
SeoTarget,
|
|
SitemapStatus,
|
|
)
|
|
from app.schemas.common import ORMBase
|
|
|
|
_FORBID = ConfigDict(extra="forbid")
|
|
|
|
|
|
class PublishReleaseCreate(BaseModel):
|
|
model_config = _FORBID
|
|
|
|
workspace_id: UUID
|
|
target_type: PublishTarget
|
|
target_id: UUID
|
|
notes: str | None = None
|
|
metadata_json: dict | None = None
|
|
|
|
|
|
class PublishReleaseUpdate(BaseModel):
|
|
model_config = _FORBID
|
|
|
|
status: PublishReleaseStatus | None = None
|
|
notes: str | None = None
|
|
error_message: str | None = None
|
|
metadata_json: dict | None = None
|
|
version: int = Field(ge=1)
|
|
|
|
|
|
class PublishReleaseRead(ORMBase):
|
|
id: UUID
|
|
tenant_id: UUID
|
|
workspace_id: UUID
|
|
target_type: PublishTarget
|
|
target_id: UUID
|
|
status: PublishReleaseStatus
|
|
notes: str | None
|
|
error_message: str | None
|
|
completed_at: datetime | None
|
|
metadata_json: dict | None
|
|
version: int
|
|
is_deleted: bool
|
|
created_by: str | None
|
|
updated_by: str | None
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
|
|
class PublishReleaseListResponse(BaseModel):
|
|
items: list[PublishReleaseRead]
|
|
total: int
|
|
page: int
|
|
page_size: int
|
|
|
|
|
|
class DomainEdgeBindingCreate(BaseModel):
|
|
model_config = _FORBID
|
|
|
|
workspace_id: UUID
|
|
site_id: UUID
|
|
site_domain_id: UUID
|
|
dns_status_ref: str | None = Field(default=None, max_length=255)
|
|
ssl_cert_ref: str | None = Field(default=None, max_length=255)
|
|
edge_map_ref: str | None = Field(default=None, max_length=255)
|
|
status: DomainEdgeStatus = DomainEdgeStatus.PENDING
|
|
metadata_json: dict | None = None
|
|
|
|
|
|
class DomainEdgeBindingUpdate(BaseModel):
|
|
model_config = _FORBID
|
|
|
|
status: DomainEdgeStatus | None = None
|
|
dns_status_ref: str | None = Field(default=None, max_length=255)
|
|
ssl_cert_ref: str | None = Field(default=None, max_length=255)
|
|
edge_map_ref: str | None = Field(default=None, max_length=255)
|
|
metadata_json: dict | None = None
|
|
version: int = Field(ge=1)
|
|
|
|
|
|
class DomainEdgeBindingRead(ORMBase):
|
|
id: UUID
|
|
tenant_id: UUID
|
|
workspace_id: UUID
|
|
site_id: UUID
|
|
site_domain_id: UUID
|
|
host: str
|
|
status: DomainEdgeStatus
|
|
dns_status_ref: str | None
|
|
ssl_cert_ref: str | None
|
|
edge_map_ref: str | None
|
|
metadata_json: dict | None
|
|
version: int
|
|
is_deleted: bool
|
|
created_by: str | None
|
|
updated_by: str | None
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
|
|
class DomainEdgeBindingListResponse(BaseModel):
|
|
items: list[DomainEdgeBindingRead]
|
|
total: int
|
|
page: int
|
|
page_size: int
|
|
|
|
|
|
class SeoMetadataUpsert(BaseModel):
|
|
model_config = _FORBID
|
|
|
|
workspace_id: UUID
|
|
target_type: SeoTarget
|
|
target_id: UUID
|
|
status: SeoStatus = SeoStatus.DRAFT
|
|
title: str | None = Field(default=None, max_length=255)
|
|
description: str | None = None
|
|
canonical_url: str | None = Field(default=None, max_length=500)
|
|
robots_directive: str | None = Field(default=None, max_length=100)
|
|
og_json: dict | None = None
|
|
metadata_json: dict | None = None
|
|
version: int | None = Field(default=None, ge=1)
|
|
|
|
|
|
class SeoMetadataUpdate(BaseModel):
|
|
model_config = _FORBID
|
|
|
|
status: SeoStatus | None = None
|
|
title: str | None = Field(default=None, max_length=255)
|
|
description: str | None = None
|
|
canonical_url: str | None = Field(default=None, max_length=500)
|
|
robots_directive: str | None = Field(default=None, max_length=100)
|
|
og_json: dict | None = None
|
|
metadata_json: dict | None = None
|
|
version: int = Field(ge=1)
|
|
|
|
|
|
class SeoMetadataRead(ORMBase):
|
|
id: UUID
|
|
tenant_id: UUID
|
|
workspace_id: UUID
|
|
target_type: SeoTarget
|
|
target_id: UUID
|
|
status: SeoStatus
|
|
title: str | None
|
|
description: str | None
|
|
canonical_url: str | None
|
|
robots_directive: str | None
|
|
og_json: dict | None
|
|
metadata_json: dict | None
|
|
version: int
|
|
is_deleted: bool
|
|
created_by: str | None
|
|
updated_by: str | None
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
|
|
class SeoMetadataListResponse(BaseModel):
|
|
items: list[SeoMetadataRead]
|
|
total: int
|
|
page: int
|
|
page_size: int
|
|
|
|
|
|
class SitemapShellUpsert(BaseModel):
|
|
model_config = _FORBID
|
|
|
|
workspace_id: UUID
|
|
site_id: UUID
|
|
status: SitemapStatus = SitemapStatus.DRAFT
|
|
entries_json: dict | None = None
|
|
storage_file_ref: str | None = Field(default=None, max_length=255)
|
|
metadata_json: dict | None = None
|
|
version: int | None = Field(default=None, ge=1)
|
|
|
|
|
|
class SitemapShellUpdate(BaseModel):
|
|
model_config = _FORBID
|
|
|
|
status: SitemapStatus | None = None
|
|
entries_json: dict | None = None
|
|
storage_file_ref: str | None = Field(default=None, max_length=255)
|
|
metadata_json: dict | None = None
|
|
version: int = Field(ge=1)
|
|
|
|
|
|
class SitemapShellRead(ORMBase):
|
|
id: UUID
|
|
tenant_id: UUID
|
|
workspace_id: UUID
|
|
site_id: UUID
|
|
status: SitemapStatus
|
|
entries_json: dict | None
|
|
storage_file_ref: str | None
|
|
metadata_json: dict | None
|
|
version: int
|
|
is_deleted: bool
|
|
created_by: str | None
|
|
updated_by: str | None
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
|
|
class SitemapShellListResponse(BaseModel):
|
|
items: list[SitemapShellRead]
|
|
total: int
|
|
page: int
|
|
page_size: int
|
|
|
|
|
|
class RobotsShellUpsert(BaseModel):
|
|
model_config = _FORBID
|
|
|
|
workspace_id: UUID
|
|
site_id: UUID
|
|
status: RobotsStatus = RobotsStatus.DRAFT
|
|
content_text: str | None = None
|
|
rules_json: dict | None = None
|
|
metadata_json: dict | None = None
|
|
version: int | None = Field(default=None, ge=1)
|
|
|
|
|
|
class RobotsShellUpdate(BaseModel):
|
|
model_config = _FORBID
|
|
|
|
status: RobotsStatus | None = None
|
|
content_text: str | None = None
|
|
rules_json: dict | None = None
|
|
metadata_json: dict | None = None
|
|
version: int = Field(ge=1)
|
|
|
|
|
|
class RobotsShellRead(ORMBase):
|
|
id: UUID
|
|
tenant_id: UUID
|
|
workspace_id: UUID
|
|
site_id: UUID
|
|
status: RobotsStatus
|
|
content_text: str | None
|
|
rules_json: dict | None
|
|
metadata_json: dict | None
|
|
version: int
|
|
is_deleted: bool
|
|
created_by: str | None
|
|
updated_by: str | None
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
|
|
class RobotsShellListResponse(BaseModel):
|
|
items: list[RobotsShellRead]
|
|
total: int
|
|
page: int
|
|
page_size: int
|
|
|
|
|
|
class PwaManifestUpsert(BaseModel):
|
|
model_config = _FORBID
|
|
|
|
workspace_id: UUID
|
|
site_id: UUID
|
|
status: PwaStatus = PwaStatus.DRAFT
|
|
name: str | None = Field(default=None, max_length=255)
|
|
short_name: str | None = Field(default=None, max_length=100)
|
|
start_url: str | None = Field(default=None, max_length=500)
|
|
manifest_json: dict | None = None
|
|
service_worker_ref: str | None = Field(default=None, max_length=255)
|
|
metadata_json: dict | None = None
|
|
version: int | None = Field(default=None, ge=1)
|
|
|
|
|
|
class PwaManifestUpdate(BaseModel):
|
|
model_config = _FORBID
|
|
|
|
status: PwaStatus | None = None
|
|
name: str | None = Field(default=None, max_length=255)
|
|
short_name: str | None = Field(default=None, max_length=100)
|
|
start_url: str | None = Field(default=None, max_length=500)
|
|
manifest_json: dict | None = None
|
|
service_worker_ref: str | None = Field(default=None, max_length=255)
|
|
metadata_json: dict | None = None
|
|
version: int = Field(ge=1)
|
|
|
|
|
|
class PwaManifestRead(ORMBase):
|
|
id: UUID
|
|
tenant_id: UUID
|
|
workspace_id: UUID
|
|
site_id: UUID
|
|
status: PwaStatus
|
|
name: str | None
|
|
short_name: str | None
|
|
start_url: str | None
|
|
manifest_json: dict | None
|
|
service_worker_ref: str | None
|
|
metadata_json: dict | None
|
|
version: int
|
|
is_deleted: bool
|
|
created_by: str | None
|
|
updated_by: str | None
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
|
|
class PwaManifestListResponse(BaseModel):
|
|
items: list[PwaManifestRead]
|
|
total: int
|
|
page: int
|
|
page_size: int
|