关于 datasource-creator
datasource-creator 是用于 Datex Studio 的技能,可生成 OData 或 Flow 数据源配置。它强调先确认需求并验证模式,再生成、校验并按 owned 或 standalone 模式处理配置。
主要功能
- 01生成 OData 与 Flow 数据源配置
- 02依据需求简报确定字段与规则
- 03通过模式探索验证 OData 实体
- 04校验配置并按模式处理数据源
- 05支持 owned 与 standalone 两种模式
适用场景
- 01为报表、网格、编辑器或表单创建数据源
- 02将集合导航数据展平为标量字段
- 03组合多个 OData 查询或进行自定义聚合
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ datex/ skills --skill datasource-creator安装后在 Claude Code 中输入/datasource-creator确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/evals.jsonreferences/datasources.mdflow-datasources.mdodata-datasources.mdoutput-contracts.mdparameter-strategies.md详细介绍
数据源创建器
为 Datex Studio 创建 OData 或基于流的数据源配置。
参考资料
- ../datex-studio-shared/branch-setup.md — 分支和连接选择(多个技能共用)
- references/parameter-strategies.md — 参数策略、关联数据源、引号规则、级联参数
- references/datasources.md — 数据源分类:组件变体(
-datasource.json与-footprintDatasource.json)× 查询类型(OData 或流)、调用约定、层级限制、嵌入式数据源 - references/odata-datasources.md — OData 查询类型平台参考:queryOptions 树、筛选表达式、扩展、结果类型形状、预检架构验证、规范骨架
- references/flow-datasources.md — 流查询类型平台参考:分页与单结果形状、getFlow/getListFlow/getByKeysFlow 槽位、调用点语法、实体定义契约、规范骨架
- references/output-contracts.md — 经过计数、链接、自定义列和扩展转换后的最终输出;组件与方法输出
- ../collection-filter-authoring/SKILL.md — 通过对象集合实现 Any/All 筛选及其网格/运行时集成
依赖项
必需背景知识: 阅读 schema-explorer 技能以发现 OData 实体,并阅读 odata-execution 技能以构建和验证查询。
OData 数据源必须进行架构探索—— 类型定义必须基于经过验证的架构构建,而不能只依赖示例或模板。流数据源可能会在底层聚合 OData 查询的数据,但如果它使用的是现有数据源,我们就假定这些数据源已经过验证。
Footprint 连接——请先查阅
footprint-entity-expert。 如果数据源将查询 Footprint WMS 实体(Tasks、Shipments、ArchivedShippingLicensePlateContents、LicensePlate、Lot、Material 等),请在架构探索前查阅footprint-entity-expert。它说明了哪些实体对应特定业务概念、指向 Owner/Project 的正确导航链、重量计算分支以及分页要求——这些背景信息不会体现在 OData 元数据中。非 Footprint 连接(自定义应用、非 WMS 数据)无需查阅。
前置条件检查
开始架构探索或生成数据源之前,检查对话上下文中是否已有需求简报(由 requirements-gathering 或 report-creator 生成)。
- 存在需求简报 → 使用该简报。简报提供字段清单、语义角色和业务规则,用于确定要探索哪些实体以及要包含哪些字段。根据简报验证数据源输出。
- 不存在需求简报 → 先调用
requirements-gathering技能。单独调用 datasource-creator(而非从 report-creator 调用)时会发生这种情况。简报可确保你不会遗漏字段、错误映射实体或跳过计算字段。
不要跳过此检查。不了解所需字段及其含义就构建数据源,会导致配置不完整并需要返工。
输入/输出约定
| 方向 | 项目 | 详情 |
|---|---|---|
| 输入 | 连接 ID | 必填——用于标识 Footprint API 连接 |
| 输入 | 分支 ID | 必填——用于验证和更新的目标分支 |
| 输入 | 模式 | owned(嵌入到托管网格 / 编辑器 / 表单 / 报表中)或 standalone(更新到分支)。默认为 owned——见下文 |
| 输入 | 数据源类型 | OData(基于查询)或 Flow(自定义 JS 代码) |
| 输出 | JSON 配置文件 | 由 dxs datasource generate 或 generate-flow 生成 |
| 输出(owned) | 文件路径 + 引用名称 | 对于报表,使用 --owned FILE:ALIAS 调用 dxs report datasource add;对于网格 / 编辑器 / 表单,则拼接到宿主的 datasources[] 中 |
| 输出(standalone) | 已更新的数据源 | 上传到分支,通过 datasource-fields 验证,并发现测试数据 |
模式默认为 owned。 如果调用方未指定模式,请将数据源设为 owned,并在返回摘要中说明。只有在符合覆盖条件时才切换为 standalone——确实有第二个使用方需要相同查询、使用方类型无法容纳 owned 数据源(选择器、列表、日历、卡片、小组件)、Flow 数据源必须通过 $datasources.<Package>.<name> 调用该数据源,或该数据源随库包一起发布。规则和完整的覆盖条件列表见 references/datasources.md → 默认由宿主持有。
按模式划分的步骤
| 步骤 | Owned | Standalone |
|---|---|---|
dxs datasource generate / generate-flow | 是 | 是 |
dxs datasource context(类型定义) | 是 | 是 |
dxs datasource validate(针对分支) | 是 | 是 |
dxs configuration upsert datasource(更新到分支) | 否 | 是 |
datasource-fields(更新后的验证) | 否(延后到报表上传后) | 是 |
测试数据 / in_params 发现 | 否(由 report-creator 处理) | 是 |
对于网格、编辑器或表单,owned 列将继续执行 references/datasources.md → 创建 Owned 数据源 中的拼接流程;宿主会取代独立数据源更新步骤接受验证。
工作流
[requirements brief in context?]
|
+-----+-----+
| |
YES NO
| |
use it invoke `requirements-gathering` skill
| |
+-----+------+
|
[determine type: OData or Flow]
|
+-----+-----+
| |
OData Flow
| |
schema -> schema -> (REQUIRED: validate entities/properties
query -> the flow code will query against the connection)
generate create standalone OData datasources (generate + dxs configuration upsert datasource each)
| write type-def YAML (from validated schema, NOT from examples)
| write flow TS code (referencing $datasources.<RepoName>.<ref_name>)
| generate-flow
| |
+-----+------+
|
context (dxs datasource context - get type defs)
validate (dxs datasource validate - both modes)
|
+-----+-----+
| |
Standalone Owned
| |
dxs configuration upsert datasource
return JSON file path
fields + ref name
test data
return ref
何时使用 OData,何时使用 Flow
| 使用 OData 的情况 | 使用 Flow 的情况 |
|---|---|
| 所需字段都是标量字段,或可通过单个导航属性访问(路径中不包含集合) | 结果需要将集合导航属性中的数据扁平化为标量字段(例如,单实体货件中,OrderLookups 或 WarehousesContactsLookup 必须作为扁平字段显示) |
| 结果本身是一个可直接映射到表格/表格区域的集合(例如 ShipmentLines) | 需要将多个 OData 查询合并或联接为一个结果 |
| 简单的基于参数的筛选已足够 | 计算字段需要来自多个实体的数据或自定义聚合 |
| 数据位于 Footprint OData 架构中 | 数据行来自云端的 *-storage.json 组件,通过 $db 按函数层级读取(基于存储的网格/选择器)——请参阅 ../db-query/references/flow-db-datasources.md |
如何判断:运行 dxs report datasource-fields <ref> --branch <id>(对于自有报表,使用 --report <ref>)。如果输出中有 collections: 部分,且其中包含你需要放在独立文本框(而非表格)中的字段,请使用 Flow 数据源。OData 数据源中的集合无法绑定为扁平的 DataSet 字段——它们会静默地解析为空白。
**生产环境中的模式:**所有现有的、具有复杂导航的 Datex Studio 报表(装箱单、BOL、主 BOL)都使用 Flow 数据源获取页眉/明细数据。Flow 代码会获取 OData 实体,并将集合扁平化为标量字段。OData 数据源用于简单的列表查询(行项目、查找表)。
**Flow 数据源与架构探索:**Flow 数据源并非绕过架构探索的捷径。Flow 数据源的 JavaScript 代码通常会查询一个或多个 OData 实体并重塑数据。在编写类型定义或 Flow 代码之前,必须使用
schema-explorer验证目标连接具有预期的实体和属性。现有报表示例和模板展示了在某些连接上曾经可行的方案——它们只是初步假设,并非针对当前连接验证过的设计。
返回调用方
完成工作流后(无论是独立模式还是归属模式),请向调用技能或用户返回以下结构化摘要:
- 引用名称 —
-r的值(例如:ds_shipment_bol) - 文件路径 —
-o的输出路径(例如:reports/bol/ds_shipment_bol.json) - 模式 —
owned(本地文件,需合并到宿主的datasources[],或使用--owned注册)或standalone(已执行 upsert)。注明使用的模式;如果是standalone,还需说明使其成立的覆盖项 - 结果类型 —
single或collection(取自生成配置的resultIsCollection) - in_params — 输入参数名称和类型列表(取自配置的
inParams);若没有则留空 - 字段摘要 — 结合 datasource 上下文描述最终的公开
result,并在持久化后参考datasource-fields。包括自定义字段和链接字段,并标注集合。单独使用queryOptionsObjectTypeDef可能只会得到基础实体,遗漏扩充字段;请参阅 output-contracts.md。
返回示例:
Datasource: ds_shipment_bol
File: reports/bol/ds_shipment_bol.json
Mode: owned
Result type: single
in_params: shipmentId (number)
Fields:
Id: number (key)
BillOfLading: string
LookupCode: string
Carrier.Name: string
Carrier.ScacCode: string
Status.Name: string
ShipmentLines [collection]:
LineNumber: number
OrderLine.Material.LookupCode: string
OrderLine.Material.Description: string
返回中的集合字段需要调用方采取措施。 如果字段摘要中包含 [collection] 标记,调用方必须选择:
- Flow datasource(首选): 将 datasource 改写为 flow,将集合展平为标量字段。调用方将获得不含集合的扁平字段列表。
- 子数据集(替代方案): 在报表中创建单独的 DataSet,使用
CommandText: "$.ds_name.result.CollectionPath.*",并在独立文本框中使用=First(Fields!Field.Value, "child_dataset")。此方法可行,但会增加复杂性。 - 单独的 OData datasource: 直接查询集合实体(例如:
ShipmentOrderLookups?$filter=ShipmentId eq {id}),将其作为独立 datasource。仅当该实体支持直接筛选时才可行。
切勿将集合路径字段(例如:OrderLookups.Order.OwnerReference)作为单结果 DataSet 上的扁平字段传递给 dxs report dataset add --field。这些字段会被静默地渲染为空白。
OData datasource 生成
平台参考: references/odata-datasources.md 介绍了底层 Datex Studio 文件结构,包括
queryOptions树、筛选表达式语法、扩展、结果类型契约、单对象与集合相关陷阱,以及规范骨架。遇到以下情况时请参阅该文档:分析生成配置为何采用当前结构、在生成器之外编写或手动编辑 JSON,或排查导入错误。
使用 dxs datasource generate 生成 OData datasource 配置:
dxs datasource generate \
-c <connection_id> \
-q '<odata_query>' \
-r <reference_name> \
-t "<reference_name>" \
-d "<description>" \
--api-setting-name <app_level_name> \
-o ds_name.json \
--branch <branch_id>
主要标志
| 标志 | 用途 |
|---|---|
-c | 连接 ID |
-q / -Q | OData 查询字符串 / 查询文件(互斥) |
-r | 引用名称(有效的 JS 标识符,遵循 ds_ 前缀约定) |
-t | 显示标题(必须与 -r 匹配——参见命名约定) |
-d | 描述(务必提供) |
--api-setting-name | 来自 dxs source branch settings 的应用级设置 name(不是连接名称,例如 DSV)。可选——省略时,CLI 会自动将 -c 连接的名称与 apiConnectionName 等于该名称的设置匹配并解析(适用于 host 和 ComponentModule 分支)。仅在存在多个 API 连接设置、需要消除歧义时显式传入。 |
--param-keys | 用于采用 Entity(0) 模式的单实体查询 |
--detect-params | 使用 ${$datasource.inParams.paramName} 语法检测筛选参数(标记为 required: false 并添加保护) |
--dynamic-filter PROP:TYPE | 可选 UI 筛选(生成带 $utils.isDefined() 保护的条件筛选) |
--dynamic-orderby PROP | 可选 UI 排序 |
--param-filter PROPERTY:OPERATOR:PARAM_NAME:TYPE | 带 $utils.isDefined() 保护的条件筛选。运算符:eq、ne、gt、ge、lt、le、in、contains、startswith、endswith |
--linked name:type:target | 链接的数据源。oneToOne/oneToMany 使用 3 部分;oneToOneWithMerge 使用 4 部分,并带有 $entity.Field |
--linked-param LINKED_NAME:PARAM_ID:EXPRESSION | 将父字段映射到链接数据源的输入参数 |
--custom-column | 添加计算列 |
--private | 将访问修饰符设为 private(默认:public) |
-o | 输出文件路径 |
--branch | 目标分支 ID |
参数策略
| 需求 | 标志 | 查询语法 |
|---|---|---|
| 限定为一个实体(详情/文档) | --param-keys | Entity(0)?$select=... |
| 报表提供的筛选参数 | --detect-params | 在 $filter 中使用 ${$datasource.inParams.paramName}。这些参数会统一标记为 required: false,并添加 $utils.isDefined() 保护——见下方说明 |
| 可选 UI 列表筛选 | --dynamic-filter PROP:TYPE + --dynamic-orderby PROP | Entity?$select=...(无占位符) |
| 带保护的条件筛选 | --param-filter PROPERTY:OPERATOR:PARAM_NAME:TYPE | 自动为其追加的谓词生成 $utils.isDefined() 保护,而基础 -q 筛选保持无条件 |
流数据源生成
平台参考: references/flow-datasources.md 介绍了底层 Datex Studio 文件结构——分页与单结果执行形态、
getFlow/getListFlow/getByKeysFlow插槽、通过referenceName调用的语法、实体定义输出契约,以及两种形态的规范骨架(包括枚举下拉菜单模式)。在判断用例需要哪种形态、在生成器之外编写 JSON,或字段在运行时静默变为 undefined 时,请参考此文档。
流运行时模型(重要)
流数据源只能从两种合法来源之一获取数据,不能使用原始 OData 查询字符串:(a)分支上已有的独立 OData 数据源,通过 $datasources.<RepoName>.<ref_name> 访问(下文介绍);或(b)云存储,通过函数层级的 $db.<Package>.<storage_referenceName> 谓词 API 访问——这是基于 *-storage.json 组件构建网格或选择器所采用的模式。$db 路径有其自身的编写规则(分页、动态筛选/排序、getQuery() 工厂);请参阅 ../db-query/references/flow-db-datasources.md。本节其余内容介绍来源(a)。
流数据源代码不会执行原始 OData 查询。相反,流通过 $datasources 对象引用分支上已有的独立 OData 数据源。独立数据源的作用域由其存储库模块名称限定(存储库的 uniqueIdentifier 名称,例如 PurchaseOrders、AsnOrders),因此路径为 $datasources.<RepoName>.<ref_name>:
// CORRECT: Reference standalone OData datasources with module scope, unwrap .result
const shipmentResp = await $datasources.PurchaseOrders.ds_shipment.get({ shipmentId: $flow.inParams.shipmentId });
const shipment = shipmentResp.result;
// For collection datasources, .result is an array:
const contactsResp = await $datasources.PurchaseOrders.ds_wh_contacts.get({ warehouseId: shipment.ActualWarehouse.Id });
const firstContact = contactsResp.result?.[0]?.Contact;
// Set output via $flow.outParams.result
$flow.outParams.result = { Name: shipment.Name, Phone: firstContact?.PrimaryTelephone };
// WRONG: Missing module scope — datasources are not at the root level
const result = await $datasources.ds_shipment.get({ shipmentId: 123 });
// WRONG: Raw OData queries in flow code — this is NOT how flows work
const result = await $datasource.getList({ query: 'Shipments(123)?$expand=Carrier' });
流代码运行时变量:
| 变量 | 用途 |
|---|---|
$flow.inParams | 访问流数据源的输入参数 |
$flow.outParams.result | 设置流的输出(赋值,不要返回) |
$datasources.<RepoName>.<ref_name> | 访问分支上的独立数据源(作用域由存储库名称限定) |
解包响应: 所有 $datasources 调用都会返回 { result?: ... }。对于 --param-keys 数据源,result 是单个对象;对于集合数据源,result 是一个数组。访问字段前,务必先访问 .result。
构建流数据源的工作流程:
- 为流所需的每个查询创建独立 OData 数据源——每个数据源都使用
dxs datasource generate+dxs configuration upsert datasource - 编写流代码,通过
$datasources.<RepoName>.<ref_name>.get()或$datasources.<RepoName>.<ref_name>.getList()引用这些数据源(其中<RepoName>是通过dxs source repo list获取的存储库name) - 使用
dxs datasource generate-flow生成流配置,其中会嵌入流代码和类型定义 - 流数据源本身默认是自有的(嵌入其宿主中),但其 OData 依赖项必须在分支上独立存在——
$datasources.<RepoName>.<ref_name>只能解析独立配置,因此嵌入式依赖项无法通过流代码访问。这是 references/datasources.md → 默认自有 中长期有效的例外之一。
$datasources API:
| 方法 | 适用场景 | 返回值 |
|---|---|---|
$datasources.RepoName.ds_name.get({ paramName: value }) | OData 数据源使用 --param-keys(单个实体) | 单个对象 |
$datasources.RepoName.ds_name.getList({ paramName: value }) | OData 数据源返回集合 | 对象数组 |
将输入参数作为对象传入——键必须与 OData 数据源的 inParams 完全一致。
高容量集合数据源的分页
OData 响应每次请求最多返回 5,000 条记录。如果某个流需要聚合跨日期范围或多个仓库范围的 Tasks、ArchivedShippingLicensePlateContents、Shipments 或其他实体,就必须显式分页——不会自动继续获取,截断也不会发出提示。
要进行分页,流调用的独立 OData 数据源必须声明一个 skip inParam,且其查询必须使用 $top=5000&$skip=${$datasource.inParams.skip}。然后,流通过 getList({ ..., skip }) 循环获取数据,并在返回的页面记录数不足时退出。
完整模式请参阅 ../datex-studio-shared/flow-code-patterns.md#odata-pagination--the-5000-record-cap,其中包括数据源查询格式、--detect-params 要求,以及标准获取循环。如果你正在构建的流数据源,其底层查询可能会超过 5,000 行,请从一开始就为底层 OData 数据源接入分页;之后再补充则需要重新生成数据源和流代码。
--param-keys 创建的是命名参数,而不是 keys 数组。 当 OData 数据源使用 --param-keys(例如 Shipments(0))时,生成器会创建以实体键命名的 inParams(例如 shipmentId)。务必查看生成配置中的 inParams,以获取准确的参数名称。切勿使用 { keys: [value] }——不存在这种模式。
// CORRECT: Use the actual inParam name from the generated config
const resp = await $datasources.ds_shipment.get({ shipmentId: $flow.inParams.shipmentId });
// WRONG: There is no "keys" parameter — this causes TS compilation errors
const resp = await $datasources.ds_shipment.get({ keys: [$flow.inParams.shipmentId] });
生成命令
使用 dxs datasource generate-flow 生成流数据源配置:
dxs datasource generate-flow \
-r ds_lookup -t "ds_lookup" -d "Custom lookup datasource" \
--type-def types.yaml \
--get-flow get.ts \
--in-param id:number \
-o ds_lookup.json --branch <branch_id>
必需项: 至少指定一个流方法(--get-flow、--get-list-flow 或 --get-by-keys-flow),并提供一个类型定义文件(--type-def)。
主要标志
| 标志 | 用途 |
|---|---|
--type-def FILE | 定义输出类型结构的 YAML/JSON 文件(必需) |
--get-flow FILE | 用于获取单个实体的 JavaScript 代码 |
--get-list-flow FILE | 用于获取集合的 JavaScript 代码 |
--get-by-keys-flow FILE | 用于按键获取数据的 JavaScript 代码(需要 --key) |
--on-init-flow FILE | 用于初始化的 JavaScript 代码 |
--in-param NAME:TYPE | 输入参数(在参数可选时追加 ?,例如 search:string?)。可重复指定 |
--key NAME:TYPE | 键字段定义。可重复指定 |
--collection | 强制设置 resultIsCollection=true |
--single | 强制设置 resultIsCollection=false |
类型定义 YAML 格式
- id: Id
type: number
- id: Name
type: string
- id: Items
type: object
isCollection: true
objectTypeDef:
- id: LineNumber
type: number
有效类型:string、number、boolean、date、object、union、blob。
增强标志(--dynamic-filter、--linked、--custom-column 等)的用法与 OData 数据源相同。对于集合导航路径,请使用 collection-filter-authoring;两个生成器都支持显式点分隔的 --dynamic-filter 路径,也支持使用 --all-dynamic-filters --include-collection-filters 自动遍历集合。
文件大小限制: 所有代码文件和类型定义文件的大小上限均为 512 KB。
服务端变体(FPDS — -footprintDatasource.json,typeId 19)
以上所有内容都会生成云端 -datasource.json(configurationTypeId: 6),可由函数和选择器调用。当数据源必须由操作调用时(Footprint 服务端层),请改为编写 FootprintDatasource(FPDS) 变体。OData 和 flow 查询类型都支持此变体;正文结构与云端变体相同,只有变体字段不同。
生成器没有 FPDS 标志——请完全按照上述方式生成配置,然后编辑生成的 JSON:
- OData FPDS: 将
configurationTypeId: 19。apiSettingName已是该分支的 Footprint API 连接名称(由generate设置),请保留不变。(仅修改一个字段。) - Flow FPDS: 将
configurationTypeId: 19,并且将apiSettingName设为该分支的 Footprint API 连接设置名称(generate-flow会将其留为null;请通过dxs source branch settings <branch_id>获取名称——通常为FootprintApi,但不同分支可能不同,例如fpapiconn)。
其余内容——queryOptions / flow 插槽、outParams、keyDef 和显式的 null 插槽——均与云端变体相同。参见 references/datasources.md → 变体之间的结构差异。
使用 footprintdatasource CLI 类型进行验证和推送(dxs datasource … / dxs configuration upsert datasource 路径固定连接到云端 datasource/6 端点,无法生成 typeId 19):
dxs configuration validate footprintdatasource -b <branch_id> -D ds_name.json # exit 1 = errors found
dxs configuration upsert footprintdatasource -b <branch_id> -D ds_name.json
upsert 按 referenceName 查找(创建或更新)。使用 dxs configuration delete footprintdatasource <id> -b <branch_id> -y 删除。
选择器绝不能由 FPDS 支持——选择器依赖项必须是云端 -datasource.json 变体(参见 references/datasources.md)。FPDS 目标供操作层调用方使用。
上下文命令
关于如何获取和读取上下文响应(包括后端与前端符号筛选)的完整指南,请参见 ../datex-studio-shared/context-navigation.md。若要快速确认 $types.<Package>.* 自定义类型或枚举成员是否存在,而无需解析完整的上下文数据块,请使用其中介绍的 nomenclature 注册表。
dxs -O json datasource context <file.json> --branch <branch_id>
返回用于编写表达式或 TypeScript 代码的设计器类型定义。适用于 OData 和 flow 数据源。在运行 generate / generate-flow 后执行,以便在编写自定义列或 flow 代码之前了解可用字段。
对于数据源,主要的作用域符号是 $entity、$ccentity 和 $datasource(位于 flowContext 或 linkedDatasourcesContext 中)。appContext 包含其他服务——请阅读 defaultContext.imports,以确定哪些服务可用(参见共享参考)。
验证
dxs datasource validate <file.json> --branch <branch_id>
根据分支验证数据源配置。独立模式和归属模式都必须运行,然后才能继续执行 upsert 或上传报告。此命令会单独验证数据源——它不会捕获使用方形状不匹配的问题,因此即使数据源的形状没有任何使用方可用,也仍会通过验证。
分支会运行两项独立的服务端检查。发布时以及通过 dxs configuration validate 都会触发这两项检查;此命令只能部分代替它们:
- 使用情况检查 — grid/selector 要求
getList+getByKeys;editor/form 要求单个结果上的get;每个linkedDatasources条目都必须与其链接type匹配(参见references/flow-datasources.md→ 链接数据源类型)。此检查仅在验证使用方时触发(dxs configuration validate <consumer type>),因此无法说明单独验证的数据源是否符合要求。 - 隔离检查 — 检查数据源自身的形状,因此,即使没有任何使用方,形状错误的数据源也不再像以前那样可以顺利发布。此检查也适用于 FootprintDatasource 配置。本仓库文档说明了流程槽规则,而此命令的本地 lint 会在离线环境中复现这些规则 — 参见
references/flow-datasources.md→ 三种执行形状。此检查还会检查 OData 查询选项和最终输出契约;CLI 现在也会在本地检查输出一致性。生成会在增强和链接解析完成后最终确定输出。
此命令无法检查筛选查询的两件事,执行 upsert 前值得花一分钟确认:
筛选列是否已编入索引,以及限定查询范围的谓词是否可能在运行时消失——每个用于参数化筛选条件的 generate 标志都会用 $utils.isDefined() 守卫将其包起来,因此参数缺失时会对整张表开放查询。参见
references/odata-datasources.md → 另请检查:筛选列是否已编入索引?
和 → 守卫式范围限定筛选条件会抵消索引检查。
阅读报告
该命令会运行本地流程形状和输出契约检查,并将检查结果与服务端的结果合并,因此一次运行即可报告两者的结果。每个条目包含四个字段:
| 字段 | 值 | 含义 |
|---|---|---|
origin | local | server | 由哪个检查器生成。local 是 CLI 自带的 lint(可离线复现);server 来自分支,可能随分支变化。 |
severity | error | warning | 错误会阻止操作;警告仅供参考。 |
source | — | 标记该问题的规则或子系统。 |
message | — | 检查结果。 |
退出代码:
- 出现任何错误(本地或服务端)→ 退出代码为 1,
validation_errors[]会将错误和警告合并到同一个列表中。非零退出表示验证发现了错误——请阅读负载、修复配置,然后重新验证。这不表示 CLI 出错,也不意味着应该停止或不作修改地重试命令。 - 只有警告 → 退出代码为 0,并返回
validation_result: {status: "valid", warnings: [...]}。仍需阅读警告;它们只是不阻止操作。
dxs configuration validate datasource 和 dxs configuration validate footprintdatasource 会运行相同的本地 lint,并报告相同的合并结果结构——这两个命令特意保持同步。其他配置类型只报告服务端检查结果。CLI 中完整的退出代码对照表(包括 dxs function validate,它在出现错误时仍会返回 0):../datex-studio-shared/configuration-roundtrip.md。
如果本地检查发现问题时服务端调用本身失败,报告会保留本地检查结果,并添加一条 validate API call failed (…),其 origin: server——本地检查结果仍然有效,也仍值得修复。
独立完成
验证通过后,完成独立工作流:
1. 新增或更新
dxs configuration upsert datasource -D <file.json> --branch <branch_id>
2. 验证字段
dxs report datasource-fields <reference_name> --branch <branch_id>
请检查输出中的以下内容:
in_params名称——必须与--datasource-param中的名称完全一致(不要想当然地使用id)result_type——single和list会影响报告布局collections——可用于表格部分的导航属性集合- 字段路径——表达式所用的精确点号表示法路径
3. 查找测试数据
不带模板字面量参数查询实体,使用基础筛选条件 + $top=5 + $orderby 查找最近的记录:
dxs odata execute -c <id> \
-q 'Entity?$top=5&$filter=<base_filters>&$select=Id,<param_fields>&$orderby=<date_field> desc'
使用 $count=true&$top=1 验证数量:
dxs odata execute -c <id> \
-q 'Entity?$count=true&$top=1&$filter=<full_filter_with_real_values>&$select=Id'
4. 删除数据源
按引用名称或配置 ID 删除:
dxs datasource delete ds_my_report --branch <branch_id>
dxs datasource delete --id 42 --branch <branch_id>
如果按引用名称查找返回 404,请使用 --id(在包含组件模块的分支上可能会发生这种情况)。通过 dxs datasource list 获取 ID。
命名约定(至关重要)
数据源的引用名称(-r)、显示标题(-t)、RDLX-JSON DataSet 名称和 --owned 别名必须完全一致:
-r ds_my_report -t "ds_my_report" # generate: -t = -r
DataSet.Name = "ds_my_report" # RDLX-JSON
--owned ds_my_report.json:ds_my_report # report datasource add: file:alias
规则:
- 使用
ds_前缀约定 - 必须是有效的 JS 标识符(以字母、
_或$开头,不含空格或连字符,且不能以数字开头) - 示例:
ds_shipment_bol、ds_orders、ds_inventory_summary
关键规则
- 使用
schema batch,将多个架构发现调用合并为 2–3 个请求,而不是 9 个以上的顺序调用 - 检查复合键——某些实体有多个字段组成的键,会影响
--param-keys的行为 - 查询测试时使用
$top=1——没有限制的大型查询会超时 $值使用单引号——Shell 会展开双引号中的$;在-q、--linked、--custom-column、--datasource-param、--linked-param中使用单引号- 始终在
$expand中包含$select——不带$select的裸$expand会提取所有字段
常见错误
| 常见错误 | 修正方法 |
|---|---|
将管理器连接名称用作 --api-setting-name | 使用 branch settings 中应用级别的 name,或完全省略该标志,让 CLI 根据分支的 AppConfig 自动解析 |
在 branch settings 输出中查找 apiConnectionId | 不要这样做——AppConfig 设置记录通过 名称 标识连接,即 apiConnectionName。将 -c 连接与 apiConnectionName 等于其名称的设置匹配,然后将该设置的 name 用作 --api-setting-name(或者直接省略该标志并自动解析)。记录结构和枚举序列化注意事项:../datex-studio-shared/branch-setup.md |
generate 无法解析 API 设置时盲目重试 | DXS-DS-021 错误表示你的 -c 连接未关联到分支上的 Footprint API 设置。请显式传入 --api-setting-name(取自 dxs source branch settings),或在 Studio 中将连接关联到分支的 AppConfig——不要重新运行相同的命令 |
| 从另一个分支/应用复制数据源配置 JSON 并原样执行 upsert | apiSettingName 是应用级别的——复制的值可能指向目标应用中未定义的设置。upsert 会静默接受该值;随后 Studio 会标记“缺少 API Connection 设置 <name>”(而在 CAC 上,dxs ng push 会在 DXS-NG-047 预检中失败)。请先检查 dxs source branch settings <target-branch>,或针对目标分支重新生成 dxs datasource generate(会自动解析;如果没有关联连接,则返回 DXS-DS-021)。如果应用完全没有 API 连接,请在 Studio 中关联一个——CLI 不会创建连接 |
在筛选条件中使用 {Param} 而非 ${$datasource.inParams.Param} | --detect-params 要求使用模板字面量语法——简单的 {花括号} 会被静默忽略 |
仅使用 --dynamic-filter 处理报表传入的参数 | 动态筛选条件是可选的 UI 筛选条件——对于报表传入的参数,请使用带模板字面量的 --detect-params |
认为 --detect-params 会将参数设为必填 | 它会设置 required: false,并为整个 $filter 添加保护条件;没有任何生成标志会生成必填且不带保护条件的筛选条件。如果谓词限定了查询范围,请在 JSON 中将其改为 required: true,或在使用方强制执行该范围——请参阅 references/odata-datasources.md |
upsert 后未验证 in_params | 始终运行 datasource-fields,并确认 in_params 已填充,而非空值 |
认为 inParam 名称是 id | 检查 datasource-fields 输出——名称可能是 shipmentId、orderId 等 |
数据源 -t 标题与 -r 引用名称不同 | 标题和引用必须完全一致(例如,-r ds_foo -t "ds_foo") |
| 链接目标缺失,或其基数/键不兼容 | 解析实际的分支目标,并在生成前修正其结构;请参阅 output-contracts.md |
| 认为生成的输出只有基础实体字段 | 使用最终确定的契约,包括链接/自定义列和 OData 计数,并将其同步到使用方 |
在 oneToOne 上使用 mergeByValue | 只有 oneToOneWithMerge 才有第 4 个组件 |
| 在筛选条件中硬编码日期 | 使用 ${new Date(...).toISOString()} 实现动态日期 |
| 在流程代码中使用原始 OData 查询 | 流程代码必须通过 $datasources.RepoName.ds_name.get() / .getList() 引用独立数据源——切勿嵌入 OData 查询字符串 |
使用不带模块作用域的 $datasources.ds_name | 独立数据源的作用域位于仓库模块下——请使用 $datasources.RepoName.ds_name(例如 $datasources.PurchaseOrders.ds_shipment)。省略模块前缀时,流程验证器会报告“Property does not exist on type 'IDatasourceService'” |
| 分支上的流程数据源没有独立的 OData 依赖项 | 先创建并执行 OData 数据源的 upsert,然后再编写引用这些数据源的流程 |
编辑完成后,请调用 post-edit-verification,以发现描述、JSON 或架构违规。进行最终审核时,请调用 component-validator。