@declarion/embed

中文文档
0.244.0发布于 2026/11/12MITTypeScriptES Module零依赖近 30 天下载 1.9万

主机集成SDK用于将声明屏嵌入为白-标签iframe.

中文使用文档
文档目录15 节
  1. 安装
  2. 嵌入如何工作
  3. Token 模型和持久性框架
  4. 快速启动: 浏览器核心
  5. 快速启动: 重现
  6. 快速启动: 服务器助手( 节点)
  7. 脚本标记( 无构建步骤)
  8. 导航模式
  9. 导航失败
  10. Iframe 沙盒
  11. 未保存的更改
  12. 嵌入时保持当前
  13. 诊断
  14. 拼凑起来
  15. 许可证

@ 声明/嵌入

嵌入式主机集成 SDK 声明 屏幕 作为第三方应用程序中的白标签 iframes.

装入时未装入声明外壳的屏幕路径 与 ?embed=1. 主机应用程序拥有外壳、导航和身份; 声明拥有屏幕渲染,数据访问,以及租户隔离. 这个 软件包是两边的输入式集成层 :

  • 浏览器核心 (单位:千美元)@declarion/embed——无依赖性. 创建 iframe,运行认证握手,自动调整大小,镜像导航.
  • 反应绑定 (单位:千美元)@declarion/embed/react) - (英语) <DeclarionEmbed />。 。 。 .
  • 服务器助手 (单位:千美元)@declarion/embed/server) - (英语) createEmbedSession,则 节点边薄荷呼叫。 留着 dcl_ API 密钥出自浏览器代码.

只安装主机 @declarion/embed它确实如此 没有 取决于 @declarion/react (全声明UI SDK).

安装

npm install @declarion/embed

react 财务报告和审定财务报表 react-dom 是可选的同伴依赖关系,仅由 @declarion/embed/react 输入.

嵌入如何工作

  1. 宿主的后端薄荷为目标租户和 用户为 createEmbedSession (单位:千美元)@declarion/embed/server),它称为 auth.create_embed_session 使用服务器控件的动作 dcl_ API密钥.
  2. 主机前端嵌入了屏幕 createDeclarionEmbed 或者说 <DeclarionEmbed />,通过一个 getToken 获取符号的回调 从主机后端.
  3. SDK运行一个 postMessage 握手: iframe要求一个符号 SDK提供它, 当iframe报告到期时更新它.

这个 dcl_ API 密钥从不离开主机后端. 对于多租户主机,请使用 最低特权 dcl_ 密钥,其服务账户所有者只持有该密钥 action:auth.create_embed_session; 租户范围钥匙只能用薄荷 自己的租户.

Token 模型和持久性框架

嵌入式代币是每件 (用户、租户) 并装满用户 有效权限。 用户可以打开的屏幕都有一个符号 - 是 不是每个屏幕。 每一次将它薄荷并再用; getToken 应该是 绑入身份,而不是当前屏幕.

切换屏幕速度快,因为 Iframe 是 持久性: 改变 route (单位:千美元) route 道具,或 handle.navigate(route)(表1) SPA-导航现有iframe. 该应用程序保持其加载的策略和 会话 - 它不重新装入或重新勾选每个屏幕的图案 。 第一个负载 获取一次 schema; 之后的屏幕开关是前端- 速度 .

更改嵌入式 身份 (不同用户或租户)必须重建 iframe,因为 iframe 缓存是权威形状的。 与 反应绑定,通过一个马厩 identityKey (例如:. `${tenant}|${user}`(三); 更改它重建了 iframe 和 重置 。 用核心来创建一个新的嵌入 为新身份。 每个屏幕访问在 Iframe 内执行 : 导航时间,永远不要缩小标志.

快速启动: 浏览器核心

import { createDeclarionEmbed } from "@declarion/embed";

const embed = createDeclarionEmbed({
  container: document.getElementById("declarion")!,
  declarionOrigin: "https://app.example.com",
  route: "/cases",
  getToken: async () => {
    const res = await fetch("/host-api/embed-token");
    return res.json(); // { token, expires_at }
  },
  onError: (err) => console.error(err.code, err.message),
});
// Later: embed.navigate("/cases/42"); embed.setTheme("dark"); embed.destroy();

快速启动: 重现

import { DeclarionEmbed } from "@declarion/embed/react";

export function CasesPanel({ tenant, user, route }) {
  return (
    <DeclarionEmbed
      declarionOrigin="https://app.example.com"
      route={route}
      // Stable per identity. Changing `route` soft-navigates the SAME iframe;
      // changing `identityKey` rebuilds it (a different user must not reuse the
      // prior user's authority-shaped schema).
      identityKey={`${tenant}|${user}`}
      getToken={async () => (await fetch("/host-api/embed-token")).json()}
      onError={(err) => console.error(err.code, err.message)}
    />
  );
}

快速启动: 服务器助手( 节点)

import { createEmbedSession } from "@declarion/embed/server";

// In a host backend route. The dcl_ API key is read from server config.
const session = await createEmbedSession({
  declarionOrigin: "https://app.example.com",
  // Prefer a least-privilege dcl_ key whose owner holds only
  // action:auth.create_embed_session. Keep it server-side only.
  apiKey: process.env.DECLARION_EMBED_API_KEY!,
  tenantCode: "acme", // target tenant
  userEmail: "[email protected]",
  screenCode: "cases_list",
});
// Return `session` ({ token, expires_at }) to the host frontend's getToken.

非节点后端的主机呼叫 POST /api/actions/auth.create_embed_session 通过 HTTP 直接操作 同样的 dcl_ API 键在 Authorization 头曰.

脚本标记( 无构建步骤)

包裹还装有一包IIFE核. 装入并使用 window.DeclarionEmbed.createDeclarionEmbed数字 :

<script src="https://unpkg.com/@declarion/embed/dist/declarion-embed.iife.js"></script>
<script>
  DeclarionEmbed.createDeclarionEmbed({ /* options */ });
</script>

导航模式

  • navigation: "self" (默认) - iframe 路由 Everyy in-frame 链接 内部( 符号是身份扫描的, 所以 iframe 已经授权) 打开用户可以去的任何地方),并发出 onNavigate({ mode: "self", route, screenCode, ... }) 这样主机就可以镜像 (原始内容存档于2017-09-21). Its URL.
  • navigation: "delegated" - iframe从不动于内联 发射 onNavigate({ mode: "delegated", route, screenCode, ... }) 编辑 主机决定打开什么(通过 route 道具/ 电源 handle.navigate) (中文(简体) ). 用此来将嵌入到单个屏幕上.

这个 onNavigate 事件携带 { mode, route, screenCode?, entity?, recordId? }。 。 。 .

由主机驱动 navigate (单位:千美元) route 改变道具,或 handle.navigate是一个 深链接命令:它以两个模式移动iframe(它是主机请求), 作为软的SPA导航——只有机体内LINKS被拦截/授权. 这个 同一符牌授权每个屏幕,所以不需要再加薄荷来切换.

导航失败

当内框导航无法处理时 -- -- 未知路线,或404 -- -- iframe 继续放放放 onNavigationFailed({ route, reason }) (单位:千美元)reason 实值 not_found 或者说 unresolved) (中文(简体) ). 主机拥有恢复:显示自己的恢复 未找到, 或重设其侧边栏选择 。 永远不要打破框架.

createDeclarionEmbed({
  // ...
  onNavigationFailed({ route, reason }) {
    hostRouter.showNotFound(route, reason);
  },
});

Iframe 沙盒

SDK设定 sandbox 默认运行完整应用程序的 iframe 省去顶端导航符号,所以被设定的应用程序无法导航主机 顶上窗口。 把它加宽 extraSandbox 选项 顶级导航标志被剥去,永远不能被再加. 留着吧 社区支助方案 frame-ancestors 配置为控件 谁 可能会设定应用程序.

未保存的更改

一个声明屏幕可以持有未保存的编辑. 当主机导航到 Iframe 远离这样的屏幕 - 通过自己的菜单,或 handle.navigate() - 应该 先与用户确认。 iframe通过 onEvent 回调 :

let embedDirty = false;
createDeclarionEmbed({
  // ...
  onEvent(event) {
    if (event.type === "dirty-changed") embedDirty = event.payload.dirty;
  },
});

// Before the host moves the iframe away:
if (embedDirty && !confirm("Discard unsaved changes?")) return;

导航 内部 iframe(一行点击,一后键)和主机驱动 route 变化/ handle.navigate 都已经由声明保护: iframe 在丢弃编辑前显示自己的确认对话框 。 这个 dirty-changed 事件是用于主机动作的 iframe CANNOT 截取 - 主机离开 通过自己的页面导航嵌入,或替换嵌入在身份上 开关。 用它来守护那些.

嵌入时保持当前

当在屏幕嵌入时调出声明部署时 iframe 不显示 Declarion 自己重新装入铬( 在 a 内错误) 白标签主机). 而是要求主机通过一个 reload-required 事件(通过 onError 有代码 embed.reload_required 和通过 onEvent) (中文(简体) ). 主机决定:重新装入iframe,显示自己的横幅,或者忽略. 长长的 Iframe 否则会保持其装入的屏幕开关 并且只在真实版本更改或SSE会话刷新时重新验证.

诊断

错误的配置被浮出水面 onError (类型) EmbedError 拥有稳定 code(中文(简体) ) 财务报告和审定财务报表 console.error。无信任 跨原产地 postMessage 框被无声地放下。 SDK探测器:

  • embed.invalid_options - 缺少必要的选项或格式不当.
  • embed.get_token_failed - 说吧 getToken 拒绝或返回错误结果.
  • embed.handshake_timeout - 在装入后窗口内不握手,通常是 declarionOrigin cSP 声明否认的不匹配或设定 (单位:千美元)DECLARION_FRAME_ANCESTORS 不列出主机来源).
  • embed.reload_required iframe要求主机重新装入.

此 SDK 和声明部署之间的协议版本不匹配 生成一个清晰的 console.warn 命名两个版本.

拼凑起来

真正的融合是两分之一 上面的片段是整个 合同:

  • 主机前端 - 让 <DeclarionEmbed /> (反应)或呼叫 createDeclarionEmbed (任何框架)和供应合成 getToken 调用。 SDK拥有iframe,the ready - > (中文) set-token 握个手, 调整大小, 导航, 和符号刷新 .
  • 主机后端 - 拿着 dcl_ API 密钥( 仅服务器侧) 和薄荷 短寿命、有范围地嵌入的标志 createEmbedSession 从 @declarion/embed/server。您的 getToken 回话从您那里取一个 拥有后端端.

这个 dcl_ 密钥绝不离开您的服务器; 浏览器只持有一个 短命的,有范围地嵌入符. 分拆是整个安全模式 保留 @declarion/embed/server 退出任何浏览器捆绑.

许可证

麻省理工学院

版本与发布记录

@declarion/embed 共发布 229 个版本,首次发布于 2026/05/22;过去 12 个月发布了 229 个版本。

版本发布日期距今
0.244.0latest2026/11/12今天
0.241.02026/11/11今天
0.240.02026/11/11今天
0.239.02026/11/11今天
0.238.02026/11/11今天
0.237.02026/11/11今天

关于 @declarion/embed 的常见问题

@declarion/embed 是什么?

主机集成SDK用于将声明屏嵌入为白-标签iframe.

如何安装 @declarion/embed?

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

@declarion/embed 支持 TypeScript 吗?

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

@declarion/embed 支持 ESM 还是 CommonJS?

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

@declarion/embed 可以商用吗?

@declarion/embed 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

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

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

@declarion/embed 还在维护吗?

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