// @bun
// src/components/docs/safety/SafetyMigrationsPage.tsx
import Link from "@contractspec/lib.ui-link";
import { ChevronRight } from "lucide-react";
import { jsx, jsxs } from "react/jsx-runtime";
function SafetyMigrationsPage() {
  return /* @__PURE__ */ jsxs("div", {
    className: "space-y-8",
    children: [
      /* @__PURE__ */ jsxs("div", {
        className: "space-y-4",
        children: [
          /* @__PURE__ */ jsx("h1", {
            className: "text-4xl font-bold",
            children: "Migrations"
          }),
          /* @__PURE__ */ jsxs("p", {
            className: "text-muted-foreground",
            children: [
              "A ",
              /* @__PURE__ */ jsx("strong", {
                children: "schema migration"
              }),
              " (also called a database migration) is a set of incremental, reversible changes to a database schema. According to",
              " ",
              /* @__PURE__ */ jsx("a", {
                href: "https://en.wikipedia.org/wiki/Schema_migration",
                target: "_blank",
                rel: "noopener noreferrer",
                className: "text-violet-400 hover:text-violet-300",
                children: "Wikipedia"
              }),
              `, schema migrations "allow the database schema to evolve as the application's requirements change, while preserving existing data."`
            ]
          })
        ]
      }),
      /* @__PURE__ */ jsxs("div", {
        className: "space-y-4",
        children: [
          /* @__PURE__ */ jsx("h2", {
            className: "text-2xl font-bold",
            children: "Why migrations matter"
          }),
          /* @__PURE__ */ jsx("p", {
            className: "text-muted-foreground",
            children: "As your application evolves, you'll need to change your data model\u2014adding new fields, renaming tables, changing data types, or restructuring relationships. Without a disciplined approach, these changes can lead to:"
          }),
          /* @__PURE__ */ jsxs("ul", {
            className: "text-muted-foreground list-inside list-disc space-y-2",
            children: [
              /* @__PURE__ */ jsx("li", {
                children: "Data loss or corruption"
              }),
              /* @__PURE__ */ jsx("li", {
                children: "Downtime during deployments"
              }),
              /* @__PURE__ */ jsx("li", {
                children: "Inconsistencies between environments (dev, staging, production)"
              }),
              /* @__PURE__ */ jsx("li", {
                children: "Difficulty rolling back failed changes"
              })
            ]
          }),
          /* @__PURE__ */ jsx("p", {
            className: "text-muted-foreground",
            children: "Migrations solve these problems by treating schema changes as versioned, tested, and reversible operations."
          })
        ]
      }),
      /* @__PURE__ */ jsxs("div", {
        className: "space-y-4",
        children: [
          /* @__PURE__ */ jsx("h2", {
            className: "text-2xl font-bold",
            children: "How MigrationSpec works"
          }),
          /* @__PURE__ */ jsxs("p", {
            className: "text-muted-foreground",
            children: [
              "In ContractSpec, migrations are defined using",
              " ",
              /* @__PURE__ */ jsx("strong", {
                children: "MigrationSpec"
              }),
              ". Each migration has:"
            ]
          }),
          /* @__PURE__ */ jsxs("ul", {
            className: "text-muted-foreground list-inside list-disc space-y-2",
            children: [
              /* @__PURE__ */ jsxs("li", {
                children: [
                  /* @__PURE__ */ jsx("strong", {
                    children: "Version"
                  }),
                  ' \u2013 A unique identifier (e.g., "2025-11-13-001") that determines the order of execution.'
                ]
              }),
              /* @__PURE__ */ jsxs("li", {
                children: [
                  /* @__PURE__ */ jsx("strong", {
                    children: "Up function"
                  }),
                  ` \u2013 The forward migration that applies the change (e.g., "add column 'email_verified'").`
                ]
              }),
              /* @__PURE__ */ jsxs("li", {
                children: [
                  /* @__PURE__ */ jsx("strong", {
                    children: "Down function"
                  }),
                  ` \u2013 The reverse migration that undoes the change (e.g., "drop column 'email_verified'").`
                ]
              }),
              /* @__PURE__ */ jsxs("li", {
                children: [
                  /* @__PURE__ */ jsx("strong", {
                    children: "Dependencies"
                  }),
                  " \u2013 Other migrations that must run before this one."
                ]
              }),
              /* @__PURE__ */ jsxs("li", {
                children: [
                  /* @__PURE__ */ jsx("strong", {
                    children: "Validation"
                  }),
                  ' \u2013 Optional checks to ensure the migration succeeded (e.g., "verify all users have an email address").'
                ]
              })
            ]
          })
        ]
      }),
      /* @__PURE__ */ jsxs("div", {
        className: "space-y-4",
        children: [
          /* @__PURE__ */ jsx("h2", {
            className: "text-2xl font-bold",
            children: "Example MigrationSpec"
          }),
          /* @__PURE__ */ jsx("p", {
            className: "text-muted-foreground",
            children: "Here's a migration that adds an email verification field to the users table:"
          }),
          /* @__PURE__ */ jsx("div", {
            className: "bg-background/50 border-border text-muted-foreground overflow-x-auto rounded-lg border p-4 font-mono text-sm",
            children: /* @__PURE__ */ jsx("pre", {
              children: `migrationId: add-email-verified
version: 2025-11-13-001
dependencies: []

up:
  - sql: |
      ALTER TABLE users
      ADD COLUMN email_verified BOOLEAN DEFAULT FALSE NOT NULL;
  - sql: |
      CREATE INDEX idx_users_email_verified
      ON users(email_verified);

down:
  - sql: |
      DROP INDEX idx_users_email_verified;
  - sql: |
      ALTER TABLE users
      DROP COLUMN email_verified;

validation:
  - sql: |
      SELECT COUNT(*) FROM users
      WHERE email_verified IS NULL;
    expectZeroRows: true`
            })
          })
        ]
      }),
      /* @__PURE__ */ jsxs("div", {
        className: "space-y-4",
        children: [
          /* @__PURE__ */ jsx("h2", {
            className: "text-2xl font-bold",
            children: "Running migrations"
          }),
          /* @__PURE__ */ jsx("p", {
            className: "text-muted-foreground",
            children: "Migrations are applied automatically during deployment. The ContractSpec runtime:"
          }),
          /* @__PURE__ */ jsxs("ol", {
            className: "text-muted-foreground list-inside list-decimal space-y-2",
            children: [
              /* @__PURE__ */ jsx("li", {
                children: "Checks which migrations have already been applied (stored in a migrations table)."
              }),
              /* @__PURE__ */ jsx("li", {
                children: "Identifies new migrations that need to run."
              }),
              /* @__PURE__ */ jsx("li", {
                children: "Executes them in order, respecting dependencies."
              }),
              /* @__PURE__ */ jsx("li", {
                children: "Runs validation checks to ensure success."
              }),
              /* @__PURE__ */ jsx("li", {
                children: "Records the migration as applied."
              })
            ]
          }),
          /* @__PURE__ */ jsx("p", {
            className: "text-muted-foreground",
            children: "If a migration fails, the deployment is aborted, and the system remains in its previous state. You can then fix the migration and redeploy."
          })
        ]
      }),
      /* @__PURE__ */ jsxs("div", {
        className: "space-y-4",
        children: [
          /* @__PURE__ */ jsx("h2", {
            className: "text-2xl font-bold",
            children: "Rolling back migrations"
          }),
          /* @__PURE__ */ jsxs("p", {
            className: "text-muted-foreground",
            children: [
              "If you need to roll back a deployment, ContractSpec automatically runs the ",
              /* @__PURE__ */ jsx("strong", {
                children: "down"
              }),
              " functions of any migrations that were applied. This restores the database to its previous state."
            ]
          }),
          /* @__PURE__ */ jsx("p", {
            className: "text-muted-foreground",
            children: "Note that rollbacks are not always possible\u2014for example, if you've deleted a column, you cannot recover the data unless you have a backup. For destructive changes, it's best to use a multi-step migration:"
          }),
          /* @__PURE__ */ jsxs("ol", {
            className: "text-muted-foreground list-inside list-decimal space-y-2",
            children: [
              /* @__PURE__ */ jsx("li", {
                children: "Add the new column (reversible)."
              }),
              /* @__PURE__ */ jsx("li", {
                children: "Backfill data from the old column to the new column (reversible)."
              }),
              /* @__PURE__ */ jsx("li", {
                children: "Update application code to use the new column (reversible)."
              }),
              /* @__PURE__ */ jsx("li", {
                children: "Drop the old column (irreversible\u2014only do this after confirming the new column works)."
              })
            ]
          })
        ]
      }),
      /* @__PURE__ */ jsxs("div", {
        className: "space-y-4",
        children: [
          /* @__PURE__ */ jsx("h2", {
            className: "text-2xl font-bold",
            children: "Best practices"
          }),
          /* @__PURE__ */ jsxs("ul", {
            className: "text-muted-foreground list-inside list-disc space-y-2",
            children: [
              /* @__PURE__ */ jsxs("li", {
                children: [
                  /* @__PURE__ */ jsx("strong", {
                    children: "Test migrations locally"
                  }),
                  " \u2013 Run them against a copy of production data to catch issues before deploying."
                ]
              }),
              /* @__PURE__ */ jsxs("li", {
                children: [
                  /* @__PURE__ */ jsx("strong", {
                    children: "Keep migrations small"
                  }),
                  " \u2013 Each migration should do one thing. This makes them easier to understand and roll back."
                ]
              }),
              /* @__PURE__ */ jsxs("li", {
                children: [
                  /* @__PURE__ */ jsx("strong", {
                    children: "Write reversible migrations"
                  }),
                  " \u2013 Always provide a down function, even if you don't plan to roll back."
                ]
              }),
              /* @__PURE__ */ jsxs("li", {
                children: [
                  /* @__PURE__ */ jsx("strong", {
                    children: "Use transactions"
                  }),
                  " \u2013 Wrap migrations in database transactions so they either fully succeed or fully fail."
                ]
              }),
              /* @__PURE__ */ jsxs("li", {
                children: [
                  /* @__PURE__ */ jsx("strong", {
                    children: "Avoid destructive changes"
                  }),
                  " \u2013 Prefer additive changes (adding columns) over destructive ones (dropping columns). If you must delete data, archive it first."
                ]
              }),
              /* @__PURE__ */ jsxs("li", {
                children: [
                  /* @__PURE__ */ jsx("strong", {
                    children: "Version your migrations"
                  }),
                  " \u2013 Use timestamps or sequential numbers to ensure migrations run in the correct order."
                ]
              }),
              /* @__PURE__ */ jsxs("li", {
                children: [
                  /* @__PURE__ */ jsx("strong", {
                    children: "Document breaking changes"
                  }),
                  " \u2013 If a migration requires application code changes, note this in the migration description."
                ]
              })
            ]
          })
        ]
      }),
      /* @__PURE__ */ jsxs("div", {
        className: "space-y-4",
        children: [
          /* @__PURE__ */ jsx("h2", {
            className: "text-2xl font-bold",
            children: "Zero-downtime migrations"
          }),
          /* @__PURE__ */ jsx("p", {
            className: "text-muted-foreground",
            children: "Some migrations can cause downtime if not handled carefully. For example, adding a NOT NULL column to a large table can lock the table for minutes. To avoid this, use a multi-step approach:"
          }),
          /* @__PURE__ */ jsxs("ol", {
            className: "text-muted-foreground list-inside list-decimal space-y-2",
            children: [
              /* @__PURE__ */ jsx("li", {
                children: "Add the column as nullable."
              }),
              /* @__PURE__ */ jsx("li", {
                children: "Backfill the column in batches (without locking the table)."
              }),
              /* @__PURE__ */ jsx("li", {
                children: "Add the NOT NULL constraint once all rows are populated."
              })
            ]
          }),
          /* @__PURE__ */ jsx("p", {
            className: "text-muted-foreground",
            children: "ContractSpec's migration system supports this pattern by allowing you to split a logical change into multiple versioned migrations."
          })
        ]
      }),
      /* @__PURE__ */ jsxs("div", {
        className: "flex items-center gap-4 pt-4",
        children: [
          /* @__PURE__ */ jsx(Link, {
            href: "/docs/safety/auditing",
            className: "btn-ghost",
            children: "Previous: Audit Logs"
          }),
          /* @__PURE__ */ jsxs(Link, {
            href: "/docs/advanced/renderers",
            className: "btn-primary",
            children: [
              "Next: Advanced Topics ",
              /* @__PURE__ */ jsx(ChevronRight, {
                size: 16
              })
            ]
          })
        ]
      })
    ]
  });
}
export {
  SafetyMigrationsPage
};
