@topogram/cli 0.3.64 → 0.3.65

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 (245) hide show
  1. package/package.json +1 -1
  2. package/src/adoption/plan/index.js +703 -0
  3. package/src/adoption/plan.js +12 -703
  4. package/src/agent-ops/query-builders/auth.js +375 -0
  5. package/src/agent-ops/query-builders/change-risk/change-plan.js +123 -0
  6. package/src/agent-ops/query-builders/change-risk/import-plan.js +49 -0
  7. package/src/agent-ops/query-builders/change-risk/maintained.js +286 -0
  8. package/src/agent-ops/query-builders/change-risk/review-packets.js +123 -0
  9. package/src/agent-ops/query-builders/change-risk/risk.js +189 -0
  10. package/src/agent-ops/query-builders/change-risk.js +25 -0
  11. package/src/agent-ops/query-builders/common.js +149 -0
  12. package/src/agent-ops/query-builders/maintained-risk.js +539 -0
  13. package/src/agent-ops/query-builders/maintained-shared.js +120 -0
  14. package/src/agent-ops/query-builders/multi-agent.js +547 -0
  15. package/src/agent-ops/query-builders/projection-impacts.js +514 -0
  16. package/src/agent-ops/query-builders/work-packets.js +417 -0
  17. package/src/agent-ops/query-builders/workflow-context-shared.js +300 -0
  18. package/src/agent-ops/query-builders/workflow-context.js +398 -0
  19. package/src/agent-ops/query-builders/workflow-presets-core.js +676 -0
  20. package/src/agent-ops/query-builders/workflow-presets.js +341 -0
  21. package/src/agent-ops/query-builders.d.ts +26 -26
  22. package/src/agent-ops/query-builders.js +42 -5021
  23. package/src/catalog/constants.js +10 -0
  24. package/src/catalog/copy.js +60 -0
  25. package/src/catalog/diagnostics.js +15 -0
  26. package/src/catalog/entries.js +42 -0
  27. package/src/catalog/files.js +67 -0
  28. package/src/catalog/provenance.js +122 -0
  29. package/src/catalog/source.js +150 -0
  30. package/src/catalog/validation.js +252 -0
  31. package/src/catalog.d.ts +2 -0
  32. package/src/catalog.js +18 -746
  33. package/src/cli/commands/catalog/check.js +31 -0
  34. package/src/cli/commands/catalog/copy.js +59 -0
  35. package/src/cli/commands/catalog/doctor.js +248 -0
  36. package/src/cli/commands/catalog/help.js +21 -0
  37. package/src/cli/commands/catalog/list.js +52 -0
  38. package/src/cli/commands/catalog/runner.js +92 -0
  39. package/src/cli/commands/catalog/shared.js +17 -0
  40. package/src/cli/commands/catalog/show.js +134 -0
  41. package/src/cli/commands/catalog.js +30 -615
  42. package/src/cli/commands/generator-policy/package-info.js +162 -0
  43. package/src/cli/commands/generator-policy/payloads.js +372 -0
  44. package/src/cli/commands/generator-policy/printers.js +159 -0
  45. package/src/cli/commands/generator-policy/runner.js +81 -0
  46. package/src/cli/commands/generator-policy/shared.js +39 -0
  47. package/src/cli/commands/generator-policy.js +15 -783
  48. package/src/cli/commands/import/adopt.js +170 -0
  49. package/src/cli/commands/import/check.js +91 -0
  50. package/src/cli/commands/import/diff.js +84 -0
  51. package/src/cli/commands/import/help.js +47 -0
  52. package/src/cli/commands/import/paths.js +277 -0
  53. package/src/cli/commands/import/plan.js +284 -0
  54. package/src/cli/commands/import/refresh.js +470 -0
  55. package/src/cli/commands/import/status-history.js +196 -0
  56. package/src/cli/commands/import/workspace.js +230 -0
  57. package/src/cli/commands/import.js +33 -1732
  58. package/src/cli/commands/package/constants.js +17 -0
  59. package/src/cli/commands/package/doctor.js +240 -0
  60. package/src/cli/commands/package/help.js +27 -0
  61. package/src/cli/commands/package/lockfile.js +135 -0
  62. package/src/cli/commands/package/npm.js +97 -0
  63. package/src/cli/commands/package/reporting.js +35 -0
  64. package/src/cli/commands/package/runner.js +33 -0
  65. package/src/cli/commands/package/shared.js +9 -0
  66. package/src/cli/commands/package/update-cli.js +252 -0
  67. package/src/cli/commands/package/versions.js +35 -0
  68. package/src/cli/commands/package.js +29 -813
  69. package/src/cli/commands/query/change-plan.js +68 -0
  70. package/src/cli/commands/query/definitions.js +202 -0
  71. package/src/cli/commands/query/import-adopt.js +121 -0
  72. package/src/cli/commands/query/runner/artifacts.js +102 -0
  73. package/src/cli/commands/query/runner/boundaries.js +211 -0
  74. package/src/cli/commands/query/runner/change.js +182 -0
  75. package/src/cli/commands/query/runner/import-adopt.js +111 -0
  76. package/src/cli/commands/query/runner/index.js +31 -0
  77. package/src/cli/commands/query/runner/output.js +12 -0
  78. package/src/cli/commands/query/runner/workflow.js +241 -0
  79. package/src/cli/commands/query/runner.js +3 -0
  80. package/src/cli/commands/query/workflow-context.js +5 -0
  81. package/src/cli/commands/query/workspace.js +274 -0
  82. package/src/cli/commands/query.js +9 -1300
  83. package/src/cli/commands/template/baseline.js +100 -0
  84. package/src/cli/commands/template/check.js +466 -0
  85. package/src/cli/commands/template/constants.js +8 -0
  86. package/src/cli/commands/template/diagnostics.js +26 -0
  87. package/src/cli/commands/template/help.js +28 -0
  88. package/src/cli/commands/template/lifecycle.js +404 -0
  89. package/src/cli/commands/template/list-show.js +287 -0
  90. package/src/cli/commands/template/policy.js +422 -0
  91. package/src/cli/commands/template/shared.js +127 -0
  92. package/src/cli/commands/template/updates.js +352 -0
  93. package/src/cli/commands/template.js +41 -2143
  94. package/src/generator/api/contracts.js +497 -0
  95. package/src/generator/api/metadata.js +221 -0
  96. package/src/generator/api/openapi.js +559 -0
  97. package/src/generator/api/schema.js +124 -0
  98. package/src/generator/api/types.d.ts +98 -0
  99. package/src/generator/api.js +3 -1195
  100. package/src/generator/context/shared/domain-sdlc.js +282 -0
  101. package/src/generator/context/shared/maintained-boundary.js +665 -0
  102. package/src/generator/context/shared/metrics.js +85 -0
  103. package/src/generator/context/shared/primitives.js +64 -0
  104. package/src/generator/context/shared/relationships.js +453 -0
  105. package/src/generator/context/shared/summaries.js +263 -0
  106. package/src/generator/context/shared/types.d.ts +207 -0
  107. package/src/generator/context/shared.d.ts +42 -0
  108. package/src/generator/context/shared.js +80 -1390
  109. package/src/generator/context/slice/core.js +397 -0
  110. package/src/generator/context/slice/sdlc.js +417 -0
  111. package/src/generator/context/slice/ui-packets.js +183 -0
  112. package/src/generator/context/slice.js +2 -859
  113. package/src/generator/registry/index.js +507 -0
  114. package/src/generator/registry.js +18 -504
  115. package/src/generator/runtime/environment/index.js +666 -0
  116. package/src/generator/runtime/environment.js +4 -666
  117. package/src/generator/runtime/runtime-check/index.js +554 -0
  118. package/src/generator/runtime/runtime-check.js +4 -554
  119. package/src/generator/runtime/shared/index.js +572 -0
  120. package/src/generator/runtime/shared.js +19 -570
  121. package/src/generator/shared.d.ts +2 -0
  122. package/src/generator/surfaces/shared.d.ts +3 -0
  123. package/src/generator/widget-conformance/behavior-report.js +258 -0
  124. package/src/generator/widget-conformance/checks.js +371 -0
  125. package/src/generator/widget-conformance/projection-context.js +200 -0
  126. package/src/generator/widget-conformance/report.js +166 -0
  127. package/src/generator/widget-conformance/types.d.ts +121 -0
  128. package/src/generator/widget-conformance.js +3 -824
  129. package/src/import/core/context.d.ts +3 -0
  130. package/src/import/core/contracts.d.ts +1 -0
  131. package/src/import/core/registry.d.ts +4 -0
  132. package/src/import/core/runner/candidates.js +217 -0
  133. package/src/import/core/runner/options.js +22 -0
  134. package/src/import/core/runner/reports.js +50 -0
  135. package/src/import/core/runner/run.js +79 -0
  136. package/src/import/core/runner/tracks.js +150 -0
  137. package/src/import/core/runner/ui-drafts.js +337 -0
  138. package/src/import/core/runner.js +3 -698
  139. package/src/import/core/shared/api-routes.js +221 -0
  140. package/src/import/core/shared/candidates.js +97 -0
  141. package/src/import/core/shared/files.js +177 -0
  142. package/src/import/core/shared/next-app.js +389 -0
  143. package/src/import/core/shared/types.d.ts +51 -0
  144. package/src/import/core/shared/ui-routes.js +230 -0
  145. package/src/import/core/shared.js +60 -861
  146. package/src/new-project/constants.js +128 -0
  147. package/src/new-project/create.js +83 -0
  148. package/src/new-project/json.js +28 -0
  149. package/src/new-project/metadata.js +96 -0
  150. package/src/new-project/package-spec.js +161 -0
  151. package/src/new-project/project-files.js +348 -0
  152. package/src/new-project/template-policy.js +269 -0
  153. package/src/new-project/template-resolution.js +368 -0
  154. package/src/new-project/template-snapshots.js +430 -0
  155. package/src/new-project/template-updates.js +512 -0
  156. package/src/new-project/types.d.ts +83 -0
  157. package/src/new-project.js +6 -2277
  158. package/src/parser.d.ts +87 -1
  159. package/src/parser.js +118 -0
  160. package/src/policy/review-boundaries.d.ts +15 -0
  161. package/src/project-config/index.js +564 -0
  162. package/src/project-config.js +19 -561
  163. package/src/resolver/enrich/acceptance-criterion.js +2 -0
  164. package/src/resolver/enrich/bug.js +2 -0
  165. package/src/resolver/enrich/pitch.js +2 -0
  166. package/src/resolver/enrich/requirement.js +2 -0
  167. package/src/resolver/enrich/task.js +2 -0
  168. package/src/resolver/index.js +19 -2089
  169. package/src/resolver/normalize.js +384 -1
  170. package/src/resolver/plans.js +168 -0
  171. package/src/resolver/projections-api.js +494 -0
  172. package/src/resolver/projections-db.js +133 -0
  173. package/src/resolver/projections-ui.js +317 -0
  174. package/src/resolver/shapes.js +251 -0
  175. package/src/resolver/shared.js +278 -0
  176. package/src/resolver/widgets.js +132 -0
  177. package/src/template-trust/constants.js +62 -0
  178. package/src/template-trust/content.js +258 -0
  179. package/src/template-trust/diff.js +92 -0
  180. package/src/template-trust/policy.js +61 -0
  181. package/src/template-trust/record.js +90 -0
  182. package/src/template-trust/status.js +182 -0
  183. package/src/template-trust.js +24 -687
  184. package/src/text-helpers.d.ts +1 -0
  185. package/src/topogram-types.d.ts +69 -0
  186. package/src/validator/common.js +488 -0
  187. package/src/validator/data-model.js +237 -0
  188. package/src/validator/docs.js +167 -0
  189. package/src/validator/expressions.js +146 -1
  190. package/src/validator/index.d.ts +23 -0
  191. package/src/validator/index.js +32 -3585
  192. package/src/validator/kinds.d.ts +41 -0
  193. package/src/validator/kinds.js +2 -0
  194. package/src/validator/model-helpers.js +46 -0
  195. package/src/validator/per-kind/acceptance-criterion.js +5 -0
  196. package/src/validator/per-kind/bug.js +6 -0
  197. package/src/validator/per-kind/domain.js +15 -2
  198. package/src/validator/per-kind/pitch.js +7 -0
  199. package/src/validator/per-kind/requirement.js +5 -0
  200. package/src/validator/per-kind/task.js +7 -0
  201. package/src/validator/per-kind/widget.js +14 -0
  202. package/src/validator/projections/api-http-async.js +410 -0
  203. package/src/validator/projections/api-http-authz.js +88 -0
  204. package/src/validator/projections/api-http-core.js +205 -0
  205. package/src/validator/projections/api-http-policies.js +339 -0
  206. package/src/validator/projections/api-http-responses.js +233 -0
  207. package/src/validator/projections/api-http.js +44 -0
  208. package/src/validator/projections/db.js +353 -0
  209. package/src/validator/projections/generator-defaults.js +45 -0
  210. package/src/validator/projections/helpers.js +87 -0
  211. package/src/validator/projections/ui-helpers.js +214 -0
  212. package/src/validator/projections/ui-navigation.js +344 -0
  213. package/src/validator/projections/ui-structure.js +364 -0
  214. package/src/validator/projections/ui-widgets.js +493 -0
  215. package/src/validator/projections/ui.js +46 -0
  216. package/src/validator/registry.js +48 -1
  217. package/src/validator/utils.d.ts +20 -0
  218. package/src/validator/utils.js +115 -12
  219. package/src/widget-behavior.d.ts +1 -0
  220. package/src/workflows/import-app/api/collect.js +221 -0
  221. package/src/workflows/import-app/api/openapi.js +257 -0
  222. package/src/workflows/import-app/api/routes.js +327 -0
  223. package/src/workflows/import-app/api/sources.js +22 -0
  224. package/src/workflows/import-app/api.js +2 -797
  225. package/src/workflows/reconcile/adoption-plan/build.js +208 -0
  226. package/src/workflows/reconcile/adoption-plan/dependencies.js +75 -0
  227. package/src/workflows/reconcile/adoption-plan/outputs.js +143 -0
  228. package/src/workflows/reconcile/adoption-plan/paths.js +58 -0
  229. package/src/workflows/reconcile/adoption-plan/projection-patches.js +177 -0
  230. package/src/workflows/reconcile/adoption-plan/reasons.js +107 -0
  231. package/src/workflows/reconcile/adoption-plan.js +30 -740
  232. package/src/workflows/reconcile/auth/closures.js +115 -0
  233. package/src/workflows/reconcile/auth/formatters.js +142 -0
  234. package/src/workflows/reconcile/auth/inference.js +330 -0
  235. package/src/workflows/reconcile/auth/roles.js +122 -0
  236. package/src/workflows/reconcile/auth.js +35 -690
  237. package/src/workflows/reconcile/bundle-core/index.js +600 -0
  238. package/src/workflows/reconcile/bundle-core.js +12 -598
  239. package/src/workflows/reconcile/canonical-surface.js +1 -1
  240. package/src/workflows/reconcile/impacts/adoption-plan.js +192 -0
  241. package/src/workflows/reconcile/impacts/indexes.js +101 -0
  242. package/src/workflows/reconcile/impacts/patches.js +252 -0
  243. package/src/workflows/reconcile/impacts/reports.js +80 -0
  244. package/src/workflows/reconcile/impacts.js +14 -623
  245. package/src/workspace-docs.d.ts +29 -0
@@ -1,2096 +1,26 @@
1
- import {
2
- blockEntries,
3
- buildRegistry,
4
- collectFieldMap,
5
- getFieldValue,
6
- stringValue,
7
- symbolValue,
8
- symbolValues,
9
- validateWorkspace,
10
- valueAsArray
11
- } from "../validator.js";
1
+ import { buildRegistry, validateWorkspace } from "../validator.js";
2
+ import { loadArchive, mergeArchivedIntoGraph } from "../archive/resolver-bridge.js";
12
3
  import { enrichPitch } from "./enrich/pitch.js";
13
4
  import { enrichRequirement } from "./enrich/requirement.js";
14
5
  import { enrichAcceptanceCriterion } from "./enrich/acceptance-criterion.js";
15
6
  import { enrichTask } from "./enrich/task.js";
16
7
  import { enrichBug } from "./enrich/bug.js";
17
- import { loadArchive, mergeArchivedIntoGraph } from "../archive/resolver-bridge.js";
18
-
19
- function groupBy(items, keyFn) {
20
- const grouped = {};
21
- for (const item of items) {
22
- const key = keyFn(item);
23
- if (!Object.hasOwn(grouped, key)) {
24
- grouped[key] = [];
25
- }
26
- grouped[key].push(item);
27
- }
28
- return grouped;
29
- }
30
-
31
- function resolveReference(registry, id) {
32
- return registry.get(id) || null;
33
- }
34
-
35
- function toRef(target) {
36
- if (!target) {
37
- return null;
38
- }
39
-
40
- return {
41
- id: target.id,
42
- kind: target.kind
43
- };
44
- }
45
-
46
- function resolveReferenceList(registry, value) {
47
- return symbolValues(value).map((id) => ({
48
- id,
49
- target: toRef(resolveReference(registry, id))
50
- }));
51
- }
52
-
53
- function resolveDomainTag(statement, registry) {
54
- const domainField = statement.fields.find((field) => field.key === "domain");
55
- if (!domainField || domainField.value.type !== "symbol") {
56
- return null;
57
- }
58
- const id = domainField.value.value;
59
- return {
60
- id,
61
- target: toRef(resolveReference(registry, id))
62
- };
63
- }
64
-
65
- function normalizeDomainScopeList(statement, key) {
66
- const field = statement.fields.find((f) => f.key === key);
67
- if (!field) return [];
68
- const items = field.value.type === "list" || field.value.type === "sequence"
69
- ? field.value.items
70
- : [field.value];
71
- return items
72
- .map((item) => (item.type === "string" || item.type === "symbol" ? item.value : null))
73
- .filter((value) => value !== null);
74
- }
75
-
76
- function normalizeSequence(items) {
77
- return items.map((item) => {
78
- if (item.type === "symbol" || item.type === "string") {
79
- return item.value;
80
- }
81
- if (item.type === "list") {
82
- return item.items.map((nested) => nested.value);
83
- }
84
- return item.type;
85
- });
86
- }
87
-
88
- function normalizeFieldsBlock(statement, key = "fields") {
89
- return blockEntries(getFieldValue(statement, key)).map((entry) => {
90
- const [name, type, requiredness, ...rest] = entry.items;
91
- let defaultValue = null;
92
-
93
- for (let i = 0; i < rest.length - 1; i += 1) {
94
- if (rest[i].type === "symbol" && rest[i].value === "default") {
95
- defaultValue = rest[i + 1]?.value ?? null;
96
- }
97
- }
98
-
99
- return {
100
- name: name?.value ?? null,
101
- fieldType: type?.value ?? null,
102
- requiredness: requiredness?.value ?? null,
103
- defaultValue,
104
- raw: normalizeSequence(entry.items),
105
- loc: entry.loc
106
- };
107
- });
108
- }
109
-
110
- function parseDefaultLiteral(token) {
111
- if (!token) return null;
112
- if (token.type === "list") {
113
- return (token.items || []).map((item) => parseDefaultLiteral(item));
114
- }
115
- if (token.type === "string") {
116
- return token.value ?? null;
117
- }
118
- if (token.type === "symbol") {
119
- if (token.value === "true") return true;
120
- if (token.value === "false") return false;
121
- if (token.value === "null") return null;
122
- if (/^-?\d+$/.test(token.value)) return Number.parseInt(token.value, 10);
123
- if (/^-?\d+\.\d+$/.test(token.value)) return Number.parseFloat(token.value);
124
- return token.value;
125
- }
126
- return token.value ?? null;
127
- }
128
-
129
- function normalizeComponentProps(statement) {
130
- return blockEntries(getFieldValue(statement, "props")).map((entry) => {
131
- const [name, type, requiredness, ...rest] = entry.items;
132
- let defaultValue = null;
133
-
134
- for (let i = 0; i < rest.length - 1; i += 1) {
135
- if (rest[i].type === "symbol" && rest[i].value === "default") {
136
- defaultValue = parseDefaultLiteral(rest[i + 1]);
137
- }
138
- }
139
-
140
- return {
141
- name: name?.value ?? null,
142
- fieldType: type?.value ?? null,
143
- requiredness: requiredness?.value ?? null,
144
- defaultValue,
145
- raw: normalizeSequence(entry.items),
146
- loc: entry.loc
147
- };
148
- });
149
- }
150
-
151
- function normalizeComponentEvents(statement, registry) {
152
- return blockEntries(getFieldValue(statement, "events")).map((entry) => {
153
- const [eventName, shapeRef] = entry.items;
154
- const shapeId = tokenValue(shapeRef);
155
- return {
156
- id: tokenValue(eventName),
157
- shape: shapeId
158
- ? {
159
- id: shapeId,
160
- kind: registry.get(shapeId)?.kind || null
161
- }
162
- : null,
163
- raw: normalizeSequence(entry.items),
164
- loc: entry.loc
165
- };
166
- });
167
- }
168
-
169
- function normalizeComponentSlots(statement) {
170
- return blockEntries(getFieldValue(statement, "slots")).map((entry) => ({
171
- id: tokenValue(entry.items[0]),
172
- description: tokenValue(entry.items[1]),
173
- raw: normalizeSequence(entry.items),
174
- loc: entry.loc
175
- }));
176
- }
177
-
178
- function normalizeBehaviorValue(token) {
179
- if (!token) {
180
- return null;
181
- }
182
- if (token.type === "list") {
183
- return token.items.map((item) => normalizeBehaviorValue(item));
184
- }
185
- return parseDefaultLiteral(token);
186
- }
187
-
188
- function normalizeComponentBehaviors(statement) {
189
- const structured = blockEntries(getFieldValue(statement, "behaviors")).map((entry) => {
190
- const kind = tokenValue(entry.items[0]);
191
- const directives = {};
192
- for (let i = 1; i < entry.items.length; i += 2) {
193
- const key = tokenValue(entry.items[i]);
194
- if (!key) {
195
- continue;
196
- }
197
- directives[key] = normalizeBehaviorValue(entry.items[i + 1]);
198
- }
199
- return {
200
- kind,
201
- directives,
202
- source: "structured",
203
- raw: normalizeSequence(entry.items),
204
- loc: entry.loc
205
- };
206
- });
207
-
208
- const structuredKinds = new Set(structured.map((entry) => entry.kind));
209
- const shorthand = symbolValues(getFieldValue(statement, "behavior"))
210
- .filter((kind) => !structuredKinds.has(kind))
211
- .map((kind) => ({
212
- kind,
213
- directives: {},
214
- source: "shorthand",
215
- raw: [kind],
216
- loc: null
217
- }));
218
-
219
- return [...structured, ...shorthand];
220
- }
221
-
222
- function normalizeGenericBlock(statement, key) {
223
- return blockEntries(getFieldValue(statement, key)).map((entry) => ({
224
- raw: normalizeSequence(entry.items),
225
- loc: entry.loc
226
- }));
227
- }
228
-
229
- function tokenValue(token) {
230
- return token?.value ?? null;
231
- }
232
-
233
- function parseLiteralToken(token) {
234
- const value = tokenValue(token);
235
- if (value == null) {
236
- return null;
237
- }
238
-
239
- if (value === "true") {
240
- return { kind: "boolean", value: true };
241
- }
242
- if (value === "false") {
243
- return { kind: "boolean", value: false };
244
- }
245
- if (value === "null") {
246
- return { kind: "null", value: null };
247
- }
248
- if (/^-?\d+$/.test(value)) {
249
- return { kind: "integer", value: Number.parseInt(value, 10) };
250
- }
251
- if (/^-?\d+\.\d+$/.test(value)) {
252
- return { kind: "number", value: Number.parseFloat(value) };
253
- }
254
-
255
- return { kind: "symbol", value };
256
- }
257
-
258
- function parseComparison(left, operator, right) {
259
- if (!left || !operator || !right) {
260
- return null;
261
- }
262
-
263
- return {
264
- type: "comparison",
265
- left: tokenValue(left),
266
- operator,
267
- right: parseLiteralToken(right)
268
- };
269
- }
270
-
271
- function parseInvariantEntry(entry) {
272
- const tokens = entry.items;
273
- const values = tokens.map((item) => item.value);
274
- const [a, b, c, d, e, f, g] = tokens;
275
-
276
- if (tokenValue(b) === "requires") {
277
- return {
278
- type: "requires",
279
- field: tokenValue(a),
280
- predicate: parseComparison(c, tokenValue(d), e),
281
- raw: values,
282
- loc: entry.loc
283
- };
284
- }
285
-
286
- if (tokenValue(b) === "length") {
287
- return {
288
- type: "length_check",
289
- field: tokenValue(a),
290
- operator: tokenValue(c),
291
- value: parseLiteralToken(d),
292
- raw: values,
293
- loc: entry.loc
294
- };
295
- }
296
-
297
- if (tokenValue(b) === "format") {
298
- return {
299
- type: "format_check",
300
- field: tokenValue(a),
301
- operator: tokenValue(c),
302
- format: tokenValue(d),
303
- raw: values,
304
- loc: entry.loc
305
- };
306
- }
307
-
308
- if (tokenValue(d) === "implies") {
309
- return {
310
- type: "implication",
311
- when: parseComparison(a, tokenValue(b), c),
312
- then:
313
- tokenValue(f) === "is"
314
- ? {
315
- type: "state_check",
316
- field: tokenValue(e),
317
- operator: "is",
318
- value: parseLiteralToken(g)
319
- }
320
- : parseComparison(e, tokenValue(f), g),
321
- raw: values,
322
- loc: entry.loc
323
- };
324
- }
325
-
326
- if (["==", "!=", "<", "<=", ">", ">="].includes(tokenValue(b))) {
327
- return {
328
- type: "comparison",
329
- left: tokenValue(a),
330
- operator: tokenValue(b),
331
- right: parseLiteralToken(c),
332
- raw: values,
333
- loc: entry.loc
334
- };
335
- }
336
-
337
- return {
338
- type: "unknown",
339
- raw: values,
340
- loc: entry.loc
341
- };
342
- }
343
-
344
- function parseRuleExpression(value) {
345
- const text = valueAsArray(value).map((item) => item.value).join(" ").trim();
346
- const match = text.match(/^(.+?)\s*(==|!=|<=|>=|<|>)\s*(.+)$/);
347
- if (!match) {
348
- return {
349
- type: "unknown",
350
- raw: text
351
- };
352
- }
353
-
354
- return {
355
- type: "comparison",
356
- left: match[1].trim(),
357
- operator: match[2],
358
- right: {
359
- kind: "symbol",
360
- value: match[3].trim()
361
- },
362
- raw: text
363
- };
364
- }
365
-
366
- function parseSymbolNode(value) {
367
- return {
368
- type: "symbol",
369
- id: value
370
- };
371
- }
372
-
373
- function parseSymbolNodes(values) {
374
- return values.map((value, index) => ({
375
- ...parseSymbolNode(value),
376
- order: index
377
- }));
378
- }
379
-
380
- function parseReferenceNodes(values) {
381
- return values.map((entry, index) => ({
382
- type: "reference",
383
- id: entry.id,
384
- target: entry.target || { id: entry.id, kind: null },
385
- order: index
386
- }));
387
- }
388
-
389
- function buildComponentContract(statement) {
390
- return {
391
- type: "ui_widget_contract",
392
- id: statement.id,
393
- name: statement.name || statement.id,
394
- description: statement.description || null,
395
- category: statement.category || null,
396
- version: statement.version || null,
397
- status: statement.status || null,
398
- props: (statement.props || []).map((prop) => ({
399
- name: prop.name,
400
- type: prop.fieldType,
401
- requiredness: prop.requiredness,
402
- defaultValue: prop.defaultValue ?? null
403
- })),
404
- events: (statement.events || []).map((event) => ({
405
- id: event.id,
406
- shape: event.shape || null
407
- })),
408
- slots: (statement.slots || []).map((slot) => ({
409
- id: slot.id,
410
- description: slot.description || null
411
- })),
412
- behavior: [...(statement.behavior || [])],
413
- behaviors: (statement.behaviors || []).map((behavior) => ({
414
- kind: behavior.kind,
415
- directives: { ...(behavior.directives || {}) },
416
- source: behavior.source || null
417
- })),
418
- patterns: [...(statement.patterns || [])],
419
- regions: [...(statement.regions || [])],
420
- approvals: [...(statement.approvals || [])],
421
- lookups: parseReferenceNodes(statement.lookups || []),
422
- dependencies: parseReferenceNodes(statement.dependencies || [])
423
- };
424
- }
425
-
426
- function buildCapabilityFlow(statement) {
427
- const effects = [];
428
-
429
- for (const [kind, refs] of [
430
- ["read", statement.reads],
431
- ["create", statement.creates],
432
- ["update", statement.updates],
433
- ["delete", statement.deletes]
434
- ]) {
435
- for (const ref of refs) {
436
- effects.push({
437
- type: "effect",
438
- action: kind,
439
- target: ref.target || { id: ref.id, kind: null }
440
- });
441
- }
442
- }
443
-
444
- return {
445
- type: "capability_flow",
446
- actors: parseReferenceNodes(statement.actors),
447
- roles: parseReferenceNodes(statement.roles),
448
- effects,
449
- contracts: {
450
- input: statement.input.map((ref) => ref.target || { id: ref.id, kind: null }),
451
- output: statement.output.map((ref) => ref.target || { id: ref.id, kind: null })
452
- }
453
- };
454
- }
455
-
456
- function buildRulePolicy(statement) {
457
- return {
458
- type: "policy",
459
- appliesTo: statement.appliesTo.map((ref) => ref.target || { id: ref.id, kind: null }),
460
- actors: statement.actors.map((ref) => ref.target || { id: ref.id, kind: null }),
461
- roles: statement.roles.map((ref) => ref.target || { id: ref.id, kind: null }),
462
- condition: statement.conditionNode,
463
- requirement: statement.requirementNode,
464
- severity: statement.severity,
465
- sourceOfTruth: statement.sourceOfTruth.map((ref) => ref.target || { id: ref.id, kind: null })
466
- };
467
- }
468
-
469
- function buildDecisionRecord(statement) {
470
- return {
471
- type: "decision_record",
472
- context: parseSymbolNodes(statement.context),
473
- consequences: parseSymbolNodes(statement.consequences),
474
- status: statement.status
475
- };
476
- }
477
-
478
- function buildProjectionPlan(statement) {
479
- return {
480
- type: "projection_plan",
481
- projectionType: statement.type,
482
- realizes: statement.realizes.map((ref, index) => ({
483
- order: index,
484
- target: ref.target || { id: ref.id, kind: null }
485
- })),
486
- outputs: parseSymbolNodes(statement.outputs),
487
- endpoints: statement.http,
488
- errorResponses: statement.httpErrors,
489
- wireFields: statement.httpFields,
490
- responses: statement.httpResponses,
491
- preconditions: statement.httpPreconditions,
492
- idempotency: statement.httpIdempotency,
493
- cache: statement.httpCache,
494
- deleteSemantics: statement.httpDelete,
495
- asyncJobs: statement.httpAsync,
496
- asyncStatus: statement.httpStatus,
497
- downloads: statement.httpDownload,
498
- authorization: statement.httpAuthz,
499
- callbacks: statement.httpCallbacks,
500
- screens: statement.uiScreens,
501
- collectionViews: statement.uiCollections,
502
- screenActions: statement.uiActions,
503
- visibilityRules: statement.uiVisibility,
504
- fieldLookups: statement.uiLookups,
505
- screenRoutes: statement.uiRoutes,
506
- webHints: statement.uiWeb,
507
- iosHints: statement.uiIos,
508
- appShell: statement.uiAppShell,
509
- designTokens: statement.uiDesign,
510
- navigation: statement.uiNavigation,
511
- screenRegions: statement.uiScreenRegions,
512
- widgetBindings: statement.widgetBindings,
513
- tables: statement.dbTables,
514
- columns: statement.dbColumns,
515
- keys: statement.dbKeys,
516
- indexes: statement.dbIndexes,
517
- relations: statement.dbRelations,
518
- lifecycle: statement.dbLifecycle,
519
- http: statement.http,
520
- httpErrors: statement.httpErrors,
521
- httpFields: statement.httpFields,
522
- httpResponses: statement.httpResponses,
523
- httpPreconditions: statement.httpPreconditions,
524
- httpIdempotency: statement.httpIdempotency,
525
- httpCache: statement.httpCache,
526
- httpDelete: statement.httpDelete,
527
- httpAsync: statement.httpAsync,
528
- httpStatus: statement.httpStatus,
529
- httpDownload: statement.httpDownload,
530
- httpAuthz: statement.httpAuthz,
531
- httpCallbacks: statement.httpCallbacks,
532
- uiScreens: statement.uiScreens,
533
- uiCollections: statement.uiCollections,
534
- uiActions: statement.uiActions,
535
- uiVisibility: statement.uiVisibility,
536
- uiRoutes: statement.uiRoutes,
537
- uiWeb: statement.uiWeb,
538
- uiDesign: statement.uiDesign,
539
- dbTables: statement.dbTables,
540
- dbColumns: statement.dbColumns,
541
- dbKeys: statement.dbKeys,
542
- dbIndexes: statement.dbIndexes,
543
- dbRelations: statement.dbRelations,
544
- dbLifecycle: statement.dbLifecycle,
545
- generatorDefaults: statement.generatorDefaults
546
- };
547
- }
548
-
549
- function buildVerificationPlan(statement) {
550
- return {
551
- type: "verification_plan",
552
- method: statement.method,
553
- validates: statement.validates.map((ref, index) => ({
554
- order: index,
555
- target: ref.target || { id: ref.id, kind: null }
556
- })),
557
- scenarios: parseSymbolNodes(statement.scenarios)
558
- };
559
- }
560
-
561
- function buildOperationMonitoring(statement) {
562
- return {
563
- type: "operation_monitoring",
564
- observes: statement.observes.map((ref, index) => ({
565
- order: index,
566
- target: ref.target || { id: ref.id, kind: null }
567
- })),
568
- metrics: parseSymbolNodes(statement.metrics),
569
- alerts: parseSymbolNodes(statement.alerts)
570
- };
571
- }
572
-
573
- function buildOrchestrationPlan(statement) {
574
- return {
575
- type: "orchestration_plan",
576
- inputs: statement.inputs.map((ref, index) => ({
577
- order: index,
578
- target: ref.target || { id: ref.id, kind: null }
579
- })),
580
- steps: parseSymbolNodes(statement.steps),
581
- outputs: parseSymbolNodes(statement.outputs)
582
- };
583
- }
584
-
585
- function buildTermVocabulary(statement) {
586
- return {
587
- type: "term_vocabulary",
588
- aliases: parseSymbolNodes(statement.aliases),
589
- excludes: parseSymbolNodes(statement.excludes)
590
- };
591
- }
592
-
593
- function parseKeyBlock(statement) {
594
- return blockEntries(getFieldValue(statement, "keys")).map((entry) => ({
595
- type: tokenValue(entry.items[0]),
596
- fields:
597
- entry.items[1]?.type === "list"
598
- ? entry.items[1].items.map((item) => item.value)
599
- : [],
600
- raw: normalizeSequence(entry.items),
601
- loc: entry.loc
602
- }));
603
- }
604
-
605
- function parseRelationBlock(statement, registry) {
606
- return blockEntries(getFieldValue(statement, "relations")).map((entry) => {
607
- const sourceField = tokenValue(entry.items[0]);
608
- const targetRef = tokenValue(entry.items[2]);
609
- const [entityId, fieldName] = (targetRef || "").split(".");
610
- const targetStatement = entityId ? registry.get(entityId) : null;
611
-
612
- return {
613
- type: "reference",
614
- sourceField,
615
- target: entityId
616
- ? {
617
- id: entityId,
618
- kind: targetStatement?.kind || null,
619
- field: fieldName || null
620
- }
621
- : null,
622
- raw: normalizeSequence(entry.items),
623
- loc: entry.loc
624
- };
625
- });
626
- }
627
-
628
- function parseInvariantBlock(statement) {
629
- return blockEntries(getFieldValue(statement, "invariants")).map((entry) => parseInvariantEntry(entry));
630
- }
631
-
632
- function parseRenameBlock(statement) {
633
- return blockEntries(getFieldValue(statement, "rename")).map((entry) => ({
634
- from: entry.items[0]?.value ?? null,
635
- to: entry.items[1]?.value ?? null,
636
- loc: entry.loc
637
- }));
638
- }
639
-
640
- function parseOverridesBlock(statement) {
641
- return blockEntries(getFieldValue(statement, "overrides")).map((entry) => {
642
- const [fieldName, ...rest] = entry.items;
643
- const override = {
644
- field: fieldName?.value ?? null,
645
- requiredness: null,
646
- fieldType: null,
647
- defaultValue: undefined,
648
- loc: entry.loc
649
- };
650
-
651
- for (let i = 0; i < rest.length; i += 1) {
652
- const token = rest[i];
653
- if (!token || token.type !== "symbol") {
654
- continue;
655
- }
656
-
657
- if (token.value === "required" || token.value === "optional") {
658
- override.requiredness = token.value;
659
- continue;
660
- }
661
-
662
- if (token.value === "type") {
663
- override.fieldType = rest[i + 1]?.value ?? null;
664
- i += 1;
665
- continue;
666
- }
667
-
668
- if (token.value === "default") {
669
- override.defaultValue = rest[i + 1]?.value ?? null;
670
- i += 1;
671
- }
672
- }
673
-
674
- return override;
675
- });
676
- }
677
-
678
- function parseProjectionHttpBlock(statement, registry) {
679
- return blockEntries(getFieldValue(statement, "endpoints")).map((entry) => {
680
- const capabilityId = tokenValue(entry.items[0]);
681
- const directives = {};
682
-
683
- for (let i = 1; i < entry.items.length; i += 2) {
684
- const key = tokenValue(entry.items[i]);
685
- const value = tokenValue(entry.items[i + 1]);
686
- if (key && value != null) {
687
- directives[key] = value;
688
- }
689
- }
690
-
691
- return {
692
- type: "http_realization",
693
- capability: capabilityId
694
- ? {
695
- id: capabilityId,
696
- kind: registry.get(capabilityId)?.kind || null
697
- }
698
- : null,
699
- method: directives.method || null,
700
- path: directives.path || null,
701
- success: directives.success ? Number.parseInt(directives.success, 10) : null,
702
- auth: directives.auth || null,
703
- request: directives.request || null,
704
- raw: normalizeSequence(entry.items),
705
- loc: entry.loc
706
- };
707
- });
708
- }
709
-
710
- function parseProjectionHttpErrorsBlock(statement, registry) {
711
- return blockEntries(getFieldValue(statement, "error_responses")).map((entry) => ({
712
- type: "http_error_mapping",
713
- capability: tokenValue(entry.items[0])
714
- ? {
715
- id: tokenValue(entry.items[0]),
716
- kind: registry.get(tokenValue(entry.items[0]))?.kind || null
717
- }
718
- : null,
719
- code: tokenValue(entry.items[1]),
720
- status: tokenValue(entry.items[2]) ? Number.parseInt(tokenValue(entry.items[2]), 10) : null,
721
- raw: normalizeSequence(entry.items),
722
- loc: entry.loc
723
- }));
724
- }
725
-
726
- function parseProjectionHttpFieldsBlock(statement, registry) {
727
- return blockEntries(getFieldValue(statement, "wire_fields")).map((entry) => ({
728
- type: "http_field_binding",
729
- capability: tokenValue(entry.items[0])
730
- ? {
731
- id: tokenValue(entry.items[0]),
732
- kind: registry.get(tokenValue(entry.items[0]))?.kind || null
733
- }
734
- : null,
735
- direction: tokenValue(entry.items[1]),
736
- field: tokenValue(entry.items[2]),
737
- location: tokenValue(entry.items[4]),
738
- wireName: tokenValue(entry.items[5]) === "as" ? tokenValue(entry.items[6]) : null,
739
- raw: normalizeSequence(entry.items),
740
- loc: entry.loc
741
- }));
742
- }
743
-
744
- function parseProjectionHttpResponsesBlock(statement, registry) {
745
- return blockEntries(getFieldValue(statement, "responses")).map((entry) => {
746
- const capabilityId = tokenValue(entry.items[0]);
747
- const directives = parseProjectionHttpResponseDirectives(entry.items.slice(1));
748
-
749
- return {
750
- type: "http_response_realization",
751
- capability: capabilityId
752
- ? {
753
- id: capabilityId,
754
- kind: registry.get(capabilityId)?.kind || null
755
- }
756
- : null,
757
- mode: directives.mode || null,
758
- item: directives.item
759
- ? {
760
- id: directives.item,
761
- kind: registry.get(directives.item)?.kind || null
762
- }
763
- : null,
764
- cursor: directives.cursor || null,
765
- limit: directives.limit
766
- ? {
767
- field: directives.limit.field,
768
- defaultValue: directives.limit.defaultValue ? Number.parseInt(directives.limit.defaultValue, 10) : null,
769
- maxValue: directives.limit.maxValue ? Number.parseInt(directives.limit.maxValue, 10) : null
770
- }
771
- : null,
772
- sort: directives.sort
773
- ? {
774
- field: directives.sort.field,
775
- direction: directives.sort.direction
776
- }
777
- : null,
778
- total: directives.total
779
- ? {
780
- included: directives.total.included === "true"
781
- }
782
- : null,
783
- raw: normalizeSequence(entry.items),
784
- loc: entry.loc
785
- };
786
- });
787
- }
788
-
789
- function parseProjectionHttpPreconditionsBlock(statement, registry) {
790
- return blockEntries(getFieldValue(statement, "preconditions")).map((entry) => {
791
- const capabilityId = tokenValue(entry.items[0]);
792
- const directives = {};
793
-
794
- for (let i = 1; i < entry.items.length; i += 2) {
795
- const key = tokenValue(entry.items[i]);
796
- const value = tokenValue(entry.items[i + 1]);
797
- if (key && value != null) {
798
- directives[key] = value;
799
- }
800
- }
801
-
802
- return {
803
- type: "http_precondition",
804
- capability: capabilityId
805
- ? {
806
- id: capabilityId,
807
- kind: registry.get(capabilityId)?.kind || null
808
- }
809
- : null,
810
- header: directives.header || null,
811
- required: directives.required === "true",
812
- error: directives.error ? Number.parseInt(directives.error, 10) : null,
813
- source: directives.source || null,
814
- code: directives.code || null,
815
- raw: normalizeSequence(entry.items),
816
- loc: entry.loc
817
- };
818
- });
819
- }
820
-
821
- function parseProjectionHttpIdempotencyBlock(statement, registry) {
822
- return blockEntries(getFieldValue(statement, "idempotency")).map((entry) => {
823
- const capabilityId = tokenValue(entry.items[0]);
824
- const directives = {};
825
-
826
- for (let i = 1; i < entry.items.length; i += 2) {
827
- const key = tokenValue(entry.items[i]);
828
- const value = tokenValue(entry.items[i + 1]);
829
- if (key && value != null) {
830
- directives[key] = value;
831
- }
832
- }
833
-
834
- return {
835
- type: "idempotency",
836
- capability: capabilityId
837
- ? {
838
- id: capabilityId,
839
- kind: registry.get(capabilityId)?.kind || null
840
- }
841
- : null,
842
- header: directives.header || null,
843
- required: directives.required === "true",
844
- error: directives.error ? Number.parseInt(directives.error, 10) : null,
845
- code: directives.code || null,
846
- raw: normalizeSequence(entry.items),
847
- loc: entry.loc
848
- };
849
- });
850
- }
851
-
852
- function parseProjectionHttpCacheBlock(statement, registry) {
853
- return blockEntries(getFieldValue(statement, "cache")).map((entry) => {
854
- const capabilityId = tokenValue(entry.items[0]);
855
- const directives = {};
856
-
857
- for (let i = 1; i < entry.items.length; i += 2) {
858
- const key = tokenValue(entry.items[i]);
859
- const value = tokenValue(entry.items[i + 1]);
860
- if (key && value != null) {
861
- directives[key] = value;
862
- }
863
- }
864
-
865
- return {
866
- type: "cache",
867
- capability: capabilityId
868
- ? {
869
- id: capabilityId,
870
- kind: registry.get(capabilityId)?.kind || null
871
- }
872
- : null,
873
- responseHeader: directives.response_header || null,
874
- requestHeader: directives.request_header || null,
875
- required: directives.required === "true",
876
- notModified: directives.not_modified ? Number.parseInt(directives.not_modified, 10) : null,
877
- source: directives.source || null,
878
- code: directives.code || null,
879
- raw: normalizeSequence(entry.items),
880
- loc: entry.loc
881
- };
882
- });
883
- }
884
-
885
- function parseProjectionHttpDeleteBlock(statement, registry) {
886
- return blockEntries(getFieldValue(statement, "delete_semantics")).map((entry) => {
887
- const capabilityId = tokenValue(entry.items[0]);
888
- const directives = {};
889
-
890
- for (let i = 1; i < entry.items.length; i += 2) {
891
- const key = tokenValue(entry.items[i]);
892
- const value = tokenValue(entry.items[i + 1]);
893
- if (key && value != null) {
894
- directives[key] = value;
895
- }
896
- }
897
-
898
- return {
899
- type: "delete_semantics",
900
- capability: capabilityId
901
- ? {
902
- id: capabilityId,
903
- kind: registry.get(capabilityId)?.kind || null
904
- }
905
- : null,
906
- mode: directives.mode || null,
907
- field: directives.field || null,
908
- value: directives.value || null,
909
- response: directives.response || null,
910
- raw: normalizeSequence(entry.items),
911
- loc: entry.loc
912
- };
913
- });
914
- }
915
-
916
- function parseProjectionHttpAsyncBlock(statement, registry) {
917
- return blockEntries(getFieldValue(statement, "async_jobs")).map((entry) => {
918
- const capabilityId = tokenValue(entry.items[0]);
919
- const directives = {};
920
-
921
- for (let i = 1; i < entry.items.length; i += 2) {
922
- const key = tokenValue(entry.items[i]);
923
- const value = tokenValue(entry.items[i + 1]);
924
- if (key && value != null) {
925
- directives[key] = value;
926
- }
927
- }
928
-
929
- return {
930
- type: "async_jobs",
931
- capability: capabilityId
932
- ? {
933
- id: capabilityId,
934
- kind: registry.get(capabilityId)?.kind || null
935
- }
936
- : null,
937
- mode: directives.mode || null,
938
- accepted: directives.accepted ? Number.parseInt(directives.accepted, 10) : null,
939
- locationHeader: directives.location_header || null,
940
- retryAfterHeader: directives.retry_after_header || null,
941
- statusPath: directives.status_path || null,
942
- statusCapability: directives.status_capability
943
- ? {
944
- id: directives.status_capability,
945
- kind: registry.get(directives.status_capability)?.kind || null
946
- }
947
- : null,
948
- job: directives.job
949
- ? {
950
- id: directives.job,
951
- kind: registry.get(directives.job)?.kind || null
952
- }
953
- : null,
954
- raw: normalizeSequence(entry.items),
955
- loc: entry.loc
956
- };
957
- });
958
- }
959
-
960
- function parseProjectionHttpStatusBlock(statement, registry) {
961
- return blockEntries(getFieldValue(statement, "async_status")).map((entry) => {
962
- const capabilityId = tokenValue(entry.items[0]);
963
- const directives = {};
964
-
965
- for (let i = 1; i < entry.items.length; i += 2) {
966
- const key = tokenValue(entry.items[i]);
967
- const value = tokenValue(entry.items[i + 1]);
968
- if (key && value != null) {
969
- directives[key] = value;
970
- }
971
- }
972
-
973
- return {
974
- type: "async_status",
975
- capability: capabilityId
976
- ? {
977
- id: capabilityId,
978
- kind: registry.get(capabilityId)?.kind || null
979
- }
980
- : null,
981
- asyncFor: directives.async_for
982
- ? {
983
- id: directives.async_for,
984
- kind: registry.get(directives.async_for)?.kind || null
985
- }
986
- : null,
987
- stateField: directives.state_field || null,
988
- completed: directives.completed || null,
989
- failed: directives.failed || null,
990
- expired: directives.expired || null,
991
- downloadCapability: directives.download_capability
992
- ? {
993
- id: directives.download_capability,
994
- kind: registry.get(directives.download_capability)?.kind || null
995
- }
996
- : null,
997
- downloadField: directives.download_field || null,
998
- errorField: directives.error_field || null,
999
- raw: normalizeSequence(entry.items),
1000
- loc: entry.loc
1001
- };
1002
- });
1003
- }
1004
-
1005
- function parseProjectionHttpDownloadBlock(statement, registry) {
1006
- return blockEntries(getFieldValue(statement, "downloads")).map((entry) => {
1007
- const capabilityId = tokenValue(entry.items[0]);
1008
- const directives = {};
1009
-
1010
- for (let i = 1; i < entry.items.length; i += 2) {
1011
- const key = tokenValue(entry.items[i]);
1012
- const value = tokenValue(entry.items[i + 1]);
1013
- if (key && value != null) {
1014
- directives[key] = value;
1015
- }
1016
- }
1017
-
1018
- return {
1019
- type: "downloads",
1020
- capability: capabilityId
1021
- ? {
1022
- id: capabilityId,
1023
- kind: registry.get(capabilityId)?.kind || null
1024
- }
1025
- : null,
1026
- asyncFor: directives.async_for
1027
- ? {
1028
- id: directives.async_for,
1029
- kind: registry.get(directives.async_for)?.kind || null
1030
- }
1031
- : null,
1032
- media: directives.media || null,
1033
- filename: directives.filename || null,
1034
- disposition: directives.disposition || null,
1035
- raw: normalizeSequence(entry.items),
1036
- loc: entry.loc
1037
- };
1038
- });
1039
- }
1040
-
1041
- function parseProjectionHttpAuthzBlock(statement, registry) {
1042
- return blockEntries(getFieldValue(statement, "authorization")).map((entry) => {
1043
- const capabilityId = tokenValue(entry.items[0]);
1044
- const directives = {};
1045
-
1046
- for (let i = 1; i < entry.items.length; i += 2) {
1047
- const key = tokenValue(entry.items[i]);
1048
- const value = tokenValue(entry.items[i + 1]);
1049
- if (key && value != null) {
1050
- directives[key] = value;
1051
- }
1052
- }
1053
-
1054
- return {
1055
- type: "authorization",
1056
- capability: capabilityId
1057
- ? {
1058
- id: capabilityId,
1059
- kind: registry.get(capabilityId)?.kind || null
1060
- }
1061
- : null,
1062
- role: directives.role || null,
1063
- permission: directives.permission || null,
1064
- claim: directives.claim || null,
1065
- claimValue: directives.claim_value || null,
1066
- ownership: directives.ownership || null,
1067
- ownershipField: directives.ownership_field || null,
1068
- raw: normalizeSequence(entry.items),
1069
- loc: entry.loc
1070
- };
1071
- });
1072
- }
1073
-
1074
- function parseProjectionHttpCallbacksBlock(statement, registry) {
1075
- return blockEntries(getFieldValue(statement, "callbacks")).map((entry) => {
1076
- const capabilityId = tokenValue(entry.items[0]);
1077
- const directives = {};
1078
-
1079
- for (let i = 1; i < entry.items.length; i += 2) {
1080
- const key = tokenValue(entry.items[i]);
1081
- const value = tokenValue(entry.items[i + 1]);
1082
- if (key && value != null) {
1083
- directives[key] = value;
1084
- }
1085
- }
1086
-
1087
- return {
1088
- type: "http_callback",
1089
- capability: capabilityId
1090
- ? {
1091
- id: capabilityId,
1092
- kind: registry.get(capabilityId)?.kind || null
1093
- }
1094
- : null,
1095
- event: directives.event || null,
1096
- targetField: directives.target_field || null,
1097
- method: directives.method || null,
1098
- payload: directives.payload
1099
- ? {
1100
- id: directives.payload,
1101
- kind: registry.get(directives.payload)?.kind || null
1102
- }
1103
- : null,
1104
- success: directives.success ? Number.parseInt(directives.success, 10) : null,
1105
- raw: normalizeSequence(entry.items),
1106
- loc: entry.loc
1107
- };
1108
- });
1109
- }
1110
-
1111
- function parseProjectionUiScreensBlock(statement, registry) {
1112
- return blockEntries(getFieldValue(statement, "screens")).map((entry) => {
1113
- const directives = {};
1114
-
1115
- for (let i = 2; i < entry.items.length; i += 2) {
1116
- const key = tokenValue(entry.items[i]);
1117
- const value = tokenValue(entry.items[i + 1]);
1118
- if (key && value != null) {
1119
- directives[key] = value;
1120
- }
1121
- }
1122
-
1123
- return {
1124
- type: "ui_screen",
1125
- id: tokenValue(entry.items[1]),
1126
- kind: directives.kind || null,
1127
- title: directives.title || null,
1128
- load: directives.load ? { id: directives.load, kind: registry.get(directives.load)?.kind || null } : null,
1129
- itemShape: directives.item_shape ? { id: directives.item_shape, kind: registry.get(directives.item_shape)?.kind || null } : null,
1130
- viewShape: directives.view_shape ? { id: directives.view_shape, kind: registry.get(directives.view_shape)?.kind || null } : null,
1131
- inputShape: directives.input_shape ? { id: directives.input_shape, kind: registry.get(directives.input_shape)?.kind || null } : null,
1132
- submit: directives.submit ? { id: directives.submit, kind: registry.get(directives.submit)?.kind || null } : null,
1133
- detailCapability: directives.detail_capability
1134
- ? { id: directives.detail_capability, kind: registry.get(directives.detail_capability)?.kind || null }
1135
- : null,
1136
- primaryAction: directives.primary_action
1137
- ? { id: directives.primary_action, kind: registry.get(directives.primary_action)?.kind || null }
1138
- : null,
1139
- secondaryAction: directives.secondary_action
1140
- ? { id: directives.secondary_action, kind: registry.get(directives.secondary_action)?.kind || null }
1141
- : null,
1142
- destructiveAction: directives.destructive_action
1143
- ? { id: directives.destructive_action, kind: registry.get(directives.destructive_action)?.kind || null }
1144
- : null,
1145
- terminalAction: directives.terminal_action
1146
- ? { id: directives.terminal_action, kind: registry.get(directives.terminal_action)?.kind || null }
1147
- : null,
1148
- successNavigate: directives.success_navigate || null,
1149
- successRefresh: directives.success_refresh || null,
1150
- emptyTitle: directives.empty_title || null,
1151
- emptyBody: directives.empty_body || null,
1152
- loadingState: directives.loading_state || null,
1153
- errorState: directives.error_state || null,
1154
- unauthorizedState: directives.unauthorized_state || null,
1155
- notFoundState: directives.not_found_state || null,
1156
- successState: directives.success_state || null,
1157
- raw: normalizeSequence(entry.items),
1158
- loc: entry.loc
1159
- };
1160
- });
1161
- }
1162
-
1163
- function parseProjectionUiCollectionsBlock(statement) {
1164
- return blockEntries(getFieldValue(statement, "collection_views")).map((entry) => {
1165
- const operation = tokenValue(entry.items[2]);
1166
- const primaryValue = tokenValue(entry.items[3]) || null;
1167
- const secondaryValue = tokenValue(entry.items[4]) || null;
1168
-
1169
- return {
1170
- type: "ui_collection_binding",
1171
- screenId: tokenValue(entry.items[1]),
1172
- operation,
1173
- field: ["filter", "search", "sort", "group"].includes(operation) ? primaryValue : null,
1174
- direction: operation === "sort" ? secondaryValue : null,
1175
- value: primaryValue,
1176
- extra: secondaryValue,
1177
- raw: normalizeSequence(entry.items),
1178
- loc: entry.loc
1179
- };
1180
- });
1181
- }
1182
-
1183
- function parseProjectionUiActionsBlock(statement, registry) {
1184
- return blockEntries(getFieldValue(statement, "screen_actions")).map((entry) => ({
1185
- type: "ui_action_binding",
1186
- screenId: tokenValue(entry.items[1]),
1187
- capability: tokenValue(entry.items[3])
1188
- ? {
1189
- id: tokenValue(entry.items[3]),
1190
- kind: registry.get(tokenValue(entry.items[3]))?.kind || null
1191
- }
1192
- : null,
1193
- prominence: tokenValue(entry.items[5]) || null,
1194
- placement: tokenValue(entry.items[6]) === "placement" ? tokenValue(entry.items[7]) || null : null,
1195
- raw: normalizeSequence(entry.items),
1196
- loc: entry.loc
1197
- }));
1198
- }
1199
-
1200
- function parseProjectionUiVisibilityBlock(statement, registry) {
1201
- return blockEntries(getFieldValue(statement, "visibility_rules")).map((entry) => {
1202
- const directives = {};
1203
- for (let i = 5; i < entry.items.length; i += 2) {
1204
- const key = tokenValue(entry.items[i]);
1205
- const value = tokenValue(entry.items[i + 1]);
1206
- if (key && value != null) {
1207
- directives[key] = value;
1208
- }
1209
- }
1210
-
1211
- return {
1212
- type: "visibility_rules_rule",
1213
- capability: tokenValue(entry.items[1])
1214
- ? {
1215
- id: tokenValue(entry.items[1]),
1216
- kind: registry.get(tokenValue(entry.items[1]))?.kind || null
1217
- }
1218
- : null,
1219
- predicate: tokenValue(entry.items[3]) || null,
1220
- value: tokenValue(entry.items[4]) || null,
1221
- claimValue: directives.claim_value || null,
1222
- raw: normalizeSequence(entry.items),
1223
- loc: entry.loc
1224
- };
1225
- });
1226
- }
1227
-
1228
- function parseProjectionUiLookupsBlock(statement, registry) {
1229
- return blockEntries(getFieldValue(statement, "field_lookups")).map((entry) => ({
1230
- type: "ui_lookup_binding",
1231
- screenId: tokenValue(entry.items[1]),
1232
- field: tokenValue(entry.items[3]) || null,
1233
- entity: tokenValue(entry.items[5])
1234
- ? {
1235
- id: tokenValue(entry.items[5]),
1236
- kind: registry.get(tokenValue(entry.items[5]))?.kind || null
1237
- }
1238
- : null,
1239
- labelField: tokenValue(entry.items[7]) || null,
1240
- emptyLabel: tokenValue(entry.items[9]) || null,
1241
- raw: normalizeSequence(entry.items),
1242
- loc: entry.loc
1243
- }));
1244
- }
1245
-
1246
- function parseProjectionUiRoutesBlock(statement) {
1247
- return blockEntries(getFieldValue(statement, "screen_routes")).map((entry) => ({
1248
- type: "ui_route",
1249
- screenId: tokenValue(entry.items[1]),
1250
- path: tokenValue(entry.items[3]) || null,
1251
- raw: normalizeSequence(entry.items),
1252
- loc: entry.loc
1253
- }));
1254
- }
1255
-
1256
- function parseProjectionUiIosBlock(statement, registry) {
1257
- return blockEntries(getFieldValue(statement, "ios_hints")).map((entry) => ({
1258
- type: "ios_hint_binding",
1259
- targetKind: tokenValue(entry.items[0]),
1260
- targetId: tokenValue(entry.items[1]),
1261
- capability:
1262
- tokenValue(entry.items[0]) === "action" && tokenValue(entry.items[1])
1263
- ? {
1264
- id: tokenValue(entry.items[1]),
1265
- kind: registry.get(tokenValue(entry.items[1]))?.kind || null
1266
- }
1267
- : null,
1268
- directive: tokenValue(entry.items[2]) || null,
1269
- value: tokenValue(entry.items[3]) || null,
1270
- raw: normalizeSequence(entry.items),
1271
- loc: entry.loc
1272
- }));
1273
- }
1274
-
1275
- function parseProjectionUiWebBlock(statement, registry) {
1276
- return blockEntries(getFieldValue(statement, "web_hints")).map((entry) => ({
1277
- type: "web_hint_binding",
1278
- targetKind: tokenValue(entry.items[0]),
1279
- targetId: tokenValue(entry.items[1]),
1280
- capability:
1281
- tokenValue(entry.items[0]) === "action" && tokenValue(entry.items[1])
1282
- ? {
1283
- id: tokenValue(entry.items[1]),
1284
- kind: registry.get(tokenValue(entry.items[1]))?.kind || null
1285
- }
1286
- : null,
1287
- directive: tokenValue(entry.items[2]) || null,
1288
- value: tokenValue(entry.items[3]) || null,
1289
- raw: normalizeSequence(entry.items),
1290
- loc: entry.loc
1291
- }));
1292
- }
1293
-
1294
- function parseProjectionUiAppShellBlock(statement) {
1295
- return blockEntries(getFieldValue(statement, "app_shell")).map((entry) => ({
1296
- type: "app_shell_binding",
1297
- key: tokenValue(entry.items[0]) || null,
1298
- value: tokenValue(entry.items[1]) || null,
1299
- raw: normalizeSequence(entry.items),
1300
- loc: entry.loc
1301
- }));
1302
- }
1303
-
1304
- function parseProjectionUiDesignBlock(statement) {
1305
- return blockEntries(getFieldValue(statement, "design_tokens")).map((entry) => ({
1306
- type: "design_tokens_token",
1307
- key: tokenValue(entry.items[0]) || null,
1308
- role: tokenValue(entry.items[1]) || null,
1309
- value: tokenValue(entry.items[2]) || null,
1310
- raw: normalizeSequence(entry.items),
1311
- loc: entry.loc
1312
- }));
1313
- }
1314
-
1315
- function parseProjectionUiNavigationBlock(statement) {
1316
- return blockEntries(getFieldValue(statement, "navigation")).map((entry) => {
1317
- const directives = {};
1318
- for (let i = 2; i < entry.items.length; i += 2) {
1319
- const key = tokenValue(entry.items[i]);
1320
- const value = tokenValue(entry.items[i + 1]);
1321
- if (key && value != null) {
1322
- directives[key] = value;
1323
- }
1324
- }
1325
-
1326
- return {
1327
- type: "navigation_binding",
1328
- targetKind: tokenValue(entry.items[0]) || null,
1329
- targetId: tokenValue(entry.items[1]) || null,
1330
- directives,
1331
- raw: normalizeSequence(entry.items),
1332
- loc: entry.loc
1333
- };
1334
- });
1335
- }
1336
-
1337
- function parseProjectionUiScreenRegionsBlock(statement) {
1338
- return blockEntries(getFieldValue(statement, "screen_regions")).map((entry) => {
1339
- const directives = {};
1340
- for (let i = 4; i < entry.items.length; i += 2) {
1341
- const key = tokenValue(entry.items[i]);
1342
- const value = tokenValue(entry.items[i + 1]);
1343
- if (key && value != null) {
1344
- directives[key] = value;
1345
- }
1346
- }
1347
-
1348
- return {
1349
- type: "ui_screen_region_binding",
1350
- screenId: tokenValue(entry.items[1]) || null,
1351
- region: tokenValue(entry.items[3]) || null,
1352
- pattern: directives.pattern || null,
1353
- placement: directives.placement || null,
1354
- title: directives.title || null,
1355
- state: directives.state || null,
1356
- variant: directives.variant || null,
1357
- raw: normalizeSequence(entry.items),
1358
- loc: entry.loc
1359
- };
1360
- });
1361
- }
1362
-
1363
- function parseProjectionUiComponentsBlock(statement, registry) {
1364
- return blockEntries(getFieldValue(statement, "widget_bindings")).map((entry) => {
1365
- const dataBindings = [];
1366
- const eventBindings = [];
1367
-
1368
- for (let i = 6; i < entry.items.length;) {
1369
- const directive = tokenValue(entry.items[i]);
1370
- if (directive === "data") {
1371
- const prop = tokenValue(entry.items[i + 1]);
1372
- const sourceId = tokenValue(entry.items[i + 3]);
1373
- dataBindings.push({
1374
- prop,
1375
- source: sourceId
1376
- ? {
1377
- id: sourceId,
1378
- kind: registry.get(sourceId)?.kind || null
1379
- }
1380
- : null
1381
- });
1382
- i += 4;
1383
- continue;
1384
- }
1385
- if (directive === "event") {
1386
- const event = tokenValue(entry.items[i + 1]);
1387
- const action = tokenValue(entry.items[i + 2]);
1388
- const targetId = tokenValue(entry.items[i + 3]);
1389
- eventBindings.push({
1390
- event,
1391
- action,
1392
- target: targetId
1393
- ? {
1394
- id: targetId,
1395
- kind: action === "navigate" ? "screen" : registry.get(targetId)?.kind || null
1396
- }
1397
- : null
1398
- });
1399
- i += 4;
1400
- continue;
1401
- }
1402
- i += 1;
1403
- }
1404
-
1405
- const widgetId = tokenValue(entry.items[5]);
1406
- const widgetRef = widgetId
1407
- ? {
1408
- id: widgetId,
1409
- kind: registry.get(widgetId)?.kind || null
1410
- }
1411
- : null;
1412
- const binding = {
1413
- type: "widget_binding",
1414
- screenId: tokenValue(entry.items[1]) || null,
1415
- region: tokenValue(entry.items[3]) || null,
1416
- widget: widgetRef,
1417
- dataBindings,
1418
- eventBindings,
1419
- raw: normalizeSequence(entry.items),
1420
- loc: entry.loc
1421
- };
1422
- return binding;
1423
- });
1424
- }
1425
-
1426
- function parseProjectionGeneratorDefaultsBlock(statement) {
1427
- return blockEntries(getFieldValue(statement, "generator_defaults")).map((entry) => ({
1428
- type: "generator_default",
1429
- key: tokenValue(entry.items[0]),
1430
- value: tokenValue(entry.items[1]) || null,
1431
- raw: normalizeSequence(entry.items),
1432
- loc: entry.loc
1433
- }));
1434
- }
1435
-
1436
- function parseProjectionDbTablesBlock(statement, registry) {
1437
- return blockEntries(getFieldValue(statement, "tables")).map((entry) => ({
1438
- type: "db_table_mapping",
1439
- entity: tokenValue(entry.items[0])
1440
- ? {
1441
- id: tokenValue(entry.items[0]),
1442
- kind: registry.get(tokenValue(entry.items[0]))?.kind || null
1443
- }
1444
- : null,
1445
- table: tokenValue(entry.items[2]) || null,
1446
- raw: normalizeSequence(entry.items),
1447
- loc: entry.loc
1448
- }));
1449
- }
1450
-
1451
- function parseProjectionDbColumnsBlock(statement, registry) {
1452
- return blockEntries(getFieldValue(statement, "columns")).map((entry) => ({
1453
- type: "db_column_mapping",
1454
- entity: tokenValue(entry.items[0])
1455
- ? {
1456
- id: tokenValue(entry.items[0]),
1457
- kind: registry.get(tokenValue(entry.items[0]))?.kind || null
1458
- }
1459
- : null,
1460
- field: tokenValue(entry.items[2]) || null,
1461
- column: tokenValue(entry.items[4]) || null,
1462
- raw: normalizeSequence(entry.items),
1463
- loc: entry.loc
1464
- }));
1465
- }
1466
-
1467
- function parseProjectionDbKeysBlock(statement, registry) {
1468
- return blockEntries(getFieldValue(statement, "keys")).map((entry) => ({
1469
- type: "db_key",
1470
- entity: tokenValue(entry.items[0])
1471
- ? {
1472
- id: tokenValue(entry.items[0]),
1473
- kind: registry.get(tokenValue(entry.items[0]))?.kind || null
1474
- }
1475
- : null,
1476
- keyType: tokenValue(entry.items[1]) || null,
1477
- fields: entry.items[2]?.type === "list" ? entry.items[2].items.map((item) => item.value) : [],
1478
- raw: normalizeSequence(entry.items),
1479
- loc: entry.loc
1480
- }));
1481
- }
1482
-
1483
- function parseProjectionDbIndexesBlock(statement, registry) {
1484
- return blockEntries(getFieldValue(statement, "indexes")).map((entry) => ({
1485
- type: "db_index",
1486
- entity: tokenValue(entry.items[0])
1487
- ? {
1488
- id: tokenValue(entry.items[0]),
1489
- kind: registry.get(tokenValue(entry.items[0]))?.kind || null
1490
- }
1491
- : null,
1492
- indexType: tokenValue(entry.items[1]) || null,
1493
- fields: entry.items[2]?.type === "list" ? entry.items[2].items.map((item) => item.value) : [],
1494
- raw: normalizeSequence(entry.items),
1495
- loc: entry.loc
1496
- }));
1497
- }
1498
-
1499
- function parseProjectionDbRelationsBlock(statement, registry) {
1500
- return blockEntries(getFieldValue(statement, "relations")).map((entry) => {
1501
- const targetRef = tokenValue(entry.items[4]) || null;
1502
- const [targetEntityId, targetField] = (targetRef || "").split(".");
1503
- return {
1504
- type: "db_relation",
1505
- entity: tokenValue(entry.items[0])
1506
- ? {
1507
- id: tokenValue(entry.items[0]),
1508
- kind: registry.get(tokenValue(entry.items[0]))?.kind || null
1509
- }
1510
- : null,
1511
- relationType: tokenValue(entry.items[1]) || null,
1512
- field: tokenValue(entry.items[2]) || null,
1513
- target: targetEntityId
1514
- ? {
1515
- id: targetEntityId,
1516
- kind: registry.get(targetEntityId)?.kind || null,
1517
- field: targetField || null
1518
- }
1519
- : null,
1520
- onDelete: tokenValue(entry.items[6]) || null,
1521
- raw: normalizeSequence(entry.items),
1522
- loc: entry.loc
1523
- };
1524
- });
1525
- }
1526
-
1527
- function parseProjectionDbLifecycleBlock(statement, registry) {
1528
- return blockEntries(getFieldValue(statement, "lifecycle")).map((entry) => {
1529
- const directives = {};
1530
- for (let i = 2; i < entry.items.length; i += 2) {
1531
- const key = tokenValue(entry.items[i]);
1532
- const value = tokenValue(entry.items[i + 1]);
1533
- if (key && value != null) {
1534
- directives[key] = value;
1535
- }
1536
- }
1537
-
1538
- return {
1539
- type: "lifecycle",
1540
- entity: tokenValue(entry.items[0])
1541
- ? {
1542
- id: tokenValue(entry.items[0]),
1543
- kind: registry.get(tokenValue(entry.items[0]))?.kind || null
1544
- }
1545
- : null,
1546
- lifecycleType: tokenValue(entry.items[1]) || null,
1547
- field: directives.field || null,
1548
- value: directives.value || null,
1549
- createdAt: directives.created_at || null,
1550
- updatedAt: directives.updated_at || null,
1551
- raw: normalizeSequence(entry.items),
1552
- loc: entry.loc
1553
- };
1554
- });
1555
- }
1556
-
1557
- function parseProjectionHttpResponseDirectives(tokens) {
1558
- const directives = {
1559
- mode: null,
1560
- item: null,
1561
- cursor: null,
1562
- limit: null,
1563
- sort: null,
1564
- total: null
1565
- };
1566
-
1567
- for (let i = 0; i < tokens.length; i += 1) {
1568
- const token = tokenValue(tokens[i]);
1569
- if (token === "mode") {
1570
- directives.mode = tokenValue(tokens[i + 1]);
1571
- i += 1;
1572
- continue;
1573
- }
1574
- if (token === "item") {
1575
- directives.item = tokenValue(tokens[i + 1]);
1576
- i += 1;
1577
- continue;
1578
- }
1579
- if (token === "cursor") {
1580
- directives.cursor = {
1581
- requestAfter: tokenValue(tokens[i + 1]) === "request_after" ? tokenValue(tokens[i + 2]) : null,
1582
- responseNext: tokenValue(tokens[i + 3]) === "response_next" ? tokenValue(tokens[i + 4]) : null,
1583
- responsePrev: tokenValue(tokens[i + 5]) === "response_prev" ? tokenValue(tokens[i + 6]) : null
1584
- };
1585
- i += directives.cursor.responsePrev ? 6 : 4;
1586
- continue;
1587
- }
1588
- if (token === "limit") {
1589
- directives.limit = {
1590
- field: tokenValue(tokens[i + 1]) === "field" ? tokenValue(tokens[i + 2]) : null,
1591
- defaultValue: tokenValue(tokens[i + 3]) === "default" ? tokenValue(tokens[i + 4]) : null,
1592
- maxValue: tokenValue(tokens[i + 5]) === "max" ? tokenValue(tokens[i + 6]) : null
1593
- };
1594
- i += 6;
1595
- continue;
1596
- }
1597
- if (token === "sort") {
1598
- directives.sort = {
1599
- field: tokenValue(tokens[i + 1]) === "by" ? tokenValue(tokens[i + 2]) : null,
1600
- direction: tokenValue(tokens[i + 3]) === "direction" ? tokenValue(tokens[i + 4]) : null
1601
- };
1602
- i += 4;
1603
- continue;
1604
- }
1605
- if (token === "total") {
1606
- directives.total = {
1607
- included: tokenValue(tokens[i + 1]) === "included" ? tokenValue(tokens[i + 2]) : null
1608
- };
1609
- i += 2;
1610
- }
1611
- }
1612
-
1613
- return directives;
1614
- }
1615
-
1616
- function cloneField(field) {
1617
- return {
1618
- ...field,
1619
- sourceName: field.sourceName ?? field.name
1620
- };
1621
- }
1622
-
1623
- function fieldRef(field) {
1624
- return {
1625
- name: field.name,
1626
- sourceName: field.sourceName ?? field.name,
1627
- fieldType: field.fieldType,
1628
- requiredness: field.requiredness,
1629
- defaultValue: field.defaultValue ?? null
1630
- };
1631
- }
1632
-
1633
- function applyRename(fields, renameRules) {
1634
- const renameBySource = new Map(renameRules.map((rule) => [rule.from, rule.to]));
1635
- return fields.map((field) => {
1636
- const renamed = cloneField(field);
1637
- const nextName = renameBySource.get(field.name);
1638
- if (nextName) {
1639
- renamed.name = nextName;
1640
- }
1641
- return renamed;
1642
- });
1643
- }
1644
-
1645
- function applyOverrides(fields, overrideRules) {
1646
- const byCurrentName = new Map(fields.map((field) => [field.name, field]));
1647
- const bySourceName = new Map(fields.map((field) => [field.sourceName, field]));
1648
-
1649
- for (const rule of overrideRules) {
1650
- const target = byCurrentName.get(rule.field) || bySourceName.get(rule.field);
1651
- if (!target) {
1652
- continue;
1653
- }
1654
-
1655
- if (rule.requiredness) {
1656
- target.requiredness = rule.requiredness;
1657
- }
1658
- if (rule.fieldType) {
1659
- target.fieldType = rule.fieldType;
1660
- }
1661
- if (rule.defaultValue !== undefined) {
1662
- target.defaultValue = rule.defaultValue;
1663
- }
1664
- }
1665
-
1666
- return fields;
1667
- }
1668
-
1669
- function buildShapeSelection(shape, byId) {
1670
- const explicitFields = shape.fields.length > 0;
1671
- const selectedFields =
1672
- explicitFields
1673
- ? shape.fields.map((field) => ({
1674
- ...cloneField(field),
1675
- sourceName: field.name
1676
- }))
1677
- : deriveShapeFields(shape, byId).map((field) => ({
1678
- ...cloneField(field),
1679
- sourceName: field.name
1680
- }));
1681
-
1682
- return {
1683
- type: "shape_selection",
1684
- mode: explicitFields ? "explicit_fields" : shape.from?.id ? "derived_from_entity" : "empty",
1685
- source: shape.from?.target || null,
1686
- include: parseSymbolNodes(shape.include),
1687
- exclude: parseSymbolNodes(shape.exclude),
1688
- selectedFields: selectedFields.map((field) => fieldRef(field))
1689
- };
1690
- }
1691
-
1692
- function buildRenameTransforms(renameRules) {
1693
- return renameRules.map((rule, index) => ({
1694
- type: "rename_field",
1695
- order: index,
1696
- from: rule.from,
1697
- to: rule.to,
1698
- loc: rule.loc
1699
- }));
1700
- }
1701
-
1702
- function buildOverrideTransforms(overrideRules) {
1703
- return overrideRules.map((rule, index) => ({
1704
- type: "override_field",
1705
- order: index,
1706
- field: rule.field,
1707
- changes: {
1708
- requiredness: rule.requiredness,
1709
- fieldType: rule.fieldType,
1710
- defaultValue: rule.defaultValue ?? null
1711
- },
1712
- loc: rule.loc
1713
- }));
1714
- }
1715
-
1716
- function buildShapeTransformGraph(shape, byId) {
1717
- const selection = buildShapeSelection(shape, byId);
1718
- return {
1719
- type: "shape_transform_graph",
1720
- selection,
1721
- transforms: [
1722
- ...buildRenameTransforms(shape.rename),
1723
- ...buildOverrideTransforms(shape.overrides)
1724
- ],
1725
- resultFields: (shape.projectedFields || []).map((field) => fieldRef(field))
1726
- };
1727
- }
1728
-
1729
- function projectShapeFields(shape, byId) {
1730
- const baseFields =
1731
- shape.fields.length > 0
1732
- ? shape.fields.map((field) => ({
1733
- ...cloneField(field),
1734
- sourceName: field.name
1735
- }))
1736
- : deriveShapeFields(shape, byId).map((field) => ({
1737
- ...cloneField(field),
1738
- sourceName: field.name
1739
- }));
1740
-
1741
- const renamedFields = applyRename(baseFields, shape.rename);
1742
- const overriddenFields = applyOverrides(renamedFields, shape.overrides);
1743
-
1744
- return overriddenFields.map((field) => ({
1745
- name: field.name,
1746
- sourceName: field.sourceName,
1747
- fieldType: field.fieldType,
1748
- requiredness: field.requiredness,
1749
- defaultValue: field.defaultValue ?? null,
1750
- raw: field.raw,
1751
- loc: field.loc
1752
- }));
1753
- }
1754
-
1755
- function deriveShapeFields(shape, byId) {
1756
- if (shape.fields.length > 0) {
1757
- return shape.fields;
1758
- }
1759
-
1760
- if (!shape.from?.target?.id) {
1761
- return [];
1762
- }
1763
-
1764
- const entity = byId.get(shape.from.target.id);
1765
- if (!entity || entity.kind !== "entity") {
1766
- return [];
1767
- }
1768
-
1769
- const sourceFields = new Map(entity.fields.map((field) => [field.name, field]));
1770
- const includes = shape.include.length > 0 ? shape.include : [...sourceFields.keys()];
1771
- const excludes = new Set(shape.exclude);
1772
-
1773
- return includes
1774
- .filter((fieldName) => !excludes.has(fieldName))
1775
- .map((fieldName) => sourceFields.get(fieldName))
1776
- .filter(Boolean)
1777
- .map((field) => cloneField(field));
1778
- }
1779
-
1780
- export function normalizeStatement(statement, registry) {
1781
- const fieldMap = collectFieldMap(statement);
1782
- const base = {
1783
- kind: statement.kind,
1784
- id: statement.id,
1785
- name: stringValue(getFieldValue(statement, "name")),
1786
- description: stringValue(getFieldValue(statement, "description")),
1787
- status: symbolValue(getFieldValue(statement, "status")),
1788
- from: statement.from
1789
- ? {
1790
- id: statement.from.value,
1791
- target: toRef(resolveReference(registry, statement.from.value))
1792
- }
1793
- : null,
1794
- loc: statement.loc
1795
- };
1796
-
1797
- switch (statement.kind) {
1798
- case "enum":
1799
- return {
1800
- ...base,
1801
- values: symbolValues(getFieldValue(statement, "values"))
1802
- };
1803
- case "actor":
1804
- case "role":
1805
- return base;
1806
- case "entity":
1807
- return {
1808
- ...base,
1809
- usesTerms: resolveReferenceList(registry, getFieldValue(statement, "uses_terms")),
1810
- fields: normalizeFieldsBlock(statement),
1811
- keys: parseKeyBlock(statement),
1812
- relations: parseRelationBlock(statement, registry),
1813
- invariants: parseInvariantBlock(statement),
1814
- resolvedDomain: resolveDomainTag(statement, registry)
1815
- };
1816
- case "shape":
1817
- return {
1818
- ...base,
1819
- include: symbolValues(getFieldValue(statement, "include")),
1820
- exclude: symbolValues(getFieldValue(statement, "exclude")),
1821
- derivedFrom: resolveReferenceList(registry, getFieldValue(statement, "derived_from")),
1822
- fields: normalizeFieldsBlock(statement),
1823
- rename: parseRenameBlock(statement),
1824
- overrides: parseOverridesBlock(statement)
1825
- };
1826
- case "capability":
1827
- return {
1828
- ...base,
1829
- actors: resolveReferenceList(registry, getFieldValue(statement, "actors")),
1830
- roles: resolveReferenceList(registry, getFieldValue(statement, "roles")),
1831
- reads: resolveReferenceList(registry, getFieldValue(statement, "reads")),
1832
- creates: resolveReferenceList(registry, getFieldValue(statement, "creates")),
1833
- updates: resolveReferenceList(registry, getFieldValue(statement, "updates")),
1834
- deletes: resolveReferenceList(registry, getFieldValue(statement, "deletes")),
1835
- input: resolveReferenceList(registry, getFieldValue(statement, "input")),
1836
- output: resolveReferenceList(registry, getFieldValue(statement, "output")),
1837
- resolvedDomain: resolveDomainTag(statement, registry)
1838
- };
1839
- case "widget":
1840
- return {
1841
- ...base,
1842
- category: symbolValue(getFieldValue(statement, "category")),
1843
- props: normalizeComponentProps(statement),
1844
- events: normalizeComponentEvents(statement, registry),
1845
- slots: normalizeComponentSlots(statement),
1846
- behavior: symbolValues(getFieldValue(statement, "behavior")),
1847
- behaviors: normalizeComponentBehaviors(statement),
1848
- patterns: symbolValues(getFieldValue(statement, "patterns")),
1849
- regions: symbolValues(getFieldValue(statement, "regions")),
1850
- approvals: symbolValues(getFieldValue(statement, "approvals")),
1851
- lookups: resolveReferenceList(registry, getFieldValue(statement, "lookups")),
1852
- dependencies: resolveReferenceList(registry, getFieldValue(statement, "dependencies")),
1853
- version: stringValue(getFieldValue(statement, "version"))
1854
- };
1855
- case "rule":
1856
- return {
1857
- ...base,
1858
- appliesTo: resolveReferenceList(registry, getFieldValue(statement, "applies_to")),
1859
- actors: resolveReferenceList(registry, getFieldValue(statement, "actors")),
1860
- roles: resolveReferenceList(registry, getFieldValue(statement, "roles")),
1861
- condition: valueAsArray(getFieldValue(statement, "condition")).map((item) => item.value),
1862
- conditionNode: getFieldValue(statement, "condition") ? parseRuleExpression(getFieldValue(statement, "condition")) : null,
1863
- requirement: valueAsArray(getFieldValue(statement, "requirement")).map((item) => item.value),
1864
- requirementNode: getFieldValue(statement, "requirement") ? parseRuleExpression(getFieldValue(statement, "requirement")) : null,
1865
- fromRequirement: getFieldValue(statement, "from_requirement")
1866
- ? {
1867
- id: symbolValue(getFieldValue(statement, "from_requirement")),
1868
- target: toRef(resolveReference(registry, symbolValue(getFieldValue(statement, "from_requirement"))))
1869
- }
1870
- : null,
1871
- severity: symbolValue(getFieldValue(statement, "severity")),
1872
- sourceOfTruth: resolveReferenceList(registry, getFieldValue(statement, "source_of_truth")),
1873
- resolvedDomain: resolveDomainTag(statement, registry)
1874
- };
1875
- case "decision":
1876
- return {
1877
- ...base,
1878
- context: symbolValues(getFieldValue(statement, "context")),
1879
- consequences: symbolValues(getFieldValue(statement, "consequences")),
1880
- pitch: getFieldValue(statement, "pitch")
1881
- ? {
1882
- id: symbolValue(getFieldValue(statement, "pitch")),
1883
- target: toRef(resolveReference(registry, symbolValue(getFieldValue(statement, "pitch"))))
1884
- }
1885
- : null,
1886
- supersedes: resolveReferenceList(registry, getFieldValue(statement, "supersedes")),
1887
- resolvedDomain: resolveDomainTag(statement, registry)
1888
- };
1889
- case "projection":
1890
- return {
1891
- ...base,
1892
- type: symbolValue(getFieldValue(statement, "type")),
1893
- realizes: resolveReferenceList(registry, getFieldValue(statement, "realizes")),
1894
- outputs: symbolValues(getFieldValue(statement, "outputs")),
1895
- endpoints: parseProjectionHttpBlock(statement, registry),
1896
- errorResponses: parseProjectionHttpErrorsBlock(statement, registry),
1897
- wireFields: parseProjectionHttpFieldsBlock(statement, registry),
1898
- responses: parseProjectionHttpResponsesBlock(statement, registry),
1899
- preconditions: parseProjectionHttpPreconditionsBlock(statement, registry),
1900
- idempotency: parseProjectionHttpIdempotencyBlock(statement, registry),
1901
- cache: parseProjectionHttpCacheBlock(statement, registry),
1902
- deleteSemantics: parseProjectionHttpDeleteBlock(statement, registry),
1903
- asyncJobs: parseProjectionHttpAsyncBlock(statement, registry),
1904
- asyncStatus: parseProjectionHttpStatusBlock(statement, registry),
1905
- downloads: parseProjectionHttpDownloadBlock(statement, registry),
1906
- authorization: parseProjectionHttpAuthzBlock(statement, registry),
1907
- callbacks: parseProjectionHttpCallbacksBlock(statement, registry),
1908
- http: parseProjectionHttpBlock(statement, registry),
1909
- httpErrors: parseProjectionHttpErrorsBlock(statement, registry),
1910
- httpFields: parseProjectionHttpFieldsBlock(statement, registry),
1911
- httpResponses: parseProjectionHttpResponsesBlock(statement, registry),
1912
- httpPreconditions: parseProjectionHttpPreconditionsBlock(statement, registry),
1913
- httpIdempotency: parseProjectionHttpIdempotencyBlock(statement, registry),
1914
- httpCache: parseProjectionHttpCacheBlock(statement, registry),
1915
- httpDelete: parseProjectionHttpDeleteBlock(statement, registry),
1916
- httpAsync: parseProjectionHttpAsyncBlock(statement, registry),
1917
- httpStatus: parseProjectionHttpStatusBlock(statement, registry),
1918
- httpDownload: parseProjectionHttpDownloadBlock(statement, registry),
1919
- httpAuthz: parseProjectionHttpAuthzBlock(statement, registry),
1920
- httpCallbacks: parseProjectionHttpCallbacksBlock(statement, registry),
1921
- uiScreens: parseProjectionUiScreensBlock(statement, registry),
1922
- screens: parseProjectionUiScreensBlock(statement, registry),
1923
- uiCollections: parseProjectionUiCollectionsBlock(statement),
1924
- collectionViews: parseProjectionUiCollectionsBlock(statement),
1925
- uiActions: parseProjectionUiActionsBlock(statement, registry),
1926
- screenActions: parseProjectionUiActionsBlock(statement, registry),
1927
- uiVisibility: parseProjectionUiVisibilityBlock(statement, registry),
1928
- visibilityRules: parseProjectionUiVisibilityBlock(statement, registry),
1929
- uiLookups: parseProjectionUiLookupsBlock(statement, registry),
1930
- fieldLookups: parseProjectionUiLookupsBlock(statement, registry),
1931
- uiRoutes: parseProjectionUiRoutesBlock(statement),
1932
- screenRoutes: parseProjectionUiRoutesBlock(statement),
1933
- uiWeb: parseProjectionUiWebBlock(statement, registry),
1934
- webHints: parseProjectionUiWebBlock(statement, registry),
1935
- uiIos: parseProjectionUiIosBlock(statement, registry),
1936
- iosHints: parseProjectionUiIosBlock(statement, registry),
1937
- uiAppShell: parseProjectionUiAppShellBlock(statement),
1938
- appShell: parseProjectionUiAppShellBlock(statement),
1939
- uiDesign: parseProjectionUiDesignBlock(statement),
1940
- designTokens: parseProjectionUiDesignBlock(statement),
1941
- uiNavigation: parseProjectionUiNavigationBlock(statement),
1942
- navigation: parseProjectionUiNavigationBlock(statement),
1943
- uiScreenRegions: parseProjectionUiScreenRegionsBlock(statement),
1944
- screenRegions: parseProjectionUiScreenRegionsBlock(statement),
1945
- widgetBindings: parseProjectionUiComponentsBlock(statement, registry),
1946
- dbTables: parseProjectionDbTablesBlock(statement, registry),
1947
- tables: parseProjectionDbTablesBlock(statement, registry),
1948
- dbColumns: parseProjectionDbColumnsBlock(statement, registry),
1949
- columns: parseProjectionDbColumnsBlock(statement, registry),
1950
- dbKeys: parseProjectionDbKeysBlock(statement, registry),
1951
- keys: parseProjectionDbKeysBlock(statement, registry),
1952
- dbIndexes: parseProjectionDbIndexesBlock(statement, registry),
1953
- indexes: parseProjectionDbIndexesBlock(statement, registry),
1954
- dbRelations: parseProjectionDbRelationsBlock(statement, registry),
1955
- relations: parseProjectionDbRelationsBlock(statement, registry),
1956
- dbLifecycle: parseProjectionDbLifecycleBlock(statement, registry),
1957
- lifecycle: parseProjectionDbLifecycleBlock(statement, registry),
1958
- generatorDefaults: parseProjectionGeneratorDefaultsBlock(statement)
1959
- };
1960
- case "orchestration":
1961
- return {
1962
- ...base,
1963
- inputs: resolveReferenceList(registry, getFieldValue(statement, "inputs")),
1964
- steps: symbolValues(getFieldValue(statement, "steps")),
1965
- outputs: symbolValues(getFieldValue(statement, "outputs")),
1966
- resolvedDomain: resolveDomainTag(statement, registry)
1967
- };
1968
- case "verification":
1969
- return {
1970
- ...base,
1971
- validates: resolveReferenceList(registry, getFieldValue(statement, "validates")),
1972
- method: symbolValue(getFieldValue(statement, "method")),
1973
- scenarios: symbolValues(getFieldValue(statement, "scenarios")),
1974
- requirementRefs: resolveReferenceList(registry, getFieldValue(statement, "requirement_refs")),
1975
- acceptanceRefs: resolveReferenceList(registry, getFieldValue(statement, "acceptance_refs")),
1976
- fixesBugs: resolveReferenceList(registry, getFieldValue(statement, "fixes_bugs")),
1977
- resolvedDomain: resolveDomainTag(statement, registry)
1978
- };
1979
- case "operation":
1980
- return {
1981
- ...base,
1982
- observes: resolveReferenceList(registry, getFieldValue(statement, "observes")),
1983
- metrics: symbolValues(getFieldValue(statement, "metrics")),
1984
- alerts: symbolValues(getFieldValue(statement, "alerts")),
1985
- resolvedDomain: resolveDomainTag(statement, registry)
1986
- };
1987
- case "term":
1988
- return {
1989
- ...base,
1990
- aliases: symbolValues(getFieldValue(statement, "aliases")),
1991
- excludes: symbolValues(getFieldValue(statement, "excludes"))
1992
- };
1993
- case "domain":
1994
- return {
1995
- ...base,
1996
- inScope: normalizeDomainScopeList(statement, "in_scope"),
1997
- outOfScope: normalizeDomainScopeList(statement, "out_of_scope"),
1998
- owners: resolveReferenceList(registry, getFieldValue(statement, "owners")),
1999
- parentDomain: getFieldValue(statement, "parent_domain")
2000
- ? {
2001
- id: symbolValue(getFieldValue(statement, "parent_domain")),
2002
- target: toRef(resolveReference(registry, symbolValue(getFieldValue(statement, "parent_domain"))))
2003
- }
2004
- : null,
2005
- aliases: normalizeDomainScopeList(statement, "aliases")
2006
- };
2007
- case "pitch":
2008
- return {
2009
- ...base,
2010
- priority: symbolValue(getFieldValue(statement, "priority")),
2011
- appetite: stringValue(getFieldValue(statement, "appetite")) || symbolValue(getFieldValue(statement, "appetite")),
2012
- problem: stringValue(getFieldValue(statement, "problem")),
2013
- solutionSketch: stringValue(getFieldValue(statement, "solution_sketch")),
2014
- rabbitHoles: stringValue(getFieldValue(statement, "rabbit_holes")) || symbolValues(getFieldValue(statement, "rabbit_holes")),
2015
- noGoAreas: stringValue(getFieldValue(statement, "no_go_areas")) || symbolValues(getFieldValue(statement, "no_go_areas")),
2016
- affects: resolveReferenceList(registry, getFieldValue(statement, "affects")),
2017
- decisions: resolveReferenceList(registry, getFieldValue(statement, "decisions")),
2018
- updated: stringValue(getFieldValue(statement, "updated")),
2019
- resolvedDomain: resolveDomainTag(statement, registry)
2020
- };
2021
- case "requirement":
2022
- return {
2023
- ...base,
2024
- priority: symbolValue(getFieldValue(statement, "priority")),
2025
- pitch: getFieldValue(statement, "pitch")
2026
- ? {
2027
- id: symbolValue(getFieldValue(statement, "pitch")),
2028
- target: toRef(resolveReference(registry, symbolValue(getFieldValue(statement, "pitch"))))
2029
- }
2030
- : null,
2031
- affects: resolveReferenceList(registry, getFieldValue(statement, "affects")),
2032
- introducesRules: resolveReferenceList(registry, getFieldValue(statement, "introduces_rules")),
2033
- respectsRules: resolveReferenceList(registry, getFieldValue(statement, "respects_rules")),
2034
- supersedes: resolveReferenceList(registry, getFieldValue(statement, "supersedes")),
2035
- updated: stringValue(getFieldValue(statement, "updated")),
2036
- resolvedDomain: resolveDomainTag(statement, registry)
2037
- };
2038
- case "acceptance_criterion":
2039
- return {
2040
- ...base,
2041
- requirement: getFieldValue(statement, "requirement")
2042
- ? {
2043
- id: symbolValue(getFieldValue(statement, "requirement")),
2044
- target: toRef(resolveReference(registry, symbolValue(getFieldValue(statement, "requirement"))))
2045
- }
2046
- : null,
2047
- supersedes: resolveReferenceList(registry, getFieldValue(statement, "supersedes")),
2048
- updated: stringValue(getFieldValue(statement, "updated"))
2049
- };
2050
- case "task":
2051
- return {
2052
- ...base,
2053
- priority: symbolValue(getFieldValue(statement, "priority")),
2054
- workType: symbolValue(getFieldValue(statement, "work_type")),
2055
- affects: resolveReferenceList(registry, getFieldValue(statement, "affects")),
2056
- satisfies: resolveReferenceList(registry, getFieldValue(statement, "satisfies")),
2057
- acceptanceRefs: resolveReferenceList(registry, getFieldValue(statement, "acceptance_refs")),
2058
- blocks: resolveReferenceList(registry, getFieldValue(statement, "blocks")),
2059
- blockedBy: resolveReferenceList(registry, getFieldValue(statement, "blocked_by")),
2060
- claimedBy: resolveReferenceList(registry, getFieldValue(statement, "claimed_by")),
2061
- introducesDecisions: resolveReferenceList(registry, getFieldValue(statement, "introduces_decisions")),
2062
- modifies: resolveReferenceList(registry, getFieldValue(statement, "modifies")),
2063
- introduces: resolveReferenceList(registry, getFieldValue(statement, "introduces")),
2064
- removes: resolveReferenceList(registry, getFieldValue(statement, "removes")),
2065
- updated: stringValue(getFieldValue(statement, "updated")),
2066
- resolvedDomain: resolveDomainTag(statement, registry)
2067
- };
2068
- case "bug":
2069
- return {
2070
- ...base,
2071
- priority: symbolValue(getFieldValue(statement, "priority")),
2072
- severity: symbolValue(getFieldValue(statement, "severity")),
2073
- affects: resolveReferenceList(registry, getFieldValue(statement, "affects")),
2074
- violates: resolveReferenceList(registry, getFieldValue(statement, "violates")),
2075
- surfacesRule: resolveReferenceList(registry, getFieldValue(statement, "surfaces_rule")),
2076
- introducedIn: resolveReferenceList(registry, getFieldValue(statement, "introduced_in")),
2077
- fixedIn: resolveReferenceList(registry, getFieldValue(statement, "fixed_in")),
2078
- fixedInRelease: stringValue(getFieldValue(statement, "fixed_in_release")) || symbolValue(getFieldValue(statement, "fixed_in_release")),
2079
- fixedInVerification: resolveReferenceList(registry, getFieldValue(statement, "fixed_in_verification")),
2080
- reproduction: stringValue(getFieldValue(statement, "reproduction")),
2081
- modifies: resolveReferenceList(registry, getFieldValue(statement, "modifies")),
2082
- introduces: resolveReferenceList(registry, getFieldValue(statement, "introduces")),
2083
- removes: resolveReferenceList(registry, getFieldValue(statement, "removes")),
2084
- updated: stringValue(getFieldValue(statement, "updated")),
2085
- resolvedDomain: resolveDomainTag(statement, registry)
2086
- };
2087
- default:
2088
- return {
2089
- ...base,
2090
- fields: [...fieldMap.keys()]
2091
- };
2092
- }
2093
- }
8
+ import { normalizeStatement } from "./normalize.js";
9
+ import { groupBy } from "./shared.js";
10
+ import { buildShapeTransformGraph, projectShapeFields } from "./shapes.js";
11
+ import { buildWidgetContract } from "./widgets.js";
12
+ import {
13
+ buildCapabilityFlow,
14
+ buildDecisionRecord,
15
+ buildOperationMonitoring,
16
+ buildOrchestrationPlan,
17
+ buildProjectionPlan,
18
+ buildRulePolicy,
19
+ buildTermVocabulary,
20
+ buildVerificationPlan
21
+ } from "./plans.js";
22
+
23
+ export { normalizeStatement } from "./normalize.js";
2094
24
 
2095
25
  function normalizeDoc(doc) {
2096
26
  return {
@@ -2337,7 +267,7 @@ export function resolveWorkspace(workspaceAst) {
2337
267
  case "widget":
2338
268
  return {
2339
269
  ...statement,
2340
- widgetContract: buildComponentContract(statement)
270
+ widgetContract: buildWidgetContract(statement)
2341
271
  };
2342
272
  case "rule":
2343
273
  return {