This repository has been archived on 2026-02-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
shared/alembic/old_versions/20251028_ghost_content.py
giles 668d9c7df8 feat: initial shared library extraction
Contains shared infrastructure for all coop services:
- shared/ (factory, urls, user_loader, context, internal_api, jinja_setup)
- models/ (User, Order, Calendar, Ticket, Product, Ghost CMS)
- db/ (SQLAlchemy async session, base)
- suma_browser/app/ (csrf, middleware, errors, authz, redis_cacher, payments, filters, utils)
- suma_browser/templates/ (shared base layouts, macros, error pages)
- static/ (CSS, JS, fonts, images)
- alembic/ (database migrations)
- config/ (app-config.yaml)
- editor/ (Lexical editor Node.js build)
- requirements.txt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 23:11:36 +00:00

136 lines
7.1 KiB
Python

"""ghost content mirror (posts/pages/authors/tags)
Revision ID: 20251028_ghost_content
Revises: 0d767ad92dd7
Create Date: 2025-10-28
"""
from alembic import op
import sqlalchemy as sa
revision = "20251028_ghost_content"
down_revision = "0d767ad92dd7"
branch_labels = None
depends_on = None
def upgrade():
op.create_table(
"authors",
sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True),
sa.Column("ghost_id", sa.String(length=64), nullable=False),
sa.Column("slug", sa.String(length=191), nullable=False),
sa.Column("name", sa.String(length=255), nullable=False),
sa.Column("profile_image", sa.Text(), nullable=True),
sa.Column("cover_image", sa.Text(), nullable=True),
sa.Column("bio", sa.Text(), nullable=True),
sa.Column("website", sa.Text(), nullable=True),
sa.Column("location", sa.Text(), nullable=True),
sa.Column("facebook", sa.Text(), nullable=True),
sa.Column("twitter", sa.Text(), nullable=True),
sa.Column("created_at", sa.DateTime(timezone=True), nullable=True),
sa.Column("updated_at", sa.DateTime(timezone=True), nullable=True),
sa.Column("deleted_at", sa.DateTime(timezone=True), nullable=True),
sa.UniqueConstraint("ghost_id", name="uq_authors_ghost_id"),
)
op.create_index("ix_authors_ghost_id", "authors", ["ghost_id"])
op.create_index("ix_authors_slug", "authors", ["slug"])
op.create_table(
"tags",
sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True),
sa.Column("ghost_id", sa.String(length=64), nullable=False),
sa.Column("slug", sa.String(length=191), nullable=False),
sa.Column("name", sa.String(length=255), nullable=False),
sa.Column("description", sa.Text(), nullable=True),
sa.Column("visibility", sa.String(length=32), nullable=False, server_default="public"),
sa.Column("feature_image", sa.Text(), nullable=True),
sa.Column("meta_title", sa.String(length=300), nullable=True),
sa.Column("meta_description", sa.Text(), nullable=True),
sa.Column("created_at", sa.DateTime(timezone=True), nullable=True),
sa.Column("updated_at", sa.DateTime(timezone=True), nullable=True),
sa.Column("deleted_at", sa.DateTime(timezone=True), nullable=True),
sa.UniqueConstraint("ghost_id", name="uq_tags_ghost_id"),
)
op.create_index("ix_tags_ghost_id", "tags", ["ghost_id"])
op.create_index("ix_tags_slug", "tags", ["slug"])
op.create_table(
"posts",
sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True),
sa.Column("ghost_id", sa.String(length=64), nullable=False),
sa.Column("uuid", sa.String(length=64), nullable=False),
sa.Column("slug", sa.String(length=191), nullable=False),
sa.Column("title", sa.String(length=500), nullable=False),
sa.Column("html", sa.Text(), nullable=True),
sa.Column("plaintext", sa.Text(), nullable=True),
sa.Column("mobiledoc", sa.Text(), nullable=True),
sa.Column("lexical", sa.Text(), nullable=True),
sa.Column("feature_image", sa.Text(), nullable=True),
sa.Column("feature_image_alt", sa.Text(), nullable=True),
sa.Column("feature_image_caption", sa.Text(), nullable=True),
sa.Column("excerpt", sa.Text(), nullable=True),
sa.Column("custom_excerpt", sa.Text(), nullable=True),
sa.Column("visibility", sa.String(length=32), nullable=False, server_default="public"),
sa.Column("status", sa.String(length=32), nullable=False, server_default="draft"),
sa.Column("featured", sa.Boolean(), nullable=False, server_default=sa.text("false")),
sa.Column("is_page", sa.Boolean(), nullable=False, server_default=sa.text("false")),
sa.Column("email_only", sa.Boolean(), nullable=False, server_default=sa.text("false")),
sa.Column("canonical_url", sa.Text(), nullable=True),
sa.Column("meta_title", sa.String(length=500), nullable=True),
sa.Column("meta_description", sa.Text(), nullable=True),
sa.Column("og_image", sa.Text(), nullable=True),
sa.Column("og_title", sa.String(length=500), nullable=True),
sa.Column("og_description", sa.Text(), nullable=True),
sa.Column("twitter_image", sa.Text(), nullable=True),
sa.Column("twitter_title", sa.String(length=500), nullable=True),
sa.Column("twitter_description", sa.Text(), nullable=True),
sa.Column("custom_template", sa.String(length=191), nullable=True),
sa.Column("reading_time", sa.Integer(), nullable=True),
sa.Column("comment_id", sa.String(length=191), nullable=True),
sa.Column("published_at", sa.DateTime(timezone=True), nullable=True),
sa.Column("updated_at", sa.DateTime(timezone=True), nullable=True),
sa.Column("created_at", sa.DateTime(timezone=True), nullable=True),
sa.Column("deleted_at", sa.DateTime(timezone=True), nullable=True),
sa.Column("primary_author_id", sa.Integer(), sa.ForeignKey("authors.id", ondelete="SET NULL"), nullable=True),
sa.Column("primary_tag_id", sa.Integer(), sa.ForeignKey("tags.id", ondelete="SET NULL"), nullable=True),
sa.UniqueConstraint("ghost_id", name="uq_posts_ghost_id"),
sa.UniqueConstraint("uuid", name="uq_posts_uuid"),
)
op.create_index("ix_posts_ghost_id", "posts", ["ghost_id"])
op.create_index("ix_posts_slug", "posts", ["slug"])
op.create_index("ix_posts_status", "posts", ["status"])
op.create_index("ix_posts_visibility", "posts", ["visibility"])
op.create_index("ix_posts_is_page", "posts", ["is_page"])
op.create_index("ix_posts_published_at", "posts", ["published_at"])
op.create_table(
"post_authors",
sa.Column("post_id", sa.Integer(), sa.ForeignKey("posts.id", ondelete="CASCADE"), primary_key=True),
sa.Column("author_id", sa.Integer(), sa.ForeignKey("authors.id", ondelete="CASCADE"), primary_key=True),
sa.Column("sort_order", sa.Integer(), nullable=False, server_default="0"),
)
op.create_table(
"post_tags",
sa.Column("post_id", sa.Integer(), sa.ForeignKey("posts.id", ondelete="CASCADE"), primary_key=True),
sa.Column("tag_id", sa.Integer(), sa.ForeignKey("tags.id", ondelete="CASCADE"), primary_key=True),
sa.Column("sort_order", sa.Integer(), nullable=False, server_default="0"),
)
def downgrade():
op.drop_table("post_tags")
op.drop_table("post_authors")
op.drop_index("ix_posts_published_at", table_name="posts")
op.drop_index("ix_posts_is_page", table_name="posts")
op.drop_index("ix_posts_visibility", table_name="posts")
op.drop_index("ix_posts_status", table_name="posts")
op.drop_index("ix_posts_slug", table_name="posts")
op.drop_index("ix_posts_ghost_id", table_name="posts")
op.drop_table("posts")
op.drop_index("ix_tags_slug", table_name="tags")
op.drop_index("ix_tags_ghost_id", table_name="tags")
op.drop_table("tags")
op.drop_index("ix_authors_slug", table_name="authors")
op.drop_index("ix_authors_ghost_id", table_name="authors")
op.drop_table("authors")