@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,211 @@
1
+ import { Entity } from "./Entity.js";
2
+ import { Config, SerializedConfig } from "./Config.js";
3
+ import { z } from "zod";
4
+
5
+ //#region src/framework/sources.d.ts
6
+ /**
7
+ * The two schemas a source kind declares its resolutions against — see {@link EntityKind.sourceResolution}.
8
+ *
9
+ * `resolved` describes where an attached source came from, carrying the identity that origin actually
10
+ * has. `unavailable` describes why a declared one could not be met — a code plus the data that case
11
+ * needs, never prose, because the fix is surface-specific: a build tells you to run `uds install`, a
12
+ * browser paints an update button, and baking one string per code would put CLI instructions into
13
+ * Studio.
14
+ *
15
+ * Both are normally `z.discriminatedUnion`s, so a surface switches exhaustively and adding a case is a
16
+ * compile error at every consumer. Nothing here requires that, because it is the kind's call.
17
+ */
18
+ interface SourceResolutionSchemas<Resolved extends z.ZodTypeAny = z.ZodTypeAny, Unavailable extends z.ZodTypeAny = z.ZodTypeAny> {
19
+ readonly resolved: Resolved;
20
+ readonly unavailable: Unavailable;
21
+ }
22
+ /** What a declared source lays over one of its entities, and whether it still offers it. */
23
+ interface SourceOverlay {
24
+ /** Fields changing a value the source defines. */
25
+ readonly override?: Record<string, unknown>;
26
+ /** Fields covering a case the source does not. */
27
+ readonly extend?: Record<string, unknown>;
28
+ /** Kept and resolving, but not offered by authoring surfaces. */
29
+ readonly hidden: boolean;
30
+ }
31
+ /**
32
+ * What a source kind is asked when the framework wants to know whether one of its declarations still
33
+ * covers a borrowed entity — the argument to {@link EntityKind.bulkAdopts}, and to the two directive
34
+ * reads beside it.
35
+ *
36
+ * Both names for the borrowed kind are handed over because the two vocabularies are both real and
37
+ * neither side can map between them alone: ops and refs are keyed by kind (`token:color/brand`) while
38
+ * anything written in a config file — which a stored declaration is — is keyed by accessor (`tokens`).
39
+ * Only the config type's manifest knows the pair, so the framework resolves it and the kind reads
40
+ * whichever it recorded under. `accessor` is `undefined` for a config with no manifest.
41
+ */
42
+ interface BulkQuery {
43
+ /** The declared source's stored body — the declaration is one of its fields. */
44
+ readonly body: Record<string, unknown>;
45
+ /** The borrowed entity's kind, and the accessor that kind is registered under. */
46
+ readonly kind: string;
47
+ readonly accessor: string | undefined;
48
+ /** The borrowed entity's path as the source spells it — what a declaration names. */
49
+ readonly path: string;
50
+ }
51
+ /**
52
+ * What a source kind is asked to lay a `SourceOverlay` over one path — the write counterpart to
53
+ * {@link EntityKind.bulkOverlay}, for the same reason that one exists: the field the directive is
54
+ * stored under is the kind's own, and the framework does not know it.
55
+ *
56
+ * Narrower than {@link BulkQuery} — a write does not need the OLD stored body, since a field-path
57
+ * `update` already merges rather than replaces.
58
+ */
59
+ interface BulkOverlayWrite {
60
+ readonly accessor: string | undefined;
61
+ readonly path: string;
62
+ /** Sparse, unlike a read `SourceOverlay` — `hidden` is worth writing only when true, so a leaf that
63
+ * changed nothing about visibility does not gain a field just for having been touched. */
64
+ readonly overlay: (Pick<SourceOverlay, 'override' | 'extend'> & {
65
+ readonly hidden?: boolean;
66
+ }) | null;
67
+ }
68
+ /**
69
+ * What this config lays over one borrowed item, and the body it lays it on — `Config.localOverlay`.
70
+ *
71
+ * `fields` is the stored delta at top level, the merge being one level deep: a record field here holds
72
+ * the whole record as this config now spells it, members it changed beside members it only carried
73
+ * along. `override` and `extend` are that delta judged leaf by leaf against `source`, in the pin's
74
+ * vocabulary, with the carried-along leaves left out; `overlayVerb` reads one leaf of them.
75
+ */
76
+ interface LocalOverlay {
77
+ /** The link the item is borrowed through. */
78
+ readonly slug: string;
79
+ /** The fields this config wrote over the source's, as stored. */
80
+ readonly fields: Readonly<Record<string, unknown>>;
81
+ /** The source's body as it reads from here; `undefined` while the source is unavailable. */
82
+ readonly source: Readonly<Record<string, unknown>> | undefined;
83
+ /** The leaves of `fields` the source defines differently. Absent when there are none. */
84
+ readonly override?: Readonly<Record<string, unknown>>;
85
+ /** The leaves of `fields` the source has nothing at. Absent when there are none. */
86
+ readonly extend?: Readonly<Record<string, unknown>>;
87
+ }
88
+ /**
89
+ * The one refusal the framework owns, rather than a source kind.
90
+ *
91
+ * Every other `unavailable` reason is a verdict about the source — never published, out of date,
92
+ * found and unreadable — and only the kind can enumerate those. This one is a fact about the attempt:
93
+ * something looked, and the look did not finish. A load path that raced the resolve against a
94
+ * deadline, a request that threw, a walk abandoned mid-flight; the declaration may be perfectly fine.
95
+ *
96
+ * It exists because the alternative is worse. Reporting nothing for a resolve that failed collapses
97
+ * it into {@link Config.sourceStatus}'s `undefined` — "nobody looked" — which is the third state that
98
+ * distinction exists to preserve, and a surface reading it says "the values arrive when the project
99
+ * builds" about a source it just failed to reach.
100
+ *
101
+ * A kind unions this into its own `unavailable` schema so its inferred type carries the case and
102
+ * every exhaustive consumer has to answer for it — `LinkedSystem.sourceUnavailable` does.
103
+ */
104
+ declare const sourceUnreachable: z.ZodObject<{
105
+ code: z.ZodLiteral<"unreachable">;
106
+ }, z.core.$strip>;
107
+ /** {@link sourceUnreachable} as a value, so a caller reporting a failed attempt states no kind's own
108
+ * vocabulary to do it. */
109
+ declare const UNREACHABLE: {
110
+ readonly code: "unreachable";
111
+ };
112
+ /**
113
+ * What a resolver answers with — the framework's tag over the kind's own two payloads.
114
+ *
115
+ * Tagged rather than structurally discriminated: `status` is what makes this a discriminated union,
116
+ * and it is the same tag {@link Config.sourceStatus} reports — so the state a resolver returns is the
117
+ * state the config exposes, and nothing can disagree about which state a source is in.
118
+ *
119
+ * Parameterized on the inferred payloads rather than on the schemas, so a kind can hand its consumers
120
+ * one concrete alias (`LinkedSystemState`) without them touching zod. Both default to `unknown`, which
121
+ * is what generic framework code genuinely knows: {@link Config.sources} spans every source kind a
122
+ * Config declares, and only the kind can say what its payloads are.
123
+ */
124
+ type SourceResolution<Resolved = unknown, Unavailable = unknown> = {
125
+ readonly status: 'attached';
126
+ readonly resolved: Resolved;
127
+ } | {
128
+ readonly status: 'unavailable';
129
+ readonly reason: Unavailable;
130
+ };
131
+ /**
132
+ * One source's state, as a config reports it — the resolution plus which source it answers for.
133
+ *
134
+ * Both halves of the address, so {@link Config.sources} is self-describing: `source` is the declared
135
+ * source's accessor name (`linkedSystems`), `slug` is the item's path within it (`ds`). A surface
136
+ * listing states can group them by collection without holding the declaration alongside, and can pick
137
+ * the kind whose payload types it knows how to read.
138
+ *
139
+ * Lookup is by slug alone ({@link Config.sourceStatus}), and that is not an inconsistency — a ref
140
+ * spells `@ds` with no room for a collection, so the slug namespace is flat and every other reader
141
+ * (`sourceFor`, `liveSourceFor`, the `sources` key `toJSON` writes) is keyed the same way. Flat is
142
+ * enforced, not assumed: `Config.assertDistinctSourceSlugs` refuses two source kinds claiming one
143
+ * slug, because nothing else could tell which of them `@ds` meant.
144
+ */
145
+ type SourceState<Resolved = unknown, Unavailable = unknown> = SourceResolution<Resolved, Unavailable> & {
146
+ /** The declared source this answers for — the accessor name, as `Config.sourceAccessors` reports it. */readonly source: string;
147
+ readonly slug: string;
148
+ };
149
+ /**
150
+ * One declared source kind's resolver. It is handed the entity stored at that kind — so `entity.path`
151
+ * is the slug and every other field is the kind's own, typed.
152
+ *
153
+ * Taking the entity is what keeps this total over kinds nobody has written yet: there is no fixed
154
+ * declaration shape in the signature, so a config declaring `linkedPackages` needs nothing added to
155
+ * the framework — its resolver is handed a `LinkedPackage` and reads `packageName`/`range`, because
156
+ * that is what that kind declares. The answer is the kind's too, which is why the payloads are
157
+ * parameters here: a kind
158
+ * exports `SourceResolver<Source, ResolvedSource, SourceUnavailable>` under one name and its
159
+ * implementers get both halves typed.
160
+ *
161
+ * `source` rides alongside the validated resolution rather than inside it: a `Config` is not a zod
162
+ * value, and a `SerializedConfig` validates itself on hydrate through its own type's schema. Two
163
+ * validators over one payload is how they drift.
164
+ *
165
+ * Answering is mandatory; answering `unavailable` is legal. No answer at all is the failure — it reads
166
+ * identically to "this config borrows nothing", which is the confusion this whole model removes.
167
+ */
168
+ type SourceResolver<E extends Entity = Entity, Resolved = unknown, Unavailable = unknown> = (entity: E) => Promise<SourceAnswer<Resolved, Unavailable>>;
169
+ /**
170
+ * One answer about one source — the resolution, plus the source itself when there is one.
171
+ *
172
+ * Named because it crosses seams a resolver signature cannot describe: a server action hands one back
173
+ * for a slug a panel asked about, and {@link Config.attachResolved} takes one. Spelling it inline at
174
+ * each of those would be three statements of the same shape, and the app-side copy is the one that
175
+ * would go stale when a kind adds a payload.
176
+ */
177
+ type SourceAnswer<Resolved = unknown, Unavailable = unknown> = SourceResolution<Resolved, Unavailable> & {
178
+ /** Rides alongside the validated resolution — a `Config` is not a zod value, and a
179
+ * `SerializedConfig` validates itself on hydrate through its own type's schema. */
180
+ readonly source?: SerializedConfig | Config;
181
+ };
182
+ /**
183
+ * An answer that has to cross a wire — the source as an artifact, never as a live class.
184
+ *
185
+ * The distinction is not pedantry: a `Config` is a class with methods, so a server action returning
186
+ * one either fails to serialize or arrives as a shape-alike with nothing on it. Narrowing the carrier
187
+ * in the type is what makes that a compile error at the boundary rather than a runtime surprise in a
188
+ * browser.
189
+ *
190
+ * Assignable to {@link SourceAnswer} in the direction that matters, so
191
+ * {@link Config.attachResolved} takes one unchanged.
192
+ */
193
+ type SerializedSourceAnswer<Resolved = unknown, Unavailable = unknown> = SourceResolution<Resolved, Unavailable> & {
194
+ readonly source?: SerializedConfig;
195
+ };
196
+ /**
197
+ * The schema a kind's resolutions validate against — its two payloads under the framework's tag.
198
+ *
199
+ * Built here rather than by each kind so the tag is stated once: a kind that composed its own union
200
+ * could spell `status` differently, or omit a branch, and the value would still typecheck as far as
201
+ * Zod is concerned while {@link Config.sourceStatus} could no longer read it.
202
+ *
203
+ * Cache the result per kind rather than calling this per item — it allocates a union, and a resolve
204
+ * walk validates every slug of a kind against the same one.
205
+ */
206
+ declare function resolutionSchema({
207
+ resolved,
208
+ unavailable
209
+ }: SourceResolutionSchemas): z.ZodTypeAny;
210
+ //#endregion
211
+ export { BulkOverlayWrite, BulkQuery, LocalOverlay, SerializedSourceAnswer, SourceAnswer, SourceOverlay, SourceResolution, SourceResolutionSchemas, SourceResolver, SourceState, UNREACHABLE, resolutionSchema, sourceUnreachable };
@@ -0,0 +1,89 @@
1
+ import { z } from "zod";
2
+ //#region src/framework/sources.ts
3
+ /**
4
+ * What a declared source resolved to — the vocabulary a resolver answers in and a config reports in,
5
+ * which is one vocabulary because there is no mapping layer between them.
6
+ *
7
+ * A source declaration is a request, and it may be moving: a repo-local one tracks whatever the sibling
8
+ * currently is, and a published one names a version someone may not have installed. These types are the
9
+ * answer, recorded per slug so a receipt can be judged stale and a build can say what it built against.
10
+ *
11
+ * **The framework owns the tag and nothing else.** `attached` against `unavailable` is structural, the
12
+ * same distinction {@link Config.sourceStatus} reports, and every source kind has it. What each branch
13
+ * carries is not: a linked system resolves from disk, a registry entry or Create, and fails as
14
+ * `unbuilt`/`stale`/`not-installed`/`not-found`, where a `linkedPackages` kind would resolve from a
15
+ * lockfile and fail as a range matching nothing. Naming either vocabulary here would be the framework
16
+ * naming a kind (`.claude/rules/config-framework-kind-agnostic.md`), in a shape no second source kind
17
+ * could fill.
18
+ *
19
+ * So the kind declares the pair, `defineEntity({ sourceResolution: { resolved, unavailable } })`, and
20
+ * {@link resolutionSchema} composes it with the tag. Validated with zod because this is the seam where
21
+ * arbitrary environment code hands a value to the framework: a resolver returning a half-filled object
22
+ * fails here and names the source, rather than hydrating into a config that reads as "borrows nothing".
23
+ */
24
+ /**
25
+ * The one refusal the framework owns, rather than a source kind.
26
+ *
27
+ * Every other `unavailable` reason is a verdict about the source — never published, out of date,
28
+ * found and unreadable — and only the kind can enumerate those. This one is a fact about the attempt:
29
+ * something looked, and the look did not finish. A load path that raced the resolve against a
30
+ * deadline, a request that threw, a walk abandoned mid-flight; the declaration may be perfectly fine.
31
+ *
32
+ * It exists because the alternative is worse. Reporting nothing for a resolve that failed collapses
33
+ * it into {@link Config.sourceStatus}'s `undefined` — "nobody looked" — which is the third state that
34
+ * distinction exists to preserve, and a surface reading it says "the values arrive when the project
35
+ * builds" about a source it just failed to reach.
36
+ *
37
+ * A kind unions this into its own `unavailable` schema so its inferred type carries the case and
38
+ * every exhaustive consumer has to answer for it — `LinkedSystem.sourceUnavailable` does.
39
+ */
40
+ const sourceUnreachable = z.object({ code: z.literal("unreachable") });
41
+ /** {@link sourceUnreachable} as a value, so a caller reporting a failed attempt states no kind's own
42
+ * vocabulary to do it. */
43
+ const UNREACHABLE = { code: "unreachable" };
44
+ /**
45
+ * The schema a kind's resolutions validate against — its two payloads under the framework's tag.
46
+ *
47
+ * Built here rather than by each kind so the tag is stated once: a kind that composed its own union
48
+ * could spell `status` differently, or omit a branch, and the value would still typecheck as far as
49
+ * Zod is concerned while {@link Config.sourceStatus} could no longer read it.
50
+ *
51
+ * Cache the result per kind rather than calling this per item — it allocates a union, and a resolve
52
+ * walk validates every slug of a kind against the same one.
53
+ */
54
+ function resolutionSchema({ resolved, unavailable }) {
55
+ return z.discriminatedUnion("status", [z.object({
56
+ status: z.literal("attached"),
57
+ resolved
58
+ }), z.object({
59
+ status: z.literal("unavailable"),
60
+ reason: unavailable
61
+ })]);
62
+ }
63
+ /**
64
+ * Parse what a resolver returned, refusing a malformed answer at the seam and naming the source.
65
+ *
66
+ * Takes the schema rather than looking one up, because the caller resolving a kind already holds it
67
+ * (`Config.load` reads it off `entityOf(kind)` once and reuses it for every slug) and because this
68
+ * function must not know which kinds exist.
69
+ *
70
+ * The resolver's `source` — the config itself — is stripped before validation and handed back as
71
+ * `config` beside the parsed resolution, for the reason {@link SourceResolver} states: it is not a zod
72
+ * value. Renamed on the way out because `source` in a {@link SourceState} is the declared source's
73
+ * name, and one word cannot be both.
74
+ */
75
+ function parseResolution({ source, slug, schema, answer }) {
76
+ const named = `${source}/${slug}`;
77
+ if (answer === null || typeof answer !== "object") throw new Error(`The resolver for source "${named}" answered ${answer === null ? "null" : typeof answer} rather than a resolution. Answering is mandatory — \`unavailable\` is a legal answer, no answer is not.`);
78
+ const { source: config, ...resolution } = answer;
79
+ const parsed = schema.safeParse(resolution);
80
+ if (!parsed.success) throw new Error(`The resolver for source "${named}" answered a value this is not: ${parsed.error.issues.map((issue) => `${issue.path.join(".") || "(root)"} — ${issue.message}`).join("; ")}`);
81
+ return {
82
+ source,
83
+ slug,
84
+ ...parsed.data,
85
+ ...config === void 0 ? {} : { config }
86
+ };
87
+ }
88
+ //#endregion
89
+ export { UNREACHABLE, parseResolution, resolutionSchema, sourceUnreachable };
@@ -0,0 +1,23 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * A schema that generates its parser ahead of time on first use, in place.
4
+ *
5
+ * The returned value IS the schema passed in — same class, `shape`, `parse`/`safeParse` and JSON
6
+ * Schema — with its parse entry swapped for one that compiles on the first parse and routes every
7
+ * later parse through the generated fast path. A schema nested inside another (a create body inside
8
+ * its `{ path, data }` op input) is compiled the same way, so the fast path applies wherever the
9
+ * schema is reached.
10
+ *
11
+ * Compiling is deferred rather than run here because `z.compile` walks the schema to check for a
12
+ * reference cycle, and that walk resolves a `z.lazy(...)`. A self-referential kind declares
13
+ * `z.lazy(() => Token)` in `Token`'s own body, so compiling during `defineEntity` would resolve the
14
+ * reference while `Token`'s binding is still in its dead zone — the getter throws and zod caches the
15
+ * lazy's inner type as undefined for the life of the process, and every later token parse then fails.
16
+ * By the first parse the module has finished initializing, so the reference resolves and zod either
17
+ * generates a fast path or, for a schema whose subtree is a cycle, hands it back on the runtime. The
18
+ * compile also runs once per schema this way, not on every ad hoc schema, and off the module-load path.
19
+ *
20
+ * Where a runtime cannot generate code — `new Function` refused by a CSP — `z.compile` returns the
21
+ * schema uncompiled and it parses on the runtime as before.
22
+ */
23
+ export declare function compileSchema<T extends z.ZodTypeAny>(schema: T): T;
@@ -0,0 +1,46 @@
1
+ import { z } from "zod";
2
+ //#region src/framework/utils/compiled-schema.ts
3
+ const internalsOf = (schema) => schema._zod;
4
+ /**
5
+ * A schema that generates its parser ahead of time on first use, in place.
6
+ *
7
+ * The returned value IS the schema passed in — same class, `shape`, `parse`/`safeParse` and JSON
8
+ * Schema — with its parse entry swapped for one that compiles on the first parse and routes every
9
+ * later parse through the generated fast path. A schema nested inside another (a create body inside
10
+ * its `{ path, data }` op input) is compiled the same way, so the fast path applies wherever the
11
+ * schema is reached.
12
+ *
13
+ * Compiling is deferred rather than run here because `z.compile` walks the schema to check for a
14
+ * reference cycle, and that walk resolves a `z.lazy(...)`. A self-referential kind declares
15
+ * `z.lazy(() => Token)` in `Token`'s own body, so compiling during `defineEntity` would resolve the
16
+ * reference while `Token`'s binding is still in its dead zone — the getter throws and zod caches the
17
+ * lazy's inner type as undefined for the life of the process, and every later token parse then fails.
18
+ * By the first parse the module has finished initializing, so the reference resolves and zod either
19
+ * generates a fast path or, for a schema whose subtree is a cycle, hands it back on the runtime. The
20
+ * compile also runs once per schema this way, not on every ad hoc schema, and off the module-load path.
21
+ *
22
+ * Where a runtime cannot generate code — `new Function` refused by a CSP — `z.compile` returns the
23
+ * schema uncompiled and it parses on the runtime as before.
24
+ */
25
+ function compileSchema(schema) {
26
+ const internals = internalsOf(schema);
27
+ const runtimeRun = internals.run;
28
+ let compiled = false;
29
+ const compileOnFirstRun = (payload, ctx) => {
30
+ if (!compiled) {
31
+ compiled = true;
32
+ internals.run = runtimeRun;
33
+ const fastPath = internalsOf(z.compile(schema));
34
+ internals.run = fastPath.run;
35
+ if (fastPath.bag.validator !== void 0) {
36
+ internals.bag.validator = fastPath.bag.validator;
37
+ internals.bag.fallbackRun = fastPath.bag.fallbackRun;
38
+ }
39
+ }
40
+ return internals.run(payload, ctx);
41
+ };
42
+ internals.run = compileOnFirstRun;
43
+ return schema;
44
+ }
45
+ //#endregion
46
+ export { compileSchema };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * A stable content key over JSON-shaped values — what names a derived artifact after the state it
3
+ * was derived from, so "did this change" is a string comparison and a cache is addressed by it.
4
+ *
5
+ * FNV-1a over a key-sorted serialization: portable (a config runs in the browser, so no
6
+ * `node:crypto`), synchronous (`crypto.subtle` is not), and collision-resistant enough for a cache
7
+ * key whose worst miss is one redundant rebuild. Not a security hash; nothing may treat it as one.
8
+ */
9
+ /** JSON serialization with every object's keys sorted, so two spellings of one value are one
10
+ * string. Arrays keep their order — order is meaning there. */
11
+ export declare function stableStringify(value: unknown): string;
12
+ /** A 64-bit FNV-1a digest of `text`, as 16 hex chars. */
13
+ export declare function fnv1a64(text: string): string;
14
+ /** The content key of a JSON-shaped value. */
15
+ export declare function contentKey(value: unknown): string;
@@ -0,0 +1,33 @@
1
+ //#region src/framework/utils/content-key.ts
2
+ /**
3
+ * A stable content key over JSON-shaped values — what names a derived artifact after the state it
4
+ * was derived from, so "did this change" is a string comparison and a cache is addressed by it.
5
+ *
6
+ * FNV-1a over a key-sorted serialization: portable (a config runs in the browser, so no
7
+ * `node:crypto`), synchronous (`crypto.subtle` is not), and collision-resistant enough for a cache
8
+ * key whose worst miss is one redundant rebuild. Not a security hash; nothing may treat it as one.
9
+ */
10
+ /** JSON serialization with every object's keys sorted, so two spellings of one value are one
11
+ * string. Arrays keep their order — order is meaning there. */
12
+ function stableStringify(value) {
13
+ if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
14
+ if (typeof value === "object" && value !== null) return `{${Object.entries(value).filter(([, entry]) => entry !== void 0).sort(([a], [b]) => a < b ? -1 : 1).map(([key, entry]) => `${JSON.stringify(key)}:${stableStringify(entry)}`).join(",")}}`;
15
+ return JSON.stringify(value) ?? "null";
16
+ }
17
+ /** A 64-bit FNV-1a digest of `text`, as 16 hex chars. */
18
+ function fnv1a64(text) {
19
+ let hash = 14695981039346656037n;
20
+ const prime = 1099511628211n;
21
+ const mask = 18446744073709551615n;
22
+ for (let i = 0; i < text.length; i++) {
23
+ hash ^= BigInt(text.charCodeAt(i));
24
+ hash = hash * prime & mask;
25
+ }
26
+ return hash.toString(16).padStart(16, "0");
27
+ }
28
+ /** The content key of a JSON-shaped value. */
29
+ function contentKey(value) {
30
+ return fnv1a64(stableStringify(value));
31
+ }
32
+ //#endregion
33
+ export { contentKey, stableStringify };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The values a domain ENUMERATES, in declaration order — or `undefined` when it doesn't enumerate.
3
+ *
4
+ * Two forms mean the same thing. A KEYED COLLECTION is how an enumerated domain is STORED: each
5
+ * value is a member with a name, an order and a body of its own (a component's variant values,
6
+ * which carry a label and can be renamed by the ordinary cascade). A LIST is the same statement
7
+ * from a source with no bodies to carry — an author's shorthand, a style property's keywords.
8
+ *
9
+ * Its own module because both readers of a domain need the same answer and neither can import the
10
+ * other: `value-domain` turns it into a schema, and `projections` turns it into the leaves a picker
11
+ * offers, while `value-domain` already reads `projections` for the ref case.
12
+ */
13
+ export declare function listedIn(domain: unknown): string[] | undefined;
@@ -0,0 +1,19 @@
1
+ //#region src/framework/utils/enumerated.ts
2
+ /**
3
+ * The values a domain ENUMERATES, in declaration order — or `undefined` when it doesn't enumerate.
4
+ *
5
+ * Two forms mean the same thing. A KEYED COLLECTION is how an enumerated domain is STORED: each
6
+ * value is a member with a name, an order and a body of its own (a component's variant values,
7
+ * which carry a label and can be renamed by the ordinary cascade). A LIST is the same statement
8
+ * from a source with no bodies to carry — an author's shorthand, a style property's keywords.
9
+ *
10
+ * Its own module because both readers of a domain need the same answer and neither can import the
11
+ * other: `value-domain` turns it into a schema, and `projections` turns it into the leaves a picker
12
+ * offers, while `value-domain` already reads `projections` for the ref case.
13
+ */
14
+ function listedIn(domain) {
15
+ if (Array.isArray(domain)) return domain.filter((value) => typeof value === "string");
16
+ return typeof domain === "object" && domain !== null ? Object.keys(domain) : void 0;
17
+ }
18
+ //#endregion
19
+ export { listedIn };
@@ -0,0 +1,95 @@
1
+ //#region src/framework/utils/field-path.d.ts
2
+ /**
3
+ * A write's ADDRESS, carried in the delta's KEY.
4
+ *
5
+ * `update` / `sub-update` take a partial whose keys are FIELD PATHS. One rule covers every depth:
6
+ * **the value replaces whatever the key addresses**, and `null` removes it.
7
+ *
8
+ * { layers: {…} } → replaces the whole `layers` field
9
+ * { 'layers.root.bg': 'hover' } → replaces one leaf, touching nothing else
10
+ * { 'layers.root.bg': null } → removes that leaf
11
+ * { 'layers.root': null } → removes the whole bag
12
+ *
13
+ * So depth is something the CALLER states rather than something the verb implies — Firestore's
14
+ * `update()` rule, and the reason there is no second "deep" verb. A deep write and a whole-field
15
+ * write differ only in how many segments the key has.
16
+ *
17
+ * The nested-object delta this replaces could not tell those two apart. Merged recursively,
18
+ * `{ value: { warning: {} } }` is both "add a value called `warning`" and "empty the one that is
19
+ * already there", and the merge had to GUESS — it pruned, so adding a variant value applied cleanly
20
+ * and stored nothing: a silent no-op with no rejection to explain it. Under an address there is
21
+ * nothing to guess, because setting and removing are different calls rather than different-looking
22
+ * data.
23
+ *
24
+ * The one thing an address cannot spell is a member key that itself contains a dot (`spacing.2`,
25
+ * which nothing names today — paths separate with `/`). Such a key is reachable by `sub-upsert`,
26
+ * which addresses it whole.
27
+ */
28
+ /** A JSON object — not an array, not a class instance. */
29
+ declare function isPlainObject(value: unknown): value is Record<string, unknown>;
30
+ /**
31
+ * The segments a delta key addresses.
32
+ *
33
+ * A key is a PATH when it contains a `.` AND its first segment names a field of the thing being
34
+ * written — decidable off the target's own schema, so it is a rule rather than a guess. A key that
35
+ * fails either test addresses one field, dot and all, which is what keeps a literal dotted key
36
+ * writable at the depth it lives at.
37
+ */
38
+ declare function pathSegments(key: string, isField: (name: string) => boolean): string[];
39
+ /**
40
+ * `body` with `value` at `segments` — assigned, or REMOVED when `value` is `null`. Neither input is
41
+ * mutated.
42
+ *
43
+ * Two rules about containers along the way, and both follow from "the value replaces what the key
44
+ * addresses":
45
+ *
46
+ * - An intermediate that is missing, or is a scalar, becomes a container. The caller addressed
47
+ * something inside it, which is a caller saying one belongs there.
48
+ * - A removal that EMPTIES a container takes the container with it, except at the first segment —
49
+ * those are the target's own declared fields, and a rule whose `layers` bag has been cleared is
50
+ * still a rule with an empty bag, not a rule missing a required field. Removing the field itself
51
+ * is what `null` AT that segment says. A SET never prunes: an empty object a caller wrote is a
52
+ * value.
53
+ */
54
+ declare function setAtPath(body: Record<string, unknown>, segments: readonly string[], value: unknown, depth?: number): Record<string, unknown>;
55
+ /**
56
+ * A path-keyed delta applied to a body, entry by entry in the order the caller wrote them.
57
+ *
58
+ * Order matters and is the caller's: two entries may address the same subtree, and the second is
59
+ * meant to win. That is also what makes one batch safe where a read-merge-write pair was not.
60
+ */
61
+ declare function applyPathDelta(current: Record<string, unknown>, delta: Record<string, unknown>, isField: (name: string) => boolean): Record<string, unknown>;
62
+ /**
63
+ * The inverse of {@link applyPathDelta}: the path-keyed delta that turns `existing` into `desired`,
64
+ * over `fields` — one entry per changed member (`null` removes), nothing restated. This is what
65
+ * makes a reconciling writer produce patches that SAY what the gesture did: a prop edit reads back
66
+ * as `props.bg`, not as a whole-body replace.
67
+ *
68
+ * Descent stops exactly where addressing stops, so applying the delta always reproduces `desired`:
69
+ * both sides must be plain records (an array, a ref, a scalar replaces at its own address), every
70
+ * member key must be dot-free (a dotted key can't be addressed — the record writes whole), and a
71
+ * NESTED record emptied of members writes whole, since {@link setAtPath} prunes a container a
72
+ * removal empties. A declared field is never pruned there, so at the field level the same
73
+ * emptying stays addressed.
74
+ *
75
+ * `same` is the caller's structural equality — bodies hold refs, and whether two spellings of one
76
+ * are equal is the caller's to say.
77
+ */
78
+ declare function pathDelta({
79
+ existing,
80
+ desired,
81
+ fields,
82
+ same
83
+ }: {
84
+ existing: Record<string, unknown>;
85
+ desired: Record<string, unknown>;
86
+ fields: readonly string[];
87
+ same: (a: unknown, b: unknown) => boolean;
88
+ }): Record<string, unknown>;
89
+ /** A field predicate over a known list of names — an entity's `fieldKeys`, straight off the kind. */
90
+ declare function namedFields(names: readonly string[]): (name: string) => boolean;
91
+ /** The FIELDS a delta touched — every key's first segment. What a write reports as changed, so work
92
+ * scoped to written fields (member coercion) covers the same set the delta reached. */
93
+ declare function touchedFields(delta: Record<string, unknown>, isField: (name: string) => boolean): Set<string>;
94
+ //#endregion
95
+ export { applyPathDelta, isPlainObject, namedFields, pathDelta, pathSegments, setAtPath, touchedFields };