@dxos/echo 0.9.0 → 0.9.1-staging.ee54ba693a

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 (289) hide show
  1. package/dist/lib/neutral/Annotation.mjs +30 -8
  2. package/dist/lib/neutral/Database.mjs +7 -3
  3. package/dist/lib/neutral/Entity.mjs +15 -11
  4. package/dist/lib/neutral/Err.mjs +7 -3
  5. package/dist/lib/neutral/Feed.mjs +15 -19
  6. package/dist/lib/neutral/Filter.mjs +13 -11
  7. package/dist/lib/neutral/Format.mjs +3 -7
  8. package/dist/lib/neutral/JsonSchema.mjs +7 -7
  9. package/dist/lib/neutral/Migration.mjs +11 -11
  10. package/dist/lib/neutral/Obj.mjs +19 -13
  11. package/dist/lib/neutral/Order.mjs +1 -1
  12. package/dist/lib/neutral/Query.mjs +17 -17
  13. package/dist/lib/neutral/QueryResult.mjs +1 -1
  14. package/dist/lib/neutral/Ref.mjs +6 -6
  15. package/dist/lib/neutral/Registry.mjs +1 -1
  16. package/dist/lib/neutral/Relation.mjs +12 -12
  17. package/dist/lib/neutral/Tag.mjs +15 -15
  18. package/dist/lib/neutral/Text.mjs +25 -0
  19. package/dist/lib/neutral/Text.mjs.map +7 -0
  20. package/dist/lib/neutral/Type.mjs +10 -10
  21. package/dist/lib/neutral/chunk-2HKGAQM4.mjs +1394 -0
  22. package/dist/lib/neutral/chunk-2HKGAQM4.mjs.map +7 -0
  23. package/dist/lib/neutral/{chunk-O6BH7EPN.mjs → chunk-2ZHECXUR.mjs} +5 -4
  24. package/dist/lib/neutral/chunk-2ZHECXUR.mjs.map +7 -0
  25. package/dist/lib/neutral/{chunk-QQIYS74I.mjs → chunk-3KTE2Y7Q.mjs} +20 -20
  26. package/dist/lib/neutral/chunk-3KTE2Y7Q.mjs.map +7 -0
  27. package/dist/lib/neutral/{chunk-R5W6DXR4.mjs → chunk-3TN2VMI4.mjs} +72 -36
  28. package/dist/lib/neutral/chunk-3TN2VMI4.mjs.map +7 -0
  29. package/dist/lib/neutral/{chunk-5SMDBFVB.mjs → chunk-42L4HJ3Z.mjs} +11 -15
  30. package/dist/lib/neutral/chunk-42L4HJ3Z.mjs.map +7 -0
  31. package/dist/lib/neutral/{chunk-7PI7C4EF.mjs → chunk-4A2NWKRJ.mjs} +5 -5
  32. package/dist/lib/neutral/chunk-ACFAOTKJ.mjs +1531 -0
  33. package/dist/lib/neutral/chunk-ACFAOTKJ.mjs.map +7 -0
  34. package/dist/lib/neutral/{chunk-SBVFRTST.mjs → chunk-BEFR7LEA.mjs} +20 -10
  35. package/dist/lib/neutral/chunk-BEFR7LEA.mjs.map +7 -0
  36. package/dist/lib/neutral/{chunk-6M2Z6WBH.mjs → chunk-BXIKXT7Q.mjs} +2 -6
  37. package/dist/lib/neutral/{chunk-6M2Z6WBH.mjs.map → chunk-BXIKXT7Q.mjs.map} +1 -1
  38. package/dist/lib/neutral/{chunk-UUP46KUQ.mjs → chunk-C57XMMBY.mjs} +21 -20
  39. package/dist/lib/neutral/chunk-C57XMMBY.mjs.map +7 -0
  40. package/dist/lib/neutral/chunk-C62JYFAD.mjs +183 -0
  41. package/dist/lib/neutral/chunk-C62JYFAD.mjs.map +7 -0
  42. package/dist/lib/neutral/{chunk-MZ7K3MLL.mjs → chunk-FSGX2R62.mjs} +3 -3
  43. package/dist/lib/neutral/chunk-FSGX2R62.mjs.map +7 -0
  44. package/dist/lib/neutral/{chunk-TYGKCRMK.mjs → chunk-HBXT3GSB.mjs} +37 -15
  45. package/dist/lib/neutral/chunk-HBXT3GSB.mjs.map +7 -0
  46. package/dist/lib/neutral/{chunk-WU3GIANS.mjs → chunk-IQR45HAD.mjs} +1 -1
  47. package/dist/lib/neutral/chunk-IQR45HAD.mjs.map +7 -0
  48. package/dist/lib/neutral/{chunk-TFEWTY5A.mjs → chunk-KCBW4BR6.mjs} +4 -8
  49. package/dist/lib/neutral/chunk-KCBW4BR6.mjs.map +7 -0
  50. package/dist/lib/neutral/{chunk-WTQJHC75.mjs → chunk-L3E5IXAE.mjs} +225 -45
  51. package/dist/lib/neutral/chunk-L3E5IXAE.mjs.map +7 -0
  52. package/dist/lib/neutral/{chunk-EVK6XBXO.mjs → chunk-PRC4FEKJ.mjs} +2 -2
  53. package/dist/lib/neutral/chunk-PRC4FEKJ.mjs.map +7 -0
  54. package/dist/lib/neutral/{chunk-6YDI3J37.mjs → chunk-SCT6FFCR.mjs} +9 -4
  55. package/dist/lib/neutral/chunk-SCT6FFCR.mjs.map +7 -0
  56. package/dist/lib/neutral/{chunk-BBFJWWAV.mjs → chunk-TOCVVFK2.mjs} +26 -2
  57. package/dist/lib/neutral/chunk-TOCVVFK2.mjs.map +7 -0
  58. package/dist/lib/neutral/{chunk-RIVWNMSF.mjs → chunk-U53LSQQA.mjs} +3 -3
  59. package/dist/lib/neutral/{chunk-RIVWNMSF.mjs.map → chunk-U53LSQQA.mjs.map} +1 -1
  60. package/dist/lib/neutral/{chunk-IGK6FN65.mjs → chunk-UGFFV2FR.mjs} +2 -2
  61. package/dist/lib/neutral/{chunk-35INCYOE.mjs → chunk-UWLP4RFM.mjs} +1 -1
  62. package/dist/lib/neutral/chunk-UWLP4RFM.mjs.map +7 -0
  63. package/dist/lib/neutral/{chunk-LWXVKPPW.mjs → chunk-UZHCQ6NI.mjs} +13 -11
  64. package/dist/lib/neutral/{chunk-LWXVKPPW.mjs.map → chunk-UZHCQ6NI.mjs.map} +3 -3
  65. package/dist/lib/neutral/{chunk-5SUJPHAE.mjs → chunk-WKIT2YY5.mjs} +2 -2
  66. package/dist/lib/neutral/{chunk-T6E37YIP.mjs → chunk-XB6ISRAO.mjs} +38 -18
  67. package/dist/lib/neutral/chunk-XB6ISRAO.mjs.map +7 -0
  68. package/dist/lib/neutral/chunk-XXL42WCB.mjs +84 -0
  69. package/dist/lib/neutral/chunk-XXL42WCB.mjs.map +7 -0
  70. package/dist/lib/neutral/{chunk-ZGNNFYHS.mjs → chunk-XXWK4J53.mjs} +27 -42
  71. package/dist/lib/neutral/chunk-XXWK4J53.mjs.map +7 -0
  72. package/dist/lib/neutral/index.mjs +30 -26
  73. package/dist/lib/neutral/internal/index.mjs +111 -69
  74. package/dist/lib/neutral/meta.json +1 -1
  75. package/dist/lib/neutral/testing/index.mjs +79 -60
  76. package/dist/lib/neutral/testing/index.mjs.map +3 -3
  77. package/dist/types/src/Annotation.d.ts +35 -1
  78. package/dist/types/src/Annotation.d.ts.map +1 -1
  79. package/dist/types/src/Collection.d.ts +9 -8
  80. package/dist/types/src/Collection.d.ts.map +1 -1
  81. package/dist/types/src/Database.d.ts +38 -0
  82. package/dist/types/src/Database.d.ts.map +1 -1
  83. package/dist/types/src/Dataset.d.ts +1 -16
  84. package/dist/types/src/Dataset.d.ts.map +1 -1
  85. package/dist/types/src/Entity.d.ts +2 -0
  86. package/dist/types/src/Entity.d.ts.map +1 -1
  87. package/dist/types/src/Err.d.ts +67 -0
  88. package/dist/types/src/Err.d.ts.map +1 -1
  89. package/dist/types/src/Feed.d.ts +59 -80
  90. package/dist/types/src/Feed.d.ts.map +1 -1
  91. package/dist/types/src/Filter.d.ts +9 -1
  92. package/dist/types/src/Filter.d.ts.map +1 -1
  93. package/dist/types/src/Hypergraph.d.ts +2 -9
  94. package/dist/types/src/Hypergraph.d.ts.map +1 -1
  95. package/dist/types/src/Migration.d.ts +1 -1
  96. package/dist/types/src/Migration.d.ts.map +1 -1
  97. package/dist/types/src/Obj.d.ts +33 -6
  98. package/dist/types/src/Obj.d.ts.map +1 -1
  99. package/dist/types/src/Order.d.ts +1 -1
  100. package/dist/types/src/Order.d.ts.map +1 -1
  101. package/dist/types/src/Query.d.ts +1 -1
  102. package/dist/types/src/Query.d.ts.map +1 -1
  103. package/dist/types/src/QueryResult.d.ts +2 -2
  104. package/dist/types/src/QueryResult.d.ts.map +1 -1
  105. package/dist/types/src/Ref.d.ts +10 -6
  106. package/dist/types/src/Ref.d.ts.map +1 -1
  107. package/dist/types/src/Registry.d.ts +1 -1
  108. package/dist/types/src/Relation.d.ts.map +1 -1
  109. package/dist/types/src/Tag.d.ts +11 -13
  110. package/dist/types/src/Tag.d.ts.map +1 -1
  111. package/dist/types/src/Text.d.ts +41 -0
  112. package/dist/types/src/Text.d.ts.map +1 -0
  113. package/dist/types/src/Text.test.d.ts +2 -0
  114. package/dist/types/src/Text.test.d.ts.map +1 -0
  115. package/dist/types/src/Type.d.ts +38 -21
  116. package/dist/types/src/Type.d.ts.map +1 -1
  117. package/dist/types/src/View.d.ts +8 -9
  118. package/dist/types/src/View.d.ts.map +1 -1
  119. package/dist/types/src/index.d.ts +1 -0
  120. package/dist/types/src/index.d.ts.map +1 -1
  121. package/dist/types/src/internal/Annotation/annotations.d.ts +50 -0
  122. package/dist/types/src/internal/Annotation/annotations.d.ts.map +1 -1
  123. package/dist/types/src/internal/Annotation/atoms.d.ts +14 -0
  124. package/dist/types/src/internal/Annotation/atoms.d.ts.map +1 -0
  125. package/dist/types/src/internal/Annotation/entity-dictionary.d.ts +13 -0
  126. package/dist/types/src/internal/Annotation/entity-dictionary.d.ts.map +1 -1
  127. package/dist/types/src/internal/Entity/api.d.ts.map +1 -1
  128. package/dist/types/src/internal/Entity/guard.d.ts.map +1 -1
  129. package/dist/types/src/internal/Entity/model.d.ts +1 -1
  130. package/dist/types/src/internal/Entity/model.d.ts.map +1 -1
  131. package/dist/types/src/internal/Entity/object.d.ts +5 -1
  132. package/dist/types/src/internal/Entity/object.d.ts.map +1 -1
  133. package/dist/types/src/internal/Entity/relation.d.ts +7 -0
  134. package/dist/types/src/internal/Entity/relation.d.ts.map +1 -1
  135. package/dist/types/src/internal/Entity/type-uri.d.ts.map +1 -1
  136. package/dist/types/src/internal/Filter/index.d.ts +2 -0
  137. package/dist/types/src/internal/Filter/index.d.ts.map +1 -0
  138. package/dist/types/src/internal/Filter/match.d.ts +22 -0
  139. package/dist/types/src/internal/Filter/match.d.ts.map +1 -0
  140. package/dist/types/src/internal/Format/format.d.ts +0 -2
  141. package/dist/types/src/internal/Format/format.d.ts.map +1 -1
  142. package/dist/types/src/internal/Format/index.d.ts +2 -2
  143. package/dist/types/src/internal/Format/index.d.ts.map +1 -1
  144. package/dist/types/src/internal/Format/string.d.ts +0 -8
  145. package/dist/types/src/internal/Format/string.d.ts.map +1 -1
  146. package/dist/types/src/internal/Format/types.d.ts +2 -1
  147. package/dist/types/src/internal/Format/types.d.ts.map +1 -1
  148. package/dist/types/src/internal/Obj/atoms.d.ts +12 -3
  149. package/dist/types/src/internal/Obj/atoms.d.ts.map +1 -1
  150. package/dist/types/src/internal/Obj/clone.d.ts +2 -1
  151. package/dist/types/src/internal/Obj/clone.d.ts.map +1 -1
  152. package/dist/types/src/internal/Obj/create-object.d.ts +3 -4
  153. package/dist/types/src/internal/Obj/create-object.d.ts.map +1 -1
  154. package/dist/types/src/internal/Obj/json-serializer.d.ts.map +1 -1
  155. package/dist/types/src/internal/Query/index.d.ts +1 -0
  156. package/dist/types/src/internal/Query/index.d.ts.map +1 -1
  157. package/dist/types/src/internal/Query/query-result-effect.d.ts +9 -0
  158. package/dist/types/src/internal/Query/query-result-effect.d.ts.map +1 -0
  159. package/dist/types/src/internal/Ref/atoms.d.ts +1 -2
  160. package/dist/types/src/internal/Ref/atoms.d.ts.map +1 -1
  161. package/dist/types/src/internal/Ref/index.d.ts +1 -0
  162. package/dist/types/src/internal/Ref/index.d.ts.map +1 -1
  163. package/dist/types/src/internal/Ref/ref.d.ts +79 -8
  164. package/dist/types/src/internal/Ref/ref.d.ts.map +1 -1
  165. package/dist/types/src/internal/Ref/strong-deps.d.ts +35 -0
  166. package/dist/types/src/internal/Ref/strong-deps.d.ts.map +1 -0
  167. package/dist/types/src/internal/common/atom-snapshot.d.ts +8 -0
  168. package/dist/types/src/internal/common/atom-snapshot.d.ts.map +1 -0
  169. package/dist/types/src/internal/common/proxy/make-object.d.ts.map +1 -1
  170. package/dist/types/src/internal/common/proxy/proxy-types.d.ts +12 -0
  171. package/dist/types/src/internal/common/proxy/proxy-types.d.ts.map +1 -1
  172. package/dist/types/src/internal/common/proxy/proxy-utils.d.ts +25 -0
  173. package/dist/types/src/internal/common/proxy/proxy-utils.d.ts.map +1 -1
  174. package/dist/types/src/internal/common/proxy/schema-validator.d.ts +5 -0
  175. package/dist/types/src/internal/common/proxy/schema-validator.d.ts.map +1 -1
  176. package/dist/types/src/internal/common/proxy/typed-handler.d.ts +17 -0
  177. package/dist/types/src/internal/common/proxy/typed-handler.d.ts.map +1 -1
  178. package/dist/types/src/internal/common/types/entity.d.ts +4 -4
  179. package/dist/types/src/internal/common/types/entity.d.ts.map +1 -1
  180. package/dist/types/src/internal/common/types/meta.d.ts +2 -4
  181. package/dist/types/src/internal/common/types/meta.d.ts.map +1 -1
  182. package/dist/types/src/internal/index.d.ts +1 -0
  183. package/dist/types/src/internal/index.d.ts.map +1 -1
  184. package/dist/types/src/testing/test-schema.d.ts +42 -171
  185. package/dist/types/src/testing/test-schema.d.ts.map +1 -1
  186. package/dist/types/tsconfig.tsbuildinfo +1 -1
  187. package/package.json +20 -13
  188. package/src/Annotation.test.ts +257 -10
  189. package/src/Annotation.ts +58 -4
  190. package/src/Collection.ts +10 -12
  191. package/src/Database.ts +55 -21
  192. package/src/Entity.ts +3 -1
  193. package/src/Err.ts +22 -0
  194. package/src/Feed.ts +117 -141
  195. package/src/Filter.test.ts +38 -0
  196. package/src/Filter.ts +17 -3
  197. package/src/Hypergraph.ts +2 -11
  198. package/src/Migration.ts +1 -1
  199. package/src/Obj.test.ts +92 -12
  200. package/src/Obj.ts +38 -5
  201. package/src/Order.ts +3 -3
  202. package/src/Query.test.ts +2 -2
  203. package/src/Query.ts +16 -16
  204. package/src/QueryResult.ts +2 -2
  205. package/src/Ref.ts +14 -6
  206. package/src/Registry.ts +1 -1
  207. package/src/Relation.ts +1 -1
  208. package/src/Tag.ts +13 -16
  209. package/src/Text.test.ts +186 -0
  210. package/src/Text.ts +116 -0
  211. package/src/Type.test.ts +52 -24
  212. package/src/Type.ts +85 -33
  213. package/src/View.ts +22 -30
  214. package/src/index.ts +1 -1
  215. package/src/internal/Annotation/annotations.ts +71 -2
  216. package/src/internal/Annotation/atoms.ts +107 -0
  217. package/src/internal/Annotation/entity-dictionary.ts +40 -37
  218. package/src/internal/Entity/api.ts +1 -1
  219. package/src/internal/Entity/guard.ts +2 -1
  220. package/src/internal/Entity/model.ts +2 -2
  221. package/src/internal/Entity/object.ts +14 -1
  222. package/src/internal/Entity/relation.ts +19 -0
  223. package/src/internal/Entity/type-uri.ts +3 -1
  224. package/src/internal/Filter/index.ts +5 -0
  225. package/src/internal/Filter/match.ts +284 -0
  226. package/src/internal/Format/format.ts +0 -2
  227. package/src/internal/Format/index.ts +2 -2
  228. package/src/internal/Format/string.ts +0 -12
  229. package/src/internal/Format/types.ts +4 -2
  230. package/src/internal/JsonSchema/json-schema.test.ts +82 -54
  231. package/src/internal/Obj/atoms.ts +62 -18
  232. package/src/internal/Obj/clone.ts +61 -20
  233. package/src/internal/Obj/create-object.test.ts +3 -3
  234. package/src/internal/Obj/create-object.ts +3 -4
  235. package/src/internal/Obj/inspect.ts +1 -1
  236. package/src/internal/Obj/json-serializer.test.ts +7 -5
  237. package/src/internal/Obj/json-serializer.ts +4 -4
  238. package/src/internal/Obj/schema-validator.test.ts +53 -0
  239. package/src/internal/Obj/set-value.test.ts +29 -19
  240. package/src/internal/Query/index.ts +1 -0
  241. package/src/internal/Query/query-result-effect.ts +35 -0
  242. package/src/internal/Ref/atoms.ts +23 -3
  243. package/src/internal/Ref/index.ts +1 -0
  244. package/src/internal/Ref/ref.test.ts +8 -8
  245. package/src/internal/Ref/ref.ts +122 -39
  246. package/src/internal/Ref/strong-deps.ts +107 -0
  247. package/src/internal/common/atom-snapshot.ts +19 -0
  248. package/src/internal/common/proxy/make-object.ts +1 -1
  249. package/src/internal/common/proxy/proxy-types.ts +20 -0
  250. package/src/internal/common/proxy/proxy-utils.ts +37 -1
  251. package/src/internal/common/proxy/reactive-array.ts +3 -3
  252. package/src/internal/common/proxy/reactive.test.ts +1 -1
  253. package/src/internal/common/proxy/schema-validator.ts +181 -8
  254. package/src/internal/common/proxy/typed-handler.ts +254 -76
  255. package/src/internal/common/types/entity.ts +15 -7
  256. package/src/internal/index.ts +1 -0
  257. package/src/testing/test-schema.ts +75 -90
  258. package/dist/lib/neutral/chunk-35INCYOE.mjs.map +0 -7
  259. package/dist/lib/neutral/chunk-3PBP4V4O.mjs +0 -101
  260. package/dist/lib/neutral/chunk-3PBP4V4O.mjs.map +0 -7
  261. package/dist/lib/neutral/chunk-4ZUHOTCG.mjs +0 -184
  262. package/dist/lib/neutral/chunk-4ZUHOTCG.mjs.map +0 -7
  263. package/dist/lib/neutral/chunk-5SMDBFVB.mjs.map +0 -7
  264. package/dist/lib/neutral/chunk-6YDI3J37.mjs.map +0 -7
  265. package/dist/lib/neutral/chunk-7FPIAJIV.mjs +0 -2279
  266. package/dist/lib/neutral/chunk-7FPIAJIV.mjs.map +0 -7
  267. package/dist/lib/neutral/chunk-BBFJWWAV.mjs.map +0 -7
  268. package/dist/lib/neutral/chunk-EVK6XBXO.mjs.map +0 -7
  269. package/dist/lib/neutral/chunk-MZ7K3MLL.mjs.map +0 -7
  270. package/dist/lib/neutral/chunk-O6BH7EPN.mjs.map +0 -7
  271. package/dist/lib/neutral/chunk-QQIYS74I.mjs.map +0 -7
  272. package/dist/lib/neutral/chunk-R5W6DXR4.mjs.map +0 -7
  273. package/dist/lib/neutral/chunk-SBVFRTST.mjs.map +0 -7
  274. package/dist/lib/neutral/chunk-T6E37YIP.mjs.map +0 -7
  275. package/dist/lib/neutral/chunk-TFEWTY5A.mjs.map +0 -7
  276. package/dist/lib/neutral/chunk-TYGKCRMK.mjs.map +0 -7
  277. package/dist/lib/neutral/chunk-UUP46KUQ.mjs.map +0 -7
  278. package/dist/lib/neutral/chunk-WTQJHC75.mjs.map +0 -7
  279. package/dist/lib/neutral/chunk-WU3GIANS.mjs.map +0 -7
  280. package/dist/lib/neutral/chunk-ZGNNFYHS.mjs.map +0 -7
  281. package/dist/types/src/exemplars.test.d.ts +0 -2
  282. package/dist/types/src/exemplars.test.d.ts.map +0 -1
  283. package/dist/types/src/hierarchy.test.d.ts +0 -2
  284. package/dist/types/src/hierarchy.test.d.ts.map +0 -1
  285. package/src/exemplars.test.ts +0 -21
  286. package/src/hierarchy.test.ts +0 -33
  287. /package/dist/lib/neutral/{chunk-7PI7C4EF.mjs.map → chunk-4A2NWKRJ.mjs.map} +0 -0
  288. /package/dist/lib/neutral/{chunk-IGK6FN65.mjs.map → chunk-UGFFV2FR.mjs.map} +0 -0
  289. /package/dist/lib/neutral/{chunk-5SUJPHAE.mjs.map → chunk-WKIT2YY5.mjs.map} +0 -0
package/src/index.ts CHANGED
@@ -8,7 +8,6 @@ export { DXN, EID, URI } from '@dxos/keys';
8
8
  export * as Annotation from './Annotation';
9
9
  export * as Database from './Database';
10
10
  export * as Entity from './Entity';
11
- // TODO(burdon): Rename to Error (less problematic than Obj/Object).
12
11
  export * as Err from './Err';
13
12
  export * as Feed from './Feed';
14
13
  export * as Filter from './Filter';
@@ -27,6 +26,7 @@ export * as Registry from './Registry';
27
26
  export * as Relation from './Relation';
28
27
  export * as Scope from './Scope';
29
28
  export * as Tag from './Tag';
29
+ export * as Text from './Text';
30
30
  export * as Type from './Type';
31
31
  export * as Collection from './Collection';
32
32
  export * as View from './View';
@@ -395,8 +395,11 @@ export const setDescriptionWithSchema = <S extends Schema.Schema.Any>(
395
395
  object: Schema.Schema.Type<S>,
396
396
  description: string,
397
397
  ) => {
398
- const accessor = DescriptionAnnotation.get(schema).pipe(Option.getOrElse(() => 'description'));
399
- object[accessor] = description;
398
+ const accessorOpt = DescriptionAnnotation.get(schema);
399
+ if (Option.isNone(accessorOpt)) {
400
+ return;
401
+ }
402
+ object[accessorOpt.value] = description;
400
403
  };
401
404
 
402
405
  /**
@@ -413,6 +416,57 @@ export const FormInputAnnotation = createAnnotationHelper<boolean>(FormInputAnno
413
416
  export const FormInlineAnnotationId = Symbol.for('@dxos/schema/annotation/FormInline');
414
417
  export const FormInlineAnnotation = createAnnotationHelper<boolean>(FormInlineAnnotationId);
415
418
 
419
+ /**
420
+ * When set on a `Ref` (or array-of-`Ref`) property, the form OWNS the referenced target(s): "add" creates a
421
+ * new object of the annotation's typename (instead of opening the existing-object picker) and each target is
422
+ * rendered inline — its own fields — like {@link FormInlineAnnotation}. The target typename is carried here
423
+ * (rather than inferred from the element type) so the field can stay `Ref.Ref(Obj.Unknown)` and avoid pulling
424
+ * the target's type (e.g. query-AST-laden `Trigger`) into the schema's emitted declaration.
425
+ */
426
+ export const FormCreateAnnotationId = Symbol.for('@dxos/schema/annotation/FormCreate');
427
+ export const FormCreateAnnotation = createAnnotationHelper<string>(FormCreateAnnotationId);
428
+
429
+ /**
430
+ * When set on an array property, the form renders it as an ordered,
431
+ * drag-to-reorder list (drag handles per row). Element order is meaningful and
432
+ * user-controllable; reordering rewrites the array.
433
+ */
434
+ export const FormOrderedAnnotationId = Symbol.for('@dxos/schema/annotation/FormOrdered');
435
+ export const FormOrderedAnnotation = createAnnotationHelper<boolean>(FormOrderedAnnotationId);
436
+
437
+ /**
438
+ * Annotation carrying one or more named layout DSL templates that control how a
439
+ * form arranges a schema's fields (consumed by `@dxos/react-ui-form`'s
440
+ * `Form.Layout` / `Form.FieldSet`). Callers select a variant by name; the
441
+ * implicit name is `DEFAULT_LAYOUT_NAME` (`'default'`).
442
+ *
443
+ * Templates use a minimal XML grammar. Example:
444
+ *
445
+ * FormLayoutAnnotation.set({
446
+ * default: `
447
+ * <grid cols="2">
448
+ * <field name="origin"/>
449
+ * <field name="destination"/>
450
+ * <field name="provider" span="2"/>
451
+ * </grid>
452
+ * `,
453
+ * card: `
454
+ * <grid cols="1">
455
+ * <field name="provider"/>
456
+ * <field name="number"/>
457
+ * </grid>
458
+ * `,
459
+ * })
460
+ */
461
+ export const FormLayoutAnnotationId = Symbol.for('@dxos/react-ui-form/annotation/Layout');
462
+
463
+ export type FormLayoutMap = Record<string, string>;
464
+
465
+ export const FormLayoutAnnotation = createAnnotationHelper<FormLayoutMap>(FormLayoutAnnotationId);
466
+
467
+ /** Name used when no explicit form-layout variant is requested. */
468
+ export const DEFAULT_LAYOUT_NAME = 'default';
469
+
416
470
  /**
417
471
  * Default field to be used on referenced schema to lookup the value.
418
472
  */
@@ -557,6 +611,21 @@ export const setLabel = (entity: Mutable<AnyProperties>, label: string) => {
557
611
  }
558
612
  };
559
613
 
614
+ /**
615
+ * Returns the primary label property key for an entity.
616
+ * Reads the first accessor from {@link LabelAnnotation}, defaulting to 'name'.
617
+ */
618
+ export const getLabelProperty = (entity: AnyProperties): string => {
619
+ const schema = getSchema(entity);
620
+ if (schema == null) {
621
+ return 'name';
622
+ }
623
+ return LabelAnnotation.get(schema).pipe(
624
+ Option.flatMap((fields) => Option.fromNullable(fields[0])),
625
+ Option.getOrElse(() => 'name'),
626
+ );
627
+ };
628
+
560
629
  /**
561
630
  * Get the description of an entity.
562
631
  * Accepts both reactive entities and snapshots.
@@ -0,0 +1,107 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import * as Atom from '@effect-atom/atom/Atom';
6
+ import * as Data from 'effect/Data';
7
+ import * as Option from 'effect/Option';
8
+
9
+ import { assertArgument } from '@dxos/invariant';
10
+
11
+ import type * as Annotation from '../../Annotation';
12
+ import type * as Entity from '../../Entity';
13
+ import { snapshotForComparison } from '../common/atom-snapshot';
14
+ import { subscribe } from '../common/proxy/reactive';
15
+ import { isEntity } from '../Entity';
16
+ import { get as getAnnotation } from './entity-dictionary';
17
+
18
+ /**
19
+ * Atom family for an annotation value on an entity instance.
20
+ * Mirrors the object-property atom family: re-emits a fresh reference whenever the entity changes
21
+ * (so an in-place array mutation is observed) and dedupes primitive values via `!==`.
22
+ */
23
+ const annotationFamily = Atom.family((target: Entity.Unknown) =>
24
+ Atom.family(<T>(annotation: Annotation.Annotation<T>): Atom.Atom<Option.Option<T>> => {
25
+ const read = (): Option.Option<T> => Option.map(getAnnotation(target, annotation), snapshotForComparison);
26
+
27
+ return Atom.make<Option.Option<T>>((get) => {
28
+ let previous = read();
29
+
30
+ const unsubscribe = subscribe(target, () => {
31
+ const next = read();
32
+ if (!sameOption(previous, next)) {
33
+ previous = next;
34
+ get.setSelf(next);
35
+ }
36
+ });
37
+ get.addFinalizer(() => unsubscribe());
38
+
39
+ return previous;
40
+ }).pipe(Atom.keepAlive);
41
+ }),
42
+ );
43
+
44
+ /**
45
+ * Atom family for a single key of a record-valued annotation on an entity instance.
46
+ * Keyed by a value-equal `Data.tuple([target, annotation, key])` so nested families are avoided.
47
+ */
48
+ const annotationPropertyFamily = Atom.family(
49
+ ([target, annotation, key]: readonly [
50
+ Entity.Unknown,
51
+ Annotation.Annotation<Record<string, any>>,
52
+ string,
53
+ ]): Atom.Atom<any> => {
54
+ const read = (): unknown =>
55
+ getAnnotation(target, annotation).pipe(
56
+ Option.map((value) => snapshotForComparison(value[key])),
57
+ Option.getOrUndefined,
58
+ );
59
+
60
+ return Atom.make<unknown>((get) => {
61
+ let previous = read();
62
+
63
+ const unsubscribe = subscribe(target, () => {
64
+ const next = read();
65
+ if (next !== previous) {
66
+ previous = next;
67
+ get.setSelf(next);
68
+ }
69
+ });
70
+ get.addFinalizer(() => unsubscribe());
71
+
72
+ return previous;
73
+ }).pipe(Atom.keepAlive);
74
+ },
75
+ );
76
+
77
+ /** Equal when both empty, or both present with the same (snapshotted) value. */
78
+ const sameOption = <T>(a: Option.Option<T>, b: Option.Option<T>): boolean =>
79
+ Option.isNone(a) || Option.isNone(b) ? Option.isNone(a) && Option.isNone(b) : a.value === b.value;
80
+
81
+ /**
82
+ * Reactive atom for an annotation value on an entity instance. Emits a shallow snapshot (a fresh
83
+ * reference for objects/arrays) so dependent atoms recompute on change. Mirrors {@link makeProperty}.
84
+ */
85
+ export const makeAtom = <T>(
86
+ target: Entity.Unknown,
87
+ annotation: Annotation.Annotation<T>,
88
+ ): Atom.Atom<Option.Option<T>> => {
89
+ assertArgument(isEntity(target), 'target', 'Must be a reactive ECHO entity');
90
+ return annotationFamily(target)(annotation);
91
+ };
92
+
93
+ /**
94
+ * Reactive atom for a single key of a record-valued annotation on an entity instance.
95
+ */
96
+ export const makeProperty = <V>(
97
+ target: Entity.Unknown,
98
+ annotation: Annotation.Annotation<Record<string, V>>,
99
+ key: string,
100
+ ): Atom.Atom<V | undefined> => {
101
+ assertArgument(isEntity(target), 'target', 'Must be a reactive ECHO entity');
102
+ // The flattened family key is a single concrete tuple type, so the generic `V` is erased at the
103
+ // family boundary and recovered here; no typed alternative exists for a per-call-generic family.
104
+ return annotationPropertyFamily(
105
+ Data.tuple(target, annotation as Annotation.Annotation<Record<string, any>>, key),
106
+ ) as Atom.Atom<V | undefined>;
107
+ };
@@ -3,72 +3,75 @@
3
3
  //
4
4
 
5
5
  import * as Option from 'effect/Option';
6
-
7
- import { deepMapValues } from '@dxos/util';
6
+ import * as Schema from 'effect/Schema';
8
7
 
9
8
  import type * as Annotation from '../../Annotation';
10
9
  import type * as Entity from '../../Entity';
11
10
  import { getMetaChecked } from '../common/api/meta';
12
- import { type Mutable } from '../common/proxy/reactive';
13
- import { getDatabase } from '../Entity/api';
11
+ import { type Mutable, change } from '../common/proxy/reactive';
14
12
  import { isEntity, isSnapshot } from '../Entity/guard';
15
- import { Ref, getRefSavedTarget } from '../Ref';
16
- import { getDictionary, setDictionary } from './dictionary';
13
+ import { getDictionary } from './dictionary';
17
14
 
18
15
  /**
19
16
  * Get the value of an annotation from an entity instance or snapshot.
17
+ *
18
+ * The value is read-only (schema types are readonly by default). To mutate it, use {@link update}
19
+ * (which reads it as mutable inside a change transaction); the reactive proxy rejects mutation of the
20
+ * live value outside an `Obj.update`. Snapshots return a decoded detached copy.
20
21
  */
21
22
  export const get = <T>(
22
23
  target: Entity.Unknown | Entity.Snapshot,
23
24
  annotation: Annotation.Annotation<T>,
24
25
  ): Option.Option<T> => {
25
- if (isEntity(target) || isSnapshot(target)) {
26
- const meta = getMetaChecked(target);
27
- return getDictionary(meta.annotations, annotation);
28
- } else {
29
- throw new TypeError('Target is not an annotation target.');
26
+ if (isSnapshot(target)) {
27
+ return getDictionary(getMetaChecked(target).annotations, annotation);
28
+ }
29
+ if (isEntity(target)) {
30
+ const annotations = getMetaChecked(target).annotations;
31
+ // The dictionary slot is typed `unknown`; at runtime it holds the annotation's live value
32
+ // (the proxy codecs nested refs in both directions), so the read coerces to the declared type.
33
+ return annotation.key in annotations ? Option.some(annotations[annotation.key] as T) : Option.none();
30
34
  }
35
+ throw new TypeError('Target is not an annotation target.');
31
36
  };
32
37
 
33
38
  /**
34
39
  * Set the value of an annotation on an entity instance.
35
40
  * Must be called with a mutable entity — i.e. inside an `Obj.update` callback.
41
+ *
42
+ * The value is assigned directly to the reactive meta dictionary; the proxy encodes nested Refs and
43
+ * links their unsaved targets on write (matching ordinary property assignment), so no manual
44
+ * encode/persist step is needed.
36
45
  */
37
46
  export const set = <T>(target: Mutable<Entity.Unknown>, annotation: Annotation.Annotation<T>, value: T): void => {
38
47
  if (isEntity(target)) {
39
- const meta = getMetaChecked(target);
40
- // Persist any unsaved Ref targets in the value into the entity's database so
41
- // the encoded DXN resolves on read. This mirrors normal property assignment,
42
- // where the reactive proxy links unsaved ref targets via `createRef` →
43
- // `database.add`. `setDictionary` pre-encodes the value (`Schema.encodeSync`),
44
- // so the live Ref never reaches the proxy's link handling and would otherwise
45
- // be stored as a dangling reference.
46
- persistRefTargets(target, value);
47
- setDictionary(meta.annotations, annotation, value);
48
+ // The dictionary slot is untyped, so the proxy can't validate against the annotation schema;
49
+ // validate here (without encoding the proxy encodes nested refs and links targets on assignment).
50
+ Schema.validateSync(annotation.schema)(value);
51
+ getMetaChecked(target).annotations[annotation.key] = value;
48
52
  } else {
49
53
  throw new TypeError('Target is not an annotation target.');
50
54
  }
51
55
  };
52
56
 
53
57
  /**
54
- * Add any unsaved Ref targets found in `value` to the host entity's database, matching the
55
- * auto-persistence applied to refs assigned to ordinary entity properties. Refs whose target
56
- * already lives in a database (the host's or a foreign one) are left untouched.
58
+ * Mutate an existing annotation value in place via a callback, wrapping the mutation in a change
59
+ * transaction (like `Obj.update`). Use when only an annotation needs to change. No-op when absent.
57
60
  */
58
- const persistRefTargets = (host: Entity.Unknown, value: unknown): void => {
59
- const database = getDatabase(host);
60
- if (database == null) {
61
- return;
62
- }
63
-
64
- deepMapValues(value, (current, recurse) => {
65
- if (Ref.isRef(current)) {
66
- const refTarget = getRefSavedTarget(current);
67
- if (refTarget != null && isEntity(refTarget) && getDatabase(refTarget) == null) {
68
- database.add(refTarget);
69
- }
70
- return current;
61
+ export const update = <T>(
62
+ target: Entity.Unknown,
63
+ annotation: Annotation.Annotation<T>,
64
+ mutator: (value: Mutable<T>) => void,
65
+ ): void => {
66
+ change(target, (mutable) => {
67
+ const current = get(mutable, annotation);
68
+ if (Option.isSome(current)) {
69
+ // `get` returns the value read-only; inside this change transaction the live value is mutable.
70
+ const value = current.value as Mutable<T>;
71
+ mutator(value);
72
+ // Validate against the annotation's own schema — the dictionary slot is untyped, so the proxy
73
+ // can't. Schema validation checks ref structure only (not targets), so it is cycle-safe.
74
+ Schema.validateSync(annotation.schema)(value);
71
75
  }
72
- return recurse(current);
73
76
  });
74
77
  };
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  import { invariant } from '@dxos/invariant';
6
- import { DXN, EID, URI, type SpaceId } from '@dxos/keys';
6
+ import { DXN, EID, type SpaceId, URI } from '@dxos/keys';
7
7
  import { assumeType } from '@dxos/util';
8
8
 
9
9
  import type { AnyEntity } from '../common/types';
@@ -9,7 +9,8 @@ import { KindId, SnapshotKindId } from '../common/types';
9
9
  * Returns true if the value is an ECHO entity instance (object or relation).
10
10
  */
11
11
  export const isEntity = (value: unknown): value is Entity.Unknown => {
12
- if (typeof value !== 'object' || value === null) {
12
+ // (some) type entities are functions since they are class declarations.
13
+ if (value == null || (typeof value !== 'object' && typeof value !== 'function')) {
13
14
  return false;
14
15
  }
15
16
  return (value as any)[KindId] !== undefined;
@@ -11,13 +11,13 @@ import { assumeType } from '@dxos/util';
11
11
 
12
12
  import type * as Database from '../../Database';
13
13
  import {
14
- type ATTR_PARENT,
15
- type ATTR_TYPE,
16
14
  ATTR_DELETED,
15
+ type ATTR_PARENT,
17
16
  ATTR_RELATION_SOURCE,
18
17
  ATTR_RELATION_TARGET,
19
18
  ATTR_SELF_URI,
20
19
  ATTR_SELF_URI_LEGACY,
20
+ type ATTR_TYPE,
21
21
  EntityKind,
22
22
  KindId,
23
23
  ObjectDatabaseId,
@@ -6,8 +6,9 @@ import * as Schema from 'effect/Schema';
6
6
  import * as SchemaAST from 'effect/SchemaAST';
7
7
 
8
8
  import { invariant } from '@dxos/invariant';
9
- import { DXN } from '@dxos/keys';
9
+ import { DXN, type EntityId } from '@dxos/keys';
10
10
 
11
+ import type * as Type from '../../Type';
11
12
  import { type TypeAnnotation, TypeAnnotationId } from '../Annotation/annotations';
12
13
  import { makeTypeJsonSchemaAnnotation } from '../Annotation/util';
13
14
  import { EntityKind } from '../common/types';
@@ -71,3 +72,15 @@ export const EchoObjectSchema: {
71
72
  );
72
73
  };
73
74
  };
75
+
76
+ export const makeObjectType = <Self, _Schema extends Schema.Schema.Any>(
77
+ dxn: DXN.DXN,
78
+ schema: _Schema,
79
+ options?: { id?: EntityId },
80
+ ): Type.ObjClass<Self, Schema.Schema.Type<_Schema>, {}> => {
81
+ const type = EchoObjectSchema(dxn, options)(schema);
82
+ const constructor = function ObjectType() {};
83
+ Object.setPrototypeOf(constructor, type);
84
+ // Boundary cast: constructor/prototype wiring cannot be expressed in TypeScript's type system.
85
+ return constructor as unknown as Type.ObjClass<Self, Schema.Schema.Type<_Schema>, {}>;
86
+ };
@@ -186,3 +186,22 @@ export const getDXNForRelationSchemaRef = (schema: Schema.Schema.Any): DXN.DXN =
186
186
 
187
187
  return DXN.make(typename);
188
188
  };
189
+
190
+ export const makeRelationType = (options: {
191
+ dxn: DXN.DXN;
192
+ source: RelationEndpoint;
193
+ target: RelationEndpoint;
194
+ schema: Schema.Schema.Any;
195
+ id?: EntityId;
196
+ }): Type.RelationClass<unknown, unknown, unknown, unknown, {}> => {
197
+ const type = EchoRelationSchema({
198
+ dxn: options.dxn,
199
+ source: options.source,
200
+ target: options.target,
201
+ id: options.id,
202
+ })(options.schema);
203
+ const constructor = function RelationType() {};
204
+ Object.setPrototypeOf(constructor, type);
205
+ // Boundary cast: constructor/prototype wiring cannot be expressed in TypeScript's type system.
206
+ return constructor as unknown as Type.RelationClass<unknown, unknown, unknown, unknown, {}>;
207
+ };
@@ -23,7 +23,9 @@ export const getTypeURIFromSpecifier = (input: Schema.Schema.All | AnyEntity | U
23
23
  if (Schema.isSchema(input)) {
24
24
  return getSchemaURI(input) ?? raise(new TypeError('Schema has no URI'));
25
25
  }
26
- if (typeof input === 'object' && input !== null && KindId in input) {
26
+ // Type entities are normally proxy objects, but class-declared types from
27
+ // `Type.makeObject` are functions whose prototype chain reaches the entity, so accept functions too.
28
+ if (input !== null && (typeof input === 'object' || typeof input === 'function') && KindId in input) {
27
29
  // `Type.Type` entity. Both in-memory and persisted forms expose the schema
28
30
  // they declare via `StaticTypeSchemaSlot`, whose URI is exactly what
29
31
  // `Obj.make` stamps on `system.type` — a static declaration carries
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ export * from './match';