@codatum/embed

中文文档
1.0.0发布于 2026/03/03Apache-2.0TypeScriptESM + CJS零依赖构建来源已验证近 30 天下载 1.1万

Codatum 签名嵌入的文本库

中文使用文档
文档目录22 节
  1. 安装
  2. 快开始
  3. 嵌入
  4. EmbedOptions
  5. 创建嵌入式实例
  6. 实例方法
  7. 实例属性
  8. 容器属性
  9. 活动
  10. 参数马普
  11. 基本用途
  12. 创建映射器
  13. 实例方法
  14. 第一次使用类型
  15. 错误
  16. 处理错误
  17. 用法实例
  18. 例A:嵌入层中的参数形式(服务器验证商店,客户端发送过滤器)
  19. 例B:仅客户端参数(SaaS拥有过滤器,隐藏参数表)
  20. 例 C: 服务器侧存储( 存储更改时重发)
  21. 光盘N
  22. 另见

@ codatum/ 嵌入

嵌入 Codatum 笔记本的核心类型SDK 已签名嵌入:在浏览器中创建iframe,从后端通过一个符号,处理参数和事件. 服务器侧式代币发行范围外.

文档数字 : 已签名嵌入 • 妇女 一体化 • 妇女 使用大小写。 。 。 . 包装器数字 : @codatum/embed-反应, (中文(简体) ), @ codatum/embed-vue。 。 。 .

安装

pnpm add @codatum/embed
# or
npm install @codatum/embed

快开始

import { createEmbed } from '@codatum/embed';

const embed = createEmbed({
  container: '#dashboard',
  embedUrl: 'https://app.codatum.com/protected/workspace/xxx/notebook/yyy',
  tokenProvider: async () => {
    // Issue a token in your backend and fetch it here
    const res = await fetch('/api/codatum/token', { method: 'POST' });
    const data = await res.json();
    return { token: data.token };
  },
});
await embed.init();

// cleanup
embed.destroy();

嵌入

EmbedOptions

财产需求说明
container对HTMLElement 插入 Iframe 的 CSS 选择器
embedUrl对来自 Codatum 的已签名嵌入 URL
tokenProvider对见 提供符号 下级
iframeOptions没有见 框架选项 下级
tokenOptions没有见 选项 下级
displayOptions没有见 显示选项 下级
devOptions没有见 备选案文 下级

tokenProvider

需要从后端发出一个令牌并返回它(可选) params) (中文(简体) ). 来电 init(), (中文(简体) ), reload()当迹象即将到期的时候 tokenOptions.disableRefresh 实值 true) (中文(简体) ).

签署: (context: TokenProviderContext) => Promise<{ token: string; params?: EncodedParam[] }>

  • context.trigger —— 说 'INIT' | 'RELOAD' | 'REFRESH'。 。 。 .
  • context.markNonRetryable() - 调用未跳过重试( ignores) tokenOptions.retryCount) (中文(简体) ).
  • params - 可选的。 如果返回, 则发送到嵌入符; 使用 参数马普 encode() 建造.

示例

tokenProvider: async (context) => {
  const res = await fetch('/api/codatum/token', {
    method: 'POST',
    body: JSON.stringify({ tenant_id: currentUser.tenantId }),
  });
  if (!res.ok) {
    if (res.status === 401) context.markNonRetryable();
    throw new Error(`Token failed: ${res.status}`);
  }
  const data = await res.json();
  const params = paramMapper.encode({ 
    store_id: currentUser.defaultStoreId,
    date_range: ['2025-01-01', '2025-01-31']
  });
  return { token: data.token, params };
}

IframeOptions

应用到 Iframe 元素并通过 URL/ search params 传递到嵌入式.

财产类型默认说明
theme'LIGHT' | 'DARK'| 'SYSTEM''SYSTEM'嵌入式笔记本的 UI 主题
localestring浏览器的语言地语区号( 如. 'en', (中文(简体) ), 'ja'用于嵌入式UI
classNamestring- 说吧Iframe 元素应用的 CSS 类名
styleobject{display: 'block', width: '100%', height: '100%', border: 'none'}Iframe 的内置样式; 覆盖默认样式
attrsRecord<string, string>- 说吧Iframe 的额外 HTML 属性( 例如 ). { title: 'Dashboard', 'data-testid': 'embed-iframe' }(中文(简体) )

TokenOptions

控制符号寿命, 刷新行为, 并加载超时 .

财产类型默认说明
disableRefreshbooleanfalse何时 true,禁用自动令牌在令牌过期前刷新
refreshBuffernumber60自动重新激活时, 符号过期前秒数
retryCountnumber2令牌获取失败的重试次数; 0 = 没有重试
loadingTimeoutnumber30马克思等几秒钟 CONTENT_READY 输入后 INITIALIZING, (中文(简体) ), RELOADING,或 REFRESHING· ; 0 = 没有超时
onRefreshError(error: EmbedError) => voidundefined当令牌自动重现失败时( 由于 tokenProvider 失败或加载超时),在所有重试后不恢复

DisplayOptions

送入所入所入所入所发相.

财产类型默认说明
sqlDisplay'SHOW' | 'RESULT_ONLY' | 'HIDE''SHOW'是否显示 SQL 块, 只显示结果, 还是隐藏
hideParamsFormbooleanfalse将参数窗体隐藏在嵌入层( 例如当您的应用程序拥有过滤器时)
expandParamsFormByDefaultbooleanfalse默认是否扩展参数窗体

DevOptions

仅限开发与测试. 未打算生产.

财产类型默认说明
debugbooleanfalse何时 true,登录 SDK 生命周期: 后Message ( in/out), sorder Provider calls/refresh/retries,状态过渡.
disableValidateUrlbooleanfalse何时 true跳过 embedUrl 格式验证(域/路径)。 用于不符合生产模式的本地或中转 URL .
mockboolean | MockOptions- 说吧启用模拟模式: 没有真正的嵌入负载, 没有网络 。 iframe 用途 srcdoc 有个有风格的占位符.

模拟选项 (当 mock 是对象 :

财产类型默认说明
labelstringembedUrl文本显示在模拟 Iframe 占位符中 。 当页面上嵌入多处时有用 .
callTokenProviderbooleanfalse何时 true,电话 tokenProvider 打开 init(), (中文(简体) ), reload()和自动更新.
loadingDelaynumber0在嵌入器被装入前秒延迟 。 可用于测试加载UI.

创建嵌入式实例

createEmbed(options: EmbedOptions): EmbedInstance

创建嵌入式实例。 掷出 EmbedError 如果选项无效。 打电话 init() 创建 iframe 并启动符号流.

实例方法

方法说明
async init()创建 Iframe, 等待它准备好, 呼叫 tokenProvider,并给嵌入物发送指示符。 当嵌入器发出时决定 CONTENT_READY拒绝 EmbedError 失败.
async reload()电话 tokenProvider,通过 SET_TOKEN当嵌入地的时候 CONTENT_READY拒绝 EmbedError 失败.
destroy()删除 Iframe, 清除听众和计时器 。 如果已经销毁了,就不要.

实例属性

财产类型说明
iframeHTMLIFrameElement | null嵌入式 Iframe 元素 .
status'CREATED' | 'INITIALIZING' | 'RELOADING' | 'REFRESHING' | 'READY' | 'DESTROYED'当前实例状态 .

容器属性

SDK设定 data-codatum-embed-status 属性,反映当前状态。 当 init() 调用并删除 destroy()。用于基于 CSS 的样式或 E2E 测试选择器.

状态何时
INITIALIZINGinit() 正在等待内容
READY内容已装入并可见
RELOADINGreload() 正在等待内容
REFRESHING正在自动更新
DESTROYED(属性已删除)

示例: 自定义装入 UI

初始化时显示您自己的加载指示器, 同时隐藏 Iframe :

<div id="dashboard" style="position: relative;">
  <div class="my-loading">Loading…</div>
</div>
/* Hide iframe and show loading UI while loading */
[data-codatum-embed-status="INITIALIZING"] iframe,
[data-codatum-embed-status="RELOADING"] iframe,
[data-codatum-embed-status="REFRESHING"] iframe {
  visibility: hidden;
}
[data-codatum-embed-status="INITIALIZING"] .my-loading,
[data-codatum-embed-status="RELOADING"] .my-loading,
[data-codatum-embed-status="REFRESHING"] .my-loading {
  display: flex;
  position: absolute;
  inset: 0;
  align-items: center;
  justify-content: center;
}

/* Hide loading UI when ready */
[data-codatum-embed-status="READY"] .my-loading {
  display: none;
}

没有自定义的 CSS,嵌入式内置加载屏幕显示为iframe内置.

活动

订阅 on(event, handler) 财务报告和审定财务报表 off(event, handler)。 。 。 .

活动说明有效载荷
statusChanged案件情况发生了变化.{ type: 'STATUS_CHANGED', status: EmbedStatus, previousStatus: EmbedStatus }
paramChanged用户更改嵌入式参数 .{ type: 'PARAM_CHANGED', params: EncodedParam[] }
executeSqlsTriggeredSQL被触发了嵌入式执行.{ type: 'EXECUTE_SQLS_TRIGGERED', params: EncodedParam[] }
executionSucceededSQL 执行成功完成.{ type: 'EXECUTION_SUCCEEDED' }
executionFailedSQL 执行失败 .{ type: 'EXECUTION_FAILED', errorMessage: string }

解码为 ParamMapper.decode(payload.params)。 。 。 . EncodedParam: 见 参数马普。 。 。 .

参数马普

嵌入式使用 param_ids(每个笔记本参数指定的ID). 您的应用程序通常使用有意义的键, 如 store_id 或者说 date_range。 。 。 . 参数马普 您的应用程序的密钥值对和 Codatum 之间的地图 param_id + 键 param_value 两个方向.

基本用途

import { createParamMapper } from '@codatum/embed';

const paramMapper = createParamMapper({
  store_id: '67a1b2c3d4e5f6a7b8c9d0e1',
  date_range: '67a1b2c3d4e5f6a7b8c9d0e2',
  product_category: '67a1b2c3d4e5f6a7b8c9d0e3',
});

const appState = {
  store_id: 'store_001',
  date_range: ['2025-01-01', '2025-01-31'],
  product_category: ['Electronics'],
};

// encode: app key:value → EncodedParam[] (use in tokenProvider return)
paramMapper.encode(appState);
// → [
//   { param_id: '67a1b2c3...', param_value: '"store_001"' },
//   { param_id: '67a1b2c3...', param_value: '["2025-01-01","2025-01-31"]' },
//   { param_id: '67a1b2c3...', param_value: '["Electronics"]' },
// ]

// decode: EncodedParam[] → app key:value (use in paramChanged / executeSqlsTriggered)
paramMapper.decode(payload.params);
// → { store_id: 'store_001', date_range: [...], product_category: ['Electronics'] }

创建映射器

createParamMapper(mapping, meta?)

参数类型说明
mappingRecord<string, string>你的应用是钥匙 – Codatum param_id 每个参数.
metaRecord<key, ParamMeta> (可选)与 mapping。按键选项: hidden, (中文(简体) ), required, (中文(简体) ), datatype。 。 。 .

ParamMeta (可选,按键):

财产类型说明
datatypeParamDatatype启用验证并改进打字。 见 参数数据类型 见下文.
requiredboolean若为 true, (中文(简体) ), encode 财务报告和审定财务报表 decode 掷出 MISSING_REQUIRED_PARAM 当参数缺失.
hiddenboolean若为 true,编码参数包括: is_hidden: true 所以嵌入体可以隐藏它们 从参数的形式.

参数数据类型

何时 meta[key].datatype 已经设定, encode 财务报告和审定财务报表 decode 验证值。 支持的数值 :

ParamDatatypeJS/TS 类型页:1
'STRING'string—— 说
'NUMBER'number拒绝 NaN。 。 。 .
'BOOLEAN'boolean—— 说
'DATE'string一定是这样 YYYY-MM-DD。 。 。 .
'STRING[]'string[]串起弦来.
'[DATE, DATE]'[string, string]日期范围;两个要素必须是 YYYY-MM-DD。 。 。 .

实例方法

方法说明
encode(values, options?)应用密钥:值 EncodedParam[]. JSON-弦乐价值. 使用 RESET_TO_DEFAULT 作为重置笔记本默认参数的值.
decode(params, options?)EncodedParam[] - 应用密钥:价值。 在映射时忽略参数 .

encode 编号 : decode 选项

这两种方法都接受可选的第二个论点:

选项类型说明
only(keyof mapping)[]仅限于这些密钥 。 当主机只发送子集时有用( 例如服务器发送一些参数; 客户端通过 encode 与 only) (中文(简体) ).
noValidateboolean何时 true,跳过所需的验证和数据类型.

第一次使用类型

当定义参数定义(例如: datatype)和想要打入编码/解码,可以使用帮助者类型.

import { createParamMapper, RESET_TO_DEFAULT, type DefineDecodedParams, type EncodedParam } from '@codatum/embed';

const paramDefs = {
  store_id: { datatype: 'STRING', required: true },
  date_range: { datatype: '[DATE, DATE]' },
  product_category: { datatype: 'STRING[]' },
} as const;

type ParamValues = DefineDecodedParams<typeof paramDefs>;
// → { store_id: string, date_range?: [string, string], product_category?: string[] }

const paramValues: ParamValues = {
  store_id: 'store_001',
  date_range: RESET_TO_DEFAULT,
  product_category: ['Electronics']
};

const paramMapper = createParamMapper({
  store_id: '67a1b2c3d4e5f6a7b8c9d0e1',
  date_range: '67a1b2c3d4e5f6a7b8c9d0e2',
  product_category: '67a1b2c3d4e5f6a7b8c9d0e3',
}, paramDefs);

// encode only the date_range and product_category params for client-side params
const clientParams = paramMapper.encode(paramValues, { only: ['date_range', 'product_category'] })
// → [
//   { param_id: '67a1b2c3d4e5f6a7b8c9d0e2', param_value: '["2025-01-01","2025-01-31"]' },
//   { param_id: '67a1b2c3d4e5f6a7b8c9d0e3', param_value: '["Electronics"]' },
// ]

const onParamChanged = (ev: { params: EncodedParam[] }) => {
  const values: ParamValues = paramMapper.decode(ev.params);
  console.log('Changed:', values);
};

错误

所有出错均以 EmbedError 带有 code 属性.

代码被丢弃说明
INVALID_OPTIONScreateEmbed选项无效
CONTAINER_NOT_FOUNDinit未找到集装箱元素
LOADING_TIMEOUTinit 编号 : reloadCONTENT_READY 未收到 tokenOptions.loadingTimeout; 自动更新报告 onRefreshError
TOKEN_PROVIDER_FAILEDinit 编号 : reloadtokenProvider 丢弃
MISSING_REQUIRED_PARAMencode 编号 : decode缺少必要的参数
INVALID_PARAM_VALUEencode 编号 : decode数值失败验证
UNEXPECTED_ERRORcreateEmbed 编号 : init 编号 : reload意外错误

处理错误

init() 财务报告和审定财务报表 reload() 投出失败——尝试/捕获。 自动更新错误通过 tokenOptions.onRefreshError 调用.

import { createEmbed, EmbedError } from '@codatum/embed';

try {
  const embed = createEmbed({
    container: '#dashboard',
    embedUrl: '...',
    tokenProvider: async () => { /* ... */ },
    tokenOptions: {
      onRefreshError: (error) => {
        // Token auto-refresh failed after all retries.
        // e.g. redirect to login, show a banner, etc.
        console.error('Refresh failed:', error);
      },
    },
  });
  await embed.init();

  // reload() also throws on failure
  await embed.reload();
} catch (error) {
  if (error instanceof EmbedError) {
      // error.cause holds the original error thrown by tokenProvider (if applicable)
    console.error(error.code, error.message);
  }
}

用法实例

以下模式显示了《公约》概述的共同一体化设想: 已签名的嵌入式使用例。 。 。 .

例A:嵌入层中的参数形式(服务器验证商店,客户端发送过滤器)

嵌入显示笔记本的参数形式. 服务器验证 store_id 并用符号编码;客户端发送电流 store_id 仅针对每个令牌请求和编码 date_range 财务报告和审定财务报表 product_category 作为客户端参数,窗体和主机保持同步.

客户端

import { createEmbed, createParamMapper, RESET_TO_DEFAULT } from '@codatum/embed';

const paramMapper = createParamMapper({...}, {
  store_id: { datatype: 'STRING' },  // server-side param
  date_range: { datatype: '[DATE, DATE]' },  // client-side param
  product_category: { datatype: 'STRING[]' },  // client-side param
});
let paramValues = { store_id: undefined, date_range: RESET_TO_DEFAULT, product_category: [] };

const embed = createEmbed({
  container: '#dashboard',
  embedUrl: '...',
  displayOptions: { expandParamsFormByDefault: true },
  tokenProvider: async () => {
    const res = await fetch('/api/codatum/token', {
      method: 'POST',
      body: JSON.stringify({ tokenUserId: userId, params: { store_id: paramValues.store_id } }),
    });
    const { token } = await res.json();
    const params = paramMapper.encode(paramValues, { only: ['date_range', 'product_category'] });
    return { token, params };
  },
});
await embed.init();

embed.on('paramChanged', (ev) => { paramValues = paramMapper.decode(ev.params); });
embed.on('executeSqlsTriggered', (ev) => { paramValues = paramMapper.decode(ev.params); });

可运行 : 反应, (中文(简体) ), 阴道

服务器 - 验证 store_id 与房客为敌,并将它写入铭文中:

import { createParamMapper } from '@codatum/embed';

// POST /token body: { tokenUserId, params?: { store_id } }
const paramMapper = createParamMapper({...}, {
  tenant_id: { datatype: 'STRING', required: true },  // server-side param
  store_id: { datatype: 'STRING', required: true },  // server-side param
});
const tenantId = await getTenantIdByUserId(tokenUserId);
const storeIdsForTenant = await getStoreIdsByTenantId(tenantId);
const storeId = params?.store_id ?? storeIdsForTenant[0];
if (!storeIdsForTenant.includes(storeId)) throw new Error('Invalid storeId');
const encoded = paramMapper.encode({ tenant_id: tenantId, store_id: storeId });
// issue token with encoded params

可运行 : 节点.js

例B:仅客户端参数(SaaS拥有过滤器,隐藏参数表)

所有参数除外 tenant_id 由主机管理;嵌入式的参数窗体被隐藏. 道具只携带租户上下文,因此可以缓存并再用. 当用户在主机 UI 中更改过滤器时,请拨 reload() 因此,符号提供者再次以更新的值运行.

客户端

import { createEmbed, createParamMapper } from '@codatum/embed';

const paramMapper = createParamMapper({...}, {
  store_id: { datatype: 'STRING' },  // client-side param
  date_range: { datatype: '[DATE, DATE]' },  // client-side param
  product_category: { datatype: 'STRING[]' },  // client-side param
});
let paramValues = { store_id: 'store_001', date_range: ['2025-01-01', '2025-01-31'], product_category: [] };

const embed = createEmbed({
  container: '#dashboard',
  embedUrl: '...',
  displayOptions: { hideParamsForm: true },
  tokenProvider: async () => {
    const res = await fetch('/api/codatum/token', { method: 'POST', body: JSON.stringify({ tokenUserId: userId }) });
    const { token } = await res.json();
    const params = paramMapper.encode(paramValues);
    return { token, params };
  },
});
await embed.init();

embed.on('paramChanged', (ev) => { paramValues = paramMapper.decode(ev.params); });
embed.on('executeSqlsTriggered', (ev) => { paramValues = paramMapper.decode(ev.params); });

// When the user changes filters in the host UI, update paramValues and reload the embed
async function onDashboardFilterChange(newValues: ParamValues) {
  paramValues = newValues;
  await embed.reload();
}

可运行 : 反应, (中文(简体) ), 阴道

服务器 - Token只需要租房范围(身体没有偏执):

import { createParamMapper } from '@codatum/embed';

// POST /token body: { tokenUserId }
const paramMapper = createParamMapper({...}, {
  tenant_id: { datatype: 'STRING', required: true },  // server-side param
});
const tenantId = await getTenantIdByUserId(tokenUserId);
const encoded = paramMapper.encode({ tenant_id: tenantId });
// issue token with encoded params

可运行 : 节点.js

例 C: 服务器侧存储( 存储更改时重发)

store_id 在符号中被固定,并验证服务器侧;更改商店需要一个新的符号。 参数形式可见于 date_range 财务报告和审定财务报表 product_category参数值 paramChanged 通过 store_id 到服务器,在每一个令牌请求中;当用户切换存储时,重新装入,这样就可以为新商店发行一个新的令牌.

客户端

import { createEmbed, createParamMapper, RESET_TO_DEFAULT } from '@codatum/embed';

const paramMapper = createParamMapper({...}, {
  store_id: { datatype: 'STRING' },  // server-side param
  date_range: { datatype: '[DATE, DATE]' },  // client-side param
  product_category: { datatype: 'STRING[]' },  // client-side param
});
let paramValues = { store_id: undefined, date_range: RESET_TO_DEFAULT, product_category: ['Electronics'] };

const embed = createEmbed({
  container: '#dashboard',
  embedUrl: '...',
  displayOptions: { expandParamsFormByDefault: true },
  tokenProvider: async () => {
    const res = await fetch('/api/codatum/token', {
      method: 'POST',
      body: JSON.stringify({ tokenUserId: userId, params: { store_id: paramValues.store_id } }),
    });
    const { token } = await res.json();
    const params = paramMapper.encode(paramValues, { only: ['date_range', 'product_category'] });
    return { token, params };
  },
});
await embed.init();

embed.on('paramChanged', (ev) => { paramValues = paramMapper.decode(ev.params); });
embed.on('executeSqlsTriggered', (ev) => { paramValues = paramMapper.decode(ev.params); });

async function onStoreSwitch(storeId: string) {
  paramValues.store_id = storeId;
  await embed.reload();
}

可运行 : 反应, (中文(简体) ), 阴道

服务器 ——与例A相同:接受 params.store_id,验证,编码 tenant_id + 键 store_id 在标志.

可运行 : 节点.js

光盘N

独立国际家庭教育研究所的建筑暴露了单一的全球情况 CodatumEmbed。装入脚本并使用 CodatumEmbed.createEmbed 接下来 embed.init()。 。 。 .

<script src="https://unpkg.com/@codatum/embed/dist/index.global.min.js"></script>
<script>
  (async function () {
    const embed = CodatumEmbed.createEmbed({ container: '#dashboard', embedUrl: '...', tokenProvider: ... });
    await embed.init();
  })();
</script>

另见

版本与发布记录

@codatum/embed 共发布 10 个版本,首次发布于 2026/02/20;过去 12 个月发布了 10 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.0.0latest2026/03/038 个月前
0.5.22026/03/038 个月前
0.5.12026/03/038 个月前
0.5.02026/03/038 个月前
0.4.02026/03/028 个月前
0.3.02026/02/248 个月前

关于 @codatum/embed 的常见问题

@codatum/embed 是什么?

Codatum 签名嵌入的文本库

如何安装 @codatum/embed?

在项目目录运行 npm install @codatum/embed,或使用 pnpm add / yarn add / bun add。

@codatum/embed 支持 TypeScript 吗?

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

@codatum/embed 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@codatum/embed 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20.12。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@codatum/embed 可以商用吗?

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

@codatum/embed 的下载量有多少?

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

@codatum/embed 还在维护吗?

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