@dxos/echo 0.8.4-main.21d9917 → 0.8.4-main.2244d791bb

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 (278) hide show
  1. package/dist/lib/{browser → neutral}/Annotation.mjs +7 -5
  2. package/dist/lib/neutral/Database.mjs +45 -0
  3. package/dist/lib/{browser → neutral}/Entity.mjs +8 -9
  4. package/dist/lib/{browser → neutral}/Err.mjs +4 -3
  5. package/dist/lib/{browser → neutral}/Filter.mjs +9 -10
  6. package/dist/lib/{browser → neutral}/Format.mjs +4 -5
  7. package/dist/lib/neutral/JsonSchema.mjs +19 -0
  8. package/dist/lib/{browser → neutral}/Key.mjs +2 -3
  9. package/dist/lib/{node-esm → neutral}/Obj.mjs +23 -10
  10. package/dist/lib/{browser → neutral}/Order.mjs +2 -3
  11. package/dist/lib/neutral/Query.mjs +26 -0
  12. package/dist/lib/neutral/QueryResult.mjs +2 -0
  13. package/dist/lib/neutral/Ref.mjs +22 -0
  14. package/dist/lib/{browser → neutral}/Relation.mjs +9 -10
  15. package/dist/lib/neutral/SchemaRegistry.mjs +2 -0
  16. package/dist/lib/neutral/Tag.mjs +25 -0
  17. package/dist/lib/{browser → neutral}/Type.mjs +8 -9
  18. package/dist/lib/{browser/chunk-W5D2GWAW.mjs → neutral/chunk-36GDMODZ.mjs} +5 -6
  19. package/dist/lib/{browser/chunk-W5D2GWAW.mjs.map → neutral/chunk-36GDMODZ.mjs.map} +1 -1
  20. package/dist/lib/{browser/chunk-ZHXZGIXD.mjs → neutral/chunk-4L6DOFXP.mjs} +1 -3
  21. package/dist/lib/{browser/chunk-ZHXZGIXD.mjs.map → neutral/chunk-4L6DOFXP.mjs.map} +1 -1
  22. package/dist/lib/{browser/chunk-NOPVNWPT.mjs → neutral/chunk-5MGEVDUW.mjs} +73 -8
  23. package/dist/lib/neutral/chunk-5MGEVDUW.mjs.map +7 -0
  24. package/dist/lib/{browser/chunk-FRDT7RA4.mjs → neutral/chunk-7WE7SBA2.mjs} +4 -5
  25. package/dist/lib/neutral/chunk-7WE7SBA2.mjs.map +7 -0
  26. package/dist/lib/{browser/chunk-INHXFXY5.mjs → neutral/chunk-ANHVGJI4.mjs} +2 -3
  27. package/dist/lib/{node-esm/chunk-AJEMYSIR.mjs.map → neutral/chunk-ANHVGJI4.mjs.map} +1 -1
  28. package/dist/lib/neutral/chunk-B4FLOYG7.mjs +130 -0
  29. package/dist/lib/neutral/chunk-B4FLOYG7.mjs.map +7 -0
  30. package/dist/lib/{browser/chunk-U2J7TA7K.mjs → neutral/chunk-BHR4XVJK.mjs} +5 -6
  31. package/dist/lib/{node-esm/chunk-DMR7OAFK.mjs.map → neutral/chunk-BHR4XVJK.mjs.map} +1 -1
  32. package/dist/lib/{browser/chunk-ZAGAOZVY.mjs → neutral/chunk-CH3HX4Z5.mjs} +4 -5
  33. package/dist/lib/{node-esm/chunk-QYR67VBV.mjs.map → neutral/chunk-CH3HX4Z5.mjs.map} +1 -1
  34. package/dist/lib/{browser/chunk-CGS2ULMK.mjs → neutral/chunk-J5LGTIGS.mjs} +1 -2
  35. package/dist/lib/{browser/chunk-YKTSSMDS.mjs → neutral/chunk-KB7RIVLK.mjs} +1 -3
  36. package/dist/lib/neutral/chunk-KB7RIVLK.mjs.map +7 -0
  37. package/dist/lib/{browser/chunk-2SBB7OWV.mjs → neutral/chunk-KSFI2POM.mjs} +11 -10
  38. package/dist/lib/neutral/chunk-KSFI2POM.mjs.map +7 -0
  39. package/dist/lib/{browser/chunk-6L5HHUVU.mjs → neutral/chunk-LKQBTRJX.mjs} +18 -5
  40. package/dist/lib/neutral/chunk-LKQBTRJX.mjs.map +7 -0
  41. package/dist/lib/{browser/chunk-CJ5YELTO.mjs → neutral/chunk-MXQJZCPY.mjs} +15 -3
  42. package/dist/lib/neutral/chunk-MXQJZCPY.mjs.map +7 -0
  43. package/dist/lib/{browser/chunk-PQZW3S6L.mjs → neutral/chunk-N2QNHMT5.mjs} +3 -4
  44. package/dist/lib/{node-esm/chunk-Y75VU7LB.mjs.map → neutral/chunk-N2QNHMT5.mjs.map} +1 -1
  45. package/dist/lib/{browser/chunk-IXVWLTG7.mjs → neutral/chunk-OMUPQMLR.mjs} +1 -3
  46. package/dist/lib/{browser/chunk-IXVWLTG7.mjs.map → neutral/chunk-OMUPQMLR.mjs.map} +1 -1
  47. package/dist/lib/{node-esm/chunk-YOLH5KS4.mjs → neutral/chunk-RIMHNJ3E.mjs} +17 -4
  48. package/dist/lib/neutral/chunk-RIMHNJ3E.mjs.map +7 -0
  49. package/dist/lib/{browser/chunk-JMKVF2YQ.mjs → neutral/chunk-ROKO4RKJ.mjs} +2 -3
  50. package/dist/lib/{node-esm/chunk-K37NA7PO.mjs.map → neutral/chunk-ROKO4RKJ.mjs.map} +1 -1
  51. package/dist/lib/{browser/chunk-KQQGVHFN.mjs → neutral/chunk-SHLKRGRB.mjs} +5 -6
  52. package/dist/lib/{node-esm/chunk-NRN3ZW2T.mjs.map → neutral/chunk-SHLKRGRB.mjs.map} +1 -1
  53. package/dist/lib/{browser/chunk-22JMFST2.mjs → neutral/chunk-UW4T7PAL.mjs} +3 -4
  54. package/dist/lib/{browser/chunk-22JMFST2.mjs.map → neutral/chunk-UW4T7PAL.mjs.map} +1 -1
  55. package/dist/lib/{browser/chunk-XDIUHAAX.mjs → neutral/chunk-WSPASOLU.mjs} +3 -4
  56. package/dist/lib/{node-esm/chunk-QLI2EIJ2.mjs.map → neutral/chunk-WSPASOLU.mjs.map} +1 -1
  57. package/dist/lib/{browser/chunk-MYCCGG2T.mjs → neutral/chunk-X2MPMYYN.mjs} +1 -3
  58. package/dist/lib/{node-esm/chunk-MOWUEW5P.mjs.map → neutral/chunk-X2MPMYYN.mjs.map} +1 -1
  59. package/dist/lib/{browser/chunk-FPOISFQK.mjs → neutral/chunk-XAJMXQ4H.mjs} +7 -4
  60. package/dist/lib/neutral/chunk-XAJMXQ4H.mjs.map +7 -0
  61. package/dist/lib/{browser/chunk-BJPE6CIC.mjs → neutral/chunk-ZUG3PNXU.mjs} +146 -83
  62. package/dist/lib/neutral/chunk-ZUG3PNXU.mjs.map +7 -0
  63. package/dist/lib/{browser → neutral}/index.mjs +23 -24
  64. package/dist/lib/{browser → neutral}/internal/index.mjs +13 -8
  65. package/dist/lib/neutral/meta.json +1 -0
  66. package/dist/lib/{browser → neutral}/testing/index.mjs +23 -24
  67. package/dist/lib/{node-esm → neutral}/testing/index.mjs.map +1 -1
  68. package/dist/types/src/Annotation.d.ts +22 -0
  69. package/dist/types/src/Annotation.d.ts.map +1 -1
  70. package/dist/types/src/Database.d.ts +72 -50
  71. package/dist/types/src/Database.d.ts.map +1 -1
  72. package/dist/types/src/Err.d.ts +43 -0
  73. package/dist/types/src/Err.d.ts.map +1 -1
  74. package/dist/types/src/Obj.d.ts +84 -4
  75. package/dist/types/src/Obj.d.ts.map +1 -1
  76. package/dist/types/src/Query.d.ts +10 -0
  77. package/dist/types/src/Query.d.ts.map +1 -1
  78. package/dist/types/src/Relation.d.ts +2 -2
  79. package/dist/types/src/Relation.d.ts.map +1 -1
  80. package/dist/types/src/hierarchy.test.d.ts +2 -0
  81. package/dist/types/src/hierarchy.test.d.ts.map +1 -0
  82. package/dist/types/src/internal/annotations/annotations.d.ts +13 -6
  83. package/dist/types/src/internal/annotations/annotations.d.ts.map +1 -1
  84. package/dist/types/src/internal/annotations/util.d.ts +12 -0
  85. package/dist/types/src/internal/annotations/util.d.ts.map +1 -1
  86. package/dist/types/src/internal/api/meta.d.ts +2 -2
  87. package/dist/types/src/internal/api/meta.d.ts.map +1 -1
  88. package/dist/types/src/internal/entities/model.d.ts +3 -1
  89. package/dist/types/src/internal/entities/model.d.ts.map +1 -1
  90. package/dist/types/src/internal/entities/object.d.ts.map +1 -1
  91. package/dist/types/src/internal/entities/relation.d.ts.map +1 -1
  92. package/dist/types/src/internal/formats/select.d.ts +2 -2
  93. package/dist/types/src/internal/formats/select.d.ts.map +1 -1
  94. package/dist/types/src/internal/json-schema/json-schema-normalize.d.ts.map +1 -1
  95. package/dist/types/src/internal/json-schema/json-schema-type.d.ts +130 -29
  96. package/dist/types/src/internal/json-schema/json-schema-type.d.ts.map +1 -1
  97. package/dist/types/src/internal/json-schema/json-schema.d.ts +2 -1
  98. package/dist/types/src/internal/json-schema/json-schema.d.ts.map +1 -1
  99. package/dist/types/src/internal/object/json-serializer.d.ts.map +1 -1
  100. package/dist/types/src/internal/object/snapshot.d.ts.map +1 -1
  101. package/dist/types/src/internal/proxy/make-object.d.ts.map +1 -1
  102. package/dist/types/src/internal/proxy/typed-handler.d.ts +2 -1
  103. package/dist/types/src/internal/proxy/typed-handler.d.ts.map +1 -1
  104. package/dist/types/src/internal/ref/ref.d.ts +16 -2
  105. package/dist/types/src/internal/ref/ref.d.ts.map +1 -1
  106. package/dist/types/src/internal/schema/compose.d.ts +2 -1
  107. package/dist/types/src/internal/schema/compose.d.ts.map +1 -1
  108. package/dist/types/src/internal/schema/echo-schema.d.ts +2 -1
  109. package/dist/types/src/internal/schema/echo-schema.d.ts.map +1 -1
  110. package/dist/types/src/internal/schema/persistent-schema.d.ts.map +1 -1
  111. package/dist/types/src/internal/types/meta.d.ts +5 -5
  112. package/dist/types/src/internal/types/meta.d.ts.map +1 -1
  113. package/dist/types/src/internal/types/typename.d.ts +8 -0
  114. package/dist/types/src/internal/types/typename.d.ts.map +1 -1
  115. package/dist/types/tsconfig.tsbuildinfo +1 -1
  116. package/package.json +34 -113
  117. package/src/Annotation.ts +27 -0
  118. package/src/Database.ts +141 -124
  119. package/src/Err.ts +20 -0
  120. package/src/Obj.test.ts +56 -0
  121. package/src/Obj.ts +140 -11
  122. package/src/Query.ts +28 -0
  123. package/src/Relation.ts +5 -3
  124. package/src/hierarchy.test.ts +33 -0
  125. package/src/internal/annotations/annotations.ts +28 -1
  126. package/src/internal/annotations/util.ts +13 -0
  127. package/src/internal/api/meta.ts +3 -3
  128. package/src/internal/entities/model.ts +4 -0
  129. package/src/internal/entities/object.ts +1 -3
  130. package/src/internal/entities/relation.ts +1 -3
  131. package/src/internal/formats/format.test.ts +1 -1
  132. package/src/internal/formats/select.ts +1 -1
  133. package/src/internal/formats/types.ts +1 -1
  134. package/src/internal/json-schema/json-schema-normalize.ts +4 -2
  135. package/src/internal/json-schema/json-schema-type.ts +30 -31
  136. package/src/internal/json-schema/json-schema.ts +10 -6
  137. package/src/internal/object/json-serializer.test.ts +26 -2
  138. package/src/internal/object/json-serializer.ts +25 -9
  139. package/src/internal/object/schema-validator.test.ts +3 -7
  140. package/src/internal/object/set-value.test.ts +9 -9
  141. package/src/internal/object/snapshot.ts +29 -6
  142. package/src/internal/proxy/make-object.ts +12 -2
  143. package/src/internal/proxy/typed-handler.test.ts +8 -12
  144. package/src/internal/proxy/typed-handler.ts +9 -1
  145. package/src/internal/proxy/typed-object.test.ts +11 -11
  146. package/src/internal/ref/ref.test.ts +1 -1
  147. package/src/internal/ref/ref.ts +26 -2
  148. package/src/internal/schema/compose.ts +13 -8
  149. package/src/internal/schema/echo-schema.ts +3 -2
  150. package/src/internal/schema/persistent-schema.ts +2 -1
  151. package/src/internal/types/meta.ts +12 -13
  152. package/src/internal/types/typename.ts +10 -0
  153. package/dist/lib/browser/Database.mjs +0 -18
  154. package/dist/lib/browser/JsonSchema.mjs +0 -20
  155. package/dist/lib/browser/Obj.mjs +0 -91
  156. package/dist/lib/browser/Query.mjs +0 -27
  157. package/dist/lib/browser/QueryResult.mjs +0 -3
  158. package/dist/lib/browser/Ref.mjs +0 -23
  159. package/dist/lib/browser/SchemaRegistry.mjs +0 -3
  160. package/dist/lib/browser/Tag.mjs +0 -26
  161. package/dist/lib/browser/chunk-2SBB7OWV.mjs.map +0 -7
  162. package/dist/lib/browser/chunk-6L5HHUVU.mjs.map +0 -7
  163. package/dist/lib/browser/chunk-7STIBCP7.mjs +0 -133
  164. package/dist/lib/browser/chunk-7STIBCP7.mjs.map +0 -7
  165. package/dist/lib/browser/chunk-BJPE6CIC.mjs.map +0 -7
  166. package/dist/lib/browser/chunk-CJ5YELTO.mjs.map +0 -7
  167. package/dist/lib/browser/chunk-FPOISFQK.mjs.map +0 -7
  168. package/dist/lib/browser/chunk-FRDT7RA4.mjs.map +0 -7
  169. package/dist/lib/browser/chunk-INHXFXY5.mjs.map +0 -7
  170. package/dist/lib/browser/chunk-JMKVF2YQ.mjs.map +0 -7
  171. package/dist/lib/browser/chunk-KQQGVHFN.mjs.map +0 -7
  172. package/dist/lib/browser/chunk-MYCCGG2T.mjs.map +0 -7
  173. package/dist/lib/browser/chunk-NOPVNWPT.mjs.map +0 -7
  174. package/dist/lib/browser/chunk-PQZW3S6L.mjs.map +0 -7
  175. package/dist/lib/browser/chunk-RK4Z4JUZ.mjs +0 -283
  176. package/dist/lib/browser/chunk-RK4Z4JUZ.mjs.map +0 -7
  177. package/dist/lib/browser/chunk-U2J7TA7K.mjs.map +0 -7
  178. package/dist/lib/browser/chunk-XDIUHAAX.mjs.map +0 -7
  179. package/dist/lib/browser/chunk-YKTSSMDS.mjs.map +0 -7
  180. package/dist/lib/browser/chunk-ZAGAOZVY.mjs.map +0 -7
  181. package/dist/lib/browser/meta.json +0 -1
  182. package/dist/lib/browser/testing/index.mjs.map +0 -7
  183. package/dist/lib/node-esm/Annotation.mjs +0 -33
  184. package/dist/lib/node-esm/Annotation.mjs.map +0 -7
  185. package/dist/lib/node-esm/Database.mjs +0 -18
  186. package/dist/lib/node-esm/Database.mjs.map +0 -7
  187. package/dist/lib/node-esm/Entity.mjs +0 -52
  188. package/dist/lib/node-esm/Entity.mjs.map +0 -7
  189. package/dist/lib/node-esm/Err.mjs +0 -11
  190. package/dist/lib/node-esm/Err.mjs.map +0 -7
  191. package/dist/lib/node-esm/Filter.mjs +0 -62
  192. package/dist/lib/node-esm/Filter.mjs.map +0 -7
  193. package/dist/lib/node-esm/Format.mjs +0 -67
  194. package/dist/lib/node-esm/Format.mjs.map +0 -7
  195. package/dist/lib/node-esm/JsonSchema.mjs +0 -20
  196. package/dist/lib/node-esm/JsonSchema.mjs.map +0 -7
  197. package/dist/lib/node-esm/Key.mjs +0 -13
  198. package/dist/lib/node-esm/Key.mjs.map +0 -7
  199. package/dist/lib/node-esm/Obj.mjs.map +0 -7
  200. package/dist/lib/node-esm/Order.mjs +0 -13
  201. package/dist/lib/node-esm/Order.mjs.map +0 -7
  202. package/dist/lib/node-esm/Query.mjs +0 -27
  203. package/dist/lib/node-esm/Query.mjs.map +0 -7
  204. package/dist/lib/node-esm/QueryResult.mjs +0 -3
  205. package/dist/lib/node-esm/QueryResult.mjs.map +0 -7
  206. package/dist/lib/node-esm/Ref.mjs +0 -23
  207. package/dist/lib/node-esm/Ref.mjs.map +0 -7
  208. package/dist/lib/node-esm/Relation.mjs +0 -85
  209. package/dist/lib/node-esm/Relation.mjs.map +0 -7
  210. package/dist/lib/node-esm/SchemaRegistry.mjs +0 -3
  211. package/dist/lib/node-esm/SchemaRegistry.mjs.map +0 -7
  212. package/dist/lib/node-esm/Tag.mjs +0 -26
  213. package/dist/lib/node-esm/Tag.mjs.map +0 -7
  214. package/dist/lib/node-esm/Type.mjs +0 -48
  215. package/dist/lib/node-esm/Type.mjs.map +0 -7
  216. package/dist/lib/node-esm/chunk-4PNXQA64.mjs +0 -250
  217. package/dist/lib/node-esm/chunk-4PNXQA64.mjs.map +0 -7
  218. package/dist/lib/node-esm/chunk-5OBN7GZW.mjs +0 -158
  219. package/dist/lib/node-esm/chunk-5OBN7GZW.mjs.map +0 -7
  220. package/dist/lib/node-esm/chunk-AJEMYSIR.mjs +0 -22
  221. package/dist/lib/node-esm/chunk-ANLVLWME.mjs +0 -98
  222. package/dist/lib/node-esm/chunk-ANLVLWME.mjs.map +0 -7
  223. package/dist/lib/node-esm/chunk-DMR7OAFK.mjs +0 -57
  224. package/dist/lib/node-esm/chunk-FWTSPIFF.mjs +0 -133
  225. package/dist/lib/node-esm/chunk-FWTSPIFF.mjs.map +0 -7
  226. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +0 -11
  227. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +0 -7
  228. package/dist/lib/node-esm/chunk-ILMLLM4R.mjs +0 -204
  229. package/dist/lib/node-esm/chunk-ILMLLM4R.mjs.map +0 -7
  230. package/dist/lib/node-esm/chunk-K37NA7PO.mjs +0 -43
  231. package/dist/lib/node-esm/chunk-LT3H4JOX.mjs +0 -3847
  232. package/dist/lib/node-esm/chunk-LT3H4JOX.mjs.map +0 -7
  233. package/dist/lib/node-esm/chunk-MOLNWFNL.mjs +0 -9
  234. package/dist/lib/node-esm/chunk-MOLNWFNL.mjs.map +0 -7
  235. package/dist/lib/node-esm/chunk-MOWUEW5P.mjs +0 -15
  236. package/dist/lib/node-esm/chunk-NBWL7UCZ.mjs +0 -40
  237. package/dist/lib/node-esm/chunk-NBWL7UCZ.mjs.map +0 -7
  238. package/dist/lib/node-esm/chunk-NRN3ZW2T.mjs +0 -143
  239. package/dist/lib/node-esm/chunk-QLI2EIJ2.mjs +0 -41
  240. package/dist/lib/node-esm/chunk-QYR67VBV.mjs +0 -288
  241. package/dist/lib/node-esm/chunk-UKGVOINP.mjs +0 -9
  242. package/dist/lib/node-esm/chunk-UKGVOINP.mjs.map +0 -7
  243. package/dist/lib/node-esm/chunk-W6QIEBTQ.mjs +0 -403
  244. package/dist/lib/node-esm/chunk-W6QIEBTQ.mjs.map +0 -7
  245. package/dist/lib/node-esm/chunk-XHJRMQZD.mjs +0 -69
  246. package/dist/lib/node-esm/chunk-XHJRMQZD.mjs.map +0 -7
  247. package/dist/lib/node-esm/chunk-Y75VU7LB.mjs +0 -74
  248. package/dist/lib/node-esm/chunk-YOLH5KS4.mjs.map +0 -7
  249. package/dist/lib/node-esm/chunk-YQ2NWGL5.mjs +0 -39
  250. package/dist/lib/node-esm/chunk-YQ2NWGL5.mjs.map +0 -7
  251. package/dist/lib/node-esm/chunk-ZBB67AKD.mjs +0 -24
  252. package/dist/lib/node-esm/chunk-ZBB67AKD.mjs.map +0 -7
  253. package/dist/lib/node-esm/index.mjs +0 -85
  254. package/dist/lib/node-esm/index.mjs.map +0 -7
  255. package/dist/lib/node-esm/internal/index.mjs +0 -457
  256. package/dist/lib/node-esm/internal/index.mjs.map +0 -7
  257. package/dist/lib/node-esm/meta.json +0 -1
  258. package/dist/lib/node-esm/testing/index.mjs +0 -367
  259. /package/dist/lib/{browser → neutral}/Annotation.mjs.map +0 -0
  260. /package/dist/lib/{browser → neutral}/Database.mjs.map +0 -0
  261. /package/dist/lib/{browser → neutral}/Entity.mjs.map +0 -0
  262. /package/dist/lib/{browser → neutral}/Err.mjs.map +0 -0
  263. /package/dist/lib/{browser → neutral}/Filter.mjs.map +0 -0
  264. /package/dist/lib/{browser → neutral}/Format.mjs.map +0 -0
  265. /package/dist/lib/{browser → neutral}/JsonSchema.mjs.map +0 -0
  266. /package/dist/lib/{browser → neutral}/Key.mjs.map +0 -0
  267. /package/dist/lib/{browser → neutral}/Obj.mjs.map +0 -0
  268. /package/dist/lib/{browser → neutral}/Order.mjs.map +0 -0
  269. /package/dist/lib/{browser → neutral}/Query.mjs.map +0 -0
  270. /package/dist/lib/{browser → neutral}/QueryResult.mjs.map +0 -0
  271. /package/dist/lib/{browser → neutral}/Ref.mjs.map +0 -0
  272. /package/dist/lib/{browser → neutral}/Relation.mjs.map +0 -0
  273. /package/dist/lib/{browser → neutral}/SchemaRegistry.mjs.map +0 -0
  274. /package/dist/lib/{browser → neutral}/Tag.mjs.map +0 -0
  275. /package/dist/lib/{browser → neutral}/Type.mjs.map +0 -0
  276. /package/dist/lib/{browser/chunk-CGS2ULMK.mjs.map → neutral/chunk-J5LGTIGS.mjs.map} +0 -0
  277. /package/dist/lib/{browser → neutral}/index.mjs.map +0 -0
  278. /package/dist/lib/{browser → neutral}/internal/index.mjs.map +0 -0
package/src/Obj.ts CHANGED
@@ -2,7 +2,9 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import * as Effect from 'effect/Effect';
5
6
  import * as Function from 'effect/Function';
7
+ import * as Option from 'effect/Option';
6
8
  import * as Schema from 'effect/Schema';
7
9
 
8
10
  import type { ForeignKey } from '@dxos/echo-protocol';
@@ -13,6 +15,7 @@ import { assumeType } from '@dxos/util';
13
15
 
14
16
  import type * as Database from './Database';
15
17
  import * as Entity from './Entity';
18
+ import * as Err from './Err';
16
19
  import {
17
20
  type ObjectJSON as APIJSON,
18
21
  type AnyEntity,
@@ -27,7 +30,9 @@ import {
27
30
  MetaId,
28
31
  type Mutable,
29
32
  type ObjectMeta,
30
- type SnapshotKindId,
33
+ // TODO(dmaretskyi): Export ParentId?
34
+ ParentId,
35
+ SnapshotKindId,
31
36
  type VersionCompareResult,
32
37
  VersionTypeId,
33
38
  addTag as addTag$,
@@ -133,6 +138,7 @@ type Props<T = any> = {
133
138
  export type MakeProps<S extends Schema.Schema.AnyNoContext> = {
134
139
  id?: ObjectId;
135
140
  [Meta]?: Partial<ObjectMeta>;
141
+ [Parent]?: Unknown;
136
142
  } & NoInfer<Props<Schema.Schema.Type<S>>>;
137
143
 
138
144
  /**
@@ -169,8 +175,16 @@ export const make: {
169
175
  delete props[MetaId];
170
176
  }
171
177
 
172
- // Filter undefined values.
173
- const filterUndefined = Object.fromEntries(Object.entries(props).filter(([_, v]) => v !== undefined));
178
+ // Filter undefined values (Object.entries only returns string-keyed properties).
179
+ const filterUndefined: any = Object.fromEntries(Object.entries(props).filter(([_, v]) => v !== undefined));
180
+
181
+ // Copy symbol properties (like ParentId) that Object.entries doesn't include.
182
+ for (const sym of Object.getOwnPropertySymbols(props)) {
183
+ const value = (props as any)[sym];
184
+ if (value !== undefined) {
185
+ filterUndefined[sym] = value;
186
+ }
187
+ }
174
188
 
175
189
  return makeObject<Schema.Schema.Type<S>>(schema, filterUndefined as any, {
176
190
  ...defaultMeta,
@@ -207,6 +221,60 @@ export const subscribe = (obj: Unknown, callback: () => void): (() => void) => {
207
221
  */
208
222
  export const getSnapshot: <T extends Unknown>(obj: T) => Snapshot<T> = getSnapshot$ as any;
209
223
 
224
+ /**
225
+ * Returns the reactive version of an object from the database, given its snapshot.
226
+ * Inverse of `Obj.getSnapshot`.
227
+ *
228
+ * Uses `Obj.getDatabase` internally to get the database from the snapshot,
229
+ * then resolves the reactive object by ID.
230
+ *
231
+ * @param snapshot - A snapshot of the object (from `Obj.getSnapshot`).
232
+ * @returns Effect that succeeds with the reactive object, or fails with `GetReactiveError`.
233
+ * @example
234
+ * ```ts
235
+ * const snapshot = Obj.getSnapshot(obj);
236
+ * const reactive = Obj.getReactive(snapshot).pipe(
237
+ * Effect.runSync
238
+ * );
239
+ * ```
240
+ */
241
+ export const getReactive = <T extends Unknown>(snapshot: Snapshot<T>): Effect.Effect<T, Err.GetReactiveError> =>
242
+ Effect.gen(function* () {
243
+ const db = getDatabase$(snapshot);
244
+ if (!db) {
245
+ return yield* Effect.fail(new Err.GetReactiveError({ reason: 'no-database', snapshotId: snapshot.id }));
246
+ }
247
+ const obj = db.getObjectById(snapshot.id);
248
+ if (!obj) {
249
+ return yield* Effect.fail(new Err.GetReactiveError({ reason: 'object-not-found', snapshotId: snapshot.id }));
250
+ }
251
+ return obj as T;
252
+ });
253
+
254
+ /**
255
+ * Like `Obj.getReactive` but returns `Option.none()` instead of failing when the object
256
+ * cannot be resolved (no database, object not found).
257
+ *
258
+ * @param snapshot - A snapshot of the object (from `Obj.getSnapshot`).
259
+ * @returns Effect that succeeds with `Option.some(reactive)` or `Option.none()`.
260
+ */
261
+ export const getReactiveOption = <T extends Unknown>(snapshot: Snapshot<T>): Effect.Effect<Option.Option<T>, never> =>
262
+ getReactive(snapshot).pipe(
263
+ Effect.map(Option.some),
264
+ Effect.catchAll(() => Effect.succeed(Option.none())),
265
+ );
266
+
267
+ /**
268
+ * Synchronous version of `Obj.getReactive`. Returns the reactive object or throws
269
+ * `GetReactiveError` when the object cannot be resolved (no database, object not found).
270
+ *
271
+ * @param snapshot - A snapshot of the object (from `Obj.getSnapshot`).
272
+ * @returns The reactive object.
273
+ * @throws {Err.GetReactiveError} When the object cannot be resolved.
274
+ */
275
+ export const getReactiveOrThrow = <T extends Unknown>(snapshot: Snapshot<T>): T =>
276
+ Effect.runSync(getReactive(snapshot));
277
+
210
278
  export type CloneOptions = {
211
279
  /**
212
280
  * Retain the original object's ID.
@@ -316,7 +384,7 @@ export const getValue = (obj: Unknown | Snapshot, path: readonly (string | numbe
316
384
  * @example
317
385
  * ```ts
318
386
  * const person = Obj.make(Person, { name: 'John' });
319
- * // Person schema has: addresses: Schema.mutable(Schema.Array(Address))
387
+ * // Person schema has: addresses: Schema.Array(Address)
320
388
  * Obj.change(person, (p) => {
321
389
  * Obj.setValue(p, ['addresses', 0, 'street'], '123 Main St');
322
390
  * });
@@ -357,6 +425,33 @@ export const instanceOf: {
357
425
  return isInstanceOf(args[0], args[1]);
358
426
  }) as any;
359
427
 
428
+ /**
429
+ * Test if a snapshot is an instance of a schema.
430
+ * Mirrors `instanceOf` but only accepts values branded with SnapshotKindId.
431
+ * Use when the value is known to be a snapshot (e.g. from `getSnapshot` or `useObject`).
432
+ *
433
+ * @example
434
+ * ```ts
435
+ * const snapshot = Obj.getSnapshot(person);
436
+ * if (Obj.snapshotOf(Person, snapshot)) {
437
+ * // snapshot is Obj.Snapshot<Person>
438
+ * }
439
+ * ```
440
+ */
441
+ export const snapshotOf: {
442
+ <S extends Type.Entity.Any>(schema: S): (value: unknown) => value is Snapshot<Schema.Schema.Type<S>>;
443
+ <S extends Type.Entity.Any>(schema: S, value: unknown): value is Snapshot<Schema.Schema.Type<S>>;
444
+ } = ((...args: [schema: Type.Entity.Any, value: unknown] | [schema: Type.Entity.Any]) => {
445
+ const check = (entity: unknown) =>
446
+ entity != null && typeof entity === 'object' && SnapshotKindId in entity && isInstanceOf(args[0], entity);
447
+
448
+ if (args.length === 1) {
449
+ return (entity: unknown) => check(entity);
450
+ }
451
+
452
+ return check(args[1]);
453
+ }) as any;
454
+
360
455
  // TODO(dmaretskyi): Allow returning undefined.
361
456
  /**
362
457
  * Get the DXN of the object.
@@ -396,7 +491,8 @@ export const getTypename = (entity: Unknown | Snapshot): string | undefined => g
396
491
  * Get the database the object belongs to.
397
492
  * Accepts both reactive objects and snapshots.
398
493
  */
399
- export const getDatabase = (entity: Unknown | Snapshot): Database.Database | undefined => getDatabase$(entity);
494
+ export const getDatabase = (entity: Entity.Unknown | Entity.Snapshot): Database.Database | undefined =>
495
+ getDatabase$(entity);
400
496
 
401
497
  //
402
498
  // Meta
@@ -436,9 +532,9 @@ export type Meta = ApiMeta;
436
532
  * ```
437
533
  */
438
534
  // TODO(wittjosiah): When passed a Snapshot, should return a snapshot of meta, not the live meta proxy.
439
- export function getMeta(entity: Mutable<Unknown>): ObjectMeta;
535
+ export function getMeta(entity: Mutable<Unknown>): Meta;
440
536
  export function getMeta(entity: Unknown | Snapshot): ReadonlyMeta;
441
- export function getMeta(entity: Unknown | Snapshot | Mutable<Unknown>): ObjectMeta | ReadonlyMeta {
537
+ export function getMeta(entity: Unknown | Snapshot | Mutable<Unknown>): Meta | ReadonlyMeta {
442
538
  return getMeta$(entity);
443
539
  }
444
540
 
@@ -520,6 +616,43 @@ export const getDescription = (entity: Unknown | Snapshot): string | undefined =
520
616
  export const setDescription = (entity: Mutable<Unknown>, description: string): void =>
521
617
  setDescription$(entity, description);
522
618
 
619
+ /**
620
+ * Symbol to set parent when creating objects with `Obj.make`.
621
+ * @example
622
+ * ```ts
623
+ * Obj.make(TestSchema.Person, {
624
+ * [Obj.Parent]: parentObject,
625
+ * name: 'John',
626
+ * })
627
+ * ```
628
+ */
629
+ export const Parent: unique symbol = ParentId as any;
630
+
631
+ /**
632
+ * Get the parent of an object.
633
+ * The parent is always loaded together with the object.
634
+ * Only objects are allowed to have a parent
635
+ * @returns The parent object, or undefined if the object has no parent.
636
+ */
637
+ export const getParent = (entity: Unknown | Snapshot): Unknown | undefined => {
638
+ assertArgument(isObject(entity), 'Expected an object');
639
+ assumeType<InternalObjectProps>(entity);
640
+ return entity[ParentId] as Unknown | undefined;
641
+ };
642
+
643
+ /**
644
+ * Sets the parent of an object.
645
+ * If a parent (or any transitive parent) is deleted, the object will be deleted.
646
+ * Only objects are allowed to have a parent.
647
+ */
648
+ export const setParent = (entity: Unknown, parent: Any | undefined) => {
649
+ assertArgument(isObject(entity), 'Expected an object');
650
+ assertArgument(parent === undefined || isObject(parent), 'Expected an object');
651
+ assumeType<InternalObjectProps>(entity);
652
+ assumeType<InternalObjectProps | undefined>(parent);
653
+ entity[ParentId] = parent;
654
+ };
655
+
523
656
  //
524
657
  // JSON
525
658
  //
@@ -549,10 +682,6 @@ export const toJSON = (entity: Unknown | Snapshot): JSON => toJSON$(entity);
549
682
  export const fromJSON: (json: unknown, options?: { refResolver?: Ref.Resolver; dxn?: DXN }) => Promise<Unknown> =
550
683
  objectFromJSON as any;
551
684
 
552
- //
553
- // Sorting
554
- //
555
-
556
685
  /**
557
686
  * Comparator function type for sorting objects.
558
687
  * Accepts both reactive objects and snapshots.
package/src/Query.ts CHANGED
@@ -102,6 +102,18 @@ export interface Query<T> {
102
102
  */
103
103
  target(): Query<Type$.Relation.Target<T>>;
104
104
 
105
+ /**
106
+ * Get the parent object of the current selection.
107
+ * @returns Query for the parent objects.
108
+ */
109
+ parent(): Query<any>;
110
+
111
+ /**
112
+ * Get all child objects of the current selection.
113
+ * @returns Query for the child objects.
114
+ */
115
+ children(): Query<any>;
116
+
105
117
  /**
106
118
  * Order the query results.
107
119
  * Orders are specified in priority order. The first order will be applied first, etc.
@@ -202,6 +214,22 @@ class QueryClass implements Any {
202
214
  });
203
215
  }
204
216
 
217
+ parent(): Any {
218
+ return new QueryClass({
219
+ type: 'hierarchy-traversal',
220
+ anchor: this.ast,
221
+ direction: 'to-parent',
222
+ });
223
+ }
224
+
225
+ children(): Any {
226
+ return new QueryClass({
227
+ type: 'hierarchy-traversal',
228
+ anchor: this.ast,
229
+ direction: 'to-children',
230
+ });
231
+ }
232
+
205
233
  orderBy(...order: Order.Order<any>[]): Any {
206
234
  return new QueryClass({
207
235
  type: 'order',
package/src/Relation.ts CHANGED
@@ -29,6 +29,7 @@ import {
29
29
  MetaId,
30
30
  type Mutable,
31
31
  type ObjectMeta,
32
+ ParentId,
32
33
  RelationSourceDXNId,
33
34
  RelationSourceId,
34
35
  RelationTargetDXNId,
@@ -133,7 +134,7 @@ export type MakeProps<S extends Type.Relation.Any> = RelationMakeProps<Schema.Sc
133
134
  * Creates new relation.
134
135
  * @param schema - Relation schema.
135
136
  * @param props - Relation properties. Endpoints are passed as [Relation.Source] and [Relation.Target] keys.
136
- * @param meta - Relation metadata.
137
+ * @param meta - Relation metadata. (deprecated; use [Obj.Meta] instead)
137
138
  * @returns
138
139
  */
139
140
  // NOTE: Writing the definition this way (with generic over schema) makes typescript perfer to infer the type from the first param (this schema) rather than the second param (the props).
@@ -144,6 +145,7 @@ export const make = <S extends Type.Relation.Any>(
144
145
  meta?: ObjectMeta,
145
146
  ): Schema.Schema.Type<S> & Entity.OfKind<typeof Entity.Kind.Relation> => {
146
147
  assertArgument(getTypeAnnotation(schema)?.kind === EntityKind.Relation, 'schema', 'Expected a relation schema');
148
+ assertArgument(props[ParentId] === undefined, 'props', 'Parent is not allowed for relations');
147
149
 
148
150
  if (props[MetaId] != null) {
149
151
  meta = props[MetaId] as any;
@@ -372,9 +374,9 @@ export type Meta = ApiMeta;
372
374
  * Returns read-only meta when passed a regular relation or snapshot.
373
375
  */
374
376
  // TODO(wittjosiah): When passed a Snapshot, should return a snapshot of meta, not the live meta proxy.
375
- export function getMeta(entity: Mutable<Unknown>): ObjectMeta;
377
+ export function getMeta(entity: Mutable<Unknown>): Meta;
376
378
  export function getMeta(entity: Unknown | Snapshot): ReadonlyMeta;
377
- export function getMeta(entity: Unknown | Snapshot | Mutable<Unknown>): ObjectMeta | ReadonlyMeta {
379
+ export function getMeta(entity: Unknown | Snapshot | Mutable<Unknown>): Meta | ReadonlyMeta {
378
380
  return getMeta$(entity);
379
381
  }
380
382
 
@@ -0,0 +1,33 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { describe, expect, test } from 'vitest';
6
+
7
+ import * as Obj from './Obj';
8
+ import { TestSchema } from './testing';
9
+
10
+ describe('Hierarchy', () => {
11
+ test('setParent and getParent', async () => {
12
+ const parent = Obj.make(TestSchema.Organization, { name: 'parent' });
13
+ const child = Obj.make(TestSchema.Person, { name: 'child' });
14
+ expect(Obj.getParent(child)).toBeUndefined();
15
+
16
+ Obj.setParent(child, parent);
17
+ expect(Obj.getParent(child)).toBe(parent);
18
+
19
+ Obj.setParent(child, undefined);
20
+ expect(Obj.getParent(child)).toBeUndefined();
21
+ });
22
+
23
+ test('create object with Obj.Parent in props', () => {
24
+ const parent = Obj.make(TestSchema.Organization, { name: 'DXOS' });
25
+ const child = Obj.make(TestSchema.Person, {
26
+ [Obj.Parent]: parent,
27
+ name: 'John',
28
+ });
29
+
30
+ expect(child.name).toBe('John');
31
+ expect(Obj.getParent(child)).toBe(parent);
32
+ });
33
+ });
@@ -15,7 +15,7 @@ import { type Primitive } from '@dxos/util';
15
15
 
16
16
  import { type AnyProperties, EntityKind, TypeId, getSchema } from '../types';
17
17
 
18
- import { createAnnotationHelper } from './util';
18
+ import { type AnnotationHelper, createAnnotationHelper } from './util';
19
19
 
20
20
  /**
21
21
  * @internal
@@ -458,3 +458,30 @@ export type GeneratorAnnotationValue =
458
458
  };
459
459
 
460
460
  export const GeneratorAnnotation = createAnnotationHelper<GeneratorAnnotationValue>(GeneratorAnnotationId);
461
+
462
+ interface MakeAnnoationsProps<T> {
463
+ id: string;
464
+ schema: Schema.Schema<T, any, never>;
465
+ }
466
+
467
+ // TODO(wittjosiah): Comment.
468
+ export const makeUserAnnotation = <T>(props: MakeAnnoationsProps<T>): AnnotationHelper<T> => {
469
+ assertArgument(
470
+ /[a-zA-Z0-9]+\.[a-zA-Z.]+\/[a-zA-Z/]+/.test(props.id),
471
+ 'id',
472
+ 'Annotation id must be in the FQN format (dxos.org/annotation/Example).',
473
+ );
474
+
475
+ const getFromAst = (ast: SchemaAST.AST) =>
476
+ SchemaAST.getAnnotation<PropertyMetaAnnotation>(PropertyMetaAnnotationId)(ast).pipe(
477
+ Option.map((meta) => meta[props.id] as unknown),
478
+ Option.map(Schema.decodeUnknownSync(props.schema)),
479
+ );
480
+
481
+ return {
482
+ get: (schema) => getFromAst(schema.ast),
483
+ getFromAst: (ast) => getFromAst(ast),
484
+ set: (value) =>
485
+ PropertyMeta(props.id, Schema.encodeSync(props.schema)(value)) as <S extends Schema.Schema.Any>(schema: S) => S,
486
+ };
487
+ };
@@ -12,11 +12,24 @@ import { DXN } from '@dxos/keys';
12
12
  import { EntityKind } from '../types';
13
13
 
14
14
  export interface AnnotationHelper<T> {
15
+ /**
16
+ * Get the annotation value from the schema.
17
+ */
15
18
  get: (schema: Schema.Schema.Any) => Option.Option<T>;
19
+ /**
20
+ * Get the annotation value from the AST.
21
+ */
16
22
  getFromAst: (ast: SchemaAST.AST) => Option.Option<T>;
23
+ /**
24
+ * Set the annotation value on the schema.
25
+ */
17
26
  set: (value: T) => <S extends Schema.Schema.Any>(schema: S) => S;
18
27
  }
19
28
 
29
+ /**
30
+ * Note: only for system annotations.
31
+ */
32
+ // TODO(dmaretskyi): Rename to createSystemAnnotationHelper.
20
33
  export const createAnnotationHelper = <T>(id: symbol): AnnotationHelper<T> => {
21
34
  return {
22
35
  get: (schema) => SchemaAST.getAnnotation(schema.ast, id),
@@ -17,7 +17,7 @@ export type ReadonlyMeta = DeepReadonly<ObjectMeta>;
17
17
  /**
18
18
  * Mutable meta type received in meta mutation callbacks.
19
19
  */
20
- export type Meta = ObjectMeta;
20
+ export type Meta = Mutable<ObjectMeta>;
21
21
 
22
22
  /**
23
23
  * Get the metadata for an entity with validation.
@@ -26,9 +26,9 @@ export type Meta = ObjectMeta;
26
26
  *
27
27
  * TODO(burdon): When passed a Snapshot, should return a snapshot of meta, not the live meta proxy.
28
28
  */
29
- export function getMetaChecked(entity: Mutable<AnyProperties>): ObjectMeta;
29
+ export function getMetaChecked(entity: Mutable<AnyProperties>): Meta;
30
30
  export function getMetaChecked(entity: AnyProperties): ReadonlyMeta;
31
- export function getMetaChecked(entity: AnyProperties): ObjectMeta | ReadonlyMeta {
31
+ export function getMetaChecked(entity: AnyProperties): Meta | ReadonlyMeta {
32
32
  assertArgument(entity, 'entity', 'Should be an entity.');
33
33
  const meta = getMeta$(entity);
34
34
  invariant(meta != null, 'Invalid entity.');
@@ -12,11 +12,13 @@ import { assumeType } from '@dxos/util';
12
12
  import type * as Database from '../../Database';
13
13
  import {
14
14
  type ATTR_META,
15
+ type ATTR_PARENT,
15
16
  type ATTR_TYPE,
16
17
  EntityKind,
17
18
  KindId,
18
19
  type MetaId,
19
20
  type ObjectMeta,
21
+ type ParentId,
20
22
  type SchemaId,
21
23
  TypeId,
22
24
  type Version,
@@ -77,6 +79,7 @@ export interface InternalObjectProps {
77
79
  readonly [SchemaId]: Schema.Schema.AnyNoContext;
78
80
  readonly [TypeId]: DXN;
79
81
  readonly [MetaId]?: ObjectMeta;
82
+ [ParentId]?: InternalObjectProps;
80
83
  readonly [ObjectDatabaseId]?: Database.Database;
81
84
  readonly [ObjectDeletedId]?: boolean;
82
85
  readonly [ObjectVersionId]?: Version;
@@ -101,6 +104,7 @@ export interface ObjectJSON {
101
104
  id: string;
102
105
  [ATTR_TYPE]: DXN.String;
103
106
  [ATTR_SELF_DXN]?: DXN.String;
107
+ [ATTR_PARENT]?: string; // Encoded reference
104
108
  [ATTR_DELETED]?: boolean;
105
109
  [ATTR_META]?: ObjectMetaJSON;
106
110
  [ATTR_RELATION_SOURCE]?: DXN.String;
@@ -40,9 +40,7 @@ export const EchoObjectSchema: {
40
40
  // Extract fields from the schema if available (Struct schemas have .fields).
41
41
  const fields = ((self as any).fields ?? {}) as Fields;
42
42
 
43
- // TODO(dmaretskyi): Does `Schema.mutable` work for deep mutability here?
44
- // TODO(dmaretskyi): Do not do mutable here.
45
- const schemaWithId = Schema.extend(Schema.mutable(self), Schema.Struct({ id: Schema.String }));
43
+ const schemaWithId = Schema.extend(self, Schema.Struct({ id: Schema.String }));
46
44
  const ast = SchemaAST.annotations(schemaWithId.ast, {
47
45
  // TODO(dmaretskyi): `extend` kills the annotations.
48
46
  ...self.ast.annotations,
@@ -129,9 +129,7 @@ export const EchoRelationSchema = <
129
129
  // Extract fields from the schema if available (Struct schemas have .fields).
130
130
  const fields = ((self as any).fields ?? {}) as Fields;
131
131
 
132
- // TODO(dmaretskyi): Does `Schema.mutable` work for deep mutability here?
133
- // TODO(dmaretskyi): Do not do mutable here.
134
- const schemaWithId = Schema.extend(Schema.mutable(self), Schema.Struct({ id: Schema.String }));
132
+ const schemaWithId = Schema.extend(self, Schema.Struct({ id: Schema.String }));
135
133
  const ast = SchemaAST.annotations(schemaWithId.ast, {
136
134
  // TODO(dmaretskyi): `extend` kills the annotations.
137
135
  ...self.ast.annotations,
@@ -20,7 +20,7 @@ describe('formats', () => {
20
20
  birthday: Schema.optional(Format.Date),
21
21
  started: Schema.optional(Format.DateTime),
22
22
  active: Schema.optional(Schema.Boolean),
23
- }).pipe(Schema.mutable);
23
+ });
24
24
 
25
25
  type TestType = Schema.Schema.Type<typeof TestSchema>;
26
26
 
@@ -13,6 +13,6 @@ export const SelectOption = Schema.Struct({
13
13
  title: Schema.String,
14
14
  /** Color palette used for visual styling. */
15
15
  color: Schema.String,
16
- }).pipe(Schema.mutable);
16
+ });
17
17
 
18
18
  export type SelectOption = Schema.Schema.Type<typeof SelectOption>;
@@ -135,7 +135,7 @@ export const typeToFormat: Partial<Record<TypeEnum, TypeFormat>> = {
135
135
  * Map of format to type.
136
136
  */
137
137
  export const formatToType: Record<TypeFormat, TypeEnum> = {
138
- [TypeFormat.None]: undefined as any,
138
+ [TypeFormat.None]: TypeEnum.String,
139
139
  [TypeFormat.String]: TypeEnum.String,
140
140
  [TypeFormat.Number]: TypeEnum.Number,
141
141
  [TypeFormat.Boolean]: TypeEnum.Boolean,
@@ -2,6 +2,8 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import type * as Types from 'effect/Types';
6
+
5
7
  import { JsonSchemaFields, type JsonSchemaType } from './json-schema-type';
6
8
 
7
9
  /**
@@ -9,12 +11,12 @@ import { JsonSchemaFields, type JsonSchemaType } from './json-schema-type';
9
11
  * Note: the input type does not necessarily match the {@link JsonSchemaType} type.
10
12
  */
11
13
  export const normalizeSchema = (schema: JsonSchemaType): JsonSchemaType => {
12
- const copy = structuredClone(schema);
14
+ const copy = structuredClone(schema) as Types.DeepMutable<JsonSchemaType>;
13
15
  go(copy);
14
16
  return copy;
15
17
  };
16
18
 
17
- const go = (schema: JsonSchemaType) => {
19
+ const go = (schema: Types.DeepMutable<JsonSchemaType>) => {
18
20
  if (typeof schema !== 'object' || schema === null) {
19
21
  return;
20
22
  }