@stalfh233/omc-cli 0.0.0-stage → 0.4.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +293 -3
  3. package/coverage/m1-coverage-manifest-v1.json +1278 -0
  4. package/dist/approval-token.js +102 -0
  5. package/dist/args.js +25 -0
  6. package/dist/artifacts.js +119 -0
  7. package/dist/bench/call-face-eval.js +256 -0
  8. package/dist/bench/context-attribution.js +151 -0
  9. package/dist/bench/discovery-cost-eval.js +230 -0
  10. package/dist/bench/driver.js +81 -0
  11. package/dist/bench/evals.js +236 -0
  12. package/dist/bench/fake-http-server.js +65 -0
  13. package/dist/bench/instrument.js +87 -0
  14. package/dist/bench/intent-face-eval.js +343 -0
  15. package/dist/bench/run.js +166 -0
  16. package/dist/bench/scenario.js +343 -0
  17. package/dist/bench/types.js +76 -0
  18. package/dist/bi-wire.js +41 -0
  19. package/dist/bizservice-config.js +581 -0
  20. package/dist/call.js +153 -0
  21. package/dist/capability-absences.js +23 -0
  22. package/dist/capability-overview.js +492 -0
  23. package/dist/capability-shape.js +154 -0
  24. package/dist/cli-contract.js +70 -0
  25. package/dist/cli-output.js +73 -0
  26. package/dist/cli.js +1418 -0
  27. package/dist/code-rules.js +69 -0
  28. package/dist/command-transport.js +155 -0
  29. package/dist/config-store.js +195 -0
  30. package/dist/context.js +21 -0
  31. package/dist/contract-consistency.js +66 -0
  32. package/dist/contract-resources.js +62 -0
  33. package/dist/coverage-consistency.js +62 -0
  34. package/dist/coverage-registry.js +76 -0
  35. package/dist/coverage.js +130 -0
  36. package/dist/data-list-filter.js +114 -0
  37. package/dist/discovery.js +390 -0
  38. package/dist/endpoints.js +154 -0
  39. package/dist/environment-policy.js +26 -0
  40. package/dist/execution-metadata.js +1092 -0
  41. package/dist/fake/app.js +45 -0
  42. package/dist/fake/b2-registration.js +594 -0
  43. package/dist/fake/businessrule.js +242 -0
  44. package/dist/fake/datarule.js +72 -0
  45. package/dist/fake/dictionary.js +108 -0
  46. package/dist/fake/environment.js +30 -0
  47. package/dist/fake/field.js +167 -0
  48. package/dist/fake/form.js +101 -0
  49. package/dist/fake/index.js +121 -0
  50. package/dist/fake/list-view.js +289 -0
  51. package/dist/fake/model.js +136 -0
  52. package/dist/fake/online-js.js +18 -0
  53. package/dist/fake/report.js +253 -0
  54. package/dist/fake/routes.js +47 -0
  55. package/dist/fake/rule-lifecycle.js +37 -0
  56. package/dist/fake/runtime-data.js +367 -0
  57. package/dist/fake/state.js +67 -0
  58. package/dist/fake/workflow.js +364 -0
  59. package/dist/field-change.js +200 -0
  60. package/dist/field-families.js +896 -0
  61. package/dist/form-layout.js +111 -0
  62. package/dist/form-support.js +821 -0
  63. package/dist/goal-routes.js +468 -0
  64. package/dist/governed-execution.js +87 -0
  65. package/dist/human-summary.js +212 -0
  66. package/dist/identity.js +62 -0
  67. package/dist/intent/baseline.js +57 -0
  68. package/dist/intent/capabilities/bizservice.js +274 -0
  69. package/dist/intent/capabilities/businessrule.js +493 -0
  70. package/dist/intent/capabilities/datarule.js +187 -0
  71. package/dist/intent/capabilities/field.js +545 -0
  72. package/dist/intent/capabilities/form.js +136 -0
  73. package/dist/intent/capabilities/index.js +64 -0
  74. package/dist/intent/capabilities/listview.js +157 -0
  75. package/dist/intent/capabilities/model.js +100 -0
  76. package/dist/intent/capabilities/onlinejs.js +108 -0
  77. package/dist/intent/capabilities/report.js +355 -0
  78. package/dist/intent/capabilities/workflow.js +458 -0
  79. package/dist/intent/capability.js +6 -0
  80. package/dist/intent/cli.js +91 -0
  81. package/dist/intent/compare.js +56 -0
  82. package/dist/intent/compiler.js +79 -0
  83. package/dist/intent/dsl.js +129 -0
  84. package/dist/intent/plan-file.js +63 -0
  85. package/dist/intent/readback.js +65 -0
  86. package/dist/intent/schema.js +158 -0
  87. package/dist/intent/validation.js +30 -0
  88. package/dist/intent/yaml.js +315 -0
  89. package/dist/json-column.js +68 -0
  90. package/dist/lanes/app-contract.js +95 -0
  91. package/dist/lanes/app-coverage.js +16 -0
  92. package/dist/lanes/app.js +174 -0
  93. package/dist/lanes/apply-changes.js +231 -0
  94. package/dist/lanes/b2-registration-contract.js +292 -0
  95. package/dist/lanes/b2-registration-coverage.js +48 -0
  96. package/dist/lanes/b2-registration.js +1187 -0
  97. package/dist/lanes/businessrule-contract.js +232 -0
  98. package/dist/lanes/businessrule-coverage.js +16 -0
  99. package/dist/lanes/businessrule.js +221 -0
  100. package/dist/lanes/contract-support.js +65 -0
  101. package/dist/lanes/coverage-declaration.js +9 -0
  102. package/dist/lanes/datarule-contract.js +155 -0
  103. package/dist/lanes/datarule-coverage.js +19 -0
  104. package/dist/lanes/datarule-protocol.js +308 -0
  105. package/dist/lanes/datarule.js +818 -0
  106. package/dist/lanes/dictionary-contract.js +78 -0
  107. package/dist/lanes/dictionary-coverage.js +24 -0
  108. package/dist/lanes/dictionary.js +235 -0
  109. package/dist/lanes/environment-contract.js +70 -0
  110. package/dist/lanes/environment-coverage.js +14 -0
  111. package/dist/lanes/environment.js +163 -0
  112. package/dist/lanes/field-contract.js +223 -0
  113. package/dist/lanes/field-coverage.js +27 -0
  114. package/dist/lanes/field.js +374 -0
  115. package/dist/lanes/form-contract.js +97 -0
  116. package/dist/lanes/form-coverage.js +16 -0
  117. package/dist/lanes/form.js +185 -0
  118. package/dist/lanes/lane-ids.js +34 -0
  119. package/dist/lanes/list-view-contract.js +175 -0
  120. package/dist/lanes/list-view-coverage.js +20 -0
  121. package/dist/lanes/list-view-shapes.js +1207 -0
  122. package/dist/lanes/list-view.js +578 -0
  123. package/dist/lanes/meta-contract.js +85 -0
  124. package/dist/lanes/meta.js +255 -0
  125. package/dist/lanes/model-contract.js +168 -0
  126. package/dist/lanes/model-coverage.js +20 -0
  127. package/dist/lanes/model.js +986 -0
  128. package/dist/lanes/online-js-contract.js +99 -0
  129. package/dist/lanes/online-js-coverage.js +28 -0
  130. package/dist/lanes/online-js.js +127 -0
  131. package/dist/lanes/report-contract.js +144 -0
  132. package/dist/lanes/report-coverage.js +21 -0
  133. package/dist/lanes/report.js +476 -0
  134. package/dist/lanes/rule-graph.js +1846 -0
  135. package/dist/lanes/rule-lifecycle-contract.js +92 -0
  136. package/dist/lanes/rule-lifecycle-coverage.js +20 -0
  137. package/dist/lanes/rule-lifecycle.js +176 -0
  138. package/dist/lanes/runtime-data-contract.js +264 -0
  139. package/dist/lanes/runtime-data-coverage.js +25 -0
  140. package/dist/lanes/runtime-data.js +1054 -0
  141. package/dist/lanes/workflow-contract.js +223 -0
  142. package/dist/lanes/workflow-coverage.js +40 -0
  143. package/dist/lanes/workflow.js +1813 -0
  144. package/dist/online-js-layout.js +58 -0
  145. package/dist/online-js-source.js +276 -0
  146. package/dist/package-tool.js +51 -0
  147. package/dist/package.js +73 -0
  148. package/dist/plan.js +73 -0
  149. package/dist/read.js +144 -0
  150. package/dist/redact.js +28 -0
  151. package/dist/rule-support.js +587 -0
  152. package/dist/runtime-support.js +134 -0
  153. package/dist/server.js +92 -0
  154. package/dist/session-manager.js +30 -0
  155. package/dist/session.js +149 -0
  156. package/dist/skills.js +112 -0
  157. package/dist/support.js +98 -0
  158. package/dist/tool-types.js +127 -0
  159. package/dist/tools.js +59 -0
  160. package/dist/usage-log.js +197 -0
  161. package/dist/wire.js +287 -0
  162. package/dist/workflow-support.js +99 -0
  163. package/dist/write-lease.js +26 -0
  164. package/dist/write-lock.js +109 -0
  165. package/dist/write.js +176 -0
  166. package/dist/zip.js +156 -0
  167. package/docs/tool-surface-map.md +42 -0
  168. package/package.json +71 -6
  169. package/skills/omc-acceptance-criteria.md +47 -0
  170. package/skills/omc-business-configuration.md +257 -0
  171. package/skills/omc-capabilities.md +197 -0
  172. package/skills/omc-capability-scouting.md +55 -0
  173. package/skills/omc-config-draft-review.md +171 -0
  174. package/skills/omc-five-piece-flow.md +35 -0
  175. package/skills/omc-glossary.md +86 -0
  176. package/skills/omc-refusals.md +110 -0
  177. package/skills/omc-requirement-analysis.md +161 -0
  178. package/skills/omc-requirement-vocabulary.md +51 -0
  179. package/skills/omc-start-here.md +82 -0
  180. package/skills/omc-tool-selection.md +119 -0
  181. package/skills/omc-write-hazards.md +87 -0
@@ -0,0 +1,76 @@
1
+ import { APP_COVERAGE } from "./lanes/app-coverage.js";
2
+ import { DICTIONARY_COVERAGE } from "./lanes/dictionary-coverage.js";
3
+ import { B2_COVERAGE } from "./lanes/b2-registration-coverage.js";
4
+ import { BUSINESSRULE_COVERAGE } from "./lanes/businessrule-coverage.js";
5
+ import { ENVIRONMENT_COVERAGE } from "./lanes/environment-coverage.js";
6
+ import { DATARULE_COVERAGE } from "./lanes/datarule-coverage.js";
7
+ import { FIELD_COVERAGE } from "./lanes/field-coverage.js";
8
+ import { FORM_COVERAGE } from "./lanes/form-coverage.js";
9
+ import { LIST_VIEW_COVERAGE } from "./lanes/list-view-coverage.js";
10
+ import { MODEL_COVERAGE } from "./lanes/model-coverage.js";
11
+ import { ONLINE_JS_COVERAGE } from "./lanes/online-js-coverage.js";
12
+ import { RULE_LIFECYCLE_COVERAGE } from "./lanes/rule-lifecycle-coverage.js";
13
+ import { RUNTIME_DATA_COVERAGE } from "./lanes/runtime-data-coverage.js";
14
+ import { WORKFLOW_COVERAGE } from "./lanes/workflow-coverage.js";
15
+ import { REPORT_COVERAGE } from "./lanes/report-coverage.js";
16
+ /**
17
+ * Every lane's structured capability declaration, gathered in one frozen
18
+ * registry. This is the source the runtime coverage gate consults, and the
19
+ * source the manifest generator/validator aligns against.
20
+ */
21
+ const DECLARATIONS = Object.freeze([
22
+ ...ENVIRONMENT_COVERAGE,
23
+ ...APP_COVERAGE,
24
+ ...DICTIONARY_COVERAGE,
25
+ ...MODEL_COVERAGE,
26
+ ...FIELD_COVERAGE,
27
+ ...DATARULE_COVERAGE,
28
+ ...FORM_COVERAGE,
29
+ ...BUSINESSRULE_COVERAGE,
30
+ ...RULE_LIFECYCLE_COVERAGE,
31
+ ...RUNTIME_DATA_COVERAGE,
32
+ ...WORKFLOW_COVERAGE,
33
+ ...ONLINE_JS_COVERAGE,
34
+ ...B2_COVERAGE,
35
+ ...LIST_VIEW_COVERAGE,
36
+ ...REPORT_COVERAGE,
37
+ ]);
38
+ export function laneCoverageDeclarations() {
39
+ return DECLARATIONS;
40
+ }
41
+ /**
42
+ * Build-time alignment: every declaration names a real manifest capability,
43
+ * carries evidence, does not double-claim a tool, and any capability that
44
+ * claims tools maps to an executable/partial manifest item.
45
+ */
46
+ export function assertDeclarationsAlignWithManifest(manifest) {
47
+ const owner = new Map();
48
+ for (const declaration of DECLARATIONS) {
49
+ const where = `${declaration.lane} / "${declaration.capability}"`;
50
+ if (!declaration.capability.trim())
51
+ throw new Error(`coverage declaration ${declaration.lane} requires a capability title`);
52
+ if (!declaration.lane.trim())
53
+ throw new Error(`coverage declaration ${where} requires a lane id`);
54
+ if (declaration.evidence.length === 0)
55
+ throw new Error(`coverage declaration ${where} requires at least one evidence anchor`);
56
+ const item = manifest.items.find((candidate) => candidate.lane === declaration.lane && candidate.capability === declaration.capability);
57
+ if (!item)
58
+ throw new Error(`coverage declaration ${where} has no matching manifest item`);
59
+ if (declaration.tools.length > 0 && item.status !== "executable" && item.status !== "partial") {
60
+ throw new Error(`coverage declaration ${where} claims tools but the manifest item is ${item.status}`);
61
+ }
62
+ const ledgerPaths = new Set((item.evidence ?? []).map((anchor) => anchor.path));
63
+ if (ledgerPaths.size > 0 && !declaration.evidence.some((anchor) => ledgerPaths.has(anchor))) {
64
+ throw new Error(`coverage declaration ${where} evidence anchors are not present in the manifest item's evidence ledger`);
65
+ }
66
+ for (const toolClaim of declaration.tools) {
67
+ if (!toolClaim.scope.trim())
68
+ throw new Error(`coverage declaration ${where} claims ${toolClaim.tool} without a scope`);
69
+ const previous = owner.get(toolClaim.tool);
70
+ if (previous)
71
+ throw new Error(`tool ${toolClaim.tool} is declared twice: ${previous} and ${where}`);
72
+ owner.set(toolClaim.tool, where);
73
+ }
74
+ }
75
+ }
76
+ //# sourceMappingURL=coverage-registry.js.map
@@ -0,0 +1,130 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { laneCoverageDeclarations } from "./coverage-registry.js";
5
+ export class CoverageBoundaryError extends Error {
6
+ citation;
7
+ constructor(citation) {
8
+ super(citation.message);
9
+ this.citation = citation;
10
+ }
11
+ }
12
+ let cachedManifest = null;
13
+ export function loadCoverageManifest() {
14
+ if (cachedManifest)
15
+ return cachedManifest;
16
+ const root = join(dirname(fileURLToPath(import.meta.url)), "..", "coverage");
17
+ cachedManifest = JSON.parse(readFileSync(join(root, "m1-coverage-manifest-v1.json"), "utf8"));
18
+ return cachedManifest;
19
+ }
20
+ export function coverageItemsByLane(manifest) {
21
+ return new Map(manifest.items.map((item) => [item.lane, item]));
22
+ }
23
+ /**
24
+ * Structured allowed-scope index built from the lane declarations joined to
25
+ * the manifest's capability status. The key is `lane\0scope`; each value is
26
+ * the manifest item the claim cites. A lane typo in a declaration surfaces at
27
+ * build time (`assertCoverageConsistency`) and here as a missing manifest item.
28
+ */
29
+ const allowedCache = new WeakMap();
30
+ function allowedScopes(manifest) {
31
+ const cached = allowedCache.get(manifest);
32
+ if (cached)
33
+ return cached;
34
+ const index = new Map();
35
+ for (const declaration of laneCoverageDeclarations()) {
36
+ const item = manifest.items.find((candidate) => candidate.lane === declaration.lane && candidate.capability === declaration.capability);
37
+ if (!item) {
38
+ throw new Error(`coverage declaration ${declaration.lane} / "${declaration.capability}" has no manifest item; ` +
39
+ "add the capability to coverage/m1-coverage-manifest-v1.json");
40
+ }
41
+ for (const claim of declaration.tools)
42
+ index.set(`${declaration.lane}\u0000${claim.scope}`, item);
43
+ }
44
+ allowedCache.set(manifest, index);
45
+ return index;
46
+ }
47
+ /**
48
+ * Map a tool's declared `(lane, scope)` onto the manifest. A call is allowed
49
+ * only when a declared capability claims that exact pair and its manifest item
50
+ * is executable/partial; blocked, static-only, and unsupported items always
51
+ * reject with a citation.
52
+ */
53
+ /**
54
+ * Ticket 84 — self-correcting lane hints. Users pass capability nicknames
55
+ * ("listview") instead of lane ids ("W1-list-view"); normalize both sides
56
+ * (lowercase, strip the M1/M2/W1/B1/G1/W7/S25 prefix segment) and suggest the
57
+ * closest declared lane.
58
+ */
59
+ function suggestLaneId(manifest, requested) {
60
+ const normalize = (value) => value.toLowerCase().replace(/^[a-z]\d+-/, "").replace(/-/g, "");
61
+ const target = normalize(requested);
62
+ if (!target)
63
+ return undefined;
64
+ const lanes = [...new Set(manifest.items.map((item) => item.lane))];
65
+ return lanes.find((lane) => normalize(lane) === target || lane.toLowerCase().endsWith(`-${requested.toLowerCase()}`));
66
+ }
67
+ export function assertWithinCoverage(manifest, lane, requestedScope) {
68
+ const claimed = allowedScopes(manifest).get(`${lane}\u0000${requestedScope}`);
69
+ if (claimed)
70
+ return claimed;
71
+ const laneItems = manifest.items.filter((candidate) => candidate.lane === lane);
72
+ if (laneItems.length === 0) {
73
+ const suggestion = suggestLaneId(manifest, lane);
74
+ const validLanes = [...new Set(manifest.items.map((item) => item.lane))].join("、");
75
+ throw new CoverageBoundaryError({
76
+ code: "capability-out-of-coverage",
77
+ lane,
78
+ capability: "<unknown>",
79
+ status: "blocked",
80
+ reason: "lane is not present in the M1 coverage manifest",
81
+ message: `rejected: lane ${lane} is not in coverage manifest ` +
82
+ `${manifest.manifest_type} v${manifest.schema_version}; no live-proven evidence exists` +
83
+ (suggestion ? `;capability 取 lane id,不是能力昵称——你传的 "${lane}" 最接近 "${suggestion}";合法取值:${validLanes};省略 capability 即自动按工具所属 lane 校验` : `;合法 lane 取值:${validLanes}`),
84
+ });
85
+ }
86
+ const runtimeItem = laneItems.find((candidate) => candidate.status === "executable" || candidate.status === "partial");
87
+ if (!runtimeItem) {
88
+ throw new CoverageBoundaryError(citationFor(laneItems[0], requestedScope));
89
+ }
90
+ throw new CoverageBoundaryError({
91
+ code: "capability-out-of-coverage",
92
+ lane: runtimeItem.lane,
93
+ capability: runtimeItem.capability,
94
+ status: runtimeItem.status,
95
+ reason: `requested scope "${requestedScope}" is not declared for ${runtimeItem.capability}`,
96
+ message: `rejected: requested scope "${requestedScope}" exceeds live-proven scope of ` +
97
+ `${runtimeItem.capability} (${runtimeItem.status}); it is not a declared scope of lane ${lane}`,
98
+ });
99
+ }
100
+ function citationFor(item, requestedScope) {
101
+ return {
102
+ code: "capability-out-of-coverage",
103
+ lane: item.lane,
104
+ capability: item.capability,
105
+ status: item.status,
106
+ reason: item.excluded_or_unsupported_reason ??
107
+ `requested scope "${requestedScope}" is not runtime coverage for lane ${item.lane}`,
108
+ message: `rejected: ${item.capability} is ${item.status} in coverage manifest ` +
109
+ `(${item.excluded_or_unsupported_reason ?? "not a runtime coverage claim"}); ` +
110
+ `citing lane ${item.lane}`,
111
+ };
112
+ }
113
+ /**
114
+ * Version-family compatibility notice.
115
+ *
116
+ * OMC's coverage manifest is anchored on the CloudPivot 8.6 family. Rather than
117
+ * hard-failing every other version, the gate is now advisory: a detected version
118
+ * outside the anchored family is ACCEPTED and this returns the notice to surface
119
+ * (omc is built on 8.6; other products/versions run in compatibility mode and
120
+ * some faces may not apply). Returns undefined when the version is inside the
121
+ * family, or when there is no evidence to judge (the caller keeps its own
122
+ * fail-closed behavior for missing evidence).
123
+ */
124
+ export function versionFamilyNotice(manifest, detectedVersion) {
125
+ if (detectedVersion.startsWith(manifest.version_family + "."))
126
+ return undefined;
127
+ return (`兼容模式:检测到 CloudPivot ${detectedVersion},不在 OMC 锚定的 ${manifest.version_family} 族` +
128
+ `(锚点 ${manifest.anchor_version})。OMC 基于 8.6 构建,非 8.6 环境按兼容支持,部分能力面可能不适用。`);
129
+ }
130
+ //# sourceMappingURL=coverage.js.map
@@ -0,0 +1,114 @@
1
+ import { RUNTIME_QUERY_OPERATORS } from "./lanes/runtime-data-contract.js";
2
+ export const SIMPLE_OP_MAP = {
3
+ eq: "Eq",
4
+ equals: "Eq",
5
+ neq: "NotEq",
6
+ notEquals: "NotEq",
7
+ gt: "Gt",
8
+ lt: "Lt",
9
+ gte: "Gte",
10
+ lte: "Lte",
11
+ like: "Like",
12
+ contains: "Like",
13
+ notlike: "NotLike",
14
+ isnull: "IsNull",
15
+ isNull: "IsNull",
16
+ isnotnull: "IsNotNull",
17
+ isNotNull: "IsNotNull",
18
+ in: "In",
19
+ notin: "NotIn",
20
+ between: "Between",
21
+ notbetween: "NotBetween",
22
+ };
23
+ export class FilterDslError extends Error {
24
+ code;
25
+ constructor(code, message) {
26
+ super(message);
27
+ this.code = code;
28
+ }
29
+ }
30
+ /**
31
+ * Translate the simplified DSL into the runtime `queryCondition` shape —
32
+ * `List<List<List<FilterModel>>>` consumed by /api/api/runtime/query/list
33
+ * (QueryDataVO.queryCondition). Semantics per decompiled 8.6.26 source
34
+ * (BizObjectFacadeImpl.getFiltersByQueryParam / buildFilter):
35
+ * level 1 = AND across groups, level 2 = OR across and-groups,
36
+ * level 3 = AND across leaves. A 2-level array fails JSON deserialization
37
+ * with errcode 10009 类型转换异常.
38
+ * leaf -> [[[leaf]]]
39
+ * and(k) -> [[[l1..lk]]]
40
+ * or(k) -> [[[l1]..[lk]]]
41
+ * Mixed nesting deeper than one group level is refused (no silent re-binding).
42
+ */
43
+ export function toQueryCondition(payload) {
44
+ if (payload.rawCondition !== undefined) {
45
+ if (payload.rawCondition === null || typeof payload.rawCondition !== "object" || !Array.isArray(payload.rawCondition))
46
+ throw new FilterDslError("invalid-raw-condition", "rawCondition must be the platform queryCondition array (and>or>and>leaf)");
47
+ return payload.rawCondition;
48
+ }
49
+ if (payload.filterGroup !== undefined)
50
+ return [translateGroup(payload.filterGroup, 0)];
51
+ const clauses = payload.filters ?? (payload.filter === undefined ? [] : [payload.filter]);
52
+ if (clauses.length === 0)
53
+ return undefined;
54
+ return [[clauses.map((clause) => translateClause(clause))]];
55
+ }
56
+ function translateGroup(group, depth) {
57
+ if (depth > 0)
58
+ throw new FilterDslError("filter-depth-exceeded", "nested groups inside filterGroup are not supported by the runtime condition format");
59
+ if (!Array.isArray(group.clauses) || group.clauses.length === 0)
60
+ throw new FilterDslError("empty-group-clauses", "filterGroup.clauses must be non-empty");
61
+ if (group.op === "and")
62
+ return [group.clauses.map((clause) => ("clauses" in clause ? badNested() : translateClause(clause)))];
63
+ return group.clauses.map((clause) => ("clauses" in clause ? badNested() : [translateClause(clause)]));
64
+ }
65
+ function badNested() {
66
+ throw new FilterDslError("filter-depth-exceeded", "nested groups inside filterGroup are not supported by the runtime condition format");
67
+ }
68
+ function translateClause(clause) {
69
+ if (!clause || typeof clause !== "object" || !(clause.op in SIMPLE_OP_MAP))
70
+ throw new FilterDslError("invalid-op", `unsupported filter op '${String(clause?.op)}'`);
71
+ const field = String(clause.field ?? "").trim();
72
+ if (!field)
73
+ throw new FilterDslError("missing-field", "filter field is required");
74
+ return {
75
+ propertyCode: field,
76
+ propertyValue: encodeValue(clause.op, clause.value),
77
+ queryFilterType: SIMPLE_OP_MAP[clause.op],
78
+ };
79
+ }
80
+ function encodeValue(op, value) {
81
+ const wireOp = SIMPLE_OP_MAP[op];
82
+ // Encoding itself comes from the shared operator table (the same table the
83
+ // fake evaluator matches through) so compiler and evaluator cannot drift.
84
+ const operator = RUNTIME_QUERY_OPERATORS[wireOp];
85
+ if (!operator)
86
+ throw new FilterDslError("invalid-op", `unsupported filter op '${String(op)}'`);
87
+ if (wireOp !== "IsNull" && wireOp !== "IsNotNull" && (value === null || value === undefined))
88
+ throw new FilterDslError("missing-value", `filter op '${op}' requires a value`);
89
+ return operator.encode(value);
90
+ }
91
+ /**
92
+ * The runtime endpoint requires every leaf filter to carry the field's
93
+ * `propertyType` (int) alongside propertyCode/propertyValue/queryFilterType;
94
+ * without it the query fails with errcode 10009 类型转换异常. The value must
95
+ * come from field metadata — never guessed (cpdocs filter-condition contract).
96
+ */
97
+ export function injectPropertyTypes(condition, resolve) {
98
+ const missing = new Set();
99
+ const walk = (node) => {
100
+ if (Array.isArray(node))
101
+ return node.map(walk);
102
+ const leaf = node;
103
+ const code = String(leaf?.propertyCode ?? "");
104
+ const type = resolve(code);
105
+ if (type === undefined) {
106
+ missing.add(code);
107
+ return leaf;
108
+ }
109
+ return { ...leaf, propertyType: type };
110
+ };
111
+ const walked = walk(condition);
112
+ return missing.size > 0 ? { ok: false, missing: [...missing].sort() } : { ok: true, condition: walked };
113
+ }
114
+ //# sourceMappingURL=data-list-filter.js.map