ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Metabase Embedding SDK 之 SdkQuestionEntityPublicProps 详解:四种互斥方式渲染嵌入问题

Metabase Embedding SDK 之 SdkQuestionEntityPublicProps 详解:四种互斥方式渲染嵌入问题 Metabase Embedding SDK 之 SdkQuestionEntityPublicProps 详解四种互斥方式渲染嵌入问题【免费下载链接】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/metabaseSdkQuestionEntityPublicProps 是 Metabase Embedding SDK 中驱动InteractiveQuestion与StaticQuestion组件渲染的核心属性联合类型discriminated union。本篇以 SdkQuestionEntityPublicProps.md 为骨架结合 question.ts 源码与官方示例片段逐条拆解questionId、token、card、query四种互斥的传入方式帮助你理解何时选用哪种方式、各自的类型约束与最佳实践从而在 React 应用中正确嵌入已保存问题、Guest Embed 问题、临时图表与 SQL/Notebook 查询。一、认识 SdkQuestionEntityPublicProps一个四分支判别联合在 Metabase Embedding SDK 中一个“问题实体”可以被四种不同方式描述通过已保存问题的 ID、通过 Guest Embed 的 JWT token、通过一个未保存的 ad-hoc card、或通过一个查询对象。为了让 API 在编译期就能阻止“同时传入 questionId 又传入 token”之类的非法组合SDK 将这四个分支定义为一个 TypeScript 判别联合type SdkQuestionEntityPublicProps | { card?: never; query?: never; questionId: SdkQuestionId | null; token?: never; } | { card?: never; query?: never; questionId?: never; token: SdkEntityToken | null; } | { card: string | MetabaseCard; query?: never; questionId?: never; token?: never; } | { card?: never; query: MetabaseQueryObject | null; questionId?: never; token?: never; };这段声明的核心技巧在于never关键字每个分支只允许一个“载体”属性存在其余属性全部标注为?: never。只要调用方同时填了两个载体TypeScript 就会因类型不匹配而直接报错——互斥约束在编译期被强制执行而不是留到运行时才校验。该类型定义位于仓库源码 frontend/src/embedding-sdk-bundle/types/question.ts#L50-L98与本文档完全一致可作为权威参考。四个分支分别对应四种使用场景分支必填载体典型场景1questionId渲染一个已保存的或新建的问题2token通过 JWT 渲染 Guest Embed 问题3card渲染一个不落库的临时图表ad-hoc4query通过useMetabaseQueryObject渲染表驱动查询二、变体一通过 questionId 渲染已保存问题{ card?: never; query?: never; questionId: SdkQuestionId | null; token?: never; }这是最常用的方式。questionId的类型为SdkQuestionId | null取null时表示尚未确定要渲染的问题。名称类型说明card?never禁止与card同时传入query?never禁止与query同时传入questionIdSdkQuestionId|null问题 ID具体取值方式见下文token?never禁止与token同时传入questionId 的四种取值SdkQuestionId是一个联合类型number \| new \| new-native \| SdkEntityId见 SdkQuestionId.md 及源码 question.ts#L44-L48数字 ID访问问题链接时取到的数字例如http://localhost:3000/question/1-my-question中的1字符串实体 ID通过 API 直接获取、或通过 SDK Collection Browser 返回数据时问题对象entity_id键中的字符串例如abc123def456new显示 Notebook 编辑器用于创建新的MBQL 可视化问题new-native显示 SQL 编辑器用于创建新的原生 SQL 问题。// 数字 ID来自问题 URL const questionId: SdkQuestionId 123; // 字符串实体 ID const questionId: SdkQuestionId abc123def456; // 新建 Notebook 问题 const questionId: SdkQuestionId new; // 新建原生 SQL 问题 const questionId: SdkQuestionId new-native;注意SdkEntityId本身由 SDK 内部定义new与new-native是 SDK 保留的两个特殊字符串字面量分别用于唤起两种新建模式。实战渲染已保存的问题官方示例 interactive-question.tsx 展示了数字 ID 的标准用法import React from react; import { InteractiveQuestion, MetabaseProvider, defineMetabaseAuthConfig, } from metabase/embedding-sdk-react; const authConfig defineMetabaseAuthConfig({ metabaseInstanceUrl: https://your-metabase.example.com, }); export default function App() { const questionId 1; // 要嵌入的问题 ID return ( MetabaseProvider authConfig{authConfig} InteractiveQuestion questionId{questionId} / /MetabaseProvider ); }只读展示场景则可换用StaticQuestion见 static-question.tsximport React from react; import { MetabaseProvider, StaticQuestion, defineMetabaseAuthConfig, } from metabase/embedding-sdk-react; const authConfig defineMetabaseAuthConfig({ metabaseInstanceUrl: https://your-metabase.example.com, }); export default function App() { const questionId 1; // 要嵌入的问题 ID return ( MetabaseProvider authConfig{authConfig} StaticQuestion questionId{questionId} withChartTypeSelector{false} / /MetabaseProvider ); }实战嵌入“新建问题”入口想直接在产品内提供新建能力将questionId设为new即可唤起 Notebook 编辑器new-question.tsxMetabaseProvider authConfig{authConfig} InteractiveQuestion questionIdnew / /MetabaseProvider同理new-native唤起 SQL 编辑器new-native-question.tsxMetabaseProvider authConfig{authConfig} InteractiveQuestion questionIdnew-native / /MetabaseProvider三、变体二通过 token 渲染 Guest Embed 问题{ card?: never; query?: never; questionId?: never; token: SdkEntityToken | null; }名称类型说明card?never禁止与card同时传入query?never禁止与query同时传入questionId?never禁止与questionId同时传入tokenSdkEntityToken|null有效的 Guest Embed JWT tokenSdkEntityToken本质就是string见 SdkEntityToken.md承载服务端签发的 JWT。该分支用于Guest Embed匿名嵌入场景宿主应用后端为未登录访客签发 token前端拿到 token 后即可让访客查看该 token 授权范围内的问题。从源码可以印证这一分支的实际使用位置在 iframe 嵌入路由 SdkIframeEmbedRoute.tsx#L306-L310 中SDK 会依据配置里是否存在token来构造实体属性const entityProps: SdkQuestionEntityPublicProps settings.token ? { token: settings.token, } : { /* 否则走 questionId 分支 */ };也就是说token分支与questionId分支在运行时也是由 SDK 按“是否提供 token”来分派的类型层面的互斥设计与运行时的分派逻辑保持一致。四、变体三通过 card 渲染临时ad-hoc问题{ card: string | MetabaseCard; query?: never; questionId?: never; token?: never; }名称类型说明cardstring|MetabaseCard无需先保存即可渲染的 ad-hoc 问题可以是MetabaseCard对象也可以是从问题 URL hash 中复制的序列化 card 字符串/question#base64或裸 base64query?never禁止与query同时传入questionId?never禁止与questionId同时传入token?never禁止与token同时传入该分支适合“不落库”的临时图表例如从某个问题 URL 的#后复制出一段 base64 序列化字符串直接渲染或在前端动态构造一个MetabaseCard对象。MetabaseCard 的结构MetabaseCard是带可视化配置的 ad-hoc card 定义完整类型见 MetabaseCard.md。其骨架可概括为基础的 card 字段配合一个按visualization类型收窄的联合将visualizationSettings与图表类型一一绑定type MetabaseCard MetabaseCardBase | { visualization?: never; visualizationSettings?: never; } | { visualization: table | pivot | object | list; visualizationSettings?: TableVisualizationSettings; } | { visualization: bar | line | area | combo | row; visualizationSettings?: CartesianVisualizationSettings; } // ... scatter / waterfall / pie / scalar / funnel / map / sankey / boxplot / 自定义图表 | { visualization: CustomVizDisplayType; visualizationSettings?: Recordstring, unknown; };设计意图很清晰只传query让 Metabase 根据查询结果自动推断展示形态需要指定图表时加上visualization字段选择图表类型如bar、line、pie、map、sankey、boxplot等需要精细定制呈现再补充visualizationSettings例如笛卡尔图的坐标轴设置、饼图配置等。另外需要注意MetabaseCardBase及各可视化设置类型TableVisualizationSettings、CartesianVisualizationSettings、ScatterVisualizationSettings等虽然出现在类型展开中但并未从 SDK 公开入口导出实际使用时通常依赖类型推断而非显式 import。五、变体四通过 query 渲染表驱动临时查询{ card?: never; query: MetabaseQueryObject | null; questionId?: never; token?: never; }名称类型说明card?never禁止与card同时传入queryMetabaseQueryObject|null通过useMetabaseQueryObject创建的表驱动 ad hoc 查询questionId?never禁止与questionId同时传入token?never禁止与token同时传入MetabaseQueryObject是useMetabaseQueryObject钩子产出的公开结构类型见 MetabaseQueryObject.md同样是三路联合type MetabaseQueryObject | { database?: unknown; parameters?: unknown; query?: unknown; type: query } | { database?: unknown; native?: unknown; parameters?: unknown; type: native } | { database?: unknown; lib/type: mbql/query; parameters?: unknown; stages?: unknown };三个分支分别对应标准的 MBQL 查询type: query、原生查询type: native携带native字段、以及新的多阶段 MBQL 查询lib/type: mbql/query携带stages字段。与card分支的区别在于query分支不携带可视化信息图表形态完全由查询结果驱动推断而card分支可以额外指定visualization与visualizationSettings。六、互斥约束的价值类型安全与运行时分派为什么 SDK 要花大力气做这样一个四分支判别联合而不是一个所有字段都可选的扁平对象编译期拦截非法组合questionId、token、card、query四个载体彼此互斥。若调用方写出StaticQuestion questionId{1} tokenxxx /token的位置是?: neverTypeScript 立即报错杜绝了“同时提供多种载体时以谁为准”的运行时歧义。自动补全与文档即代码开发者每选一个分支IDE 便只提示该分支合法的属性天然引导正确用法文档中的属性表格Name/Type/Description即由该类型声明自动生成保证文档与源码不脱节。与运行时行为对齐从 SdkIframeEmbedRoute.tsx#L306-L310 可见运行时同样遵循“有 token 走 token、否则走 questionId”的分派逻辑类型约束与实现逻辑一一对应。该类型在实际组件中的组合方式可从两个入口确认InteractiveQuestionProps InteractiveQuestionBaseProps SdkQuestionEntityPublicPropsInteractiveQuestion.tsx#L60-L61StaticQuestionProps StaticQuestionBaseProps SdkQuestionEntityPublicPropsStaticQuestion.tsx#L75-L76。即无论是交互式问题组件还是静态展示组件问题实体的定位方式都统一复用这套四分支联合其余交互/展示相关 props 通过基础类型叠加。七、选择指南与自检清单你的需求应选分支载体示例渲染已保存问题含数字 ID 与实体 ID变体一questionId{1}或questionIdabc123def456提供“新建 Notebook 问题”入口变体一questionIdnew提供“新建原生 SQL 问题”入口变体一questionIdnew-native访客免登录查看Guest Embed变体二tokenJWT渲染未保存的临时图表含可视化配置变体三card{cardObject}或card{serializedBase64}渲染useMetabaseQueryObject产出的表驱动查询变体四query{queryObject}编写代码时的快速自检四个载体questionId/token/card/query是否恰好只填了一个多余字段应为?: neverquestionId的字符串取值是否只用了new与new-native两个保留字面量其余字符串应为实体 IDtoken分支是否只用于 Guest Embed服务端签发 JWT场景需要指定图表类型时用card分支并给MetabaseCard加visualization仅需查询结果自动推断展示形态时可考虑query分支。八、总结SdkQuestionEntityPublicProps 用 TypeScript 判别联合为“渲染哪个问题”提供了四种互斥且类型安全的表达方式questionId覆盖已保存与新建两类场景token覆盖匿名 Guest Embedcard覆盖带可视化配置的临时图表query覆盖由useMetabaseQueryObject驱动的表驱动查询。理解这四分支的边界与取舍是正确使用InteractiveQuestion/StaticQuestion嵌入问题能力的前提——而never标记的互斥约束则保证这类错误在编译期就被 TypeScript 拦截让嵌入 API 既灵活又不易误用。【免费下载链接】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),仅供参考
返回列表