Metabase Embedding SDK 动作响应类型解析ActionResultForCreate 与 useAction 的类型化 result【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabaseActionResultForCreate是 Metabase Embedding SDK 中定义单行创建动作create action响应体的 TypeScript 类型当嵌入式应用通过useAction触发一个 basic create 动作时result的形态就是{ created-row: Recordstring, RowValue }其中created-row携带被插入的那一行数据。本文以该类型为切入点完整讲解它的定义、RowValue取值语义、它在ActionKind/ActionResultForKind/AnyActionResult判别式类型体系中的位置以及在实际嵌入场景中如何拿到、读取和利用这个类型化结果。类型定义与核心语义类型的完整定义位于 ActionResultForCreate.mdtype ActionResultForCreate { created-row: Recordstring, RowValue; };文档对其语义的官方描述只有一句话Response from a single-row create — the inserted row.单行创建动作的响应——被插入的那一行。解读如下该类型只适用于basic action 中的单行插入create即用户在一个表单里填写一条新记录、提交后写入数据库一行的场景响应体是一个对象唯一的键created-row注意是连字符 kebab-case而非驼峰createdRow这沿用了 Metabase 后端 Clojure 序列化 JSON 时的键命名风格前端 SDK 直接透传不做驼峰转换created-row的值是一个Recordstring, RowValue键是列名column name值是该列在插入后得到的值。它的属性表Properties如下PropertyTypecreated-rowRecordRowValue行中单个单元格的取值范围created-row的每个属性值都收窄为RowValue类型定义见 RowValue.mdtype RowValue string | number | null | boolean | object;RowValue是 Metabase 查询结果或动作响应中单个值的公共类型字符串、数字、布尔、null数据库 NULL 值以及object用于 JSON 字段、展开的嵌套结构等复杂值。因此created-row是一个列名 → 单元格值的字典读取方式为const newRow result[created-row]; const newId newRow[id]; // 通常是自动生成的主键 const customerName newRow[name];在动作响应类型体系中的位置ActionResultForCreate并不是孤立存在的它隶属于 Metabase Embedding SDK 的一套按动作类型kind判别响应形态的类型体系。动作类型字面量由 ActionKind.md 定义type ActionKind create | update | delete | bulk | sql;五种 kind 各自对应一个独立的响应类型见 actions.md 中的对照表Action kind覆盖范围result形态create单行插入basic action{ created-row: Recordstring, RowValue }update单行更新{ rows-updated: readonly RowValue[] }delete单行删除{ rows-deleted: readonly RowValue[] }bulk任意批量变体批量创建/更新/删除{ success: boolean; rows-created?: number; rows-updated?: number; rows-deleted?: number }sql自定义 SQL 动作{ rows-affected: number }各兄弟类型分别定义在 ActionResultForUpdate.md、ActionResultForDelete.md、ActionResultForBulk.md、ActionResultForSql.md 中。对比可见只有 create 动作会回传完整的新行数据更新/删除只回传受影响的主键批量动作只回传成功标志与计数SQL 动作只回传影响行数因此created-row是嵌入应用拿到服务器权威数据的唯一机会可用于确认插入成功、取回自动生成的主键或直接驱动详情页导航。判别式映射ActionResultForKindActionResultForKind.md 定义了一个条件类型负责把TKind字面量映射到具体的响应形态type ActionResultForKindTKind TKind extends create ? ActionResultForCreate : TKind extends update ? ActionResultForUpdate : TKind extends delete ? ActionResultForDelete : TKind extends bulk ? ActionResultForBulk : TKind extends sql ? ActionResultForSql : AnyActionResult;省略TKind传入undefined时会回退到AnyActionResult联合类型。未指定 kind 时的默认AnyActionResultAnyActionResult.md 定义了所有可能响应体的联合type AnyActionResult | ActionResultForCreate | ActionResultForUpdate | ActionResultForDelete | ActionResultForBulk | ActionResultForSql;当调用方在编写时不知道动作的 kindresult的默认类型就是这个联合。SDK 这样设计而非退化为宽松的Recordstring, unknown是为了保留可窄化性narrowabilityTypeScript 知道结果必然是五种已知形态之一调用方可以用key in result判别式收窄而不是靠强转。若类型系统无法证明result上存在某个键读取时会直接报错从而拦截拼写错误。实战在 useAction 中获取类型化的 create 结果SDK 提供useActionhook 触发 Metabase 中已存在的动作签名见 useAction.mdfunction useActionTParameters, TKind( actionId: SdkActionId | null, ): UseActionResultTParameters, TKind;actionId动作的数字 id、entity_id字符串或null数字 id 可在 Metabase 动作编辑器中从 URL 复制第一个泛型TParametersexecute参数对象的类型键是参数的 slug即动作编辑器中显示的参数名第二个泛型TKind可选传入create后result会被自动类型化为ActionResultForCreate。由于 create 动作的响应形态是已知的推荐直接指定TKindimport { useAction } from metabase/embedding-sdk-react; // 单行 create 动作id 为 42参数为 name / email const { execute, isExecuting, result, error } useAction { name: string; email: string }, create // 驱动 result 的类型为 ActionResultForCreate (42); async function handleCreate() { const inserted await execute({ name: Ada, email: adaexample.com }); if (inserted) { // inserted 的类型为 ActionResultForCreate console.log(新行主键, inserted[created-row][id]); } }如果不知道 kind就省略TKind此时result的类型为AnyActionResult再用in操作符收窄const r result; if (r created-row in r) { // 此处 r 已被收窄为 ActionResultForCreate const newRow r[created-row]; }useAction与查询类 hook 有一个关键差异它不会在挂载时自动执行必须由调用方在事件处理器按钮点击、表单提交中显式调用execute。需要条件化执行时在事件处理器内先判断再调用如if (!user.canEdit) return;。execute成功后 resolve 为响应体create 场景即ActionResultForCreate失败则 throw 并把同一错误写入error状态因此即使不写try/catch渲染层的错误提示也会出现。isExecuting在调用期间为true可用来禁用触发按钮、防止重复提交。读取 result 的正确姿势关于如何处理resultactions.md 给出了几条重要实践准则多数场景下根本不需要读取 result。动作成功后必须手动刷新界面数据见下一条result的主要用途是确认——行数、插入行的主键等——可用于 toast 提示或详情页导航不要用result直接驱动 UI 状态。响应体只是确认信息屏幕上展示的数据仍需从数据源重新读取动作成功后必须刷新数据SDK 不会自动刷新。推荐做法是维护一个refreshKeystate把它作为 question 组件的key传入动作成功后setRefreshKey(k k 1)新的key会触发 question 重新挂载并重新执行查询如果单个动作会同时影响多个视图让所有依赖的 question 共用同一个refreshKey一次状态更新即可全部重查。错误处理与空读取当驱动层无法解析参数如日期字符串非法或数据库约束失败时异常会被 hook 归一化为ActionExecuteError见 ActionExecuteErrorerror.status是可选字段仅在收到 HTTP 4xx/5xx 响应时存在纯传输层失败离线、请求中断时不存在对最终用户最有用的诊断信息位于error.data.message而参数级校验失败会以{ slug: message }的形式出现在error.data.errors中键与传给execute的参数 slug 一一对应。SQL/驱动类错误的消息往往在换行后附带失败 SQL因此渲染时建议使用white-space: pre-wrap如pre避免换行被折叠成一整段文字并原样展示错误消息不要替换成笼统的 Something went wrong。与动作后端的对应关系从前端类型体系可以反推后端语义Metabase 后端的动作分为 basic行级 CRUD对应前端 kind 中的create/update/delete/bulk与 custom query自定义 SQL对应sql相关实现集中在 src/metabase/actions/后端动作执行核心包含批量与行级动作的解析与执行逻辑。SDK 侧始终建议通过useAction触发动作而不是直接用fetch调POST /api/action/:id/execute——在沙箱化嵌入上下文中裸 HTTP 调用可能被拦截。前端把五种 kind 统一映射为create/update/delete/bulk/sql的扁平公共字面量而ActionResultForCreate.created-row中的列名正是数据库表中实际返回的列读取时以目标表的 schema 为准。小结ActionResultForCreate虽然只有一行类型声明却是嵌入应用中写操作闭环的关键一环它通过{ created-row: Recordstring, RowValue }把服务器权威的新行数据带回客户端配合useActionTParameters, create的第二泛型即可获得零强转的类型安全。理解它在ActionKind→ActionResultForKind→AnyActionResult体系中的位置并遵守用 result 做确认、用 refreshKey 刷数据的实践就能在嵌入应用里稳健地完成增删改查闭环。相关文档Modular embedding SDK - actionsuseAction Hook 参考ActionKind / ActionResultForKind / AnyActionResultRowValue / ActionExecuteError动作Actions功能文档 与 基本动作Basic actions【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考