# @codatum/embed 中文文档

规范地址：https://npmcn.com/package/%40codatum/embed/

版本：1\.0\.0
npm 元数据更新时间：2026-03-03T02:59:53.534Z
中文译文更新时间：2026-11-10T05:49:21.804Z
软件包许可：Apache-2\.0

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40codatum/embed
原文对照：https://npmcn.com/package/%40codatum/embed/?lang=original
项目主页：https://github.com/codatum/codatum-embed-js/tree/main/packages/embed#readme
源码仓库：https://github.com/codatum/codatum-embed-js

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：345 kB，11 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- Node.js 要求：\>=20\.12
- 运行依赖：0 个
- 首次发布：2026-02-20T06:21:09.641Z
- 最新版本发布：2026-03-03T02:59:53.245Z
- 近 30 天下载量：10834（2026-10-10 至 2026-11-08，npm 官方下载统计）
- 已发布版本数：10（近 12 个月 10 个）

## 中文简介

Codatum 签名嵌入的文本库

## 安装

```sh
npm install @codatum/embed
```

也可以使用：`pnpm add @codatum/embed`、`yarn add @codatum/embed`、`bun add @codatum/embed`

## README

# @ codatum/ 嵌入

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

**文档**数字 : [已签名嵌入](https://docs.codatum.com/sharing/signed-embed) • 妇女 [一体化](https://docs.codatum.com/sharing/signed-embed/integration) • 妇女 [使用大小写](https://docs.codatum.com/sharing/signed-embed/use-case)。 。 。 . **包装器**数字 : [@codatum/embed-反应](https://github.com/codatum/codatum-embed-js/tree/main/packages/embed-react#readme), (中文(简体) ), [@ codatum/embed-vue](https://github.com/codatum/codatum-embed-js/tree/main/packages/embed-vue#readme)。 。 。 .

## 安装

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

## 快开始

```ts
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` | 对 | 见 [提供符号](https://npmcn.com/package/%40codatum/embed/#readme-tokenprovider) 下级 |
| `iframeOptions` | 没有 | 见 [框架选项](https://npmcn.com/package/%40codatum/embed/#readme-iframeoptions) 下级 |
| `tokenOptions` | 没有 | 见 [选项](https://npmcn.com/package/%40codatum/embed/#readme-tokenoptions) 下级 |
| `displayOptions` | 没有 | 见 [显示选项](https://npmcn.com/package/%40codatum/embed/#readme-displayoptions) 下级 |
| `devOptions` | 没有 | 见 [备选案文](https://npmcn.com/package/%40codatum/embed/#readme-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`** - 可选的。 如果返回, 则发送到嵌入符; 使用 [参数马普](https://npmcn.com/package/%40codatum/embed/#readme-parammapper) `encode()` 建造.

**示例**

```ts
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 主题 |
| `locale` | `string` | 浏览器的语言 | 地语区号( 如. `'en'`, (中文(简体) ), `'ja'`用于嵌入式UI |
| `className` | `string` | \- 说吧 | Iframe 元素应用的 CSS 类名 |
| `style` | `object` | `{display: 'block', width: '100%', height: '100%', border: 'none'}` | Iframe 的内置样式; 覆盖默认样式 |
| `attrs` | `Record<string, string>` | \- 说吧 | Iframe 的额外 HTML 属性( 例如 ). `{ title: 'Dashboard', 'data-testid': 'embed-iframe' }`(中文(简体) ) |

#### `TokenOptions`

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

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

#### `DisplayOptions`

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

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

#### `DevOptions`

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

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

**模拟选项** (当 `mock` 是对象 :

| 财产 | 类型 | 默认 | 说明 |
| --- | --- | --- | --- |
| `label` | `string` | `embedUrl` | 文本显示在模拟 Iframe 占位符中 。 当页面上嵌入多处时有用 . |
| `callTokenProvider` | `boolean` | `false` | 何时 `true`,电话 `tokenProvider` 打开 `init()`, (中文(简体) ), `reload()`和自动更新. |
| `loadingDelay` | `number` | `0` | 在嵌入器被装入前秒延迟 。 可用于测试加载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, 清除听众和计时器 。 如果已经销毁了,就不要. |

### 实例属性

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

### 容器属性

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

| 状态 | 何时 |
| --- | --- |
| `INITIALIZING` | `init()` 正在等待内容 |
| `READY` | 内容已装入并可见 |
| `RELOADING` | `reload()` 正在等待内容 |
| `REFRESHING` | 正在自动更新 |
| `DESTROYED` | (属性已删除) |

#### 示例: 自定义装入 UI

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

```html
<div id="dashboard" style="position: relative;">
  <div class="my-loading">Loading…</div>
</div>
```

```css
/* 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[] }` |
| `executeSqlsTriggered` | SQL被触发了嵌入式执行. | `{ type: 'EXECUTE_SQLS_TRIGGERED', params: EncodedParam[] }` |
| `executionSucceeded` | SQL 执行成功完成. | `{ type: 'EXECUTION_SUCCEEDED' }` |
| `executionFailed` | SQL 执行失败 . | `{ type: 'EXECUTION_FAILED', errorMessage: string }` |

解码为 `ParamMapper.decode(payload.params)`。 。 。 . `EncodedParam`: 见 [参数马普](https://npmcn.com/package/%40codatum/embed/#readme-parammapper)。 。 。 .

## 参数马普

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

### 基本用途

```ts
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?)`**

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

**`ParamMeta`** (可选,按键):

| 财产 | 类型 | 说明 |
| --- | --- | --- |
| `datatype` | `ParamDatatype` | 启用验证并改进打字。 见 [参数数据类型](https://npmcn.com/package/%40codatum/embed/#readme-param-datatypes) 见下文. |
| `required` | `boolean` | 若为 `true`, (中文(简体) ), `encode` 财务报告和审定财务报表 `decode` 掷出 `MISSING_REQUIRED_PARAM` 当参数缺失. |
| `hidden` | `boolean` | 若为 `true`,编码参数包括: `is_hidden: true` 所以嵌入体可以隐藏它们 从参数的形式. |

#### 参数数据类型

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

| `ParamDatatype` | JS/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`) (中文(简体) ). |
| `noValidate` | `boolean` | 何时 `true`,跳过所需的验证和数据类型. |

### 第一次使用类型

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

```ts
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_OPTIONS` | `createEmbed` | 选项无效 |
| `CONTAINER_NOT_FOUND` | `init` | 未找到集装箱元素 |
| `LOADING_TIMEOUT` | `init` 编号 : `reload` | `CONTENT_READY` 未收到 `tokenOptions.loadingTimeout`; 自动更新报告 `onRefreshError` |
| `TOKEN_PROVIDER_FAILED` | `init` 编号 : `reload` | `tokenProvider` 丢弃 |
| `MISSING_REQUIRED_PARAM` | `encode` 编号 : `decode` | 缺少必要的参数 |
| `INVALID_PARAM_VALUE` | `encode` 编号 : `decode` | 数值失败验证 |
| `UNEXPECTED_ERROR` | `createEmbed` 编号 : `init` 编号 : `reload` | 意外错误 |

### 处理错误

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

```ts
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);
  }
}
```

## 用法实例

以下模式显示了《公约》概述的共同一体化设想: [已签名的嵌入式使用例](https://docs.codatum.com/sharing/signed-embed/use-case)。 。 。 .

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

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

**客户端**

```ts
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); });
```

可运行 : [反应](https://github.com/codatum/codatum-embed-js/blob/main/examples/react/src/scenarios/Scenario1.tsx), (中文(简体) ), [阴道](https://github.com/codatum/codatum-embed-js/blob/main/examples/vue/src/scenarios/Scenario1.vue)

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

```ts
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](https://github.com/codatum/codatum-embed-js/blob/main/examples/server/src/scenarios/scenario1/handlers.ts)

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

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

**客户端**

```ts
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();
}
```

可运行 : [反应](https://github.com/codatum/codatum-embed-js/blob/main/examples/react/src/scenarios/Scenario2.tsx), (中文(简体) ), [阴道](https://github.com/codatum/codatum-embed-js/blob/main/examples/vue/src/scenarios/Scenario2.vue)

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

```ts
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](https://github.com/codatum/codatum-embed-js/blob/main/examples/server/src/scenarios/scenario2/handlers.ts)

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

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

**客户端**

```ts
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();
}
```

可运行 : [反应](https://github.com/codatum/codatum-embed-js/blob/main/examples/react/src/scenarios/Scenario3.tsx), (中文(简体) ), [阴道](https://github.com/codatum/codatum-embed-js/blob/main/examples/vue/src/scenarios/Scenario3.vue)

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

可运行 : [节点.js](https://github.com/codatum/codatum-embed-js/blob/main/examples/server/src/scenarios/scenario3/handlers.ts)

## 光盘N

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

```html
<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>
```

## 另见

-   **版本和更改日志**数字 : [版本](https://github.com/codatum/codatum-embed-js#versioning)
-   **安保和部署**数字 : [安保和部署](https://github.com/codatum/codatum-embed-js#security-and-deployment)
-   **支持的环境**数字 : [支持的环境](https://github.com/codatum/codatum-embed-js#supported-environments)

## 常见问题

### @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 和提交记录判断。

