@convex-dev/migrations

中文文档
0.3.7发布于 2026/10/10Apache-2.0TypeScriptES Module零依赖近 30 天下载 230.4万

Convex 的迁移组件 。 定义、运行和跟踪您的数据库迁移 。 从 CLI 或 Convex 服务器函数运行 .

中文使用文档
文档目录26 节
  1. 预先要求: Convex
  2. 安装
  3. 初始化
  4. 定义迁移
  5. 短期语法
  6. 使用索引移动表格的子集
  7. 一次进行一次迁移
  8. 使用 Dashboard 或 CLI
  9. 程序
  10. 行为
  11. 连续进行迁移
  12. 使用 Dashboard 或 CLI
  13. 程序
  14. 行为
  15. 业务
  16. 用干流测试迁移
  17. 重新开始迁移
  18. 停止迁移
  19. 获取移民状况
  20. 作为生产部署的一部分进行迁移
  21. 配置选项
  22. 覆盖内部Mutation以应用自定义 DB 行为
  23. 自定义批量大小
  24. 平行批次
  25. 短手运行语法 :
  26. 同步进行迁移

国家移徙部分

npm version

定义和运行迁移, 如此设定用户的默认值 :

export const setDefaultValue = migrations.define({
  table: "users",
  migrateOne: async (ctx, user) => {
    if (user.optionalField === undefined) {
      await ctx.db.patch(user._id, { optionalField: "default" });
    }
  },
});

然后可以从CLI或程序上直接运行. 见 下级。 。 。 .

npx convex run migrations:setDefaultValue

迁移允许您定义表格中所有文档上的函数 (或指定的子集). 它们分批同步运行(在线迁移).

组件跟踪迁移状态, 避免运行两次, 抓取 (如果在路上发生错误或故障) 通过 Convex 查询实时迁移状态.

见 迁移入门员额 为在线对离线迁移的概念概述。 如果你的迁徙是 小事一桩,你走得很快,还检查一下 仪表板中的轻量级迁移。 。 。 .

移徙的典型步骤:

  1. 修改您的方案以允许新旧值。 通常这是添加一个 新建可选字段或将一个字段标为可选字段,以便删除。 作为 部分内容,更新您的代码处理两个版本.
  2. 定义将数据转换到新方案.
  3. 推动迁移和计划变化.
  4. 运行迁移到完成 .
  5. 修改您的策略和代码以承担新值 。 推动这一变化 只有在所有数据都符合新方案时才会成功。 这是默认 convex的行为,除非您禁用计划验证 .

见 此堆栈帖 用于普通使用案例.

预先要求: Convex

你需要一个现有的 Convex 项目来使用组件。 Convex 是一个主机 后端平台,包括数据库、无服务器功能和多一个吨 可以学习 这里。 。 。 .

运行 npm create convex 或遵循其中任何一条 快速启动 来设置一个.

安装

安装组件包 :

npm install @convex-dev/migrations

创建一个 convex.config.ts 应用程序中的文件 convex/ 文件夹并安装 通过调用 use数字 :

// convex/convex.config.ts
import { defineApp } from "convex/server";
import migrations from "@convex-dev/migrations/convex.config.js";

const app = defineApp();
app.use(migrations);

export default app;

初始化

下面的例子假设该代码是在 convex/migrations.ts。这不是一个 页:1 如果您想要使用不同的文件, 请务必更改 下面的例子 internal.migrations.* 到您的新文件名, 如 internal.myFolder.myMigrationsFile.* 或 CLI 参数类 migrations:* 改为 myFolder/myMigrationsFile:*。 。 。 .

import { Migrations } from "@convex-dev/migrations";
import { components } from "./_generated/api.js";
import schema from "./_generated/schema.js";

export const migrations = new Migrations(components.migrations, { schema });

这个 schema 为移徙定义和支持提供类型安全 在自定义索引上加页 customRange。 。 。 . 与往常一样,迁移中的数据库操作将得到遵守 根据您运行时的策略定义. 说明: 如果您使用的话 自定义函数 要覆盖 internalMutation,参见 下级。 。 。 .

定义迁移

内部 migrateOne 函数,您可以写入代码来修改单个文档 在指定的表格中。 改变是可选的,你也可以阅读 写入此函数的其他表格.

export const setDefaultValue = migrations.define({
  table: "myTable",
  migrateOne: async (ctx, doc) => {
    if (doc.optionalField === undefined) {
      await ctx.db.patch(doc._id, { optionalField: "default" });
    }
  },
});

短期语法

由于最常见的迁移包括补丁每个文档,如果返回 对象,将自动作为补丁应用.

export const clearField = migrations.define({
  table: "myTable",
  migrateOne: () => ({ optionalField: undefined }),
});
// is equivalent to `await ctx.db.patch(doc._id, { optionalField: undefined })`

使用索引移动表格的子集

如果您想要迁移一系列文档, 您可以避免处理 表格全文,以指定 customRange。您可以使用任何已有索引 或内置 by_creation_time 指数.

import { Migrations } from "@convex-dev/migrations";
import { components } from "./_generated/api.js";
import schema from "./_generated/schema.js";

export const migrations = new Migrations(components.migrations, { schema });

export const validateRequiredField = migrations.define({
  table: "myTable",
  customRange: (query) =>
    query.withIndex("by_requiredField", (q) => q.eq("requiredField", "")),
  migrateOne: async (_ctx, doc) => {
    console.log("Needs fixup: " + doc._id);
    // Shorthand for patching
    return { requiredField: "<unknown>" };
  },
});

注意: 要使用自定义 Range, 您必须向移民提供您的计划 .

一次进行一次迁移

使用 Dashboard 或 CLI

管理移民的最简单方式是直接称呼:

npx convex run migrations:setDefaultValue

过 --prod 用于生产.

在仪表板上运行:

Dashboard screenshot

您也可以定义接受迁移的通用跑道:

export const run = migrations.runner();

那就用那个 函数名称数字 :

npx convex run migrations:run '{fn: "migrations:setDefaultValue"}'

见 下级 以通过的方式 setDefaultValue。 。 。 .

程序

也可以运行来自其他 Convex 变异或动作的迁移 :

await migrations.runOne(ctx, internal.example.setDefaultValue);

行为

  • 如果它已经在运行,它会拒绝再开始一个重复的工人.
  • 如果它以前在一些批次上失败了,它将继续从该批次开始 除非您手动指定 cursor 或者说 reset。 。 。 .
  • 如果你提供明确 cursor (单位:千美元)null 表示从头开始, 从那里开始.
  • 如果你通过了 reset: true,它会重新开始迁移 该组的所有迁移(包括任何迁移) next 移民问题).
  • 如果你通过了 true 页:1 dryRun 然后它会运行一批 然后扔,所以 你可以看到它会做什么。 见 下级 这对验证它有用 你所期望的.

连续进行迁移

可以按顺序进行一系列迁移. 如果有迁移的话, 这样做是有用的 取决于先前的,或者如果您保留所有迁移的运行列表 下个部署就应该开始.

使用 Dashboard 或 CLI

您可以通过迁移列表到 runner 让它运行一系列 移徙,而不只是一次:

export const runAll = migrations.runner([
  internal.migrations.setDefaultValue,
  internal.migrations.validateRequiredField,
  internal.migrations.convertUnionField,
]);

然后就运行:

npx convex run migrations:runAll # migrations:runAll is equivalent to convex/migrations.ts:runAll on the CLI

直接拨打移民电话时,或与 runner 函数,您可以通过 一个"next"的参数在第一次迁移后运行一系列迁移:

npx convex run migrations:setDefaultValue '{next:["migrations:clearField"]}'
# OR
npx convex run migrations:run '{fn: "migrations:setDefaultValue", next:["migrations:clearField"]}'

程序

await migrations.runSerially(ctx, [
  internal.migrations.setDefaultValue,
  internal.migrations.validateRequiredField,
  internal.migrations.convertUnionField,
]);

行为

  • 如果在试图迁移时已经在进行中,那就行不通.
  • 如果迁移已经完成,它将跳过它.
  • 如果移徙有部分进展,移徙将恢复原状.
  • 如果一次迁移失败或被取消,它将不再继续,如果您有的话 移民之间的一些依赖关系。 再次调用系列重试.

注意:如果开始多次串行迁移,行为是:

  • 如果它们在功能上不重叠,它们就会快乐地平行运行.
  • 如果他们有一个共同的功能,一个在另一个尝试之前完成 它,第二会只是跳过它.
  • 如果它们有一个共同的功能,一个正在进行,第二个将 不再继续移动.

业务

用干流测试迁移

在运行可能不可逆转地更改数据的迁移之前,您可以验证一个 批次通过 dryRun 对任意 runner 或者说 runOne 命令 :

npx convex run migrations:setDefaultValue '{dryRun: true}'

重新开始迁移

过 reset: true 迫使移民从头开始.

npx convex run migrations:setDefaultValue '{reset: true}'

如果您指定 next 或运行定义的迁移序列,这将重设 光标指向组中的所有迁移.

npx convex run migrations:runAll '{reset: true}'

您也可以从任何有效的光标中通过。 您可以找到有效的光标 答复 getStatus。这可以允许重试迁移 从一个已知的好点, 当你在代码上.

注意:如果您正在从 CLI 的特定光标开始迁移,或者 仪表板,不要通过 dryRun: false 明确,不要定义它.

停止迁移

您可以停止 CLI 或仪表板的迁移, 调用组件 API 直接 :

npx convex run --component migrations lib:cancel '{name: "migrations:myMigration"}'

或者通过 migrations.cancel 程序上.

await migrations.cancel(ctx, internal.migrations.myMigration);

获取移民状况

要了解移民的动态状况,你可以通过 CLI: 爱丽丝

npx convex run --component migrations lib:getStatus --watch

这个 --watch 随时更新状态 或在方案方面:

const status: MigrationStatus[] = await migrations.getStatus(ctx, {
  limit: 10,
});
// or
const status: MigrationStatus[] = await migrations.getStatus(ctx, {
  migrations: [
    internal.migrations.setDefaultValue,
    internal.migrations.validateRequiredField,
    internal.migrations.convertUnionField,
  ],
});

该类型被注释为避免循环类型依赖, 例如, 如果您 正在返回一个查询的结果,该查询在同一个文件中被定义 引用的迁移.

作为生产部署的一部分进行迁移

作为构建和部署命令的一部分,你可以将相应的命令链条链条 npx convex run 命令,例如:

npx convex deploy --cmd 'npm run build' && npx convex run convex/migrations.ts:runAll --prod

配置选项

覆盖内部Mutation以应用自定义 DB 行为

您可以自定义哪个 internalMutation b. 减少移徙 应用.

如果你用的话,这可能很重要 自定义函数 要拦截 数据库写入以应用验证或 更改时触发操作。 。 。 .

假设您定义自己的 internalMutation 内 convex/functions.ts数字 :

import { internalMutation } from "./functions";
import { Migrations } from "@convex-dev/migrations";
import { components } from "./_generated/api";

export const migrations = new Migrations(components.migrations, {
  internalMutation,
});

见 本条 页:1 关于使用和先进模式的更多信息.

自定义批量大小

该组件将获取您的数据, 分批为100, 并调用您的功能 每批文档。 如果您想要更改批量大小, 您可以指定 这个 如果您的文档是大的, 这会有所帮助, 以避免运行在 交易限制, (中文(简体) ), 或文档经常更新且您正在看到OCC 冲突 在迁徙时.

export const clearField = migrations.define({
  table: "myTable",
  batchSize: 10,
  migrateOne: () => ({ optionalField: undefined }),
});

您也可以在单个引用时覆盖此批量大小 :

await migrations.runOne(ctx, internal.migrations.clearField, {
  batchSize: 1,
});

平行批次

每个批次都是按序处理的,但是在一个批次内,你可以拥有每个批次 migrateOne 如果通过, 呼叫并行运行 parallelize: true如果你这样做, 保证你的回话不会认为每个电话都是孤立的 例如,如果 每次通话读取后都会更新相同的计数器,然后在 同样的批量可以读取相同的反相值,然后从一个上下车. 结果, 迁移在默认情况下进行.

export const clearField = migrations.define({
  table: "myTable",
  parallelize: true,
  migrateOne: () => ({ optionalField: undefined }),
});

短手运行语法 :

对不想打字的人来说 migrations:myNewMigration 每一次 他们从CLI或仪表盘上运行一个迁移,特别是如果你定义你的 其他地方的移民情况 ops/db/migrations:myNewMigration,您可以配置 前缀 :

export const migrations = new Migrations(components.migrations, {
  internalMigration,
  migrationsLocationPrefix: "migrations:",
});

然后打电话给:

npx convex run migrations:run '{fn: "myNewMutation", next: ["myNextMutation"]}'

或用代码 :

await migrations.getStatus(ctx, { migrations: ["myNewMutation"] });
await migrations.cancel(ctx, "myNewMutation");

同步进行迁移

如果您想要从测试或动作同步运行迁移, 您可以使用 runToCompletion。请注意,如果动作崩溃或被取消,则不会 在背景中继续迁徙.

从动作 :

import { components, internal } from "./_generated/api";
import { internalAction } from "./_generated/server";
import { runToCompletion } from "@convex-dev/migrations";

export const myAction = internalAction({
  args: {},
  handler: async (ctx) => {
    //...
    const toRun = internal.example.setDefaultValue;
    await runToCompletion(ctx, components.migrations, toRun);
  },
});

在测试中:

import { test } from "vitest";
import { convexTest } from "convex-test";
import component from "@convex-dev/migrations/test";
import { runToCompletion } from "@convex-dev/migrations";
import { components, internal } from "./_generated/api";
import schema from "./schema";

test("test setDefaultValue migration", async () => {
  const t = convexTest(schema);
  // Register the component in the test instance
  component.register(t);

  await t.run(async (ctx) => {
    // Add sample data to migrate
    await ctx.db.insert("myTable", { optionalField: undefined });

    // Run the migration to completion
    const migrationToTest = internal.example.setDefaultValue;
    await runToCompletion(ctx, components.migrations, migrationToTest);

    // Assert that the migration was successful by checking the data
    const docs = await ctx.db.query("myTable").collect();
    expect(docs.every((doc) => doc.optionalField !== undefined)).toBe(true);
  });
});

版本与发布记录

@convex-dev/migrations 共发布 31 个版本,首次发布于 2024/09/21;过去 12 个月发布了 11 个版本。

版本发布日期距今
0.3.7latest2026/10/101 个月前
0.3.62026/07/283 个月前
0.3.52026/05/295 个月前
0.3.5-alpha.1alpha2026/05/215 个月前
0.3.5-alpha.02026/05/215 个月前
0.3.42026/04/256 个月前

关于 @convex-dev/migrations 的常见问题

@convex-dev/migrations 是什么?

Convex 的迁移组件 。 定义、运行和跟踪您的数据库迁移 。 从 CLI 或 Convex 服务器函数运行 .

如何安装 @convex-dev/migrations?

在项目目录运行 npm install @convex-dev/migrations,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:convex(^1.42.0)、convex-helpers(^0.1.115)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@convex-dev/migrations 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@convex-dev/migrations 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@convex-dev/migrations 可以商用吗?

@convex-dev/migrations 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@convex-dev/migrations 的下载量有多少?

根据 npm 官方下载统计,@convex-dev/migrations 在 2026/10/11 – 2026/11/09 这 30 天内被下载 2,303,978 次,日均约 76,799 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@convex-dev/migrations 还在维护吗?

最新版本 0.3.7 发布于 2026/10/10(1 个月前);至今共发布 31 个版本,其中过去 12 个月发布了 11 个;首次发布于 2024/09/21。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。