# 从 Supabase 迁移到 Insforge：分步式指南

> 一款开源工具包，助您无损迁移整个 Supabase 项目——包含用户、数据库及文件。

## 分分钟从 Supabase 迁移到 Insforge：一份经过生产环境检验的完整指南

你好！既然你决定将项目从 Supabase 迁移到 [Insforge](https://insforge.dev/)，那么本指南就是为你准备的。数据迁移可能令人望而生畏。你可能会想：如何在不强制用户重置密码的情况下迁移所有用户？如何传输每一个文件并更新所有链接？数据库结构和那些宝贵的数据又该怎么办？

别担心，我们都已为你考虑周全。

本指南将介绍一个经过生产环境检验的完整迁移工具包，旨在将你的整个 Supabase 项目无缝过渡到一个自托管的 [Insforge](https://github.com/InsForge/InsForge) 实例。我们所说的不仅仅是部分数据转储，而是一次完整的迁移，它将保留：

* ✅ **用户认证**（包括密码！）
* ✅ **完整的数据库**（结构和数据）
* ✅ **所有存储文件**（路径完全一致）
* ✅ **外键关系**（通过保留用户 ID）

该工具包已在真实的生产环境中经过实战检验，成功迁移了 **39 个用户、985 条数据库记录以及超过 1500 个存储文件**，无一数据丢失。有关自托管的更多信息，请查看 [Insforge GitHub 仓库](https://github.com/InsForge/supabase-to-insforge)。

让我们开始吧。

### 开始之前：你的迁移前检查清单

在开始之前，让我们先设置好环境，确保迁移过程顺利。

### 1. 前提条件

首先，请确保你已具备必要的工具和访问权限：

- **软件：**
    - Node.js (v20+)
    - PostgreSQL 客户端 (`psql`)
- **访问权限：**
    - 你的 Supabase 项目凭据（API 密钥、数据库 URL）。
    - 一个拥有管理员 API 密钥的有效 Insforge 实例。

### 2. 环境设置

现在，让我们来配置迁移工具本身。

首先，克隆该工具包的[仓库](https://github.com/InsForge/supabase-to-insforge)（或下载源码）并安装依赖项。

```bash
# 克隆仓库 (如果适用)
# git clone <https://github.com/InsForge/supabase-to-insforge>

# 安装依赖项
npm install
```

接下来，创建你的环境配置文件。复制示例文件来创建你自己的 `.env` 文件。

```bash
cp .env.example .env
```

现在，打开新创建的 `.env` 文件，并填入你决定迁移的 Supabase 项目和新的 Insforge 项目的凭据。

### **查找你的 Supabase 凭据**

要填写 `.env` 文件，你需要从 Supabase 项目仪表板中获取三项关键信息。

1.  **`SUPABASE_URL` 和 `SUPABASE_SERVICE_ROLE_KEY`**：
    -   导航到你的 Supabase 项目。
    -   进入 **Project Settings**（齿轮图标）。
    -   点击 **API**。
    -   在这里，你将找到你的项目 URL 和 `service_role` 密钥。
2.  **`SUPABASE_DB_URL`（你的连接字符串）**：
    -   在你的 Supabase 项目仪表板中，点击页面顶部的 **Connect** 按钮。
    -   一个面板将会打开，其中包含你的数据库连接详细信息。
    -   从 **Direct connection** 部分复制 URI。
    -   **重要提示：** 你必须将字符串中的 `[YOUR-PASSWORD]` 占位符替换为你的实际数据库密码。如果你忘记了密码，可以在 **Project Settings** > **Database** 中重置。

![PSQL String](https://cdn.zeabur.com/psqlstring.png)

```
# ============================================
# Supabase 配置
# ============================================
# 在 Supabase 设置中找到这些凭据
SUPABASE_URL=https://你的项目.supabase.co
SUPABASE_SERVICE_ROLE_KEY=你的_supabase_service_role_key
SUPABASE_DB_URL=postgresql://postgres.xxx:[你的密码]@...

# ============================================
# Insforge 配置
# ============================================
# 你的 Insforge 实例详情
INSFORGE_API_URL=http://localhost:7130 # 或你的远程 URL
INSFORGE_API_KEY=你的_insforge_api_key
```

### 3. 验证你的连接

在运行迁移之前，让我们确保该工具可以连接到两个数据库。运行以下命令来测试你的连接：

```bash
# 测试 Supabase 连接
psql "$SUPABASE_DB_URL" -c "SELECT version();"

# 测试 Insforge 连接 (根据你的本地/远程设置进行调整)
psql postgresql://postgres:postgres@localhost:5432/insforge -c "SELECT version();"

# 退出
\\q
```

如果两个命令都无误执行，那么你就可以开始正式迁移了！

---

### 伟大的迁移：分步指南

迁移过程分为三个逻辑阶段。请按顺序执行以获得最佳效果。

### 阶段 1：迁移你的用户（无需重置密码！）

这通常是任何迁移中最棘手的部分，但这个工具包让它变得简单。我们将迁移所有用户账户，同时保留他们原有的密码。

### 步骤 1.1：从 Supabase 导出用户

此命令会连接到你的 Supabase 项目，并将 `auth.users` 表中的所有用户导出到一个本地 JSON 文件中。

```bash
npm run export:auth
```

**预期输出：**

```
✅ 已连接到 Supabase PostgreSQL
✅ 已将 39 个用户导出到 auth-export.json
```

这将创建一个名为 `auth-export.json` 的文件，其中包含用户详情，包括他们的 ID 和加密密码。

### 步骤 1.2：将用户导入 Insforge

现在，我们将从 `auth-export.json` 文件中将用户导入到你的 Insforge 实例。该脚本会保留原始的用户 ID（对于外键至关重要）和他们经过 bcrypt 哈希的密码。

```bash
npm run import:auth
```

**预期输出：**

```
✅ 已连接到 Insforge API
   URL: <https://your-insforge-instance.insforge.app>

📦 已加载导出数据...
⬆️  正在导入用户...
   ✅ 已导入 41/41 个账户
✅ 导入完成！
```

**专业提示：** 这个脚本是**幂等**的，这意味着你可以多次运行它而不会创建重复的用户。如果发现现有记录，它只会更新这些记录。

### 阶段 2：迁移你的数据库

接下来，我们将迁移你的整个 PostgreSQL 数据库，包括结构、数据，甚至你的行级安全（RLS）策略。

### 步骤 2.1：导出数据库结构和数据

此命令使用 `pg_dump` 为你的 Supabase 公共模式创建一个完整的 SQL 备份。

```bash
npm run export:db
```

**预期输出：**

```
✅ 数据库导出成功
   文件: database-export.sql (245 KB)
```

这将生成一个 `database-export.sql` 文件。

### 步骤 2.2：为 Insforge 转换 SQL

Supabase 使用了一些特定的函数和扩展。此脚本会清理导出的 SQL 文件，移除 Supabase 特定的代码，更新 RLS 策略（例如，`auth.uid()` 变为 `uid()`），并使其与 Insforge 兼容。

```bash
npm run transform:db
```

**预期输出：**

```
✅ 已为 Insforge 转换 SQL
   输出: database-export.insforge.sql
```

这将创建一个新的、为 Insforge 准备好的文件：`database-export.insforge.sql`。

### 步骤 2.3：将数据库导入 Insforge

最后，让我们将转换后的 SQL 文件导入到你的 Insforge 项目中。

```bash
npm run import:db
```

**预期输出：**

```
🗄️  正在将数据库导入 Insforge...
✅ 数据库导入完成！
受影响的表: 12
导入的行数: 985
```

你的数据库结构和数据现已成功迁移！

### 阶段 3：迁移你的文件存储

最后一个阶段是将你所有的文件从 Supabase Storage 移动到 Insforge Storage。这个过程会保留精确的文件路径，这对于防止链接失效至关重要。

### 步骤 3.1：重新创建存储桶

首先，该脚本将从你的 Supabase 项目中读取存储桶列表，并在 Insforge 中创建相同的存储桶，同时保留它们的公共或私有设置。

```bash
npm run create:buckets
```

**预期输出：**

```
✅ 已连接到 Supabase PostgreSQL
📦 在 Supabase 中找到 4 个存储桶:
📋 正在创建存储桶: generated-images (public)... ✅ 创建成功
📋 正在创建存储桶: raw-product-images (public)... ✅ 创建成功
...
✅ 存储桶创建完成！
```

### 步骤 3.2：从 Supabase 下载所有文件

此命令会从你所有的 Supabase 存储桶中下载每一个文件，并保留原始的目录结构。

```bash
npm run export:storage
```

**预期输出：**

```
📦 开始从 Supabase 导出存储...
⬇️  正在下载文件...
   [1/1572] generated-images/user123/image.jpg ✅
   ...
   [1572/1572] reference-images/ref5.jpg ✅

✅ 导出完成！已下载: 1,572 个文件
```

所有文件都将保存在本地的 `storage-downloads/` 目录中。

### 步骤 3.3：将所有文件上传到 Insforge

现在，我们将所有下载的文件上传到 Insforge 中对应的存储桶。

```bash
npm run import:storage
```

**预期输出：**

```
📦 找到 1572 个待导入文件
⬆️  [1/1572] generated-images/user123/scene/image.jpg... ✅ 上传成功
...
✅ 导入完成！成功: 1569/1572
```

### 步骤 3.4：点睛之笔 - 更新所有存储 URL

这是见证奇迹的时刻。你的数据库中可能包含数千个指向 Supabase Storage 的 URL。此脚本会连接到你的 **Insforge** 数据库，并在所有表上执行通用的查找和替换。它会智能地将每个 Supabase 存储 URL 更新为新的 Insforge URL，即使是在复杂的 JSONB 字段内部。

```bash
npm run update:storage-urls
```

**预期输出：**

```
✅ 已连接到 Insforge API
🔄 通用 URL 替换...
📊 发现:
   - 997 个生成的输入中包含 Supabase URL
   - 1023 个生成的输出中包含 Supabase URL
⏳ 正在通用更新所有 URL...
✅ 所有 Supabase 存储 URL 均已更新！
```

就这样！你的整个项目现已迁移完毕。

---

### 接下来做什么？迁移后步骤

你的数据已迁移，但工作尚未完成。以下是让你的应用程序在 Insforge 上运行的最后几个步骤。

1.  **更新应用程序代码：** 将你的应用程序客户端配置指向你的 Insforge 实例，而不是 Supabase。有关使用 MCP 重新配置 SDK 的详细指导，请查看我们的[配套博文](https://zeabur.com/blogs/lovable-to-zeabur-insforge)。

    ```jsx
    // 之前 (Supabase)
    const supabase = createClient('SUPABASE_URL', 'SUPABASE_ANON_KEY');
    
    // 之后 (Insforge)
    const insforge = createClient('你的_INSFORGE_API_URL', '你的_INSFORGE_API_KEY');
    ```

2.  **端到端测试：** 全面测试你的应用程序。
    -   用户能用旧密码登录吗？
    -   图片和文件能正常加载吗？
    -   所有与数据相关的功能都按预期工作吗？
3.  **清理工作：** 一旦你确认一切正常，就可以删除临时的迁移文件（`storage-downloads/`、`.sql`、`.json`）。

### 常见问题排查

-   **存储导入时出现 `File too large` 错误：** 你的文件超出了 Insforge 实例的上传限制。你可能需要提高限制或手动迁移该文件。
-   **密码登录失败：** 仔细检查 `import:auth` 脚本是否成功运行。bcrypt 密码哈希应该被原样保留。
-   **连接超时：** 验证你的 IP 是否已在 Supabase 的网络限制中加入白名单，以及你的 `.env` 连接字符串是否正确。

迁移愉快！🚀
