mcpField
E
enable-tables-offline

enable-tables-offline

github.com/microsoft数据与数据库1.1k127 次安装今天更新
代码仓库

关于 enable-tables-offline

用于启用 Microsoft Dataverse 表离线支持的技能,面向离线配置维护者。它为指定表设置离线可用和更改跟踪标志,按顺序更新并发布自定义项。

主要功能

  1. 01启用表的离线可用标志
  2. 02启用更改跟踪
  3. 03逐表顺序更新元数据
  4. 04发布并验证自定义项
  5. 05跳过已启用的表

适用场景

  1. 01将表设为可加入移动离线配置
  2. 02为指定表开启更改跟踪
  3. 03确认元数据更新并发布

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/microsoft/power-platform-skills --skill enable-tables-offline

安装后在 Claude Code 中输入/enable-tables-offline确认已加载。

详细介绍

共享说明:shared-instructions.md — 请先阅读。

参考资料:

启用表的离线功能

在一个或多个 Dataverse 表的 EntityMetadata 上将 IsAvailableOffline=true 和 ChangeTrackingEnabled=true 设置为 true,然后发布自定义项。这是创作者门户中图像 4 所示(“可脱机使用”+“跟踪更改”)的前提条件;如果未同时启用这两项,表就无法添加到 Mobile Offline Profile。

按顺序执行(Dataverse 元数据锁),且具备幂等性:对已启用的表重新运行不会执行任何操作。

调用上下文和根目录绑定

此内部辅助工具始终作为子调用运行。在读取任何项目或执行任何命令之前, 执行 app-working-directory.md。 要求提供所有者的绝对路径 working_dir;如果提供了 --working-dir,它必须 指向同一个原生规范根目录。缺失、相对或冲突的根目录上下文会在访问项目之前返回 NEEDS_CONTEXT;无法访问的目录则返回 BLOCKED。绝不可使用启动时的 cwd,也不可引入其他根目录解析器。

接收 MOBILE_APP_ORCHESTRATING=1、orchestrator: setup-offline-profile、 working_dir、phase、approved_scope 以及提供的答案。保留所选环境 ID/URL/租户,以及精确的表、前提条件和发布许可列表。 此标记不代表已获批准。仅重用与当前离线审批相匹配的批准;范围缺失或变更时,向所有者返回 NEEDS_CONTEXT。对于 --plan-only 或规划阶段的交接,在允许的只读检查后、执行 PUT、发布或写入构件之前,返回拟议的前提条件变更。 门控响应不能解除仅提案模式。

将规范根目录约定应用于每次 shell 调用和文件工具调用。 每次调用都要重新提供绝对路径 PLUGIN_ROOT 和调用上下文;之前的 cd、导出或 shell 变量不会保留。值缺失时返回 NEEDS_CONTEXT;绝不可执行尚未解析的占位符。 所有关联的恢复命令、重新 GET 验证和重试,都必须使用同一根目录、环境和显式租户。只读取绝对应用内路径, 包括 <working_dir>/power.config.json、<working_dir>/memory-bank.md 以及下文所列的清单位置。

工作流

  1. 验证项目和身份验证 → 2. 确定表列表 → 3. 检查当前状态 → 门控 → 4. 对每个表执行 PUT EntityMetadata → 5. 发布 → 6. 验证 → 7. 总结

步骤 1 — 验证项目和身份验证
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
if [ ! -f power.config.json ] || [ ! -f app.config.js ]; then
  echo "BLOCKED: working_dir is not an initialized app" >&2
  exit 1
fi

在进行任何发现或修改之前,要求应用的 environmentId 与所有者所选环境一致。使用同一根目录执行此非持久化查找:

cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
environment_id=$(node -p "require('./power.config.json').environmentId || ''") || {
  echo "BLOCKED: unreadable power.config.json" >&2; exit 1;
}
if [ -z "$environment_id" ] || [ "$environment_id" != "<selected-environment-id>" ]; then
  echo "NEEDS_CONTEXT: selected environment does not match working_dir" >&2
  exit 1
fi
node "${PLUGIN_ROOT}/scripts/resolve-environment.js" "$environment_id" --no-cache --require-tenant

从解析器中获取 <envUrl> 和 <tenantId> 对应的环境 URL和租户 ID。在下方每次辅助工具调用和重试时,都要显式传入此租户;租户上下文缺失或冲突时返回 NEEDS_CONTEXT。 要求 ID、URL 和租户均与所有者的信息一致;绝不可为恢复操作切换账户或环境。若尚未通过身份验证,立即停止。

步骤 2 — 确定表列表

仅使用所有者 approved_scope 中精确列出的表许可列表。$ARGUMENTS 中以逗号 或空格分隔的表列表必须与该列表一致;--working-dir 用于指定根目录上下文,不是表名。表选择缺失或冲突时返回 NEEDS_CONTEXT;明确为空的批准列表表示已验证的无操作。

仅检查 <working_dir>/.datamodel-manifest.json;对于较新的应用,则检查 <working_dir>/docs/plan-artifacts/.datamodel-manifest.json,以验证所选表。清单不代表有权启用其中每一行。不要查找其他应用的清单,也不要擅自扩大许可列表。

步骤 3 — 检查当前状态

开始前打印:

“→ 正在查询 个表的当前 IsAvailableOffline + ChangeTrackingEnabled 状态……”

按顺序检查每个表:

cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" "<envUrl>" GET \
  "EntityDefinitions(LogicalName='<table>')?\$select=LogicalName,DisplayName,IsAvailableOffline,ChangeTrackingEnabled,IsCustomizable" \
  --tenant-id "<tenantId>"

生成状态表:

| Table              | IsAvailableOffline | ChangeTrackingEnabled | IsCustomizable | Needs change? |
|--------------------|--------------------|-----------------------|----------------|---------------|
| cr123_note         | false              | false                 | true           | YES (both)    |
| cr123_visit        | true               | false                 | true           | YES (track)   |
| contact            | true               | true                  | true           | NO            |

**硬性规则:**如果任何表的 IsCustomizable.Value=false,则无法修改该表。将其从变更集中移除,并在 DONE_WITH_CONCERNS 中标记——系统管理的表(大多数 OOB 表)需要使用此技能不支持的管理员解决方案补丁路径。

闸门 — 变更前审批

将步骤 3 中的状态表与所有者已批准的前置条件和发布差异进行比较。如果与当前 Gate 1 审批一致,则沿用该审批,不重复提示。否则,将状态表和 NEEDS_CONTEXT: offline prerequisite approval 返回给负责审批闸门的 /setup-offline-profile。不要扩大范围,也不要覆盖仅提案模式。

计划正文:

The following EntityMetadata changes will be PUT in sequence:

cr123_note   → set IsAvailableOffline=true, ChangeTrackingEnabled=true
cr123_visit  → set ChangeTrackingEnabled=true (IsAvailableOffline already true)

After all updates, targeted PublishXml will publish only the changed tables.

Tables already in the desired state are skipped (no API call).

如果用户拒绝,则停止。只有在获得对确切变更差异的批准后才能继续。

步骤 4 — 对每个表执行 EntityMetadata PUT

开始前打印:

“→ 正在依次为 个表更新 EntityMetadata(Dataverse 会串行处理元数据写入)……”

**⚠️ 并发规则 — 不得违反。**元数据写入会对每个组织持有独占锁。执行一个 PUT,等待收到 2xx 响应后,再执行下一个。不得批处理或并行调用。规则与 /add-dataverse 步骤 5 相同。

对于每个需要变更的表(已处于目标状态的表跳过):

cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/update-entity-offline-flags.js" "<envUrl>" \
  --table "<table>" \
  --offline true \
  --tracking true \
  --tenant-id "<tenantId>"

该辅助程序:

  • 重新读取 EntityMetadata,以获取当前的 MetadataId + SchemaName(PUT 请求正文中两者均为必需项;缺少时 Dataverse 会拒绝 PUT)。
  • 发送 MSCRM.MergeLabels: true,以保留显示标签(另一种设置会清除标签——切勿使用 false)。
  • 如果表已处于目标状态,则返回 { "status": 200, "noop": true, ... }(静默跳过)。
  • 对于 IsCustomizable.Value=false 的表(由系统管理;必须将其报告为 DONE_WITH_CONCERNS),返回 { "status": 200, "skipped": "uncustomizable", ... }。
  • 成功更新时返回 { "status": 204, ... }。
  • 自动处理 401 令牌刷新和 429 退避。

**如果辅助程序返回状态 403 PrivilegeCheckFailed:**用户缺少“Customize System”权限。打印表名和缺少的权限,然后停止。

**如果返回状态 400,且提示 ChangeTrackingEnabled cannot be disabled:**忽略——只有在将值从 true 改为 false 时才会触发该错误,而我们绝不会这样做。

每收到一个 204 后打印 ✓ <table>;对于无操作的表打印 ↷ <table> (already enabled);对于跳过的表打印 ⚠ <table> (uncustomizable)。

步骤 5 — 发布自定义项(针对性 PublishXml,失败时回退到 PublishAllXml)

开始前打印:

"→ 正在发布自定义项(对刚刚编辑的实体执行针对性 PublishXml)…"

使用针对性 PublishXml,仅针对实际修改过的实体 — 避免在共享环境中观察到的组织范围限流风暴(0x80071151「已有并发 PublishAll 正在运行」)。经验数据,2026-05-25。

cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
# Build the <entities> XML body from the list of tables modified in Step 4
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" "<envUrl>" POST \
  "PublishXml" --tenant-id "<tenantId>" --body '{
    "ParameterXml": "<importexportxml><entities><entity><table></entity></entities></importexportxml>"
  }'

为步骤 4 中 helper PUT 了标志的每个表替换 <entity>...</entity> 行。未执行任何操作或不可自定义的表应省略。

收到 204 时:成功 — 继续步骤 6。

收到 429 / 0x80071151(「已有并发发布正在运行」)时:通过 dataverse-request.js 的重试逻辑自动退避。如果重试 4 次后仍然失败,则返回 DONE_WITH_CONCERNS: 发布受共享环境瓶颈影响;元数据更改已提交,但 maker portal 需等到下次发布后才会刷新。下游技能(/setup-offline-profile)可以继续 — 元数据层级的写入是持久的。

**仅当针对性调用返回非限流错误(例如 0x80048d19),且所有者另行批准更广泛的发布时,才回退到 PublishAllXml。**仅批准发布指定表,并不代表授权发布无关更改。

cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" "<envUrl>" POST \
  "PublishAllXml" --tenant-id "<tenantId>" --body '{}'

超时但操作成功时的处理方式与 /setup-offline-profile 步骤 8 相同:如果客户端超时,但后续 GET 请求显示表的 EntityMetadata 中已设置这些标志,则视为成功。

步骤 6 — 验证

开始前打印:

"→ 正在重新查询 EntityMetadata,以确认标志已设置…"

对每个已修改的表重新运行步骤 3 中的查询。断言每个已更改的行上 IsAvailableOffline=true 且 ChangeTrackingEnabled=true。如果有任何不一致,则返回 BLOCKED — 某些内容静默拒绝了 PUT(极不可能;通常表明托管解决方案层掩盖了非托管更改)。

步骤 7 — 总结

打印:

✓ Offline prerequisites enabled on <N> table(s):
  - cr123_note    (IsAvailableOffline + ChangeTrackingEnabled set)
  - cr123_visit   (ChangeTrackingEnabled set; IsAvailableOffline already on)

Skipped (already enabled): contact

Next: return to the current /setup-offline-profile workflow.

在 <working_dir>/memory-bank.md 的 ## Offline profile 下更新时间戳和已验证的表列表。将结果返回给当前所有者;不要启动另一个离线设置工作流。

状态码

技能响应的第一行必须是以下内容之一:

  • DONE — 所有请求的表现在都已设置两个标志
  • DONE_WITH_CONCERNS: <list> — 跳过了部分表(不可自定义、发布警告等)
  • NEEDS_CONTEXT: <missing> — 无法解析表列表,且用户未提供
  • BLOCKED: <reason> — 身份验证失败、权限检查失败,或 PUT 后验证结果不一致

评论

支持 Markdown