@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,194 @@
1
+ import { z } from "zod";
2
+
3
+ //#region src/framework/utils/refs.d.ts
4
+ interface Ref {
5
+ readonly __ref: string;
6
+ }
7
+ /** A ref as the authoring API returns it. The method is non-enumerable, so an ordinary ref remains
8
+ * exactly `{ __ref }` in JSON and anywhere that walks its data. Calling it produces the explicit
9
+ * wire value below: a base ref plus the sparse fields this config owns. */
10
+ type ExtendableRef<Delta extends Record<string, unknown>> = Ref & {
11
+ extend(delta: Delta): ExtendedRef<Delta>;
12
+ };
13
+ /** A linked entity plus the sparse local fields layered over it. `extend` is data here, not the
14
+ * authoring method: this is the value stored by Config after `.extend(delta)` is called. */
15
+ interface ExtendedRef<Delta extends Record<string, unknown> = Record<string, unknown>> extends Ref {
16
+ readonly extend: Delta;
17
+ }
18
+ /**
19
+ * Whether `path` can be an entity's own path — the invariant {@link splitSource} rests on, so it is
20
+ * stated next to it.
21
+ *
22
+ * An `@` is legal only as the first character, where it opens an npm scope: `package:@ariakit/react`
23
+ * is that package, and `package:@yahoo/uds-create-config` is this one. Anywhere else it reads as the
24
+ * source marker, and the split is what every provenance surface believes.
25
+ *
26
+ * Without this, a legitimately-named entity misparses in silence. A token called `1@2x` under `size`
27
+ * is a plausible name for a retina scale and was storable, and `token:size/1@2x` then reports its path
28
+ * as `size/1` and invents a source called `2x` — which paints nothing (`renderStyleValue` takes its
29
+ * `if (!source) return ''` escape and the declaration vanishes), reports a false dangling ref naming a
30
+ * source that does not exist, and marks the item borrowed on every provenance surface. Nothing throws.
31
+ *
32
+ * Checked where a path becomes an identity — a create, a rename's target, an authored entry — and
33
+ * deliberately not on reads, so an existing bad path stays addressable and, more to the point,
34
+ * deletable.
35
+ */
36
+ declare function isEntityPath(path: string): boolean;
37
+ /** What a refused path should say, in one place, so a create, a rename and a register word it alike. */
38
+ declare const ENTITY_PATH_MESSAGE = "An entity path may not contain \"@\" except as a leading npm scope \u2014 \"@\" marks the source a ref is drawn from, so a path carrying one cannot be told apart from a borrowed address.";
39
+ /** A ref's parts. */
40
+ interface RefParts {
41
+ readonly kind: string;
42
+ readonly source: string | undefined;
43
+ /** without the source — `pathOf`'s answer. */
44
+ readonly path: string;
45
+ /** with the source, when there is one — the form an authored value and an emitted union spell,
46
+ * because a string in value position has nowhere to put a second argument. */
47
+ readonly qualifiedPath: string;
48
+ readonly member: string | undefined;
49
+ /** whether a `kind:` marker was present — without one, `kind` and `path` are both the whole
50
+ * string, and each caller reads the one it means. */
51
+ readonly marked: boolean;
52
+ }
53
+ /**
54
+ * `kind:path[@source][#member]`, split — the one place a ref is read. This is the ref spelling of the
55
+ * address grammar written down whole in `framework/config-op.ts`.
56
+ *
57
+ * Every accessor below goes through this, and so does anything outside this file that needs a part of
58
+ * a ref. Code that slices at `indexOf(':')` or tests `startsWith('token:')` has its own copy of the
59
+ * grammar, which means the grammar cannot move without hunting for the copies — and a copy that is
60
+ * subtly wrong (a prefix test that a sourced ref fails) is silent.
61
+ */
62
+ declare function splitRef(target: string | Ref): RefParts;
63
+ /**
64
+ * A reference to another entity: `ref('token', 'color/brand')`. Resolution is prefix-or-leaf against
65
+ * the flat store.
66
+ *
67
+ * With a `source` it points into a linked system instead — `ref('token', 'color/brand', 'yahoo-os')`.
68
+ * That is the whole of what a per-entity link marker used to record: the kind is the ref's kind and
69
+ * the source key is its path, while the version lives once on the pin rather than being repeated on
70
+ * every linked entity.
71
+ */
72
+ declare function ref(kind: string, path: string, source?: string): Ref;
73
+ /** A reference to one member of an entity's sub-entity collection — a component's prop, a layer:
74
+ * `memberRef('component', 'Pressable', 'props', 'gap')` → `component:Pressable#props/gap`. A
75
+ * `source` qualifies the entity the member is reached through. */
76
+ declare function memberRef(kind: string, path: string, sub: string, member: string, source?: string): Ref;
77
+ /** The entity half of any ref — a plain entity ref is itself. This is the form the dependency
78
+ * graph and kind-narrowing speak, so a member ref participates in both unchanged. */
79
+ declare function entityRefOf(target: string): string;
80
+ /** The member half (`props/gap`), or `undefined` for a plain entity ref. Takes the ref itself or its
81
+ * string form, like {@link pathOf} / {@link kindOf} / {@link sourceOf}. */
82
+ declare function memberOf(target: string | Ref): string | undefined;
83
+ /** The path of the entity a ref points at — kind, source and any member stripped, so a member ref
84
+ * resolves to the item that contains it (`component:buttons/Primary#props/gap` → `buttons/Primary`)
85
+ * and a linked ref yields the path as its source spells it (`token:color/brand@yahoo-os` →
86
+ * `color/brand`). Takes the ref itself or its string form, so a caller holding a ref field never
87
+ * spells `__ref`. */
88
+ declare function pathOf(target: string | Ref): string;
89
+ /** The source half — the link slug a ref points through, or `undefined` when it points at something
90
+ * in this config. This is the one question that distinguishes a linked entity from a local one, and
91
+ * it replaces reading a per-entity provenance marker. */
92
+ declare function sourceOf(target: string | Ref): string | undefined;
93
+ /** The kind a ref points at (`component:buttons/Primary#props/gap` → `component`) — the twin of
94
+ * {@link pathOf}, so a consumer holding a `kind:path` string (a `dependentsOf` result) never splits
95
+ * it by hand. Takes the ref itself or its string form. */
96
+ declare function kindOf(target: string | Ref): string;
97
+ /** The zod schema of a ref value — used via {@link orRef} so a field never spells the
98
+ * `{ __ref }` shape by hand. `.meta({ ref: true })` marks it as a ref for any consumer (JSON
99
+ * Schema, an authoring UI) — this generic form carries no target kind (use an entity as the field
100
+ * to bake one in). */
101
+ declare const refSchema: z.ZodObject<{
102
+ __ref: z.ZodString;
103
+ }, z.core.$strip>;
104
+ /** Widen a field's value type to also accept a ref: `value: orRef(z.string())`. */
105
+ declare function orRef<T extends z.ZodTypeAny>(schema: T): z.ZodUnion<readonly [T, z.ZodObject<{
106
+ __ref: z.ZodString;
107
+ }, z.core.$strip>]>;
108
+ declare function isRef(value: unknown): value is Ref;
109
+ /** Whether a ref is the stored result of `.extend(delta)`. Kept separate from {@link isRef}: every
110
+ * existing ref consumer should continue to see the base pointer, while Config is the place that
111
+ * gives the sibling delta its merge semantics. */
112
+ declare function isExtendedRef(value: unknown): value is ExtendedRef;
113
+ /**
114
+ * The key marking a row the build minted rather than a person authored.
115
+ *
116
+ * A link declares what it took; the rows for everything it brings are made by the build, at the paths
117
+ * the source spells them, so they are stored — `list`, the rename gate and every emitter reach them
118
+ * on the way past — without ever having been written down. This is the one thing that tells the two
119
+ * apart, and three readers turn on it: `uds pull` skips a minted row, a write to one lands on the
120
+ * source's `options` instead of the row (`Config.apply`'s update handler), and a serialize keeps it
121
+ * distinguishable rather than laundering it into source.
122
+ *
123
+ * Not `DERIVED` — a config already has an unrelated `derived` KIND (`EntityKind.derived`, what
124
+ * `Package` is), and `Config.derive` clones state on every mutation. A third meaning of the same word
125
+ * on the one marker that most needs to read unambiguously.
126
+ *
127
+ * On the body rather than in a parallel set, so the mark rides with the row through every snapshot
128
+ * change instead of being a second thing to keep in step.
129
+ */
130
+ declare const MINTED = "__minted";
131
+ /** Whether a stored body is a row the build minted. See {@link MINTED}. */
132
+ declare function isMintedRow(value: unknown): boolean;
133
+ /**
134
+ * Every `kind:path` a definition points at — the one generic edge harvester.
135
+ *
136
+ * A ref can contribute more than one edge, at different granularities, so that a query at any of
137
+ * them resolves:
138
+ * • a member ref contributes its entity edge too, so pointing at a component's prop still counts
139
+ * as depending on that component;
140
+ * A sourced ref's edge at the link is not here. It needs the kind a `@slug` resolves against, which is
141
+ * whichever kind the config declared `sourceIdentity` on — and this is a pure walk with no config to
142
+ * ask. `Config.nameEdgeReaders` contributes it through the ref index's `extra` channel instead, so the
143
+ * grammar names no kind. This function used to hardcode `'linked-system'` for it.
144
+ */
145
+ declare function collectRefs(value: unknown, acc?: string[]): string[];
146
+ /**
147
+ * Deep-rewrite every ref whose target is `from` to `to`, returning a new structure — the generic
148
+ * rename-cascade the same way `collectRefs` is the generic edge walk.
149
+ *
150
+ * Matching is exact on the entity (or on the `#` boundary for members), which is also what keeps a
151
+ * local rename from reaching across a link: `token:color/brand` and `token:color/brand@yahoo-os` are
152
+ * different strings, so renaming ours leaves theirs alone. Your key and their key were never the
153
+ * same field. Don't loosen this to a prefix match.
154
+ */
155
+ declare function rewriteRefs(value: unknown, from: string, to: string): unknown;
156
+ /**
157
+ * A value that may be a ref, as the name it names.
158
+ *
159
+ * The read twin of {@link rewriteRefNamespace}: a relative ref namespaced under its owner
160
+ * (`value:variant/solid`) reads back as the leaf every consumer actually compares and emits
161
+ * (`solid`), so storing the ref costs no reader a branch.
162
+ *
163
+ * A non-ref is returned as it is, not stringified, so a condition keeps a real boolean rather than
164
+ * the string `"true"`. A condition compiles `true` to a bare truthiness test and `false` to
165
+ * `eq: false`, and both of those need the boolean to still be one by the time they are read.
166
+ */
167
+ declare function refLeaf(value: unknown): unknown;
168
+ /**
169
+ * Deep-rewrite the first path segment of every `kind` ref namespaced under `from`.
170
+ *
171
+ * The third rename axis, for a relative ref whose path is `<owner-member>/<name>` — a variant
172
+ * value (`value:variant/solid`) belongs to the prop that declares it, so renaming the prop has to
173
+ * move every value under it or they all dangle at once. {@link rewriteRefs} can't: it matches the
174
+ * whole entity or the `#` boundary, and this is a `/` boundary inside the path.
175
+ *
176
+ * Narrowed to one `kind` so it can't reach a same-named member of another collection — a layer
177
+ * called `variant` is `layer:variant` and is left alone.
178
+ *
179
+ * A sourced ref is skipped outright. {@link rewriteRefs} gets that property from exact-matching —
180
+ * `token:color/brand` and `token:color/brand@yahoo-os` are different strings — but a prefix match
181
+ * would catch both, and renaming our prop is no reason to rewrite a ref into someone else's values.
182
+ */
183
+ declare function rewriteRefNamespace(value: unknown, kind: string, from: string, to: string): unknown;
184
+ /**
185
+ * Deep-rewrite the source half of every ref pointing through link `from`, leaving what each one
186
+ * points at untouched — the cascade for renaming a link.
187
+ *
188
+ * The twin of {@link rewriteRefs} on the other axis: that one moves an entity and keeps the source,
189
+ * this one moves the source and keeps the entity. A link's slug is a local name like any other, so
190
+ * renaming it has to reach every ref that spells it or they all dangle at once.
191
+ */
192
+ declare function rewriteRefSource(value: unknown, from: string, to: string): unknown;
193
+ //#endregion
194
+ export { ENTITY_PATH_MESSAGE, ExtendableRef, ExtendedRef, MINTED, Ref, collectRefs, entityRefOf, isEntityPath, isExtendedRef, isMintedRow, isRef, kindOf, memberOf, memberRef, orRef, pathOf, ref, refLeaf, refSchema, rewriteRefNamespace, rewriteRefSource, rewriteRefs, sourceOf, splitRef };
@@ -0,0 +1,403 @@
1
+ import { z } from "zod";
2
+ //#region src/framework/utils/refs.ts
3
+ /**
4
+ * Refs are imported, typed markers pointing at another entity by `kind` + qualified
5
+ * path. Because a ref is just data inside a definition, the dependency graph falls out
6
+ * of a generic walk (`collectRefs`) — no per-entity edge wiring.
7
+ */
8
+ /** Separates the entity from the member it points inside — the URL convention (a path, then a
9
+ * fragment). Everything before it is byte-identical to a plain entity ref, which is what lets the
10
+ * existing machinery keep working; an entity path may contain `/`, so a distinct character is what
11
+ * keeps the boundary unambiguous. */
12
+ const MEMBER = "#";
13
+ /**
14
+ * Qualifies an entity with the linked system it lives in — the link's local slug, not the source's
15
+ * database id, so the ref stays readable and survives a rename on their side.
16
+ *
17
+ * It sits before {@link member} because it qualifies the entity: `component:Button@yahoo-os` is a
18
+ * whole identity, and `#props/gap` points inside whatever that resolved to.
19
+ */
20
+ const SOURCE = "@";
21
+ /** The `@source` suffix for a ref, or `''` when it's local. */
22
+ const qualifier = (source) => source === void 0 ? "" : `${SOURCE}${source}`;
23
+ /**
24
+ * Whether `path` can be an entity's own path — the invariant {@link splitSource} rests on, so it is
25
+ * stated next to it.
26
+ *
27
+ * An `@` is legal only as the first character, where it opens an npm scope: `package:@ariakit/react`
28
+ * is that package, and `package:@yahoo/uds-create-config` is this one. Anywhere else it reads as the
29
+ * source marker, and the split is what every provenance surface believes.
30
+ *
31
+ * Without this, a legitimately-named entity misparses in silence. A token called `1@2x` under `size`
32
+ * is a plausible name for a retina scale and was storable, and `token:size/1@2x` then reports its path
33
+ * as `size/1` and invents a source called `2x` — which paints nothing (`renderStyleValue` takes its
34
+ * `if (!source) return ''` escape and the declaration vanishes), reports a false dangling ref naming a
35
+ * source that does not exist, and marks the item borrowed on every provenance surface. Nothing throws.
36
+ *
37
+ * Checked where a path becomes an identity — a create, a rename's target, an authored entry — and
38
+ * deliberately not on reads, so an existing bad path stays addressable and, more to the point,
39
+ * deletable.
40
+ */
41
+ function isEntityPath(path) {
42
+ return path.lastIndexOf(SOURCE) <= 0;
43
+ }
44
+ /** What a refused path should say, in one place, so a create, a rename and a register word it alike. */
45
+ const ENTITY_PATH_MESSAGE = "An entity path may not contain \"@\" except as a leading npm scope — \"@\" marks the source a ref is drawn from, so a path carrying one cannot be told apart from a borrowed address.";
46
+ /**
47
+ * Splits a qualified path into what it names and where from.
48
+ *
49
+ * A path can OPEN with `@`: a package's path is an npm specifier, and `package:@ariakit/react` is
50
+ * scoped. So the source is the last `@`, and never a leading one — a scope opens a path, it doesn't
51
+ * qualify it. `package:@ariakit/react@yahoo-os` is that package, as their system has it.
52
+ *
53
+ * Total for every path {@link isEntityPath} admits, which is what makes "the last `@`" a rule rather
54
+ * than a heuristic: with at most a leading `@` in the path, any later one is the marker.
55
+ */
56
+ function splitSource(qualified) {
57
+ const at = qualified.lastIndexOf(SOURCE);
58
+ if (at <= 0) return [qualified, void 0];
59
+ return [qualified.slice(0, at), qualified.slice(at + 1)];
60
+ }
61
+ /**
62
+ * `kind:path[@source][#member]`, split — the one place a ref is read. This is the ref spelling of the
63
+ * address grammar written down whole in `framework/config-op.ts`.
64
+ *
65
+ * Every accessor below goes through this, and so does anything outside this file that needs a part of
66
+ * a ref. Code that slices at `indexOf(':')` or tests `startsWith('token:')` has its own copy of the
67
+ * grammar, which means the grammar cannot move without hunting for the copies — and a copy that is
68
+ * subtly wrong (a prefix test that a sourced ref fails) is silent.
69
+ */
70
+ function splitRef(target) {
71
+ const raw = isRef(target) ? target.__ref : target;
72
+ const hash = raw.indexOf(MEMBER);
73
+ const entity = hash === -1 ? raw : raw.slice(0, hash);
74
+ const member = hash === -1 ? void 0 : raw.slice(hash + 1);
75
+ const colon = entity.indexOf(":");
76
+ const kind = colon === -1 ? entity : entity.slice(0, colon);
77
+ const qualifiedPath = colon === -1 ? entity : entity.slice(colon + 1);
78
+ const [path, source] = splitSource(qualifiedPath);
79
+ return {
80
+ kind,
81
+ source,
82
+ path,
83
+ qualifiedPath,
84
+ member,
85
+ marked: colon !== -1
86
+ };
87
+ }
88
+ /**
89
+ * A reference to another entity: `ref('token', 'color/brand')`. Resolution is prefix-or-leaf against
90
+ * the flat store.
91
+ *
92
+ * With a `source` it points into a linked system instead — `ref('token', 'color/brand', 'yahoo-os')`.
93
+ * That is the whole of what a per-entity link marker used to record: the kind is the ref's kind and
94
+ * the source key is its path, while the version lives once on the pin rather than being repeated on
95
+ * every linked entity.
96
+ */
97
+ function ref(kind, path, source) {
98
+ const value = { __ref: `${kind}:${path}${qualifier(source)}` };
99
+ Object.defineProperty(value, "extend", {
100
+ enumerable: false,
101
+ configurable: false,
102
+ value: (delta) => ({
103
+ __ref: value.__ref,
104
+ extend: delta
105
+ })
106
+ });
107
+ return value;
108
+ }
109
+ /** A reference to one member of an entity's sub-entity collection — a component's prop, a layer:
110
+ * `memberRef('component', 'Pressable', 'props', 'gap')` → `component:Pressable#props/gap`. A
111
+ * `source` qualifies the entity the member is reached through. */
112
+ function memberRef(kind, path, sub, member, source) {
113
+ return { __ref: `${kind}:${path}${qualifier(source)}${MEMBER}${sub}/${member}` };
114
+ }
115
+ /**
116
+ * A ref to a singleton kind, in the form the index and the resolver read: the item at the kind's own
117
+ * name, with whatever path the ref named as its member path. `settings:css/prefix@ds` is
118
+ * `settings:settings@ds#css/prefix`, and `settings:` is `settings:settings`. A ref already at the item
119
+ * is handed back as it came. The caller knows the kind is a singleton; this is pure string work.
120
+ */
121
+ function singletonRef(target) {
122
+ const { kind, source, path, member } = splitRef(target);
123
+ if (path === kind) return target;
124
+ const tail = [path === "" ? void 0 : path, member].filter((part) => part !== void 0).join("/");
125
+ return `${kind}:${kind}${qualifier(source)}${tail ? `${MEMBER}${tail}` : ""}`;
126
+ }
127
+ /** The entity half of any ref — a plain entity ref is itself. This is the form the dependency
128
+ * graph and kind-narrowing speak, so a member ref participates in both unchanged. */
129
+ function entityRefOf(target) {
130
+ const at = target.indexOf(MEMBER);
131
+ return at === -1 ? target : target.slice(0, at);
132
+ }
133
+ /** The member half (`props/gap`), or `undefined` for a plain entity ref. Takes the ref itself or its
134
+ * string form, like {@link pathOf} / {@link kindOf} / {@link sourceOf}. */
135
+ function memberOf(target) {
136
+ const raw = isRef(target) ? target.__ref : target;
137
+ const at = raw.indexOf(MEMBER);
138
+ return at === -1 ? void 0 : raw.slice(at + 1);
139
+ }
140
+ /** The path of the entity a ref points at — kind, source and any member stripped, so a member ref
141
+ * resolves to the item that contains it (`component:buttons/Primary#props/gap` → `buttons/Primary`)
142
+ * and a linked ref yields the path as its source spells it (`token:color/brand@yahoo-os` →
143
+ * `color/brand`). Takes the ref itself or its string form, so a caller holding a ref field never
144
+ * spells `__ref`. */
145
+ function pathOf(target) {
146
+ return splitRef(target).path;
147
+ }
148
+ /** The source half — the link slug a ref points through, or `undefined` when it points at something
149
+ * in this config. This is the one question that distinguishes a linked entity from a local one, and
150
+ * it replaces reading a per-entity provenance marker. */
151
+ function sourceOf(target) {
152
+ return splitRef(target).source;
153
+ }
154
+ /** The kind a ref points at (`component:buttons/Primary#props/gap` → `component`) — the twin of
155
+ * {@link pathOf}, so a consumer holding a `kind:path` string (a `dependentsOf` result) never splits
156
+ * it by hand. Takes the ref itself or its string form. */
157
+ function kindOf(target) {
158
+ return splitRef(target).kind;
159
+ }
160
+ /** The zod schema of a ref value — used via {@link orRef} so a field never spells the
161
+ * `{ __ref }` shape by hand. `.meta({ ref: true })` marks it as a ref for any consumer (JSON
162
+ * Schema, an authoring UI) — this generic form carries no target kind (use an entity as the field
163
+ * to bake one in). */
164
+ const refSchema = z.object({ __ref: z.string() }).meta({ ref: true });
165
+ /** Widen a field's value type to also accept a ref: `value: orRef(z.string())`. */
166
+ function orRef(schema) {
167
+ return z.union([schema, refSchema]);
168
+ }
169
+ function isRef(value) {
170
+ return typeof value === "object" && value !== null && "__ref" in value;
171
+ }
172
+ /** Whether a ref is the stored result of `.extend(delta)`. Kept separate from {@link isRef}: every
173
+ * existing ref consumer should continue to see the base pointer, while Config is the place that
174
+ * gives the sibling delta its merge semantics. */
175
+ function isExtendedRef(value) {
176
+ return isRef(value) && "extend" in value && typeof value.extend === "object" && value.extend !== null && !Array.isArray(value.extend);
177
+ }
178
+ /**
179
+ * The key marking a row the build minted rather than a person authored.
180
+ *
181
+ * A link declares what it took; the rows for everything it brings are made by the build, at the paths
182
+ * the source spells them, so they are stored — `list`, the rename gate and every emitter reach them
183
+ * on the way past — without ever having been written down. This is the one thing that tells the two
184
+ * apart, and three readers turn on it: `uds pull` skips a minted row, a write to one lands on the
185
+ * source's `options` instead of the row (`Config.apply`'s update handler), and a serialize keeps it
186
+ * distinguishable rather than laundering it into source.
187
+ *
188
+ * Not `DERIVED` — a config already has an unrelated `derived` KIND (`EntityKind.derived`, what
189
+ * `Package` is), and `Config.derive` clones state on every mutation. A third meaning of the same word
190
+ * on the one marker that most needs to read unambiguously.
191
+ *
192
+ * On the body rather than in a parallel set, so the mark rides with the row through every snapshot
193
+ * change instead of being a second thing to keep in step.
194
+ */
195
+ const MINTED = "__minted";
196
+ /** Whether a stored body is a row the build minted. See {@link MINTED}. */
197
+ function isMintedRow(value) {
198
+ return typeof value === "object" && value !== null && value["__minted"] === true;
199
+ }
200
+ /**
201
+ * Every `kind:path` a definition points at — the one generic edge harvester.
202
+ *
203
+ * A ref can contribute more than one edge, at different granularities, so that a query at any of
204
+ * them resolves:
205
+ * • a member ref contributes its entity edge too, so pointing at a component's prop still counts
206
+ * as depending on that component;
207
+ * A sourced ref's edge at the link is not here. It needs the kind a `@slug` resolves against, which is
208
+ * whichever kind the config declared `sourceIdentity` on — and this is a pure walk with no config to
209
+ * ask. `Config.nameEdgeReaders` contributes it through the ref index's `extra` channel instead, so the
210
+ * grammar names no kind. This function used to hardcode `'linked-system'` for it.
211
+ */
212
+ function collectRefs(value, acc = []) {
213
+ if (isRef(value)) {
214
+ const entity = entityRefOf(value.__ref);
215
+ if (entity !== value.__ref) acc.push(entity);
216
+ acc.push(value.__ref);
217
+ if (isExtendedRef(value)) collectRefs(value.extend, acc);
218
+ } else if (Array.isArray(value)) for (const item of value) collectRefs(item, acc);
219
+ else if (value && typeof value === "object") for (const nested of Object.values(value)) collectRefs(nested, acc);
220
+ return acc;
221
+ }
222
+ /**
223
+ * Deep-rewrite every ref whose target is `from` to `to`, returning a new structure — the generic
224
+ * rename-cascade the same way `collectRefs` is the generic edge walk.
225
+ *
226
+ * Matching is exact on the entity (or on the `#` boundary for members), which is also what keeps a
227
+ * local rename from reaching across a link: `token:color/brand` and `token:color/brand@yahoo-os` are
228
+ * different strings, so renaming ours leaves theirs alone. Your key and their key were never the
229
+ * same field. Don't loosen this to a prefix match.
230
+ */
231
+ function rewriteRefs(value, from, to) {
232
+ if (isRef(value)) {
233
+ const siblings = {
234
+ ...isExtendedRef(value) ? { extend: rewriteRefs(value.extend, from, to) } : {},
235
+ ...isMintedRow(value) ? { [MINTED]: true } : {}
236
+ };
237
+ if (value.__ref === from) return {
238
+ __ref: to,
239
+ ...siblings
240
+ };
241
+ if (value.__ref.startsWith(`${from}${MEMBER}`)) return {
242
+ __ref: `${to}${value.__ref.slice(from.length)}`,
243
+ ...siblings
244
+ };
245
+ return isExtendedRef(value) ? {
246
+ __ref: value.__ref,
247
+ ...siblings
248
+ } : value;
249
+ }
250
+ if (Array.isArray(value)) return value.map((item) => rewriteRefs(item, from, to));
251
+ if (value && typeof value === "object") {
252
+ const out = {};
253
+ for (const [key, nested] of Object.entries(value)) out[key] = rewriteRefs(nested, from, to);
254
+ return out;
255
+ }
256
+ return value;
257
+ }
258
+ /**
259
+ * A value that may be a ref, as the name it names.
260
+ *
261
+ * The read twin of {@link rewriteRefNamespace}: a relative ref namespaced under its owner
262
+ * (`value:variant/solid`) reads back as the leaf every consumer actually compares and emits
263
+ * (`solid`), so storing the ref costs no reader a branch.
264
+ *
265
+ * A non-ref is returned as it is, not stringified, so a condition keeps a real boolean rather than
266
+ * the string `"true"`. A condition compiles `true` to a bare truthiness test and `false` to
267
+ * `eq: false`, and both of those need the boolean to still be one by the time they are read.
268
+ */
269
+ function refLeaf(value) {
270
+ if (!isRef(value)) return value;
271
+ const path = pathOf(value);
272
+ const slash = path.indexOf("/");
273
+ return slash === -1 ? path : path.slice(slash + 1);
274
+ }
275
+ /**
276
+ * Deep-rewrite the first path segment of every `kind` ref namespaced under `from`.
277
+ *
278
+ * The third rename axis, for a relative ref whose path is `<owner-member>/<name>` — a variant
279
+ * value (`value:variant/solid`) belongs to the prop that declares it, so renaming the prop has to
280
+ * move every value under it or they all dangle at once. {@link rewriteRefs} can't: it matches the
281
+ * whole entity or the `#` boundary, and this is a `/` boundary inside the path.
282
+ *
283
+ * Narrowed to one `kind` so it can't reach a same-named member of another collection — a layer
284
+ * called `variant` is `layer:variant` and is left alone.
285
+ *
286
+ * A sourced ref is skipped outright. {@link rewriteRefs} gets that property from exact-matching —
287
+ * `token:color/brand` and `token:color/brand@yahoo-os` are different strings — but a prefix match
288
+ * would catch both, and renaming our prop is no reason to rewrite a ref into someone else's values.
289
+ */
290
+ function rewriteRefNamespace(value, kind, from, to) {
291
+ if (isRef(value)) {
292
+ const siblings = isExtendedRef(value) ? { extend: rewriteRefNamespace(value.extend, kind, from, to) } : {};
293
+ if (sourceOf(value) !== void 0) return isExtendedRef(value) ? {
294
+ __ref: value.__ref,
295
+ ...siblings
296
+ } : value;
297
+ const prefix = `${kind}:${from}/`;
298
+ return value.__ref.startsWith(prefix) ? {
299
+ __ref: `${kind}:${to}/${value.__ref.slice(prefix.length)}`,
300
+ ...siblings
301
+ } : isExtendedRef(value) ? {
302
+ __ref: value.__ref,
303
+ ...siblings
304
+ } : value;
305
+ }
306
+ if (Array.isArray(value)) return value.map((item) => rewriteRefNamespace(item, kind, from, to));
307
+ if (value && typeof value === "object") {
308
+ const out = {};
309
+ for (const [key, nested] of Object.entries(value)) out[key] = rewriteRefNamespace(nested, kind, from, to);
310
+ return out;
311
+ }
312
+ return value;
313
+ }
314
+ /**
315
+ * Deep-qualify every unqualified ref with `source` — how a borrowed body's refs read once they have
316
+ * been resolved into the config doing the borrowing.
317
+ *
318
+ * A source spells its own refs locally, because from where it was authored they are local. Merged
319
+ * into a consumer unchanged, each one then names something that consumer was never supposed to own:
320
+ * `file:components/card.tsx` is the publisher's sealed file and the borrower has no such file, so it
321
+ * dangles. The quieter half is worse — a borrower that happens to declare its own `bg` binds
322
+ * `style-property:bg` to its property rather than the one the render was written against, and
323
+ * nothing reads as broken.
324
+ *
325
+ * `owns` decides what counts as an entity reference: only a kind the source actually owns. A ref to
326
+ * a sub-entity (`layer:root`) is scoped to the body holding it and means the same thing on either
327
+ * side of the seam, so qualifying it would invent a link no config could follow.
328
+ *
329
+ * A ref at the kind root (`motion:`, no path) is the same case one level up: it names the kind rather
330
+ * than an entity — the domain a prop is bound to, as `Box`'s `motion` prop is bound to every motion —
331
+ * and a domain means the same thing on either side of the seam too. Qualifying it produced
332
+ * `motion:@uds`, which is not an entity anywhere and cannot be: borrowing a component whose prop is
333
+ * bound to a whole kind left one dangling ref that no amount of linking could satisfy, because there
334
+ * is nothing at that path to link.
335
+ *
336
+ * An already-qualified ref is left alone. It points through the source's own pin, which this config
337
+ * has no slug for — a chain, and a different thing to report.
338
+ *
339
+ * And a ref the borrower already names is left alone too — see `namesItAlready`. That is the one case
340
+ * where the quieter half above does not apply: the borrower's row at that path is a pointer at the very
341
+ * entity the ref means, so binding to it is binding to the same thing, spelled the way everything local
342
+ * spells it.
343
+ */
344
+ function qualifyRefs({ value, source, owns, namesItAlready }) {
345
+ const walk = (node) => {
346
+ if (isRef(node)) {
347
+ const siblings = isExtendedRef(node) ? { extend: walk(node.extend) } : {};
348
+ if (sourceOf(node) !== void 0 || !owns(kindOf(node)) || pathOf(node) === "" || namesItAlready?.(node) === true) return isExtendedRef(node) ? {
349
+ __ref: node.__ref,
350
+ ...siblings
351
+ } : node;
352
+ const member = memberOf(node.__ref);
353
+ const rebuilt = ref(kindOf(node), pathOf(node), source).__ref;
354
+ return {
355
+ __ref: member === void 0 ? rebuilt : `${rebuilt}${MEMBER}${member}`,
356
+ ...siblings
357
+ };
358
+ }
359
+ if (Array.isArray(node)) return node.map(walk);
360
+ if (node && typeof node === "object") {
361
+ const out = {};
362
+ for (const [key, nested] of Object.entries(node)) out[key] = walk(nested);
363
+ return out;
364
+ }
365
+ return node;
366
+ };
367
+ return walk(value);
368
+ }
369
+ /**
370
+ * Deep-rewrite the source half of every ref pointing through link `from`, leaving what each one
371
+ * points at untouched — the cascade for renaming a link.
372
+ *
373
+ * The twin of {@link rewriteRefs} on the other axis: that one moves an entity and keeps the source,
374
+ * this one moves the source and keeps the entity. A link's slug is a local name like any other, so
375
+ * renaming it has to reach every ref that spells it or they all dangle at once.
376
+ */
377
+ function rewriteRefSource(value, from, to) {
378
+ if (isRef(value)) {
379
+ const siblings = {
380
+ ...isExtendedRef(value) ? { extend: rewriteRefSource(value.extend, from, to) } : {},
381
+ ...isMintedRow(value) ? { [MINTED]: true } : {}
382
+ };
383
+ if (sourceOf(value) !== from) return isExtendedRef(value) ? {
384
+ __ref: value.__ref,
385
+ ...siblings
386
+ } : value;
387
+ const member = memberOf(value.__ref);
388
+ const rebuilt = ref(kindOf(value), pathOf(value), to).__ref;
389
+ return {
390
+ __ref: member === void 0 ? rebuilt : `${rebuilt}${MEMBER}${member}`,
391
+ ...siblings
392
+ };
393
+ }
394
+ if (Array.isArray(value)) return value.map((item) => rewriteRefSource(item, from, to));
395
+ if (value && typeof value === "object") {
396
+ const out = {};
397
+ for (const [key, nested] of Object.entries(value)) out[key] = rewriteRefSource(nested, from, to);
398
+ return out;
399
+ }
400
+ return value;
401
+ }
402
+ //#endregion
403
+ export { ENTITY_PATH_MESSAGE, MINTED, collectRefs, entityRefOf, isEntityPath, isExtendedRef, isMintedRow, isRef, kindOf, memberOf, memberRef, orRef, pathOf, qualifyRefs, ref, refLeaf, refSchema, rewriteRefNamespace, rewriteRefSource, rewriteRefs, singletonRef, sourceOf, splitRef };
@@ -0,0 +1,27 @@
1
+ import { Config } from "./Config.js";
2
+
3
+ //#region src/framework/validate-spec.d.ts
4
+ /**
5
+ * A node in a render spec — what it renders, its prop values, its children. The spec is the
6
+ * HIERARCHY half of rendering and config-v2 does not render: it validates a spec against the config
7
+ * (are these things real, are these prop values in domain) and leaves drawing to codegen's emitted
8
+ * components. This type lives here because validation is what config-v2 does with a spec.
9
+ *
10
+ * `type` is a REF — the same string an entity ref serializes to, so what a design file stores is
11
+ * what the config resolves:
12
+ *
13
+ * component:studio/Button — a component of this system
14
+ * icon:phosphor/TrophyIcon — a glyph from one of its libraries
15
+ * package:ariakit/TooltipAnchor — an export of a package it renders through
16
+ */
17
+ interface SpecNode {
18
+ readonly type: string;
19
+ readonly props?: Record<string, unknown>;
20
+ readonly children?: readonly SpecNode[];
21
+ readonly text?: string;
22
+ }
23
+ /** Validate a design-file spec against the config — every node's `type` a real component and its
24
+ * props that component's props. Returns per-node error strings (empty = a valid design). */
25
+ declare function validateSpec(config: Config, spec: SpecNode): string[];
26
+ //#endregion
27
+ export { SpecNode, validateSpec };
@@ -0,0 +1,45 @@
1
+ import { kindOf, memberOf, pathOf, splitRef } from "./utils/refs.js";
2
+ import { childrenPolicy } from "../entities/system/element.js";
3
+ import { resolveComponentProps } from "./projections.js";
4
+ import { refResolves } from "./ref-integrity.js";
5
+ //#region src/framework/validate-spec.ts
6
+ /**
7
+ * `validateSpec` — validate a design-file spec (a tree of component INSTANCES) against a config.
8
+ * Every node is checked against the REAL component: its `type` must be a registered component and
9
+ * its props must be that component's (effective, inheritance included) props. Returns per-node
10
+ * error strings so a caller can reject a bad node and self-correct — the config-v2 edge over
11
+ * composing against loosely-checked tools.
12
+ *
13
+ * Pure over a Config (no mutation): a design file is a document. This is the check the design-file
14
+ * config's `Artboard` entity runs on its `spec` against the SYSTEM config.
15
+ */
16
+ /** `package:@ariakit/react#Menu` → `@ariakit/react#Menu` — the whole address a node named, minus
17
+ * the kind, for a message that has to say WHICH export was not found. */
18
+ function qualifiedPathOf(target) {
19
+ const { qualifiedPath, member } = splitRef(target);
20
+ return member === void 0 ? qualifiedPath : `${qualifiedPath}#${member}`;
21
+ }
22
+ function walk(config, node, path, errors) {
23
+ const kind = kindOf(node.type);
24
+ const target = pathOf(node.type);
25
+ if (!refResolves(config, node.type)) {
26
+ const named = config.resolve(kind, target) !== void 0 && memberOf(node.type) ? qualifiedPathOf(node.type) : target;
27
+ errors.push(`${path}: unknown ${kind} "${named}"`);
28
+ } else if (kind === "component") {
29
+ const props = resolveComponentProps(config, target);
30
+ for (const name of Object.keys(node.props ?? {})) if (!(name in props)) errors.push(`${path}: unknown prop "${name}" on "${node.type}"`);
31
+ if (node.children?.length && childrenPolicy(config, target) === "none") errors.push(`${path}: "${node.type}" takes no children`);
32
+ }
33
+ (node.children ?? []).forEach((child, i) => {
34
+ walk(config, child, `${path} > ${node.type}[${i}]`, errors);
35
+ });
36
+ }
37
+ /** Validate a design-file spec against the config — every node's `type` a real component and its
38
+ * props that component's props. Returns per-node error strings (empty = a valid design). */
39
+ function validateSpec(config, spec) {
40
+ const errors = [];
41
+ walk(config, spec, "root", errors);
42
+ return errors;
43
+ }
44
+ //#endregion
45
+ export { validateSpec };