@yahoo/uds-create-config 2.45.0 → 3.0.1

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 (376) hide show
  1. package/README.md +129 -0
  2. package/dist/ai-lanes.d.ts +23 -0
  3. package/dist/ai-lanes.js +34 -0
  4. package/dist/authoring/define-component.d.ts +85 -0
  5. package/dist/configs/CanvasConfig.d.ts +3237 -0
  6. package/dist/configs/CanvasConfig.js +332 -0
  7. package/dist/configs/build-options.d.ts +10 -0
  8. package/dist/configs/build-options.js +68 -0
  9. package/dist/configs/platform.d.ts +15 -0
  10. package/dist/configs/platform.js +17 -0
  11. package/dist/configs/react-native-system.d.ts +3026 -0
  12. package/dist/configs/react-native-system.js +64 -0
  13. package/dist/configs/system.d.ts +2771 -0
  14. package/dist/configs/system.js +74 -0
  15. package/dist/css/properties.generated.d.ts +14 -0
  16. package/dist/css/properties.generated.js +6260 -0
  17. package/dist/css/value-type.d.ts +48 -0
  18. package/dist/css/value-type.js +131 -0
  19. package/dist/css/values.d.ts +33 -0
  20. package/dist/css/values.js +116 -0
  21. package/dist/entities/native/NativeModifier.d.ts +25 -0
  22. package/dist/entities/native/NativeModifier.js +41 -0
  23. package/dist/entities/native/NativeSettings.d.ts +44 -0
  24. package/dist/entities/native/NativeSettings.js +39 -0
  25. package/dist/entities/native/NativeStyleProperty.d.ts +355 -0
  26. package/dist/entities/native/NativeStyleProperty.js +28 -0
  27. package/dist/entities/native/NativeToken.d.ts +31 -0
  28. package/dist/entities/native/NativeToken.js +49 -0
  29. package/dist/entities/system/CanvasRole.d.ts +34 -0
  30. package/dist/entities/system/CanvasRole.js +45 -0
  31. package/dist/entities/system/Component.d.ts +1287 -0
  32. package/dist/entities/system/Component.js +1840 -0
  33. package/dist/entities/system/Composite.d.ts +12 -0
  34. package/dist/entities/system/Composite.js +26 -0
  35. package/dist/entities/system/Device.d.ts +11 -0
  36. package/dist/entities/system/Device.js +18 -0
  37. package/dist/entities/system/File.d.ts +72 -0
  38. package/dist/entities/system/File.js +136 -0
  39. package/dist/entities/system/Font.d.ts +48 -0
  40. package/dist/entities/system/Font.js +56 -0
  41. package/dist/entities/system/GlobalStyle.d.ts +26 -0
  42. package/dist/entities/system/GlobalStyle.js +54 -0
  43. package/dist/entities/system/Guidance.d.ts +85 -0
  44. package/dist/entities/system/Guidance.js +59 -0
  45. package/dist/entities/system/GuidanceStyle.d.ts +14 -0
  46. package/dist/entities/system/GuidanceStyle.js +8 -0
  47. package/dist/entities/system/Icon.d.ts +46 -0
  48. package/dist/entities/system/Icon.js +46 -0
  49. package/dist/entities/system/LinkedSystem.d.ts +504 -0
  50. package/dist/entities/system/LinkedSystem.js +814 -0
  51. package/dist/entities/system/Modifier.d.ts +92 -0
  52. package/dist/entities/system/Modifier.js +120 -0
  53. package/dist/entities/system/Motion.d.ts +28 -0
  54. package/dist/entities/system/Motion.js +48 -0
  55. package/dist/entities/system/Operation.d.ts +100 -0
  56. package/dist/entities/system/Operation.js +236 -0
  57. package/dist/entities/system/Package.d.ts +42 -0
  58. package/dist/entities/system/Package.js +75 -0
  59. package/dist/entities/system/Settings.d.ts +94 -0
  60. package/dist/entities/system/Settings.js +166 -0
  61. package/dist/entities/system/StyleProperty.d.ts +135 -0
  62. package/dist/entities/system/StyleProperty.js +438 -0
  63. package/dist/entities/system/Token.d.ts +67 -0
  64. package/dist/entities/system/Token.js +129 -0
  65. package/dist/entities/system/Tool.d.ts +134 -0
  66. package/dist/entities/system/Tool.js +124 -0
  67. package/dist/entities/system/color.d.ts +64 -0
  68. package/dist/entities/system/color.js +123 -0
  69. package/dist/entities/system/component-module.d.ts +63 -0
  70. package/dist/entities/system/component-module.js +258 -0
  71. package/dist/entities/system/copy-plan.d.ts +98 -0
  72. package/dist/entities/system/copy-plan.js +451 -0
  73. package/dist/entities/system/defineComponent.d.ts +428 -0
  74. package/dist/entities/system/defineComponent.js +337 -0
  75. package/dist/entities/system/element.d.ts +101 -0
  76. package/dist/entities/system/element.js +171 -0
  77. package/dist/entities/system/icon-library.d.ts +64 -0
  78. package/dist/entities/system/icon-library.js +112 -0
  79. package/dist/entities/system/icon-metadata.d.ts +72 -0
  80. package/dist/entities/system/icon-metadata.js +111 -0
  81. package/dist/entities/system/link-declaration.d.ts +27 -0
  82. package/dist/entities/system/link-declaration.js +64 -0
  83. package/dist/entities/system/link-plan.d.ts +160 -0
  84. package/dist/entities/system/link-plan.js +770 -0
  85. package/dist/entities/system/runtime-modules.d.ts +25 -0
  86. package/dist/entities/system/runtime-modules.js +38 -0
  87. package/dist/entities/system/style-bag.d.ts +20 -0
  88. package/dist/entities/system/style-bag.js +246 -0
  89. package/dist/entities/system/token-index.d.ts +89 -0
  90. package/dist/entities/system/token-index.js +112 -0
  91. package/dist/framework/Config.d.ts +2472 -0
  92. package/dist/framework/Config.js +5023 -0
  93. package/dist/framework/Entity.d.ts +127 -0
  94. package/dist/framework/Entity.js +125 -0
  95. package/dist/framework/authoring.d.ts +24 -0
  96. package/dist/framework/authoring.js +7 -0
  97. package/dist/framework/change-hooks.d.ts +119 -0
  98. package/dist/framework/change-hooks.js +131 -0
  99. package/dist/framework/changes.d.ts +88 -0
  100. package/dist/framework/changes.js +246 -0
  101. package/dist/framework/class-names.d.ts +260 -0
  102. package/dist/framework/class-names.js +630 -0
  103. package/dist/framework/coalesce.d.ts +25 -0
  104. package/dist/framework/coalesce.js +60 -0
  105. package/dist/framework/config-op.d.ts +76 -0
  106. package/dist/framework/config-op.js +43 -0
  107. package/dist/framework/config-operation-kind.d.ts +14 -0
  108. package/dist/framework/config-operation-kind.js +14 -0
  109. package/dist/framework/config-ops.d.ts +34 -0
  110. package/dist/framework/config-ops.js +187 -0
  111. package/dist/framework/defineConfig.d.ts +196 -0
  112. package/dist/framework/defineConfig.js +100 -0
  113. package/dist/framework/defineDerivedEntity.d.ts +74 -0
  114. package/dist/framework/defineDerivedEntity.js +83 -0
  115. package/dist/framework/defineEntity.d.ts +318 -0
  116. package/dist/framework/defineEntity.js +183 -0
  117. package/dist/framework/defineSubEntity.d.ts +148 -0
  118. package/dist/framework/defineSubEntity.js +121 -0
  119. package/dist/framework/derived-mutations.d.ts +20 -0
  120. package/dist/framework/derived-mutations.js +38 -0
  121. package/dist/framework/entity-search.d.ts +29 -0
  122. package/dist/framework/entity-search.js +117 -0
  123. package/dist/framework/inline-sources.d.ts +49 -0
  124. package/dist/framework/inline-sources.js +388 -0
  125. package/dist/framework/layer-styles.d.ts +25 -0
  126. package/dist/framework/layer-styles.js +49 -0
  127. package/dist/framework/memo.d.ts +48 -0
  128. package/dist/framework/memo.js +84 -0
  129. package/dist/framework/overlay.d.ts +49 -0
  130. package/dist/framework/overlay.js +17 -0
  131. package/dist/framework/plan.d.ts +49 -0
  132. package/dist/framework/plan.js +73 -0
  133. package/dist/framework/projections.d.ts +480 -0
  134. package/dist/framework/projections.js +974 -0
  135. package/dist/framework/prop-surface.d.ts +132 -0
  136. package/dist/framework/prop-surface.js +278 -0
  137. package/dist/framework/ref-graph.d.ts +71 -0
  138. package/dist/framework/ref-graph.js +158 -0
  139. package/dist/framework/ref-integrity.d.ts +55 -0
  140. package/dist/framework/ref-integrity.js +171 -0
  141. package/dist/framework/registered.d.ts +95 -0
  142. package/dist/framework/registry-dir.d.ts +42 -0
  143. package/dist/framework/registry-dir.js +48 -0
  144. package/dist/framework/registry.d.ts +300 -0
  145. package/dist/framework/registry.js +104 -0
  146. package/dist/framework/rejection.d.ts +58 -0
  147. package/dist/framework/rejection.js +111 -0
  148. package/dist/framework/rename-inference.d.ts +26 -0
  149. package/dist/framework/rename-inference.js +50 -0
  150. package/dist/framework/render-spec.d.ts +296 -0
  151. package/dist/framework/render-spec.js +809 -0
  152. package/dist/framework/schema-version.d.ts +140 -0
  153. package/dist/framework/schema-version.js +214 -0
  154. package/dist/framework/schemas.d.ts +109 -0
  155. package/dist/framework/schemas.js +615 -0
  156. package/dist/framework/session.d.ts +196 -0
  157. package/dist/framework/session.js +367 -0
  158. package/dist/framework/signature.d.ts +15 -0
  159. package/dist/framework/signature.js +83 -0
  160. package/dist/framework/snapshot.d.ts +115 -0
  161. package/dist/framework/snapshot.js +277 -0
  162. package/dist/framework/source-integrity.d.ts +226 -0
  163. package/dist/framework/source-integrity.js +478 -0
  164. package/dist/framework/sources.d.ts +211 -0
  165. package/dist/framework/sources.js +89 -0
  166. package/dist/framework/utils/compiled-schema.d.ts +23 -0
  167. package/dist/framework/utils/compiled-schema.js +46 -0
  168. package/dist/framework/utils/content-key.d.ts +15 -0
  169. package/dist/framework/utils/content-key.js +33 -0
  170. package/dist/framework/utils/enumerated.d.ts +13 -0
  171. package/dist/framework/utils/enumerated.js +19 -0
  172. package/dist/framework/utils/field-path.d.ts +95 -0
  173. package/dist/framework/utils/field-path.js +136 -0
  174. package/dist/framework/utils/field-schema.d.ts +55 -0
  175. package/dist/framework/utils/field-schema.js +183 -0
  176. package/dist/framework/utils/group.d.ts +37 -0
  177. package/dist/framework/utils/group.js +13 -0
  178. package/dist/framework/utils/package-path.d.ts +37 -0
  179. package/dist/framework/utils/package-path.js +61 -0
  180. package/dist/framework/utils/refs.d.ts +194 -0
  181. package/dist/framework/utils/refs.js +403 -0
  182. package/dist/framework/validate-spec.d.ts +27 -0
  183. package/dist/framework/validate-spec.js +45 -0
  184. package/dist/framework/value-domain.d.ts +26 -0
  185. package/dist/framework/value-domain.js +202 -0
  186. package/dist/framework/views-facade.d.ts +15 -0
  187. package/dist/framework/views-facade.js +19 -0
  188. package/dist/index.d.ts +90 -42
  189. package/dist/index.js +86 -37
  190. package/dist/migrations/2.0.0/raw-css.d.ts +11 -0
  191. package/dist/migrations/2.0.0/raw-css.js +72 -0
  192. package/dist/migrations/2.0.0/v1-artifact.d.ts +1559 -0
  193. package/dist/migrations/2.0.0/v1-artifact.js +1018 -0
  194. package/dist/migrations/20260908171448_settings_as_kind.d.ts +22 -0
  195. package/dist/migrations/20260908171448_settings_as_kind.js +89 -0
  196. package/dist/migrations/20260908194245_visible_state_pointer.d.ts +19 -0
  197. package/dist/migrations/20260908194245_visible_state_pointer.js +115 -0
  198. package/dist/migrations/20260909183001_icon_knockout_variants.d.ts +18 -0
  199. package/dist/migrations/20260909183001_icon_knockout_variants.js +8 -0
  200. package/dist/migrations/20260910212453_linked_system_link_ops.d.ts +13 -0
  201. package/dist/migrations/20260910212453_linked_system_link_ops.js +8 -0
  202. package/dist/migrations/index.d.ts +2 -0
  203. package/dist/migrations/index.js +2 -0
  204. package/dist/react-native/style-keys.generated.d.ts +10 -0
  205. package/dist/react-native/style-keys.generated.js +167 -0
  206. package/dist/renderer/RendererErrorBoundary.d.ts +32 -5
  207. package/dist/renderer/RendererErrorBoundary.js +59 -10
  208. package/dist/renderer/UdsRenderer.d.ts +11 -10
  209. package/dist/renderer/UdsRenderer.js +1 -1
  210. package/dist/renderer/assetEntries.d.ts +37 -0
  211. package/dist/renderer/assetEntries.js +39 -0
  212. package/dist/renderer/assetRenderable.d.ts +14 -6
  213. package/dist/renderer/assetRenderable.js +8 -2
  214. package/dist/renderer/componentEntry.d.ts +58 -0
  215. package/dist/renderer/componentEntry.js +71 -0
  216. package/dist/renderer/icon-library.d.ts +20 -0
  217. package/dist/renderer/index.d.ts +7 -7
  218. package/dist/renderer/index.js +5 -5
  219. package/dist/renderer/primitives/SlotRenderer.d.ts +1 -1
  220. package/dist/renderer/primitives/SlotRenderer.js +1 -1
  221. package/dist/renderer/runtimeComponent.d.ts +33 -0
  222. package/dist/renderer/runtimeComponent.js +113 -0
  223. package/dist/renderer/spec-content.d.ts +43 -0
  224. package/dist/renderer/spec-content.js +95 -0
  225. package/dist/renderer/wrapRegistry.d.ts +22 -37
  226. package/dist/renderer/wrapRegistry.js +10 -20
  227. package/dist/renderer/wrappers/event-bridge.js +6 -5
  228. package/dist/renderer/wrappers/hex-normalize.js +6 -5
  229. package/dist/renderer/wrappers/html-aliases.d.ts +7 -2
  230. package/dist/renderer/wrappers/html-aliases.js +36 -19
  231. package/dist/renderer/wrappers/inline-styles.js +7 -6
  232. package/dist/spec/asset-jsx.d.ts +18 -5
  233. package/dist/spec/asset-jsx.js +27 -16
  234. package/dist/spec/collapse-text-labels.d.ts +5 -15
  235. package/dist/spec/collapse-text-labels.js +26 -19
  236. package/dist/spec/empty-node-slots.d.ts +56 -34
  237. package/dist/spec/empty-node-slots.js +87 -47
  238. package/dist/spec/index.d.ts +21 -10
  239. package/dist/spec/index.js +21 -10
  240. package/dist/spec/jsxToSpec.d.ts +14 -9
  241. package/dist/spec/jsxToSpec.js +20 -3
  242. package/dist/spec/preview-elements.d.ts +63 -0
  243. package/dist/spec/preview-elements.js +89 -0
  244. package/dist/spec/rewrite-refs.d.ts +58 -0
  245. package/dist/spec/rewrite-refs.js +250 -0
  246. package/dist/spec/specToJsx.js +18 -29
  247. package/dist/tsconfig.tsbuildinfo +1 -1
  248. package/package.json +39 -52
  249. package/dist/AssetGroup.d.ts +0 -77
  250. package/dist/AssetGroup.js +0 -125
  251. package/dist/Component.d.ts +0 -333
  252. package/dist/Component.js +0 -1061
  253. package/dist/ComponentGroup.d.ts +0 -22
  254. package/dist/ComponentGroup.js +0 -51
  255. package/dist/CompositeStyle.d.ts +0 -30
  256. package/dist/CompositeStyle.js +0 -59
  257. package/dist/Config.d.ts +0 -528
  258. package/dist/Config.js +0 -1712
  259. package/dist/Mode.d.ts +0 -41
  260. package/dist/Mode.js +0 -81
  261. package/dist/Modifier.d.ts +0 -51
  262. package/dist/Modifier.js +0 -97
  263. package/dist/MotionDef.d.ts +0 -81
  264. package/dist/MotionDef.js +0 -212
  265. package/dist/Props.d.ts +0 -332
  266. package/dist/Props.js +0 -35
  267. package/dist/Provider.d.ts +0 -20
  268. package/dist/Provider.js +0 -14
  269. package/dist/StyleProp.d.ts +0 -145
  270. package/dist/StyleProp.js +0 -239
  271. package/dist/Token.d.ts +0 -76
  272. package/dist/Token.js +0 -133
  273. package/dist/TokenGroup.d.ts +0 -33
  274. package/dist/TokenGroup.js +0 -69
  275. package/dist/asset-kind.d.ts +0 -55
  276. package/dist/asset-kind.js +0 -29
  277. package/dist/asset-value.d.ts +0 -23
  278. package/dist/asset-value.js +0 -40
  279. package/dist/brands.d.ts +0 -30
  280. package/dist/brands.js +0 -20
  281. package/dist/captureCallerPath.d.ts +0 -48
  282. package/dist/captureCallerPath.js +0 -95
  283. package/dist/colorExpressions.d.ts +0 -131
  284. package/dist/colorExpressions.js +0 -148
  285. package/dist/component-referrers.d.ts +0 -30
  286. package/dist/component-referrers.js +0 -40
  287. package/dist/config-diagnostics.d.ts +0 -21
  288. package/dist/config-diagnostics.js +0 -12
  289. package/dist/defineAssetGroup.d.ts +0 -200
  290. package/dist/defineAssetGroup.js +0 -323
  291. package/dist/defineProvider.d.ts +0 -29
  292. package/dist/defineProvider.js +0 -60
  293. package/dist/element-marker.d.ts +0 -63
  294. package/dist/element-marker.js +0 -113
  295. package/dist/entity-utils.d.ts +0 -56
  296. package/dist/entity-utils.js +0 -105
  297. package/dist/extension.d.ts +0 -55
  298. package/dist/extension.js +0 -214
  299. package/dist/factories.d.ts +0 -863
  300. package/dist/factories.js +0 -475
  301. package/dist/font-face.d.ts +0 -25
  302. package/dist/font-face.js +0 -72
  303. package/dist/foreign-component-name.d.ts +0 -21
  304. package/dist/foreign-component-name.js +0 -42
  305. package/dist/interpolate.d.ts +0 -20
  306. package/dist/interpolate.js +0 -10
  307. package/dist/jsx/__fixtures__/cross-component-preview.d.ts +0 -3
  308. package/dist/jsx/__fixtures__/cross-component-preview.js +0 -15
  309. package/dist/jsx/jsx-dev-runtime.d.ts +0 -15
  310. package/dist/jsx/jsx-dev-runtime.js +0 -11
  311. package/dist/jsx/jsx-runtime.d.ts +0 -48
  312. package/dist/jsx/jsx-runtime.js +0 -305
  313. package/dist/linked-system-pins.d.ts +0 -30
  314. package/dist/linked-system-pins.js +0 -45
  315. package/dist/linkedNodePrefixes.d.ts +0 -73
  316. package/dist/linkedNodePrefixes.js +0 -99
  317. package/dist/markers.d.ts +0 -235
  318. package/dist/markers.js +0 -70
  319. package/dist/motion-constants.d.ts +0 -37
  320. package/dist/motion-constants.js +0 -61
  321. package/dist/native/NativeConfig.d.ts +0 -56
  322. package/dist/native/NativeConfig.js +0 -162
  323. package/dist/native/assets.d.ts +0 -20
  324. package/dist/native/assets.js +0 -17
  325. package/dist/native/components.d.ts +0 -139
  326. package/dist/native/components.js +0 -67
  327. package/dist/native/index.d.ts +0 -18
  328. package/dist/native/index.js +0 -17
  329. package/dist/native/modes.d.ts +0 -10
  330. package/dist/native/modes.js +0 -11
  331. package/dist/native/types.d.ts +0 -95
  332. package/dist/native/types.js +0 -0
  333. package/dist/native/validation.d.ts +0 -8
  334. package/dist/native/validation.js +0 -885
  335. package/dist/native/values.d.ts +0 -7
  336. package/dist/native/values.js +0 -15
  337. package/dist/native.d.ts +0 -12
  338. package/dist/native.js +0 -10
  339. package/dist/refs.d.ts +0 -204
  340. package/dist/refs.js +0 -129
  341. package/dist/registry-aliases.d.ts +0 -33
  342. package/dist/registry-aliases.js +0 -35
  343. package/dist/registry-dir.d.ts +0 -22
  344. package/dist/registry-dir.js +0 -10
  345. package/dist/renderer/makeRegistry.d.ts +0 -34
  346. package/dist/renderer/makeRegistry.js +0 -52
  347. package/dist/renderer/makeUdsRenderer.d.ts +0 -13
  348. package/dist/renderer/makeUdsRenderer.js +0 -51
  349. package/dist/renderer/wrappers/component-slots.d.ts +0 -41
  350. package/dist/renderer/wrappers/component-slots.js +0 -66
  351. package/dist/renderer/wrappers/slot-resolution.d.ts +0 -25
  352. package/dist/renderer/wrappers/slot-resolution.js +0 -68
  353. package/dist/renderer/wrappers/void-elements.d.ts +0 -37
  354. package/dist/renderer/wrappers/void-elements.js +0 -40
  355. package/dist/spec/layer-props.d.ts +0 -52
  356. package/dist/spec/layer-props.js +0 -149
  357. package/dist/spec/preview-controls.d.ts +0 -44
  358. package/dist/spec/preview-controls.js +0 -139
  359. package/dist/spec/slot-refs.d.ts +0 -39
  360. package/dist/spec/slot-refs.js +0 -56
  361. package/dist/token-override-rows.d.ts +0 -68
  362. package/dist/token-override-rows.js +0 -233
  363. package/dist/tokenValueType.d.ts +0 -34
  364. package/dist/tokenValueType.js +0 -138
  365. package/dist/types/css-properties.d.ts +0 -233
  366. package/dist/types/css-properties.js +0 -14
  367. package/dist/types/css-property-keywords.d.ts +0 -156
  368. package/dist/types/css-property-keywords.js +0 -616
  369. package/dist/types/css-values.d.ts +0 -63
  370. package/dist/types/css-values.js +0 -16
  371. package/dist/types.d.ts +0 -1138
  372. package/dist/types.js +0 -12
  373. package/dist/units.d.ts +0 -14
  374. package/dist/units.js +0 -16
  375. package/dist/utils/index.d.ts +0 -4
  376. package/dist/utils/index.js +0 -4
@@ -0,0 +1,478 @@
1
+ import { collectRefs, isExtendedRef, isRef, kindOf, memberOf, pathOf, sourceOf, splitRef } from "./utils/refs.js";
2
+ import { isPlainObject, setAtPath } from "./utils/field-path.js";
3
+ //#region src/framework/source-integrity.ts
4
+ /**
5
+ * Every `@source` ref in `config` that does not resolve against its attached source.
6
+ *
7
+ * This is the guarantee the emitted types can only approximate. A union narrows what an author can type, but
8
+ * nothing types a Studio-authored patch, a js consumer, or a config whose source moved on since the last
9
+ * install — and an unresolvable ref renders as the empty string, so the stylesheet gets `--x: ;`: syntactically
10
+ * a declaration, semantically nothing, and silent. Precisely the failure mode a build should refuse.
11
+ *
12
+ * Only sourced refs are checked here. A dangling local ref is the dependency graph's own complaint and has its
13
+ * own reporting; this is about the seam between systems, where the other side can change without us.
14
+ *
15
+ * Walks what this config authored, not what it currently resolves to, and the difference is two bugs
16
+ * rather than a nicety. Resolution loses the subject in both directions:
17
+ *
18
+ * • An extension whose base cannot be found resolves to nothing, so the item drops out of `list` and
19
+ * the broken ref goes unreported — a build passing on a config whose token has silently vanished.
20
+ * That is the case a `Token.ref('palette@ds')` naming a group produces, since a group is not an
21
+ * item and the lookup misses.
22
+ * • An extension that can be found resolves to its source's fields merged over ours, so the walk sees
23
+ * the source's refs through the source's slugs. A source that itself borrows made this config
24
+ * report `@upstream` — a slug it never declared and cannot resolve — and refuse a legitimate chain.
25
+ *
26
+ * The authored body has neither problem: it is exactly the set of refs this config is answerable for.
27
+ */
28
+ function danglingSourcedRefs(config) {
29
+ const found = [];
30
+ /**
31
+ * Whether a slug is answerable — the three-state question, not the two-state one.
32
+ *
33
+ * `sourceStatus` keeps three answers and only two of them are a problem here. Nobody asked
34
+ * (`undefined`, an ordinary `fromJSON` in an editor) is not a broken ref: the config was never
35
+ * resolved, so every sourced ref would read as dangling and the report would be noise. Asked and
36
+ * could not (`unavailable`) is broken, and is exactly what a build must refuse.
37
+ *
38
+ * Reading only `liveSourceFor` collapsed those into one, which is why the sole non-build caller —
39
+ * `orphanedBorrowsFromJSON` in the studio — had to filter its results down to the one slug it had
40
+ * attached, with a comment explaining that otherwise "its every sourced ref dangles". That filter is
41
+ * a workaround for this line.
42
+ *
43
+ * Both halves are needed, and `sourceStatus` alone is not enough: `registerSources` attaches a
44
+ * source without recording a state, so a config assembled that way answers `undefined` while
45
+ * holding a perfectly good source. So the question is whether there is anything to be answerable
46
+ * against — an attached source, or a resolver's recorded answer.
47
+ */
48
+ const answerable = (slug) => config.liveSourceFor(slug) !== void 0 || config.sourceStatus(slug) !== void 0;
49
+ for (const kind of config.ownedKinds()) {
50
+ for (const item of config.authoredItems(kind)) for (const target of collectRefs(item.body)) {
51
+ const slug = sourceOf(target);
52
+ if (slug === void 0) continue;
53
+ if (!answerable(slug)) continue;
54
+ if (config.liveSourceFor(slug)?.resolve(kindOf(target), pathOf(target))) continue;
55
+ found.push({
56
+ from: `${kind}:${item.path}`,
57
+ ref: target,
58
+ slug
59
+ });
60
+ }
61
+ for (const group of config.groups(kind)) {
62
+ const ref = group.meta.ref;
63
+ if (!isRef(ref)) continue;
64
+ const slug = sourceOf(ref);
65
+ if (slug === void 0) continue;
66
+ if (!answerable(slug)) continue;
67
+ const path = pathOf(ref);
68
+ if (config.liveSourceFor(slug)?.members(kind, path).length) continue;
69
+ found.push({
70
+ from: `${kind} group:${group.path}`,
71
+ ref: ref.__ref,
72
+ slug
73
+ });
74
+ }
75
+ }
76
+ return found;
77
+ }
78
+ /**
79
+ * Every extended borrow whose merged body this config's kind will not parse.
80
+ *
81
+ * The third way a link can be broken, and the only one that is nobody's mistake: the source resolved
82
+ * perfectly and said something this config has no way to hold. Two config types need not share a
83
+ * value domain — a native modifier activates on `{ state: 'pressed' }` where a web one takes a CSS
84
+ * fragment, a mode, a composite or a list of modes — so the same kind string can name two shapes
85
+ * neither of which contains the other. `mobile-app`'s `size/control` is the same crossing answered
86
+ * rather than broken: `1rem` has no arm in `NativeToken`, and the local `extend: { value: 16 }` is
87
+ * what makes the merged body legal.
88
+ *
89
+ * A report rather than a throw. Reads answer "nothing" for
90
+ * a row they cannot express, because they must: `list`, `sourceClosure` and `toJSON` all reach stored
91
+ * rows, and a throw from inside serialization has no caller in a position to catch it. So the refusal
92
+ * has to live somewhere a caller asks, which is here — a build refuses on it, and a surface says which
93
+ * Entity and which field.
94
+ *
95
+ * Walks what this config authored, for the reason {@link danglingSourcedRefs} does: a row that fails
96
+ * to resolve is absent from `list`, so a walk over resolved entities is a walk with the subject
97
+ * already removed from it.
98
+ */
99
+ function unreadableBorrows(config) {
100
+ const found = [];
101
+ for (const kind of config.ownedKinds()) for (const item of config.authoredItems(kind)) {
102
+ if (!isExtendedRef(item.body)) continue;
103
+ const slug = sourceOf(item.body);
104
+ if (slug === void 0) continue;
105
+ const verdict = config.canBorrow({
106
+ kind,
107
+ path: pathOf(item.body),
108
+ slug,
109
+ extend: item.body.extend
110
+ });
111
+ if (verdict.ok) continue;
112
+ found.push({
113
+ from: `${kind}:${item.path}`,
114
+ ref: item.body.__ref,
115
+ slug,
116
+ error: verdict.error
117
+ });
118
+ }
119
+ return found;
120
+ }
121
+ /**
122
+ * Every sourced ref whose target this config already holds at that path, so the qualifier says
123
+ * nothing the bare path doesn't.
124
+ *
125
+ * A link brings a row per entity it takes, at the path the source spells it, so after the build
126
+ * `token:palette/violet` and `token:palette/violet@ds` are one entity with two names. Two spellings
127
+ * for one thing is what this refuses. It reads as harmless and isn't: the qualified form resolves
128
+ * through the seam, so it breaks the moment the pin is retargeted or dropped while the bare form
129
+ * follows the row wherever it goes, and a config with both in it has half its references surviving the
130
+ * pin's deletion.
131
+ *
132
+ * The one qualified spelling that stays is an entity pointer — `Token.ref('violet@ds').extend({ … })`
133
+ * stored as the row's own body, and a linked folder's `ref`. Both are authored at the local key the
134
+ * bare form would name, so there is nothing else they could say. Everything below that key is a value
135
+ * pointing at another entity, and that is what this walks.
136
+ *
137
+ * A row the pin declares is the subject, never one reachability derived. `sourceClosure` seeds from
138
+ * this config's own refs too, so a hand-written borrow with no `link` declaration derives a row at its
139
+ * target — and telling that author to drop the qualifier would delete the only reason the row exists,
140
+ * leaving a bare ref pointing at nothing. Hence {@link Config.adoptedFrom}: what stands without the
141
+ * ref asking.
142
+ *
143
+ * Walks what this config authored, for the reason {@link danglingSourcedRefs} does — a resolved
144
+ * borrow carries its source's refs through its source's slugs, none of which this config wrote.
145
+ */
146
+ function redundantQualifiers(config) {
147
+ const found = [];
148
+ /**
149
+ * Whether a row of this config's stands at `path` pointing at the same entity as the ref.
150
+ *
151
+ * Nothing here asks whether that row was derived. A row is minted for what a pin adopts and for
152
+ * nothing else, so a derived row is a declared one — where a row seeded by reachability would have
153
+ * existed because of the very ref being judged, and telling that author to drop the qualifier would
154
+ * delete the only reason the row is there.
155
+ */
156
+ const named = (kind, path, slug) => {
157
+ const pointsHere = (body) => isRef(body) && sourceOf(body) === slug && pathOf(body) === path;
158
+ return pointsHere(config.storedBody(kind, path)) || pointsHere(config.groupMeta(kind, path)?.ref);
159
+ };
160
+ const check = (from, data) => {
161
+ for (const target of new Set(collectRefs(data))) {
162
+ if (memberOf(target) !== void 0) continue;
163
+ const slug = sourceOf(target);
164
+ if (slug === void 0) continue;
165
+ const kind = kindOf(target);
166
+ const path = pathOf(target);
167
+ if (!named(kind, path, slug)) continue;
168
+ found.push({
169
+ from,
170
+ ref: target,
171
+ slug,
172
+ local: `${kind}:${path}`
173
+ });
174
+ }
175
+ };
176
+ for (const kind of config.ownedKinds()) {
177
+ for (const item of config.authoredItems(kind)) {
178
+ let body = item.body;
179
+ if (isRef(item.body)) body = isExtendedRef(item.body) ? item.body.extend : {};
180
+ check(`${kind}:${item.path}`, body);
181
+ }
182
+ for (const group of config.groups(kind)) {
183
+ const { ref: _pointer, ...rest } = group.meta;
184
+ check(`${kind} group:${group.path}`, rest);
185
+ }
186
+ }
187
+ return found;
188
+ }
189
+ function segmentsOf(field) {
190
+ return typeof field === "string" ? field.split(".") : field;
191
+ }
192
+ /** A leaf is anything that is not a plain object to walk into. A ref is one value, not a shape. */
193
+ function leafEntries(value, prefix = []) {
194
+ if (!isPlainObject(value) || isRef(value)) return [[prefix, value]];
195
+ return Object.entries(value).flatMap(([key, child]) => leafEntries(child, [...prefix, key]));
196
+ }
197
+ /** Every leaf address under `body`, as segments, so a member key that contains a dot stays one key. */
198
+ function leafAddresses(body) {
199
+ return leafEntries(body).map(([address]) => address).filter((address) => address.length > 0);
200
+ }
201
+ /** The value at a leaf address, or `undefined` where the body has none. A ref is one value, not walked into. */
202
+ function valueAt(body, field) {
203
+ return segmentsOf(field).reduce((at, key) => isPlainObject(at) && !isRef(at) ? at[key] : void 0, body);
204
+ }
205
+ /**
206
+ * The verb one local leaf is against the source's value at the same address: `extend` where the
207
+ * source has nothing there, `override` where it has something different, and `undefined` where
208
+ * nothing local sits there or the two agree. A leaf carried along unchanged is not overlaid: a sub-op
209
+ * copies the whole record it touched into the delta, so a token given one local condition holds the
210
+ * source's other conditions beside it.
211
+ */
212
+ function leafVerb({ ours, theirs }) {
213
+ if (ours === void 0) return void 0;
214
+ if (theirs === void 0) return "extend";
215
+ return sameValue(ours, theirs) ? void 0 : "override";
216
+ }
217
+ /**
218
+ * Which verb this config's value at `field` is, in the pin's vocabulary — `override` where the source
219
+ * defines the leaf, `extend` where it does not — and `undefined` where nothing local sits there. A
220
+ * record field answers `override` when any member under it does, else `extend` when any was added.
221
+ */
222
+ function overlayVerb(overlay, field) {
223
+ if (valueAt(overlay.override, field) !== void 0) return "override";
224
+ if (valueAt(overlay.extend, field) !== void 0) return "extend";
225
+ }
226
+ /** Structural equality over JSON-shaped values. */
227
+ function sameValue(a, b) {
228
+ if (a === b) return true;
229
+ if (Array.isArray(a) && Array.isArray(b)) return a.length === b.length && a.every((item, i) => sameValue(item, b[i]));
230
+ if (isPlainObject(a) && isPlainObject(b)) {
231
+ const keys = Object.keys(a);
232
+ return keys.length === Object.keys(b).length && keys.every((key) => sameValue(a[key], b[key]));
233
+ }
234
+ return false;
235
+ }
236
+ /**
237
+ * Every overlay whose verb the source disagrees with — an `extend` at a field they already define, or
238
+ * an `override` at one they do not.
239
+ *
240
+ * The verb is derivable, and this is the derivation. It runs anyway because a declared verb is the
241
+ * only thing that notices the source moving: a field they add in a later version turns an extension
242
+ * into an override, and without the declaration there is nothing for that to contradict. The same
243
+ * check catches the first-order mistake, which is writing an extension for something they already had.
244
+ *
245
+ * Judged leaf by leaf, because one entity legitimately carries both — a token overridden under one
246
+ * modifier and extended under another is one body with two verbs, and a whole-entity comparison would
247
+ * have to call it one or the other.
248
+ */
249
+ function misdeclaredOverlays(config) {
250
+ const found = [];
251
+ for (const slug of config.sourceSlugs()) {
252
+ const source = config.liveSourceFor(slug);
253
+ if (!source) continue;
254
+ for (const { kind, path } of config.sourceDirectives(slug)) {
255
+ if (kind === void 0) continue;
256
+ const overlay = config.sourceOverlay(slug, kind, path);
257
+ if (!overlay) continue;
258
+ const theirs = source.resolve(kind, path)?.toJSON();
259
+ for (const field of leafAddresses(overlay.extend)) if (valueAt(theirs, field) !== void 0) found.push({
260
+ slug,
261
+ kind,
262
+ path,
263
+ declared: "extend",
264
+ field
265
+ });
266
+ for (const field of leafAddresses(overlay.override)) if (valueAt(theirs, field) === void 0) found.push({
267
+ slug,
268
+ kind,
269
+ path,
270
+ declared: "override",
271
+ field
272
+ });
273
+ }
274
+ }
275
+ return found;
276
+ }
277
+ /**
278
+ * Split a merged body into `override`/`extend` by judging each leaf against the source — the forward
279
+ * direction of the walk {@link misdeclaredOverlays} runs to check one. A leaf the source defines
280
+ * differently is an override; one it lacks is an extension; one it spells the same is neither, and is
281
+ * left out.
282
+ *
283
+ * What a directive written this way can never do is trip the check that classified it: every leaf
284
+ * lands on the side the live source agrees it belongs on, by construction.
285
+ */
286
+ function classifyOverlay(local, theirs) {
287
+ let override = {};
288
+ let extend = {};
289
+ for (const [address, value] of leafEntries(local)) {
290
+ if (address.length === 0) continue;
291
+ const verb = leafVerb({
292
+ ours: value,
293
+ theirs: valueAt(theirs, address)
294
+ });
295
+ if (verb === "override") override = setAtPath(override, address, value);
296
+ else if (verb === "extend") extend = setAtPath(extend, address, value);
297
+ }
298
+ return {
299
+ ...Object.keys(override).length > 0 ? { override } : {},
300
+ ...Object.keys(extend).length > 0 ? { extend } : {}
301
+ };
302
+ }
303
+ /**
304
+ * Every hide the pin aims at a kind it does not adopt.
305
+ *
306
+ * A hide takes a name back, and a config that never adopted the kind never had it: their entity is
307
+ * reachable only qualified either way, so the entry changes nothing and reads as though it did.
308
+ * Reported rather than ignored, because the fix is usually the missing adoption.
309
+ *
310
+ * An overlay on an unadopted path is a different question and is not this one — it would be laid over
311
+ * a row that is never minted, which is worth reporting too, but the message is about a body rather
312
+ * than about a name.
313
+ */
314
+ function unadoptedDirectives(config) {
315
+ const found = [];
316
+ for (const slug of config.sourceSlugs()) for (const { kind, path } of config.sourceDirectives(slug)) {
317
+ if (kind === void 0) continue;
318
+ if (config.sourceStance(slug, kind, path).adopted) continue;
319
+ if (config.sourceOverlay(slug, kind, path)?.hidden === true) found.push({
320
+ slug,
321
+ kind,
322
+ path,
323
+ act: "hide"
324
+ });
325
+ }
326
+ return found;
327
+ }
328
+ /**
329
+ * Every directive aimed at nothing — an accessor this config has no kind for, or a path the source
330
+ * does not have.
331
+ *
332
+ * The one mistake the other checks structurally cannot see. Each of them answers for a path it is
333
+ * already holding, so it asks "does the declaration mention this one" — and a name nobody has is
334
+ * never a question anyone puts. `toknes` and `palette/nope` both simply cover nothing, silently, and
335
+ * an overlay that covers nothing looks exactly like one that was never needed.
336
+ *
337
+ * Also what notices the source dropping a path. A directive written against an entity a later version
338
+ * removed keeps parsing and keeps doing nothing, which is the same failure the declared verb exists to
339
+ * catch one level down.
340
+ */
341
+ function danglingDirectives(config) {
342
+ const found = [];
343
+ for (const slug of config.sourceSlugs()) {
344
+ const source = config.liveSourceFor(slug);
345
+ if (!source) continue;
346
+ for (const { kind, accessor, path } of config.sourceDirectives(slug)) {
347
+ if (kind === void 0) {
348
+ found.push({
349
+ slug,
350
+ accessor,
351
+ path,
352
+ missing: "accessor"
353
+ });
354
+ continue;
355
+ }
356
+ if (source.resolve(kind, path) || source.members(kind, path).length > 0) continue;
357
+ found.push({
358
+ slug,
359
+ accessor,
360
+ path,
361
+ missing: "path"
362
+ });
363
+ }
364
+ }
365
+ return found;
366
+ }
367
+ /**
368
+ * Every borrowed token that varies under a modifier this config does not declare.
369
+ *
370
+ * A borrowed token's conditional values apply under your modifier of that name — so if you don't have the
371
+ * name, the condition is unstatable and the token silently behaves like a lesser version of itself: one
372
+ * colour where the source had two. Refusing is the same rule inlining already enforces; this is the other
373
+ * path to the same place, for a token a consumer references directly rather than one that got inlined.
374
+ */
375
+ function unstatableConditions(config) {
376
+ const found = [];
377
+ for (const slug of config.sourceSlugs()) {
378
+ const source = config.liveSourceFor(slug);
379
+ if (!source) continue;
380
+ for (const target of config.sourceClosure(slug, "token")) {
381
+ const token = pathOf(target);
382
+ const { overrides } = source.resolve("token", token)?.toJSON() ?? {};
383
+ if (!overrides) continue;
384
+ for (const entry of Object.values(overrides)) {
385
+ const refs = Array.isArray(entry.on) ? entry.on : [entry.on];
386
+ for (const ref of refs) {
387
+ if (!isRef(ref)) continue;
388
+ const modifier = splitRef(ref.__ref).qualifiedPath;
389
+ if (config.resolve("modifier", modifier)) continue;
390
+ found.push({
391
+ slug,
392
+ token,
393
+ modifier
394
+ });
395
+ }
396
+ }
397
+ }
398
+ }
399
+ return found;
400
+ }
401
+ /**
402
+ * Which of this item's own fields point outside the config, and through which slug — the walk behind
403
+ * the `linked` computed the framework installs on every kind.
404
+ *
405
+ * This is the one fact resolution cannot supply, and it is what a provenance surface names: reading a
406
+ * ref is uniform (`resolveFieldValue` chases local and sourced refs identically, which is what makes
407
+ * referencing one feature rather than two), so nothing about the read says a value came from another
408
+ * System. A badge, a link adornment and a "Source" row all want that, and this is where they get it.
409
+ *
410
+ * Not the write gate, which is {@link borrowedSlug}. Naming where a value comes from and deciding
411
+ * whose the entity is are different questions, and this one answers the first: a ref this config
412
+ * declared is ours to retarget however far away it points, so an edit gated on this locks a pointer
413
+ * its own author wrote.
414
+ *
415
+ * Shallow and structural — no field is named and no kind is asked. A ref sitting one level down is a
416
+ * value this item uses, not a claim about the item, so `{ styles: { bg: violet@ds } }` reports nothing
417
+ * while `{ styles: violet@ds }` reports the slug.
418
+ *
419
+ * A local ref reports nothing on purpose. It resolves through the same chase, but it points inside
420
+ * this config, and there is no other system for a surface to name.
421
+ *
422
+ * One kind is asked, not named: a ref at a kind declaring `linkable: false` (`File`) can never be
423
+ * copied in, so the pin stays qualified forever by design — that permanence is an implementation
424
+ * detail of how the item's code loads, not a claim that the item itself still follows the link. A
425
+ * `config` lets this tell the two apart; without one (a bare fixture with no config to ask) every
426
+ * qualified ref still counts, which is the answer this gave before the distinction existed.
427
+ */
428
+ function sourcedFields(member, config) {
429
+ const fields = {};
430
+ for (const [field, value] of Object.entries(member)) {
431
+ if (!isRef(value)) continue;
432
+ const slug = sourceOf(value);
433
+ if (slug === void 0) continue;
434
+ if (config?.entityOf(kindOf(value))?.linkable === false) continue;
435
+ fields[field] = slug;
436
+ }
437
+ return fields;
438
+ }
439
+ /**
440
+ * The dependencies this item's own fields point through, deduped — the `sources` computed the
441
+ * framework installs on every kind.
442
+ *
443
+ * Which fields borrow is {@link sourcedFields}; which dependencies they borrow from is every
444
+ * provenance surface's question, and it is the same walk. Sorted so the value is stable across field
445
+ * order, because it lands in a memoized entity that dep arrays hold.
446
+ *
447
+ * Usually one slug. Two means the item's fields disagree about where it comes from, and the callers
448
+ * split there rather than here: `Entity.sources.length > 0` says the item draws on something outside
449
+ * this config at all, while `Entity.source` answers `undefined`, because naming one of two would put
450
+ * a confident wrong label on screen.
451
+ */
452
+ function sourceSlugs(member, config) {
453
+ return [...new Set(Object.values(sourcedFields(member, config)))].sort();
454
+ }
455
+ /**
456
+ * The dependency this item's stored body is borrowed from — the `borrowedFrom` computed the framework
457
+ * installs on every kind, and the question {@link sourcedFields} cannot answer.
458
+ *
459
+ * An item stored as a ref into a source (`Token.ref('palette/accent@ds').extend({ value: 16 })`) is
460
+ * that source's item, resolved there and shallowly overlaid by the fields named here. An item this
461
+ * Config authored is its own, and stays its own no matter where its fields point.
462
+ *
463
+ * That is the whole distinction, and it is the one a write gate needs. `sources` reports where a
464
+ * value comes from, which is what a provenance badge names — and for a local item holding a sourced
465
+ * ref (`{ value: token:palette/accent@ds }`) it reports the source while the item is ours, so gating
466
+ * an edit on it locks a pointer we declared. Retargeting that pointer is an ordinary local edit; the
467
+ * ref is in our artifact, and nothing on the other side changes when it moves.
468
+ *
469
+ * Reads the stored body rather than the resolved one, because resolution is exactly what erases the
470
+ * difference: an extension resolves to the source's fields merged with ours, and those fields hold
471
+ * whatever literals the source authored — so the resolved item looks local and `sources` on it reads
472
+ * empty. The pointer only exists before the merge.
473
+ */
474
+ function borrowedSlug(body) {
475
+ return isRef(body) ? sourceOf(body) : void 0;
476
+ }
477
+ //#endregion
478
+ export { borrowedSlug, classifyOverlay, danglingDirectives, danglingSourcedRefs, leafAddresses, leafVerb, misdeclaredOverlays, overlayVerb, redundantQualifiers, sourceSlugs, unadoptedDirectives, unreadableBorrows, unstatableConditions, valueAt };