@dxos/echo 0.8.4-main.d05673bc65 → 0.8.4-main.e00bdcdb52

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 (271) hide show
  1. package/dist/lib/neutral/Annotation.mjs +3 -3
  2. package/dist/lib/neutral/Database.mjs +8 -4
  3. package/dist/lib/neutral/Entity.mjs +16 -14
  4. package/dist/lib/neutral/Err.mjs +1 -1
  5. package/dist/lib/neutral/Extension.mjs +18 -0
  6. package/dist/lib/neutral/Extension.mjs.map +7 -0
  7. package/dist/lib/neutral/Feed.mjs +21 -17
  8. package/dist/lib/neutral/Filter.mjs +21 -13
  9. package/dist/lib/neutral/Format.mjs +3 -3
  10. package/dist/lib/neutral/JsonSchema.mjs +8 -8
  11. package/dist/lib/neutral/Key.mjs +1 -1
  12. package/dist/lib/neutral/Migration.mjs +17 -0
  13. package/dist/lib/neutral/Migration.mjs.map +7 -0
  14. package/dist/lib/neutral/Obj.mjs +16 -13
  15. package/dist/lib/neutral/Order.mjs +1 -1
  16. package/dist/lib/neutral/Query.mjs +19 -16
  17. package/dist/lib/neutral/QueryResult.mjs +1 -1
  18. package/dist/lib/neutral/Ref.mjs +7 -7
  19. package/dist/lib/neutral/Relation.mjs +15 -14
  20. package/dist/lib/neutral/SchemaRegistry.mjs +1 -1
  21. package/dist/lib/neutral/Tag.mjs +14 -13
  22. package/dist/lib/neutral/Type.mjs +10 -10
  23. package/dist/lib/neutral/{chunk-VA2F47ZC.mjs → chunk-2T22UGGN.mjs} +68 -14
  24. package/dist/lib/neutral/chunk-2T22UGGN.mjs.map +7 -0
  25. package/dist/lib/neutral/{chunk-FZO7LQO7.mjs → chunk-44HT3MEC.mjs} +2 -2
  26. package/dist/lib/neutral/{chunk-UFDK26FO.mjs → chunk-6VC3FI5E.mjs} +12 -8
  27. package/dist/lib/neutral/chunk-6VC3FI5E.mjs.map +7 -0
  28. package/dist/lib/neutral/{chunk-DYDJBZEG.mjs → chunk-7JFW72MX.mjs} +51 -21
  29. package/dist/lib/neutral/chunk-7JFW72MX.mjs.map +7 -0
  30. package/dist/lib/neutral/{chunk-ANHVGJI4.mjs → chunk-7RVZT53K.mjs} +1 -1
  31. package/dist/lib/neutral/{chunk-BNCCGLJN.mjs → chunk-BICZKPQG.mjs} +1 -1
  32. package/dist/lib/neutral/chunk-CIWZ5MHQ.mjs +36 -0
  33. package/dist/lib/neutral/chunk-CIWZ5MHQ.mjs.map +7 -0
  34. package/dist/lib/neutral/{chunk-724GQYEN.mjs → chunk-DUNXPKAC.mjs} +4 -4
  35. package/dist/lib/neutral/{chunk-YWXWXIE5.mjs → chunk-FAW7PJRO.mjs} +2 -2
  36. package/dist/lib/neutral/{chunk-YWXWXIE5.mjs.map → chunk-FAW7PJRO.mjs.map} +2 -2
  37. package/dist/lib/neutral/{chunk-UTBRYVQC.mjs → chunk-FAYW32CW.mjs} +2 -2
  38. package/dist/lib/neutral/chunk-GWFFC34K.mjs +50 -0
  39. package/dist/lib/neutral/chunk-GWFFC34K.mjs.map +7 -0
  40. package/dist/lib/neutral/{chunk-NXMFBIT5.mjs → chunk-I2MFJ76N.mjs} +59 -4
  41. package/dist/lib/neutral/chunk-I2MFJ76N.mjs.map +7 -0
  42. package/dist/lib/neutral/{chunk-SEMVAGBM.mjs → chunk-JALF2CVV.mjs} +13 -23
  43. package/dist/lib/neutral/chunk-JALF2CVV.mjs.map +7 -0
  44. package/dist/lib/neutral/{chunk-NEGC54NE.mjs → chunk-KQUQZ3CB.mjs} +17 -19
  45. package/dist/lib/neutral/chunk-KQUQZ3CB.mjs.map +7 -0
  46. package/dist/lib/neutral/{chunk-NQRLRYJM.mjs → chunk-LOTZLYHB.mjs} +119 -12
  47. package/dist/lib/neutral/chunk-LOTZLYHB.mjs.map +7 -0
  48. package/dist/lib/neutral/{chunk-WYOKA6AE.mjs → chunk-N4B7FHQT.mjs} +2 -2
  49. package/dist/lib/neutral/{chunk-WYOKA6AE.mjs.map → chunk-N4B7FHQT.mjs.map} +1 -1
  50. package/dist/lib/neutral/{chunk-RMLF7JOZ.mjs → chunk-NKXEKBP5.mjs} +6 -22
  51. package/dist/lib/neutral/{chunk-RMLF7JOZ.mjs.map → chunk-NKXEKBP5.mjs.map} +3 -3
  52. package/dist/lib/neutral/{chunk-CIRHIEMW.mjs → chunk-NSMLBSFS.mjs} +18 -46
  53. package/dist/lib/neutral/chunk-NSMLBSFS.mjs.map +7 -0
  54. package/dist/lib/neutral/{chunk-OENWMTE6.mjs → chunk-QBIGOSRF.mjs} +2 -2
  55. package/dist/lib/neutral/{chunk-BOZZPUXE.mjs → chunk-QBLYZ4IV.mjs} +12 -65
  56. package/dist/lib/neutral/chunk-QBLYZ4IV.mjs.map +7 -0
  57. package/dist/lib/neutral/{chunk-KTAWP7GI.mjs → chunk-QEVM3JUP.mjs} +42 -7
  58. package/dist/lib/neutral/chunk-QEVM3JUP.mjs.map +7 -0
  59. package/dist/lib/neutral/{chunk-43Y5DOS6.mjs → chunk-REP7WWAQ.mjs} +16 -66
  60. package/dist/lib/neutral/chunk-REP7WWAQ.mjs.map +7 -0
  61. package/dist/lib/neutral/{chunk-B5OXLWZL.mjs → chunk-TRPZU2HV.mjs} +2 -2
  62. package/dist/lib/neutral/{chunk-UI6MWK5W.mjs → chunk-TTCSATUD.mjs} +1 -1
  63. package/dist/lib/neutral/{chunk-FXEG7EOK.mjs → chunk-TW76K7H5.mjs} +3 -3
  64. package/dist/lib/neutral/{chunk-TQQZLKB7.mjs → chunk-UYJYDSD7.mjs} +193 -469
  65. package/dist/lib/neutral/chunk-UYJYDSD7.mjs.map +7 -0
  66. package/dist/lib/neutral/{chunk-OMUPQMLR.mjs → chunk-V72DY6LU.mjs} +1 -1
  67. package/dist/lib/neutral/{chunk-UBEZSGXY.mjs → chunk-ZISMEVKD.mjs} +1 -1
  68. package/dist/lib/neutral/{chunk-UBEZSGXY.mjs.map → chunk-ZISMEVKD.mjs.map} +2 -2
  69. package/dist/lib/neutral/index.mjs +38 -28
  70. package/dist/lib/neutral/internal/index.mjs +13 -9
  71. package/dist/lib/neutral/meta.json +1 -1
  72. package/dist/lib/neutral/testing/index.mjs +30 -28
  73. package/dist/lib/neutral/testing/index.mjs.map +2 -2
  74. package/dist/types/src/Collection.d.ts.map +1 -1
  75. package/dist/types/src/Database.d.ts +13 -1
  76. package/dist/types/src/Database.d.ts.map +1 -1
  77. package/dist/types/src/Dataset.d.ts +2 -1
  78. package/dist/types/src/Dataset.d.ts.map +1 -1
  79. package/dist/types/src/Entity.d.ts +17 -11
  80. package/dist/types/src/Entity.d.ts.map +1 -1
  81. package/dist/types/src/Err.d.ts +18 -18
  82. package/dist/types/src/Err.d.ts.map +1 -1
  83. package/dist/types/src/Extension.d.ts +80 -0
  84. package/dist/types/src/Extension.d.ts.map +1 -0
  85. package/dist/types/src/Extension.test.d.ts +2 -0
  86. package/dist/types/src/Extension.test.d.ts.map +1 -0
  87. package/dist/types/src/Feed.d.ts +37 -20
  88. package/dist/types/src/Feed.d.ts.map +1 -1
  89. package/dist/types/src/Filter.d.ts +33 -4
  90. package/dist/types/src/Filter.d.ts.map +1 -1
  91. package/dist/types/src/Filter.test.d.ts +2 -0
  92. package/dist/types/src/Filter.test.d.ts.map +1 -0
  93. package/dist/types/src/Json.d.ts +33 -0
  94. package/dist/types/src/Json.d.ts.map +1 -0
  95. package/dist/types/src/Json.test.d.ts +2 -0
  96. package/dist/types/src/Json.test.d.ts.map +1 -0
  97. package/dist/types/src/JsonSchema.d.ts +1 -1
  98. package/dist/types/src/Migration.d.ts +57 -0
  99. package/dist/types/src/Migration.d.ts.map +1 -0
  100. package/dist/types/src/Obj.d.ts +41 -27
  101. package/dist/types/src/Obj.d.ts.map +1 -1
  102. package/dist/types/src/Order.d.ts.map +1 -1
  103. package/dist/types/src/Query.d.ts +13 -2
  104. package/dist/types/src/Query.d.ts.map +1 -1
  105. package/dist/types/src/Ref.d.ts.map +1 -1
  106. package/dist/types/src/Relation.d.ts +17 -18
  107. package/dist/types/src/Relation.d.ts.map +1 -1
  108. package/dist/types/src/Tag.d.ts +2 -2
  109. package/dist/types/src/Tag.d.ts.map +1 -1
  110. package/dist/types/src/Type.d.ts +3 -3
  111. package/dist/types/src/Type.d.ts.map +1 -1
  112. package/dist/types/src/View.d.ts +1 -1
  113. package/dist/types/src/View.d.ts.map +1 -1
  114. package/dist/types/src/index.d.ts +3 -0
  115. package/dist/types/src/index.d.ts.map +1 -1
  116. package/dist/types/src/internal/Annotation/annotations.d.ts +3 -2
  117. package/dist/types/src/internal/Annotation/annotations.d.ts.map +1 -1
  118. package/dist/types/src/internal/Annotation/sorting.d.ts.map +1 -1
  119. package/dist/types/src/internal/Annotation/util.d.ts +1 -1
  120. package/dist/types/src/internal/Annotation/util.d.ts.map +1 -1
  121. package/dist/types/src/internal/Entity/api.d.ts.map +1 -1
  122. package/dist/types/src/internal/Entity/object.d.ts.map +1 -1
  123. package/dist/types/src/internal/Entity/relation.d.ts.map +1 -1
  124. package/dist/types/src/internal/Entity/version.d.ts.map +1 -1
  125. package/dist/types/src/internal/Format/date.d.ts.map +1 -1
  126. package/dist/types/src/internal/Format/format.d.ts.map +1 -1
  127. package/dist/types/src/internal/Format/number.d.ts.map +1 -1
  128. package/dist/types/src/internal/Format/object.d.ts.map +1 -1
  129. package/dist/types/src/internal/Format/types.d.ts.map +1 -1
  130. package/dist/types/src/internal/JsonSchema/json-schema-normalize.d.ts.map +1 -1
  131. package/dist/types/src/internal/JsonSchema/json-schema-type.d.ts +28 -28
  132. package/dist/types/src/internal/JsonSchema/json-schema-type.d.ts.map +1 -1
  133. package/dist/types/src/internal/JsonSchema/json-schema.d.ts +1 -1
  134. package/dist/types/src/internal/JsonSchema/json-schema.d.ts.map +1 -1
  135. package/dist/types/src/internal/Obj/clone.d.ts.map +1 -1
  136. package/dist/types/src/internal/Obj/common.d.ts.map +1 -1
  137. package/dist/types/src/internal/Obj/create-object.d.ts.map +1 -1
  138. package/dist/types/src/internal/Obj/deleted.d.ts.map +1 -1
  139. package/dist/types/src/internal/Obj/ids.d.ts.map +1 -1
  140. package/dist/types/src/internal/Obj/json-serializer.d.ts +4 -3
  141. package/dist/types/src/internal/Obj/json-serializer.d.ts.map +1 -1
  142. package/dist/types/src/internal/Obj/set-value.d.ts +1 -1
  143. package/dist/types/src/internal/Obj/set-value.d.ts.map +1 -1
  144. package/dist/types/src/internal/Obj/snapshot.d.ts.map +1 -1
  145. package/dist/types/src/internal/Query.d.ts +10 -0
  146. package/dist/types/src/internal/Query.d.ts.map +1 -0
  147. package/dist/types/src/internal/Ref/ref-array.d.ts.map +1 -1
  148. package/dist/types/src/internal/Ref/ref.d.ts +14 -1
  149. package/dist/types/src/internal/Ref/ref.d.ts.map +1 -1
  150. package/dist/types/src/internal/Type/compose.d.ts.map +1 -1
  151. package/dist/types/src/internal/Type/echo-schema.d.ts +2 -2
  152. package/dist/types/src/internal/Type/echo-schema.d.ts.map +1 -1
  153. package/dist/types/src/internal/Type/manipulation.d.ts.map +1 -1
  154. package/dist/types/src/internal/common/api/meta.d.ts +3 -3
  155. package/dist/types/src/internal/common/api/meta.d.ts.map +1 -1
  156. package/dist/types/src/internal/common/proxy/change-context.d.ts +1 -1
  157. package/dist/types/src/internal/common/proxy/change-context.d.ts.map +1 -1
  158. package/dist/types/src/internal/common/proxy/define-hidden-property.d.ts.map +1 -1
  159. package/dist/types/src/internal/common/proxy/errors.d.ts +1 -1
  160. package/dist/types/src/internal/common/proxy/errors.d.ts.map +1 -1
  161. package/dist/types/src/internal/common/proxy/event-batch.d.ts.map +1 -1
  162. package/dist/types/src/internal/common/proxy/json-serializer.d.ts.map +1 -1
  163. package/dist/types/src/internal/common/proxy/make-object.d.ts.map +1 -1
  164. package/dist/types/src/internal/common/proxy/ownership.d.ts.map +1 -1
  165. package/dist/types/src/internal/common/proxy/proxy-utils.d.ts.map +1 -1
  166. package/dist/types/src/internal/common/proxy/reactive-array.d.ts +1 -1
  167. package/dist/types/src/internal/common/proxy/reactive.d.ts +1 -1
  168. package/dist/types/src/internal/common/proxy/reactive.d.ts.map +1 -1
  169. package/dist/types/src/internal/common/proxy/reactive.test.d.ts +2 -0
  170. package/dist/types/src/internal/common/proxy/reactive.test.d.ts.map +1 -0
  171. package/dist/types/src/internal/common/proxy/schema-validator.d.ts.map +1 -1
  172. package/dist/types/src/internal/common/proxy/typed-handler.d.ts.map +1 -1
  173. package/dist/types/src/internal/common/types/base.d.ts.map +1 -1
  174. package/dist/types/src/internal/common/types/entity.d.ts +4 -4
  175. package/dist/types/src/internal/common/types/entity.d.ts.map +1 -1
  176. package/dist/types/src/internal/common/types/meta.d.ts.map +1 -1
  177. package/dist/types/src/internal/common/types/version.d.ts +1 -1
  178. package/dist/types/src/internal/index.d.ts +1 -0
  179. package/dist/types/src/internal/index.d.ts.map +1 -1
  180. package/dist/types/src/testing/test-data.d.ts.map +1 -1
  181. package/dist/types/src/testing/test-schema.d.ts +53 -53
  182. package/dist/types/src/testing/test-schema.d.ts.map +1 -1
  183. package/dist/types/src/testing/util.d.ts.map +1 -1
  184. package/dist/types/tsconfig.tsbuildinfo +1 -1
  185. package/package.json +24 -14
  186. package/src/Collection.ts +5 -0
  187. package/src/Database.ts +49 -14
  188. package/src/Entity.ts +18 -12
  189. package/src/Extension.test.ts +235 -0
  190. package/src/Extension.ts +122 -0
  191. package/src/Feed.ts +79 -32
  192. package/src/Filter.test.ts +90 -0
  193. package/src/Filter.ts +66 -3
  194. package/src/Json.test.ts +175 -0
  195. package/src/Json.ts +102 -0
  196. package/src/Migration.ts +94 -0
  197. package/src/Obj.test.ts +105 -13
  198. package/src/Obj.ts +153 -33
  199. package/src/Query.test.ts +198 -8
  200. package/src/Query.ts +46 -1
  201. package/src/Relation.ts +24 -20
  202. package/src/Type.ts +1 -1
  203. package/src/View.ts +5 -0
  204. package/src/index.ts +4 -0
  205. package/src/internal/Annotation/annotations.test.ts +51 -2
  206. package/src/internal/Annotation/annotations.ts +19 -13
  207. package/src/internal/Annotation/sorting.ts +0 -1
  208. package/src/internal/Entity/api.ts +0 -1
  209. package/src/internal/Entity/object.ts +0 -1
  210. package/src/internal/Entity/version.ts +0 -1
  211. package/src/internal/Format/date.test.ts +0 -1
  212. package/src/internal/Format/format.test.ts +0 -1
  213. package/src/internal/JsonSchema/json-schema-type.ts +1 -1
  214. package/src/internal/JsonSchema/json-schema.test.ts +1 -2
  215. package/src/internal/JsonSchema/json-schema.ts +1 -2
  216. package/src/internal/Obj/clone.ts +1 -1
  217. package/src/internal/Obj/create-object.test.ts +2 -4
  218. package/src/internal/Obj/create-object.ts +2 -3
  219. package/src/internal/Obj/deleted.ts +1 -1
  220. package/src/internal/Obj/json-serializer.test.ts +4 -5
  221. package/src/internal/Obj/json-serializer.ts +22 -15
  222. package/src/internal/Obj/set-value.test.ts +24 -24
  223. package/src/internal/Obj/set-value.ts +1 -1
  224. package/src/internal/Query.ts +137 -0
  225. package/src/internal/Ref/ref-array.ts +0 -1
  226. package/src/internal/Ref/ref.test.ts +0 -1
  227. package/src/internal/Ref/ref.ts +18 -1
  228. package/src/internal/Type/compose.test.ts +0 -1
  229. package/src/internal/Type/echo-schema.ts +3 -4
  230. package/src/internal/Type/persistent-schema.ts +2 -2
  231. package/src/internal/common/README.md +1 -1
  232. package/src/internal/common/api/meta.ts +3 -3
  233. package/src/internal/common/proxy/change-context.ts +1 -1
  234. package/src/internal/common/proxy/change.test.ts +94 -94
  235. package/src/internal/common/proxy/errors.ts +2 -2
  236. package/src/internal/common/proxy/handler.test.ts +0 -2
  237. package/src/internal/common/proxy/make-object.ts +0 -1
  238. package/src/internal/common/proxy/ownership.ts +0 -1
  239. package/src/internal/common/proxy/reactive-array.ts +1 -1
  240. package/src/internal/common/proxy/reactive.test.ts +54 -0
  241. package/src/internal/common/proxy/reactive.ts +11 -3
  242. package/src/internal/common/proxy/typed-handler.test.ts +0 -1
  243. package/src/internal/common/proxy/typed-handler.ts +8 -10
  244. package/src/internal/common/proxy/typed-object.test.ts +2 -3
  245. package/src/internal/common/types/entity.ts +1 -1
  246. package/src/internal/common/types/meta.ts +0 -1
  247. package/src/internal/index.ts +1 -0
  248. package/src/testing/api.test.ts +0 -1
  249. package/src/testing/test-data.ts +0 -1
  250. package/dist/lib/neutral/chunk-43Y5DOS6.mjs.map +0 -7
  251. package/dist/lib/neutral/chunk-BOZZPUXE.mjs.map +0 -7
  252. package/dist/lib/neutral/chunk-CIRHIEMW.mjs.map +0 -7
  253. package/dist/lib/neutral/chunk-DYDJBZEG.mjs.map +0 -7
  254. package/dist/lib/neutral/chunk-KTAWP7GI.mjs.map +0 -7
  255. package/dist/lib/neutral/chunk-NEGC54NE.mjs.map +0 -7
  256. package/dist/lib/neutral/chunk-NQRLRYJM.mjs.map +0 -7
  257. package/dist/lib/neutral/chunk-NXMFBIT5.mjs.map +0 -7
  258. package/dist/lib/neutral/chunk-SEMVAGBM.mjs.map +0 -7
  259. package/dist/lib/neutral/chunk-TQQZLKB7.mjs.map +0 -7
  260. package/dist/lib/neutral/chunk-UFDK26FO.mjs.map +0 -7
  261. package/dist/lib/neutral/chunk-VA2F47ZC.mjs.map +0 -7
  262. /package/dist/lib/neutral/{chunk-FZO7LQO7.mjs.map → chunk-44HT3MEC.mjs.map} +0 -0
  263. /package/dist/lib/neutral/{chunk-ANHVGJI4.mjs.map → chunk-7RVZT53K.mjs.map} +0 -0
  264. /package/dist/lib/neutral/{chunk-BNCCGLJN.mjs.map → chunk-BICZKPQG.mjs.map} +0 -0
  265. /package/dist/lib/neutral/{chunk-724GQYEN.mjs.map → chunk-DUNXPKAC.mjs.map} +0 -0
  266. /package/dist/lib/neutral/{chunk-UTBRYVQC.mjs.map → chunk-FAYW32CW.mjs.map} +0 -0
  267. /package/dist/lib/neutral/{chunk-OENWMTE6.mjs.map → chunk-QBIGOSRF.mjs.map} +0 -0
  268. /package/dist/lib/neutral/{chunk-B5OXLWZL.mjs.map → chunk-TRPZU2HV.mjs.map} +0 -0
  269. /package/dist/lib/neutral/{chunk-UI6MWK5W.mjs.map → chunk-TTCSATUD.mjs.map} +0 -0
  270. /package/dist/lib/neutral/{chunk-FXEG7EOK.mjs.map → chunk-TW76K7H5.mjs.map} +0 -0
  271. /package/dist/lib/neutral/{chunk-OMUPQMLR.mjs.map → chunk-V72DY6LU.mjs.map} +0 -0
package/src/Relation.ts CHANGED
@@ -15,8 +15,8 @@ import { assumeType } from '@dxos/util';
15
15
 
16
16
  import type * as Database from './Database';
17
17
  import * as Entity from './Entity';
18
- import * as entityInternal from './internal/Entity';
19
18
  import * as internal from './internal';
19
+ import * as entityInternal from './internal/Entity';
20
20
  import * as Obj from './Obj';
21
21
  import type * as Type from './Type';
22
22
 
@@ -67,7 +67,7 @@ export const Unknown: Type.Relation<Unknown, Obj.Any, Obj.Any> = Schema.Struct({
67
67
  // NOTE: The EchoRelationSchema annotation is required for Ref.Ref(Relation.Unknown) to work.
68
68
  // The typename/version/source/target only satisfy ECHO schema machinery for reference targets.
69
69
  internal.EchoRelationSchema({
70
- typename: 'org.dxos.schema.any-relation',
70
+ typename: 'org.dxos.schema.anyRelation',
71
71
  version: '0.0.0',
72
72
  source: Obj.Unknown,
73
73
  target: Obj.Unknown,
@@ -237,7 +237,9 @@ export const getSource = <T extends Unknown | Snapshot>(relation: T): SourceOf<T
237
237
  assertArgument(isRelation(relation), 'Expected a relation');
238
238
  assumeType<internal.InternalObjectProps>(relation);
239
239
  const obj = (relation as internal.InternalObjectProps)[internal.RelationSourceId];
240
- invariant(obj !== undefined, `Invalid source: ${relation.id}`);
240
+ if (obj === undefined) {
241
+ throw new Error(`Relation source could not be resolved.`);
242
+ }
241
243
  return obj as SourceOf<T>;
242
244
  };
243
245
 
@@ -250,7 +252,9 @@ export const getTarget = <T extends Unknown | Snapshot>(relation: T): TargetOf<T
250
252
  assertArgument(isRelation(relation), 'Expected a relation');
251
253
  assumeType<internal.InternalObjectProps>(relation);
252
254
  const obj = (relation as internal.InternalObjectProps)[internal.RelationTargetId];
253
- invariant(obj !== undefined, `Invalid target: ${relation.id}`);
255
+ if (obj === undefined) {
256
+ throw new Error(`Relation target could not be resolved.`);
257
+ }
254
258
  return obj as TargetOf<T>;
255
259
  };
256
260
 
@@ -260,7 +264,7 @@ export const getTarget = <T extends Unknown | Snapshot>(relation: T): TargetOf<T
260
264
 
261
265
  /**
262
266
  * Makes all properties mutable recursively.
263
- * Used to provide a mutable view of a relation within `Relation.change`.
267
+ * Used to provide a mutable view of a relation within `Relation.update`.
264
268
  */
265
269
  export type Mutable<T> = internal.Mutable<T>;
266
270
 
@@ -268,10 +272,10 @@ export type Mutable<T> = internal.Mutable<T>;
268
272
  * Perform mutations on an echo relation within a controlled context.
269
273
  *
270
274
  * All mutations within the callback are batched and trigger a single notification
271
- * when the callback completes. Direct mutations outside of `Relation.change` will throw
275
+ * when the callback completes. Direct mutations outside of `Relation.update` will throw
272
276
  * an error for echo relations.
273
277
  *
274
- * @param relation - The echo relation to mutate. Use `Obj.change` for objects.
278
+ * @param relation - The echo relation to mutate. Use `Obj.update` for objects.
275
279
  * @param callback - The callback that performs mutations on the relation.
276
280
  *
277
281
  * @example
@@ -282,15 +286,15 @@ export type Mutable<T> = internal.Mutable<T>;
282
286
  * role: 'Engineer',
283
287
  * });
284
288
  *
285
- * // Mutate within Relation.change
286
- * Relation.change(worksFor, (r) => {
287
- * r.role = 'Senior Engineer';
289
+ * // Mutate within Relation.update
290
+ * Relation.update(worksFor, (obj) => {
291
+ * obj.role = 'Senior Engineer';
288
292
  * });
289
293
  * ```
290
294
  *
291
- * Note: Only accepts relations. Use `Obj.change` for objects.
295
+ * Note: Only accepts relations. Use `Obj.update` for objects.
292
296
  */
293
- export const change = <T extends Unknown>(relation: T, callback: internal.ChangeCallback<T>): void => {
297
+ export const update = <T extends Unknown>(relation: T, callback: internal.ChangeCallback<T>): void => {
294
298
  internal.change(relation, callback);
295
299
  };
296
300
 
@@ -333,7 +337,7 @@ export const getValue = (rel: Unknown | Snapshot, path: readonly (string | numbe
333
337
 
334
338
  /**
335
339
  * Set a deeply nested property on a relation.
336
- * Must be called within a `Relation.change` callback.
340
+ * Must be called within a `Relation.update` callback.
337
341
  *
338
342
  * NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`
339
343
  * parameters, so there is no compile-time error. Enforcement is runtime-only.
@@ -395,13 +399,13 @@ export const Meta = internal.MetaId;
395
399
  export type ReadonlyMeta = internal.ReadonlyMeta;
396
400
 
397
401
  /**
398
- * Mutable meta type returned by `Relation.getMeta` inside a `Relation.change` callback.
402
+ * Mutable meta type returned by `Relation.getMeta` inside a `Relation.update` callback.
399
403
  */
400
404
  export type Meta = internal.Meta;
401
405
 
402
406
  /**
403
407
  * Get the metadata for a relation.
404
- * Returns mutable meta when passed a mutable relation (inside `Relation.change` callback).
408
+ * Returns mutable meta when passed a mutable relation (inside `Relation.update` callback).
405
409
  * Returns read-only meta when passed a regular relation or snapshot.
406
410
  */
407
411
  // TODO(wittjosiah): When passed a Snapshot, should return a snapshot of meta, not the live meta proxy.
@@ -419,7 +423,7 @@ export const getKeys = (entity: Unknown | Snapshot, source: string): ForeignKey[
419
423
 
420
424
  /**
421
425
  * Delete all keys from the relation for the specified source.
422
- * Must be called within a `Relation.change` callback.
426
+ * Must be called within a `Relation.update` callback.
423
427
  *
424
428
  * NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`
425
429
  * parameters, so there is no compile-time error. Enforcement is runtime-only.
@@ -428,7 +432,7 @@ export const deleteKeys = (entity: Mutable<Unknown>, source: string): void => in
428
432
 
429
433
  /**
430
434
  * Add a tag to the relation.
431
- * Must be called within a `Relation.change` callback.
435
+ * Must be called within a `Relation.update` callback.
432
436
  *
433
437
  * NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`
434
438
  * parameters, so there is no compile-time error. Enforcement is runtime-only.
@@ -437,7 +441,7 @@ export const addTag = (entity: Mutable<Unknown>, tag: string): void => internal.
437
441
 
438
442
  /**
439
443
  * Remove a tag from the relation.
440
- * Must be called within a `Relation.change` callback.
444
+ * Must be called within a `Relation.update` callback.
441
445
  *
442
446
  * NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`
443
447
  * parameters, so there is no compile-time error. Enforcement is runtime-only.
@@ -462,7 +466,7 @@ export const getLabel = (entity: Unknown | Snapshot): string | undefined => inte
462
466
 
463
467
  /**
464
468
  * Set the label of the relation.
465
- * Must be called within a `Relation.change` callback.
469
+ * Must be called within a `Relation.update` callback.
466
470
  *
467
471
  * NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`
468
472
  * parameters, so there is no compile-time error. Enforcement is runtime-only.
@@ -477,7 +481,7 @@ export const getDescription = (entity: Unknown | Snapshot): string | undefined =
477
481
 
478
482
  /**
479
483
  * Set the description of the relation.
480
- * Must be called within a `Relation.change` callback.
484
+ * Must be called within a `Relation.update` callback.
481
485
  *
482
486
  * NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`
483
487
  * parameters, so there is no compile-time error. Enforcement is runtime-only.
package/src/Type.ts CHANGED
@@ -12,8 +12,8 @@ import { type DXN } from '@dxos/keys';
12
12
  import { type ToMutable } from '@dxos/util';
13
13
 
14
14
  import type * as Entity from './Entity';
15
- import * as typeInternal from './internal/Type';
16
15
  import * as internal from './internal';
16
+ import * as typeInternal from './internal/Type';
17
17
  import type * as ObjModule from './Obj';
18
18
  import type * as RelationModule from './Relation';
19
19
 
package/src/View.ts CHANGED
@@ -10,6 +10,7 @@ import { QueryAST } from '@dxos/echo-protocol';
10
10
  import { JsonPath } from '@dxos/effect';
11
11
  import { PublicKey } from '@dxos/keys';
12
12
 
13
+ import * as Annotation from './Annotation';
13
14
  import * as Filter from './Filter';
14
15
  import * as internal from './internal';
15
16
  import * as Obj from './Obj';
@@ -79,6 +80,10 @@ const ViewSchema = Schema.Struct({
79
80
  version: '0.1.0',
80
81
  }),
81
82
  internal.SystemTypeAnnotation.set(true),
83
+ Annotation.IconAnnotation.set({
84
+ icon: 'ph--funnel--regular',
85
+ hue: 'green',
86
+ }),
82
87
  );
83
88
 
84
89
  export interface View extends Schema.Schema.Type<typeof ViewSchema> {}
package/src/index.ts CHANGED
@@ -9,13 +9,16 @@ export { DXN } from '@dxos/keys';
9
9
  export * as Annotation from './Annotation';
10
10
  export * as Database from './Database';
11
11
  export * as Entity from './Entity';
12
+ // TODO(burdon): Rename to Error (less problematic than Obj/Object).
12
13
  export * as Err from './Err';
13
14
  export * as Feed from './Feed';
14
15
  export * as Filter from './Filter';
15
16
  export * as Format from './Format';
16
17
  export * as Hypergraph from './Hypergraph';
18
+ export * as Json from './Json';
17
19
  export * as JsonSchema from './JsonSchema';
18
20
  export * as Key from './Key';
21
+ export * as Migration from './Migration';
19
22
  export * as Obj from './Obj';
20
23
  export * as Order from './Order';
21
24
  export * as Query from './Query';
@@ -28,3 +31,4 @@ export * as Type from './Type';
28
31
  export * as Collection from './Collection';
29
32
  export * as View from './View';
30
33
  export * as Dataset from './Dataset';
34
+ export * as Extension from './Extension';
@@ -6,7 +6,6 @@ import * as Schema from 'effect/Schema';
6
6
  import { describe, test } from 'vitest';
7
7
 
8
8
  import { EchoObjectSchema } from '../Entity';
9
-
10
9
  import { LabelAnnotation, TypenameSchema, VersionSchema, getLabelWithSchema } from './annotations';
11
10
 
12
11
  // TODO(dmaretskyi): Use one of the testing schemas.
@@ -32,7 +31,7 @@ describe('annotations', () => {
32
31
  test('should validate typename', ({ expect }) => {
33
32
  // Valid (reverse-DNS format).
34
33
  expect(TypenameSchema.make('org.dxos.type.foo')).to.exist;
35
- expect(TypenameSchema.make('org.dxos.type.foo-bar')).to.exist;
34
+ expect(TypenameSchema.make('org.dxos.type.fooBar')).to.exist;
36
35
  expect(TypenameSchema.make('org.dxos.type.foobar')).to.exist;
37
36
 
38
37
  // Invalid.
@@ -82,6 +81,56 @@ describe('annotations', () => {
82
81
  expect(getLabelWithSchema(TestObject, obj)).toBeUndefined();
83
82
  });
84
83
 
84
+ test('should skip empty string and fallback to next path', ({ expect }) => {
85
+ const obj: TestObject = {
86
+ name: '',
87
+ fallbackName: 'Fallback Name',
88
+ other: 'Other',
89
+ };
90
+
91
+ expect(getLabelWithSchema(TestObject, obj)).toEqual('Fallback Name');
92
+ });
93
+
94
+ test('should skip whitespace-only string and fallback to next path', ({ expect }) => {
95
+ const obj: TestObject = {
96
+ name: ' ',
97
+ fallbackName: 'Fallback Name',
98
+ other: 'Other',
99
+ };
100
+
101
+ expect(getLabelWithSchema(TestObject, obj)).toEqual('Fallback Name');
102
+ });
103
+
104
+ test('should return undefined if all paths are empty strings', ({ expect }) => {
105
+ const obj: TestObject = {
106
+ name: '',
107
+ fallbackName: '',
108
+ other: 'Other',
109
+ };
110
+
111
+ expect(getLabelWithSchema(TestObject, obj)).toBeUndefined();
112
+ });
113
+
114
+ test('should return undefined if all paths are whitespace-only', ({ expect }) => {
115
+ const obj: TestObject = {
116
+ name: ' ',
117
+ fallbackName: '\t\n',
118
+ other: 'Other',
119
+ };
120
+
121
+ expect(getLabelWithSchema(TestObject, obj)).toBeUndefined();
122
+ });
123
+
124
+ test('should preserve original string with leading/trailing whitespace when valid', ({ expect }) => {
125
+ const obj: TestObject = {
126
+ name: ' Valid Name ',
127
+ fallbackName: 'Fallback Name',
128
+ other: 'Other',
129
+ };
130
+
131
+ expect(getLabelWithSchema(TestObject, obj)).toEqual(' Valid Name ');
132
+ });
133
+
85
134
  test('should return label from echo object', ({ expect }) => {
86
135
  const obj: TestEchoSchema = {
87
136
  id: 'test',
@@ -15,7 +15,6 @@ import { type Primitive } from '@dxos/util';
15
15
 
16
16
  import { type Mutable } from '../common/proxy';
17
17
  import { type AnyProperties, EntityKind, TypeId, getSchema } from '../common/types';
18
-
19
18
  import { type AnnotationHelper, createAnnotationHelper } from './util';
20
19
 
21
20
  /**
@@ -90,14 +89,15 @@ export const getTypeDXNFromSpecifier = (input: Schema.Schema.All | string): DXN
90
89
  * Fully qualified globally unique typename.
91
90
  * Example: `org.dxos.type.message`
92
91
  */
93
- // TODO(burdon): Reconcile with short DXN format.
94
- // TODO(burdon): Change "type" => "schema" throughout.
95
- export const TypenameSchema = Schema.String.pipe(Schema.pattern(/^[a-z][a-z0-9]*(\.[a-z][a-z0-9-]*){2,}$/)).annotations(
96
- {
97
- description: 'Fully qualified globally unique typename in lowercase reverse-DNS form.',
98
- example: 'org.dxos.type.message',
99
- },
100
- );
92
+ // TODO(wittjosiah): Factor out to DXN spec.
93
+ export const TypenameSchema = Schema.String.pipe(
94
+ Schema.pattern(
95
+ /^[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(\.[a-zA-Z]([a-zA-Z0-9]{0,62})?)$/,
96
+ ),
97
+ ).annotations({
98
+ description: 'Fully qualified globally unique typename in reverse-DNS form.',
99
+ example: 'org.dxos.type.message',
100
+ });
101
101
 
102
102
  /**
103
103
  * Semantic version format: `major.minor.patch`
@@ -338,6 +338,7 @@ export const LabelAnnotation = createAnnotationHelper<string[]>(LabelAnnotationI
338
338
  /**
339
339
  * Returns the label for a given object based on {@link LabelAnnotationId}.
340
340
  * Lower-level version that requires explicit schema parameter.
341
+ * Skips empty strings and whitespace-only strings, continuing to the next field.
341
342
  */
342
343
  // TODO(burdon): Convert to JsonPath?
343
344
  export const getLabelWithSchema = <S extends Schema.Schema.Any>(
@@ -353,7 +354,13 @@ export const getLabelWithSchema = <S extends Schema.Schema.Any>(
353
354
  );
354
355
  const value = getField(object, accessor as JsonPath);
355
356
  switch (typeof value) {
356
- case 'string':
357
+ case 'string': {
358
+ const trimmed = value.trim();
359
+ if (trimmed.length > 0) {
360
+ return value;
361
+ }
362
+ continue;
363
+ }
357
364
  case 'number':
358
365
  case 'boolean':
359
366
  case 'bigint':
@@ -436,7 +443,6 @@ export const setDescriptionWithSchema = <S extends Schema.Schema.Any>(
436
443
  * Identifies if a property should be included in a form or not.
437
444
  * By default, all properties are included in forms, so this is opt-out.
438
445
  */
439
- // TODO(burdon): UI concern.
440
446
  export const FormInputAnnotationId = Symbol.for('@dxos/schema/annotation/FormInput');
441
447
  export const FormInputAnnotation = createAnnotationHelper<boolean>(FormInputAnnotationId);
442
448
 
@@ -539,7 +545,7 @@ export const getLabel = (entity: AnyProperties): string | undefined => {
539
545
 
540
546
  /**
541
547
  * Set the label of an entity.
542
- * Must be called within an Obj.change or Relation.change callback.
548
+ * Must be called within an Obj.update or Relation.update callback.
543
549
  */
544
550
  export const setLabel = (entity: Mutable<AnyProperties>, label: string) => {
545
551
  const schema = getSchema(entity);
@@ -561,7 +567,7 @@ export const getDescription = (entity: AnyProperties): string | undefined => {
561
567
 
562
568
  /**
563
569
  * Set the description of an entity.
564
- * Must be called within an Obj.change or Relation.change callback.
570
+ * Must be called within an Obj.update or Relation.update callback.
565
571
  */
566
572
  export const setDescription = (entity: Mutable<AnyProperties>, description: string) => {
567
573
  const schema = getSchema(entity);
@@ -3,7 +3,6 @@
3
3
  //
4
4
 
5
5
  import type { AnyEntity } from '../common/types';
6
-
7
6
  import { getLabel, getTypename } from './annotations';
8
7
 
9
8
  /**
@@ -7,7 +7,6 @@ import { type DXN } from '@dxos/keys';
7
7
  import { assumeType } from '@dxos/util';
8
8
 
9
9
  import type { AnyEntity } from '../common/types';
10
-
11
10
  import { type InternalObjectProps, ObjectDatabaseId } from './model';
12
11
  import { getObjectDXN } from './util';
13
12
 
@@ -9,7 +9,6 @@ import { invariant } from '@dxos/invariant';
9
9
 
10
10
  import { type TypeAnnotation, TypeAnnotationId, type TypeMeta, makeTypeJsonSchemaAnnotation } from '../Annotation';
11
11
  import { EntityKind } from '../common/types';
12
-
13
12
  import { type EchoTypeSchema, makeEchoTypeSchema } from './entity';
14
13
 
15
14
  /**
@@ -5,7 +5,6 @@
5
5
  import { assertArgument } from '@dxos/invariant';
6
6
 
7
7
  import { type AnyEntity, VersionTypeId } from '../common/types';
8
-
9
8
  import { ObjectVersionId } from './model';
10
9
 
11
10
  /**
@@ -8,7 +8,6 @@ import { describe, expect, test } from 'vitest';
8
8
  import { log } from '@dxos/log';
9
9
 
10
10
  import { toJsonSchema } from '../JsonSchema';
11
-
12
11
  import {
13
12
  DateOnly,
14
13
  DateTime,
@@ -6,7 +6,6 @@ import * as Schema from 'effect/Schema';
6
6
  import { describe, test } from 'vitest';
7
7
 
8
8
  import { toJsonSchema } from '../JsonSchema';
9
-
10
9
  import { Format } from './format';
11
10
  import { TypeEnum, TypeFormat, getTypeEnum } from './types';
12
11
 
@@ -6,9 +6,9 @@ import * as Schema from 'effect/Schema';
6
6
 
7
7
  import { JsonPath, type JsonProp } from '@dxos/effect';
8
8
 
9
- import { FormatAnnotation, TypeFormat } from '../Format';
10
9
  import { type Mutable } from '../common/proxy';
11
10
  import { EntityKindSchema } from '../common/types';
11
+ import { FormatAnnotation, TypeFormat } from '../Format';
12
12
 
13
13
  //
14
14
  // JSON Schema
@@ -21,13 +21,12 @@ import {
21
21
  getTypeAnnotation,
22
22
  getTypeIdentifierAnnotation,
23
23
  } from '../Annotation';
24
+ import { EntityKind } from '../common/types';
24
25
  import { EchoObjectSchema } from '../Entity';
25
26
  import { Email, FormatAnnotation, TypeFormat } from '../Format';
26
27
  import { JsonSchemaType, getNormalizedEchoAnnotations, getSchemaProperty, setSchemaProperty } from '../JsonSchema';
27
28
  import { Ref, createSchemaReference, getReferenceAst, getSchemaReference } from '../Ref';
28
29
  import { PersistentSchema } from '../Type';
29
- import { EntityKind } from '../common/types';
30
-
31
30
  import { toEffectSchema, toJsonSchema } from './json-schema';
32
31
 
33
32
  const EXAMPLE_NAMESPACE = '@example';
@@ -23,9 +23,8 @@ import {
23
23
  TypeIdentifierAnnotationId,
24
24
  makeTypeJsonSchemaAnnotation,
25
25
  } from '../Annotation';
26
- import { type JsonSchemaReferenceInfo, createEchoReferenceSchema } from '../Ref';
27
26
  import { ANY_OBJECT_TYPENAME, ANY_OBJECT_VERSION, EntityKind, EntityKindSchema } from '../common/types';
28
-
27
+ import { type JsonSchemaReferenceInfo, createEchoReferenceSchema } from '../Ref';
29
28
  import { CustomAnnotations, DecodedAnnotations, EchoAnnotations } from './annotations';
30
29
  import {
31
30
  ECHO_ANNOTATIONS_NS_DEPRECATED_KEY,
@@ -7,8 +7,8 @@ import { deepMapValues } from '@dxos/util';
7
7
 
8
8
  import type * as Obj from '../../Obj';
9
9
  import { makeObject } from '../common/proxy';
10
- import { Ref } from '../Ref';
11
10
  import { getMeta, getSchema } from '../common/types';
11
+ import { Ref } from '../Ref';
12
12
 
13
13
  /**
14
14
  * Clones an object or relation.
@@ -2,9 +2,8 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { inspect } from 'util';
6
-
7
5
  import * as Schema from 'effect/Schema';
6
+ import { inspect } from 'util';
8
7
  import { describe, expect, test } from 'vitest';
9
8
 
10
9
  import { DXN } from '@dxos/keys';
@@ -12,9 +11,8 @@ import { DXN } from '@dxos/keys';
12
11
  import { Relation } from '../../index';
13
12
  import { TestSchema } from '../../testing';
14
13
  import { getSchemaDXN, getTypeDXN, isInstanceOf } from '../Annotation';
15
- import { ATTR_RELATION_SOURCE, ATTR_RELATION_TARGET } from '../Entity';
16
14
  import { ATTR_META, ATTR_TYPE, getSchema } from '../common/types';
17
-
15
+ import { ATTR_RELATION_SOURCE, ATTR_RELATION_TARGET } from '../Entity';
18
16
  import { createObject } from './create-object';
19
17
  import { objectToJSON } from './json-serializer';
20
18
 
@@ -9,6 +9,8 @@ import { assertArgument, failedInvariant } from '@dxos/invariant';
9
9
  import { ObjectId } from '@dxos/keys';
10
10
 
11
11
  import { getSchemaDXN, getTypeAnnotation, setTypename } from '../Annotation';
12
+ import { defineHiddenProperty } from '../common/proxy';
13
+ import { EntityKind, KindId, MetaId, setSchema } from '../common/types';
12
14
  import {
13
15
  RelationSourceDXNId,
14
16
  RelationSourceId,
@@ -17,9 +19,6 @@ import {
17
19
  assertObjectModel,
18
20
  getObjectDXN,
19
21
  } from '../Entity';
20
- import { defineHiddenProperty } from '../common/proxy';
21
- import { EntityKind, KindId, MetaId, setSchema } from '../common/types';
22
-
23
22
  import { attachedTypedObjectInspector } from './inspect';
24
23
  import { attachTypedJsonSerializer } from './json-serializer';
25
24
 
@@ -2,8 +2,8 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { ObjectDeletedId } from '../Entity';
6
5
  import { type AnyProperties } from '../common/types';
6
+ import { ObjectDeletedId } from '../Entity';
7
7
 
8
8
  /**
9
9
  * @returns `true` if the object has been marked as deleted.
@@ -10,19 +10,18 @@ import * as Obj from '../../Obj';
10
10
  import { TestSchema } from '../../testing';
11
11
  import { getSchemaDXN, getSchemaTypename, getTypeDXN, getTypename } from '../Annotation';
12
12
  import { getMetaChecked } from '../common/api';
13
- import { RelationSourceId, RelationTargetId, getObjectDXN } from '../Entity';
14
13
  import { makeObject } from '../common/proxy';
15
- import { Ref, StaticRefResolver } from '../Ref';
16
14
  import { ATTR_TYPE, EntityKind, KindId, MetaId, TypeId, getSchema } from '../common/types';
17
-
15
+ import { RelationSourceId, RelationTargetId, getObjectDXN } from '../Entity';
16
+ import { Ref, StaticRefResolver } from '../Ref';
18
17
  import { createObject } from './create-object';
19
18
  import { objectFromJSON, objectToJSON } from './json-serializer';
20
19
 
21
20
  describe('Object JSON serializer', () => {
22
21
  test('should serialize and deserialize object', async () => {
23
22
  const contact = makeObject(TestSchema.Person, { name: 'Alice' });
24
- Obj.change(contact, (c) => {
25
- getMetaChecked(c).keys.push({ id: '12345', source: 'example.com' });
23
+ Obj.update(contact, (contact) => {
24
+ getMetaChecked(contact).keys.push({ id: '12345', source: 'example.com' });
26
25
  });
27
26
 
28
27
  const task = createObject(TestSchema.Task, {
@@ -13,6 +13,19 @@ import { assumeType, deepMapValues, visitValues } from '@dxos/util';
13
13
  import type * as Database from '../../Database';
14
14
  import type * as Obj from '../../Obj';
15
15
  import { getTypeDXN, setTypename } from '../Annotation';
16
+ import { attachTypedJsonSerializer, defineHiddenProperty, typedJsonSerializer } from '../common/proxy';
17
+ import {
18
+ ATTR_META,
19
+ ATTR_PARENT,
20
+ ATTR_TYPE,
21
+ type AnyEntity,
22
+ EntityKind,
23
+ KindId,
24
+ MetaId,
25
+ ObjectMetaSchema,
26
+ ParentId,
27
+ setSchema,
28
+ } from '../common/types';
16
29
  import {
17
30
  ATTR_DELETED,
18
31
  ATTR_RELATION_SOURCE,
@@ -27,20 +40,7 @@ import {
27
40
  SelfDXNId,
28
41
  assertObjectModel,
29
42
  } from '../Entity';
30
- import { attachTypedJsonSerializer, defineHiddenProperty, typedJsonSerializer } from '../common/proxy';
31
43
  import { Ref, type RefResolver, refFromEncodedReference, setRefResolver } from '../Ref';
32
- import {
33
- ATTR_META,
34
- ATTR_PARENT,
35
- ATTR_TYPE,
36
- type AnyEntity,
37
- EntityKind,
38
- KindId,
39
- MetaId,
40
- ObjectMetaSchema,
41
- ParentId,
42
- setSchema,
43
- } from '../common/types';
44
44
 
45
45
  // Re-export for backward compatibility.
46
46
  export { attachTypedJsonSerializer };
@@ -80,7 +80,12 @@ export const objectToJSON = <T extends AnyEntity>(obj: T): SerializedObject<T> =
80
80
  */
81
81
  export const objectFromJSON = async (
82
82
  jsonData: unknown,
83
- { refResolver, dxn, database }: { refResolver?: RefResolver; dxn?: DXN; database?: Database.Database } = {},
83
+ {
84
+ refResolver,
85
+ dxn,
86
+ database,
87
+ parent,
88
+ }: { refResolver?: RefResolver; dxn?: DXN; database?: Database.Database; parent?: Obj.Unknown } = {},
84
89
  ): Promise<AnyEntity> => {
85
90
  assumeType<ObjectJSON>(jsonData);
86
91
  assertArgument(typeof jsonData === 'object' && jsonData !== null, 'jsonData', 'expect object');
@@ -138,7 +143,9 @@ export const objectFromJSON = async (
138
143
 
139
144
  if (jsonData[ATTR_PARENT]) {
140
145
  const parentDxn = DXN.parse(jsonData[ATTR_PARENT]);
141
- const parent = (await refResolver?.resolve(parentDxn)) as Obj.Unknown | undefined;
146
+ const resolvedParent = (await refResolver?.resolve(parentDxn)) as Obj.Unknown | undefined;
147
+ defineHiddenProperty(obj, ParentId, resolvedParent);
148
+ } else if (parent) {
142
149
  defineHiddenProperty(obj, ParentId, parent);
143
150
  }
144
151