@dxos/echo 0.10.0 → 0.11.0

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 (274) hide show
  1. package/dist/lib/Annotation.mjs +3 -0
  2. package/dist/lib/Blob.mjs +160 -0
  3. package/dist/lib/Blob.mjs.map +1 -0
  4. package/dist/lib/Database.mjs +2 -0
  5. package/dist/lib/Entity.mjs +231 -0
  6. package/dist/lib/Entity.mjs.map +1 -0
  7. package/dist/lib/Err.mjs +105 -0
  8. package/dist/lib/Err.mjs.map +1 -0
  9. package/dist/lib/Feed.mjs +338 -0
  10. package/dist/lib/Feed.mjs.map +1 -0
  11. package/dist/lib/Filter.mjs +380 -0
  12. package/dist/lib/Filter.mjs.map +1 -0
  13. package/dist/lib/Format.mjs +47 -0
  14. package/dist/lib/Format.mjs.map +1 -0
  15. package/dist/lib/JsonSchema.mjs +21 -0
  16. package/dist/lib/JsonSchema.mjs.map +1 -0
  17. package/dist/lib/Key.mjs +15 -0
  18. package/dist/lib/Key.mjs.map +1 -0
  19. package/dist/lib/Migration.mjs +38 -0
  20. package/dist/lib/Migration.mjs.map +1 -0
  21. package/dist/lib/Obj.mjs +660 -0
  22. package/dist/lib/Obj.mjs.map +1 -0
  23. package/dist/lib/Order.mjs +65 -0
  24. package/dist/lib/Order.mjs.map +1 -0
  25. package/dist/lib/Query.mjs +336 -0
  26. package/dist/lib/Query.mjs.map +1 -0
  27. package/dist/lib/QueryResult.mjs +7 -0
  28. package/dist/lib/QueryResult.mjs.map +1 -0
  29. package/dist/lib/Ref.mjs +44 -0
  30. package/dist/lib/Ref.mjs.map +1 -0
  31. package/dist/lib/Registry.mjs +35 -0
  32. package/dist/lib/Registry.mjs.map +1 -0
  33. package/dist/lib/Relation.mjs +397 -0
  34. package/dist/lib/Relation.mjs.map +1 -0
  35. package/dist/lib/Scope.mjs +51 -0
  36. package/dist/lib/Scope.mjs.map +1 -0
  37. package/dist/lib/Tag.mjs +70 -0
  38. package/dist/lib/Tag.mjs.map +1 -0
  39. package/dist/lib/Text.mjs +82 -0
  40. package/dist/lib/Text.mjs.map +1 -0
  41. package/dist/lib/Type.mjs +371 -0
  42. package/dist/lib/Type.mjs.map +1 -0
  43. package/dist/lib/chunk-Annotation.mjs +221 -0
  44. package/dist/lib/chunk-Annotation.mjs.map +1 -0
  45. package/dist/lib/chunk-Database.mjs +918 -0
  46. package/dist/lib/chunk-Database.mjs.map +1 -0
  47. package/dist/lib/chunk-atom-snapshot.mjs +249 -0
  48. package/dist/lib/chunk-atom-snapshot.mjs.map +1 -0
  49. package/dist/lib/chunk-internal.mjs +2775 -0
  50. package/dist/lib/chunk-internal.mjs.map +1 -0
  51. package/dist/lib/chunk-json-schema.mjs +660 -0
  52. package/dist/lib/chunk-json-schema.mjs.map +1 -0
  53. package/dist/lib/chunk-number.mjs +164 -0
  54. package/dist/lib/chunk-number.mjs.map +1 -0
  55. package/dist/lib/chunk-ref-array.mjs +31 -0
  56. package/dist/lib/chunk-ref-array.mjs.map +1 -0
  57. package/dist/lib/chunk-ref.mjs +590 -0
  58. package/dist/lib/chunk-ref.mjs.map +1 -0
  59. package/dist/lib/chunk-rolldown-runtime.mjs +13 -0
  60. package/dist/lib/chunk-select.mjs +186 -0
  61. package/dist/lib/chunk-select.mjs.map +1 -0
  62. package/dist/lib/chunk-src.mjs +234 -0
  63. package/dist/lib/chunk-src.mjs.map +1 -0
  64. package/dist/lib/chunk-util.mjs +140 -0
  65. package/dist/lib/chunk-util.mjs.map +1 -0
  66. package/dist/lib/index.mjs +24 -0
  67. package/dist/lib/internal.mjs +10 -0
  68. package/dist/lib/testing.mjs +346 -0
  69. package/dist/lib/testing.mjs.map +1 -0
  70. package/dist/types/src/Aggregate.d.ts +86 -0
  71. package/dist/types/src/Aggregate.d.ts.map +1 -0
  72. package/dist/types/src/Blob.d.ts +153 -0
  73. package/dist/types/src/Blob.d.ts.map +1 -0
  74. package/dist/types/src/Blob.test.d.ts +2 -0
  75. package/dist/types/src/Blob.test.d.ts.map +1 -0
  76. package/dist/types/src/Database.d.ts +153 -4
  77. package/dist/types/src/Database.d.ts.map +1 -1
  78. package/dist/types/src/Err.d.ts +116 -0
  79. package/dist/types/src/Err.d.ts.map +1 -1
  80. package/dist/types/src/Feed.d.ts +116 -28
  81. package/dist/types/src/Feed.d.ts.map +1 -1
  82. package/dist/types/src/Feed.test.d.ts +2 -0
  83. package/dist/types/src/Feed.test.d.ts.map +1 -0
  84. package/dist/types/src/Filter.d.ts +14 -6
  85. package/dist/types/src/Filter.d.ts.map +1 -1
  86. package/dist/types/src/Hypergraph.d.ts +18 -0
  87. package/dist/types/src/Hypergraph.d.ts.map +1 -1
  88. package/dist/types/src/Json.d.ts.map +1 -1
  89. package/dist/types/src/Obj.d.ts +14 -1
  90. package/dist/types/src/Obj.d.ts.map +1 -1
  91. package/dist/types/src/Order.d.ts +9 -3
  92. package/dist/types/src/Order.d.ts.map +1 -1
  93. package/dist/types/src/Query.d.ts +107 -26
  94. package/dist/types/src/Query.d.ts.map +1 -1
  95. package/dist/types/src/Relation.d.ts +6 -0
  96. package/dist/types/src/Relation.d.ts.map +1 -1
  97. package/dist/types/src/Type.d.ts.map +1 -1
  98. package/dist/types/src/View.d.ts +1 -1
  99. package/dist/types/src/index.d.ts +2 -0
  100. package/dist/types/src/index.d.ts.map +1 -1
  101. package/dist/types/src/internal/Entity/api.d.ts +6 -0
  102. package/dist/types/src/internal/Entity/api.d.ts.map +1 -1
  103. package/dist/types/src/internal/Entity/model.d.ts +3 -2
  104. package/dist/types/src/internal/Entity/model.d.ts.map +1 -1
  105. package/dist/types/src/internal/Filter/match.d.ts.map +1 -1
  106. package/dist/types/src/internal/JsonSchema/json-schema-type.d.ts +34 -8
  107. package/dist/types/src/internal/JsonSchema/json-schema-type.d.ts.map +1 -1
  108. package/dist/types/src/internal/JsonSchema/json-schema.d.ts.map +1 -1
  109. package/dist/types/src/internal/Obj/atoms.d.ts.map +1 -1
  110. package/dist/types/src/internal/Obj/json-serializer.d.ts.map +1 -1
  111. package/dist/types/src/internal/Query/pretty.d.ts.map +1 -1
  112. package/dist/types/src/internal/Query/query-result-effect.d.ts.map +1 -1
  113. package/dist/types/src/internal/common/proxy/make-object.d.ts +13 -0
  114. package/dist/types/src/internal/common/proxy/make-object.d.ts.map +1 -1
  115. package/dist/types/src/internal/common/proxy/reactive.d.ts.map +1 -1
  116. package/dist/types/src/internal/common/proxy/symbols.d.ts.map +1 -1
  117. package/dist/types/src/internal/common/proxy/typed-handler.d.ts +12 -0
  118. package/dist/types/src/internal/common/proxy/typed-handler.d.ts.map +1 -1
  119. package/dist/types/src/internal/common/types/index.d.ts +1 -0
  120. package/dist/types/src/internal/common/types/index.d.ts.map +1 -1
  121. package/dist/types/src/internal/common/types/model-symbols.d.ts +5 -0
  122. package/dist/types/src/internal/common/types/model-symbols.d.ts.map +1 -1
  123. package/dist/types/src/internal/common/types/projection.d.ts +32 -0
  124. package/dist/types/src/internal/common/types/projection.d.ts.map +1 -0
  125. package/dist/types/tsconfig.tsbuildinfo +1 -1
  126. package/package.json +40 -35
  127. package/src/Aggregate.ts +105 -0
  128. package/src/Blob.test.ts +45 -0
  129. package/src/Blob.ts +205 -0
  130. package/src/Database.ts +207 -17
  131. package/src/Err.ts +36 -0
  132. package/src/Feed.test.ts +188 -0
  133. package/src/Feed.ts +238 -62
  134. package/src/Filter.ts +28 -10
  135. package/src/Hypergraph.ts +18 -0
  136. package/src/Json.ts +1 -0
  137. package/src/Obj.test.ts +2 -2
  138. package/src/Obj.ts +21 -1
  139. package/src/Order.ts +16 -9
  140. package/src/Query.test.ts +319 -2
  141. package/src/Query.ts +165 -51
  142. package/src/Relation.ts +14 -0
  143. package/src/Type.ts +5 -6
  144. package/src/index.ts +2 -0
  145. package/src/internal/Entity/api.ts +11 -1
  146. package/src/internal/Entity/model.ts +3 -0
  147. package/src/internal/Filter/match.ts +30 -1
  148. package/src/internal/JsonSchema/json-schema-type.ts +14 -2
  149. package/src/internal/JsonSchema/json-schema.test.ts +28 -1
  150. package/src/internal/JsonSchema/json-schema.ts +33 -6
  151. package/src/internal/Obj/atoms.ts +4 -2
  152. package/src/internal/Obj/json-serializer.test.ts +162 -2
  153. package/src/internal/Obj/json-serializer.ts +6 -0
  154. package/src/internal/Query/pretty.ts +19 -1
  155. package/src/internal/Query/query-result-effect.ts +2 -4
  156. package/src/internal/Ref/atoms.ts +1 -1
  157. package/src/internal/common/proxy/change-context.ts +1 -1
  158. package/src/internal/common/proxy/make-object.ts +42 -3
  159. package/src/internal/common/proxy/reactive.ts +5 -0
  160. package/src/internal/common/proxy/symbols.ts +1 -0
  161. package/src/internal/common/proxy/typed-handler.ts +71 -29
  162. package/src/internal/common/types/index.ts +1 -0
  163. package/src/internal/common/types/model-symbols.ts +6 -0
  164. package/src/internal/common/types/projection.ts +45 -0
  165. package/src/testing/test-data.ts +14 -14
  166. package/dist/lib/neutral/Annotation.mjs +0 -90
  167. package/dist/lib/neutral/Annotation.mjs.map +0 -7
  168. package/dist/lib/neutral/Database.mjs +0 -42
  169. package/dist/lib/neutral/Database.mjs.map +0 -7
  170. package/dist/lib/neutral/Entity.mjs +0 -76
  171. package/dist/lib/neutral/Entity.mjs.map +0 -7
  172. package/dist/lib/neutral/Err.mjs +0 -16
  173. package/dist/lib/neutral/Err.mjs.map +0 -7
  174. package/dist/lib/neutral/Feed.mjs +0 -50
  175. package/dist/lib/neutral/Feed.mjs.map +0 -7
  176. package/dist/lib/neutral/Filter.mjs +0 -72
  177. package/dist/lib/neutral/Filter.mjs.map +0 -7
  178. package/dist/lib/neutral/Format.mjs +0 -82
  179. package/dist/lib/neutral/Format.mjs.map +0 -7
  180. package/dist/lib/neutral/JsonSchema.mjs +0 -18
  181. package/dist/lib/neutral/JsonSchema.mjs.map +0 -7
  182. package/dist/lib/neutral/Key.mjs +0 -16
  183. package/dist/lib/neutral/Key.mjs.map +0 -7
  184. package/dist/lib/neutral/Migration.mjs +0 -18
  185. package/dist/lib/neutral/Migration.mjs.map +0 -7
  186. package/dist/lib/neutral/Obj.mjs +0 -128
  187. package/dist/lib/neutral/Obj.mjs.map +0 -7
  188. package/dist/lib/neutral/Order.mjs +0 -16
  189. package/dist/lib/neutral/Order.mjs.map +0 -7
  190. package/dist/lib/neutral/Query.mjs +0 -38
  191. package/dist/lib/neutral/Query.mjs.map +0 -7
  192. package/dist/lib/neutral/QueryResult.mjs +0 -2
  193. package/dist/lib/neutral/QueryResult.mjs.map +0 -7
  194. package/dist/lib/neutral/Ref.mjs +0 -25
  195. package/dist/lib/neutral/Ref.mjs.map +0 -7
  196. package/dist/lib/neutral/Registry.mjs +0 -14
  197. package/dist/lib/neutral/Registry.mjs.map +0 -7
  198. package/dist/lib/neutral/Relation.mjs +0 -97
  199. package/dist/lib/neutral/Relation.mjs.map +0 -7
  200. package/dist/lib/neutral/Scope.mjs +0 -12
  201. package/dist/lib/neutral/Scope.mjs.map +0 -7
  202. package/dist/lib/neutral/Tag.mjs +0 -32
  203. package/dist/lib/neutral/Tag.mjs.map +0 -7
  204. package/dist/lib/neutral/Text.mjs +0 -25
  205. package/dist/lib/neutral/Text.mjs.map +0 -7
  206. package/dist/lib/neutral/Type.mjs +0 -65
  207. package/dist/lib/neutral/Type.mjs.map +0 -7
  208. package/dist/lib/neutral/chunk-2HKGAQM4.mjs +0 -1394
  209. package/dist/lib/neutral/chunk-2HKGAQM4.mjs.map +0 -7
  210. package/dist/lib/neutral/chunk-2ZHECXUR.mjs +0 -95
  211. package/dist/lib/neutral/chunk-2ZHECXUR.mjs.map +0 -7
  212. package/dist/lib/neutral/chunk-3KTE2Y7Q.mjs +0 -336
  213. package/dist/lib/neutral/chunk-3KTE2Y7Q.mjs.map +0 -7
  214. package/dist/lib/neutral/chunk-3TN2VMI4.mjs +0 -714
  215. package/dist/lib/neutral/chunk-3TN2VMI4.mjs.map +0 -7
  216. package/dist/lib/neutral/chunk-42L4HJ3Z.mjs +0 -104
  217. package/dist/lib/neutral/chunk-42L4HJ3Z.mjs.map +0 -7
  218. package/dist/lib/neutral/chunk-4A2NWKRJ.mjs +0 -747
  219. package/dist/lib/neutral/chunk-4A2NWKRJ.mjs.map +0 -7
  220. package/dist/lib/neutral/chunk-7LOUAPYZ.mjs +0 -25
  221. package/dist/lib/neutral/chunk-7LOUAPYZ.mjs.map +0 -7
  222. package/dist/lib/neutral/chunk-ACFAOTKJ.mjs +0 -1531
  223. package/dist/lib/neutral/chunk-ACFAOTKJ.mjs.map +0 -7
  224. package/dist/lib/neutral/chunk-BEFR7LEA.mjs +0 -170
  225. package/dist/lib/neutral/chunk-BEFR7LEA.mjs.map +0 -7
  226. package/dist/lib/neutral/chunk-BXIKXT7Q.mjs +0 -89
  227. package/dist/lib/neutral/chunk-BXIKXT7Q.mjs.map +0 -7
  228. package/dist/lib/neutral/chunk-C57XMMBY.mjs +0 -206
  229. package/dist/lib/neutral/chunk-C57XMMBY.mjs.map +0 -7
  230. package/dist/lib/neutral/chunk-C62JYFAD.mjs +0 -183
  231. package/dist/lib/neutral/chunk-C62JYFAD.mjs.map +0 -7
  232. package/dist/lib/neutral/chunk-FSGX2R62.mjs +0 -48
  233. package/dist/lib/neutral/chunk-FSGX2R62.mjs.map +0 -7
  234. package/dist/lib/neutral/chunk-HBXT3GSB.mjs +0 -459
  235. package/dist/lib/neutral/chunk-HBXT3GSB.mjs.map +0 -7
  236. package/dist/lib/neutral/chunk-IQR45HAD.mjs +0 -31
  237. package/dist/lib/neutral/chunk-IQR45HAD.mjs.map +0 -7
  238. package/dist/lib/neutral/chunk-J5LGTIGS.mjs +0 -10
  239. package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +0 -7
  240. package/dist/lib/neutral/chunk-KCBW4BR6.mjs +0 -424
  241. package/dist/lib/neutral/chunk-KCBW4BR6.mjs.map +0 -7
  242. package/dist/lib/neutral/chunk-L3E5IXAE.mjs +0 -575
  243. package/dist/lib/neutral/chunk-L3E5IXAE.mjs.map +0 -7
  244. package/dist/lib/neutral/chunk-PRC4FEKJ.mjs +0 -56
  245. package/dist/lib/neutral/chunk-PRC4FEKJ.mjs.map +0 -7
  246. package/dist/lib/neutral/chunk-SCT6FFCR.mjs +0 -351
  247. package/dist/lib/neutral/chunk-SCT6FFCR.mjs.map +0 -7
  248. package/dist/lib/neutral/chunk-TOCVVFK2.mjs +0 -75
  249. package/dist/lib/neutral/chunk-TOCVVFK2.mjs.map +0 -7
  250. package/dist/lib/neutral/chunk-U53LSQQA.mjs +0 -41
  251. package/dist/lib/neutral/chunk-U53LSQQA.mjs.map +0 -7
  252. package/dist/lib/neutral/chunk-UGFFV2FR.mjs +0 -27
  253. package/dist/lib/neutral/chunk-UGFFV2FR.mjs.map +0 -7
  254. package/dist/lib/neutral/chunk-UWLP4RFM.mjs +0 -7
  255. package/dist/lib/neutral/chunk-UWLP4RFM.mjs.map +0 -7
  256. package/dist/lib/neutral/chunk-UZHCQ6NI.mjs +0 -283
  257. package/dist/lib/neutral/chunk-UZHCQ6NI.mjs.map +0 -7
  258. package/dist/lib/neutral/chunk-WISOH2XH.mjs +0 -36
  259. package/dist/lib/neutral/chunk-WISOH2XH.mjs.map +0 -7
  260. package/dist/lib/neutral/chunk-WKIT2YY5.mjs +0 -34
  261. package/dist/lib/neutral/chunk-WKIT2YY5.mjs.map +0 -7
  262. package/dist/lib/neutral/chunk-XB6ISRAO.mjs +0 -271
  263. package/dist/lib/neutral/chunk-XB6ISRAO.mjs.map +0 -7
  264. package/dist/lib/neutral/chunk-XXL42WCB.mjs +0 -84
  265. package/dist/lib/neutral/chunk-XXL42WCB.mjs.map +0 -7
  266. package/dist/lib/neutral/chunk-XXWK4J53.mjs +0 -117
  267. package/dist/lib/neutral/chunk-XXWK4J53.mjs.map +0 -7
  268. package/dist/lib/neutral/index.mjs +0 -115
  269. package/dist/lib/neutral/index.mjs.map +0 -7
  270. package/dist/lib/neutral/internal/index.mjs +0 -581
  271. package/dist/lib/neutral/internal/index.mjs.map +0 -7
  272. package/dist/lib/neutral/meta.json +0 -1
  273. package/dist/lib/neutral/testing/index.mjs +0 -477
  274. package/dist/lib/neutral/testing/index.mjs.map +0 -7
@@ -0,0 +1,2775 @@
1
+ import { a as isEntity, d as ATTR_META, f as EntityMetaSchema, g as getMeta, l as getMetaChecked, t as snapshotForComparison } from "./chunk-atom-snapshot.mjs";
2
+ import { d as SnapshotKindId, f as StaticTypeSchemaSlot, g as getStaticTypeSchema, l as KindId, n as makeTypeJsonSchemaAnnotation, o as EntityKind, u as SchemaKindId } from "./chunk-util.mjs";
3
+ import { $t as RelationTargetId, At as ATTR_PARENT, Bt as ATTR_DELETED, Ct as getTypename, E as getObjectEchoUri, Ft as TypeId, Gt as MetaId, Ht as ATTR_RELATION_TARGET, It as getSchema, Jt as ObjectDeletedId, Lt as getType, Mt as ParentId, Nt as SchemaId, Pt as TypeEntityId, Qt as RelationTargetDXNId, Rt as setSchema, St as getTypeURI, Ut as ATTR_SELF_URI, Vt as ATTR_RELATION_SOURCE, Wt as ATTR_SELF_URI_LEGACY, Xt as RelationSourceDXNId, Y as LabelAnnotation, Yt as ObjectVersionId, Zt as RelationSourceId, _t as getSchemaTypename, bt as getTypeAnnotation, en as SelfURIId, jt as ATTR_TYPE, kt as setTypename, pt as getLabel, q as IconAnnotation, qt as ObjectDatabaseId, rt as TypeAnnotationId, ut as getEntityKind, vt as getSchemaURI, w as getDatabase, xt as getTypeIdentifierAnnotation, zt as setType } from "./chunk-Database.mjs";
4
+ import { C as getProxyTarget, D as normalizeSpliceRange, E as isValidProxyTarget, O as symbolIsProxy, T as isReactiveRecord, _ as ChangeId, f as refFromEncodedReference, g as subscribe, i as RefTypeId, k as symbolReactivePrototype, m as loadRefTarget, n as Ref, p as setRefResolver, v as EventId, w as isProxy, y as createProxy } from "./chunk-ref.mjs";
5
+ import { c as JsonSchemaFields, l as JsonSchemaType, n as toEffectSchema, r as toJsonSchema } from "./chunk-json-schema.mjs";
6
+ import { EncodedReference, EntityStructure, isEncodedReference } from "@dxos/echo-protocol";
7
+ import { DXN, EID, EntityId, URI } from "@dxos/keys";
8
+ import * as Function from "effect/Function";
9
+ import * as Option from "effect/Option";
10
+ import * as Schema from "effect/Schema";
11
+ import * as SchemaAST from "effect/SchemaAST";
12
+ import { assertArgument, failedInvariant, invariant } from "@dxos/invariant";
13
+ import { SchemaEx } from "@dxos/effect";
14
+ import { assumeType, decodeUint8ArrayFromJson, deepMapValues, encodeUint8ArrayToJson, getDeep, isEncodedUint8Array, setDeep, visitValues } from "@dxos/util";
15
+ import * as Effect from "effect/Effect";
16
+ import { Event } from "@dxos/async";
17
+ import { inspectCustom, raise } from "@dxos/debug";
18
+ import * as Atom from "@effect-atom/atom/Atom";
19
+ import * as semver from "semver";
20
+ import * as Match from "effect/Match";
21
+ import * as Result from "@effect-atom/atom/Result";
22
+ //#region src/internal/common/types/base.ts
23
+ /**
24
+ * The raw object should not include the ECHO id, but may include metadata.
25
+ */
26
+ var RawObject = (schema) => {
27
+ return Schema.make(SchemaAST.omit(schema.ast, ["id"]));
28
+ };
29
+ //#endregion
30
+ //#region src/internal/common/types/projection.ts
31
+ /**
32
+ * Brand for a query projected to a single scalar property (`Query.project`), consumed by
33
+ * `Filter.in` to build a subquery-membership predicate — an uncorrelated
34
+ * `col IN (SELECT property FROM ...)` semi-join. Defined in common/ (not in Query/) so
35
+ * Filter.ts can recognize the brand without importing Query.ts as a value: Query.ts already
36
+ * imports Filter.ts as a value, so a reverse value import would create a cycle. Both
37
+ * Filter.ts and Query.ts import this shared leaf module instead.
38
+ *
39
+ * A string-literal id (not a `Symbol.for`), matching `FilterTypeId`/`QueryTypeId`/`OrderTypeId` —
40
+ * this lets the sandboxed `query-lite` mirror (which cannot import `@dxos/echo`'s runtime) declare
41
+ * its own local constant with the same literal and construct structurally-compatible objects,
42
+ * the same way it already does for those brands.
43
+ */
44
+ var ProjectionTypeId = "~@dxos/echo/Query.Projection";
45
+ var isProjection = (value) => typeof value === "object" && value !== null && "~@dxos/echo/Query.Projection" in value;
46
+ var variance = {};
47
+ var makeProjection = (query, property) => ({
48
+ [ProjectionTypeId]: variance,
49
+ query,
50
+ property
51
+ });
52
+ //#endregion
53
+ //#region src/internal/common/types/version.ts
54
+ /**
55
+ * Version type identifier.
56
+ */
57
+ var VersionTypeId = "~@dxos/echo/VersionTypeId";
58
+ //#endregion
59
+ //#region src/internal/Annotation/sorting.ts
60
+ /**
61
+ * String comparison helper for sorting.
62
+ */
63
+ var compare = (a, b) => {
64
+ if (a == null) return b == null ? 0 : 1;
65
+ if (b == null) return -1;
66
+ return a.localeCompare(b);
67
+ };
68
+ /**
69
+ * Sort entities by label.
70
+ */
71
+ var sortByLabel = (a, b) => compare(getLabel(a), getLabel(b));
72
+ /**
73
+ * Sort entities by typename.
74
+ */
75
+ var sortByTypename = (a, b) => compare(getTypename(a), getTypename(b));
76
+ /**
77
+ * Compose multiple comparators into one.
78
+ * Applies comparators in order until one returns non-zero.
79
+ */
80
+ var sort = (...comparators) => {
81
+ return (a, b) => {
82
+ for (const comparator of comparators) {
83
+ const result = comparator(a, b);
84
+ if (result !== 0) return result;
85
+ }
86
+ return 0;
87
+ };
88
+ };
89
+ //#endregion
90
+ //#region src/internal/Entity/model.ts
91
+ var __dxlog_file$11 = "/__w/dxos/dxos/packages/core/echo/echo/src/internal/Entity/model.ts";
92
+ /**
93
+ * NOTE: Keep as `function` to avoid type inference issues.
94
+ */
95
+ function assertObjectModel(obj) {
96
+ invariant(typeof obj === "object" && obj !== null, "Invalid object model: not an object", {
97
+ "~LogMeta": "~LogMeta",
98
+ F: __dxlog_file$11,
99
+ L: 107,
100
+ S: this,
101
+ A: ["typeof obj === 'object' && obj !== null", "'Invalid object model: not an object'"]
102
+ });
103
+ assumeType(obj);
104
+ invariant(EntityId.isValid(obj.id), "Invalid object model: invalid id", {
105
+ "~LogMeta": "~LogMeta",
106
+ F: __dxlog_file$11,
107
+ L: 109,
108
+ S: this,
109
+ A: ["EntityId.isValid(obj.id)", "'Invalid object model: invalid id'"]
110
+ });
111
+ invariant(obj[TypeId] === void 0 || typeof obj[TypeId] === "string", "Invalid object model: invalid type", {
112
+ "~LogMeta": "~LogMeta",
113
+ F: __dxlog_file$11,
114
+ L: 110,
115
+ S: this,
116
+ A: ["obj[TypeId] === undefined || typeof obj[TypeId] === 'string'", "'Invalid object model: invalid type'"]
117
+ });
118
+ invariant(obj["~@dxos/echo/Kind"] === EntityKind.Object || obj["~@dxos/echo/Kind"] === EntityKind.Relation || obj["~@dxos/echo/Kind"] === EntityKind.Type, "Invalid object model: invalid entity kind", {
119
+ "~LogMeta": "~LogMeta",
120
+ F: __dxlog_file$11,
121
+ L: 111,
122
+ S: this,
123
+ A: ["obj[KindId] === EntityKind.Object || obj[KindId] === EntityKind.Relation || obj[KindId] === EntityKind.Type", "'Invalid object model: invalid entity kind'"]
124
+ });
125
+ if (obj["~@dxos/echo/Kind"] === EntityKind.Relation) {
126
+ invariant(EID.isEID(obj[RelationSourceDXNId]), "Invalid object model: invalid relation source", {
127
+ "~LogMeta": "~LogMeta",
128
+ F: __dxlog_file$11,
129
+ L: 117,
130
+ S: this,
131
+ A: ["EID.isEID(obj[RelationSourceDXNId])", "'Invalid object model: invalid relation source'"]
132
+ });
133
+ invariant(EID.isEID(obj[RelationTargetDXNId]), "Invalid object model: invalid relation target", {
134
+ "~LogMeta": "~LogMeta",
135
+ F: __dxlog_file$11,
136
+ L: 118,
137
+ S: this,
138
+ A: ["EID.isEID(obj[RelationTargetDXNId])", "'Invalid object model: invalid relation target'"]
139
+ });
140
+ invariant(!EID.isEID(obj[RelationSourceId]), "Invalid object model: source pointer is a DXN", {
141
+ "~LogMeta": "~LogMeta",
142
+ F: __dxlog_file$11,
143
+ L: 119,
144
+ S: this,
145
+ A: ["!EID.isEID(obj[RelationSourceId])", "'Invalid object model: source pointer is a DXN'"]
146
+ });
147
+ invariant(!EID.isEID(obj[RelationTargetId]), "Invalid object model: target pointer is a DXN", {
148
+ "~LogMeta": "~LogMeta",
149
+ F: __dxlog_file$11,
150
+ L: 120,
151
+ S: this,
152
+ A: ["!EID.isEID(obj[RelationTargetId])", "'Invalid object model: target pointer is a DXN'"]
153
+ });
154
+ }
155
+ }
156
+ //#endregion
157
+ //#region src/internal/Query/pretty.ts
158
+ /**
159
+ * Returns a human-readable string representation of a Filter AST.
160
+ */
161
+ var prettyFilter = (filter) => {
162
+ switch (filter.type) {
163
+ case "object": {
164
+ if (filter.typename === null && (filter.id === void 0 || filter.id.length === 0) && Object.keys(filter.props).length === 0 && (filter.foreignKeys === void 0 || filter.foreignKeys.length === 0) && filter.metaKey !== void 0) return filter.metaVersion !== void 0 ? `Filter.key(${JSON.stringify(filter.metaKey)}, { version: ${JSON.stringify(filter.metaVersion)} })` : `Filter.key(${JSON.stringify(filter.metaKey)})`;
165
+ const parts = [];
166
+ if (filter.typename !== null) parts.push(String(filter.typename));
167
+ if (filter.id !== void 0 && filter.id.length > 0) parts.push(`id: [${filter.id.join(", ")}]`);
168
+ const propEntries = Object.entries(filter.props);
169
+ if (propEntries.length > 0) {
170
+ const propsStr = propEntries.map(([k, v]) => `${k}: ${prettyFilter(v)}`).join(", ");
171
+ parts.push(`{ ${propsStr} }`);
172
+ }
173
+ if (filter.foreignKeys !== void 0 && filter.foreignKeys.length > 0) parts.push(`foreignKeys: [${filter.foreignKeys.map((fk) => JSON.stringify(fk)).join(", ")}]`);
174
+ if (filter.metaKey !== void 0) parts.push(filter.metaVersion !== void 0 ? `metaKey: ${JSON.stringify(filter.metaKey)} (${filter.metaVersion})` : `metaKey: ${JSON.stringify(filter.metaKey)}`);
175
+ return parts.length > 0 ? `Filter.type(${parts.join(", ")})` : "Filter.everything()";
176
+ }
177
+ case "compare": return `Filter.${filter.operator}(${JSON.stringify(filter.value)})`;
178
+ case "in": return `Filter.in([${filter.values.map((v) => JSON.stringify(v)).join(", ")}])`;
179
+ case "in-query": return `Filter.in(${prettyQuery(filter.subquery)}.project(${JSON.stringify(filter.property)}))`;
180
+ case "contains": return `Filter.contains(${JSON.stringify(filter.value)})`;
181
+ case "tag": return `Filter.tag(${JSON.stringify(filter.tag)})`;
182
+ case "range": return `Filter.range(${JSON.stringify(filter.from)}, ${JSON.stringify(filter.to)})`;
183
+ case "text-search": return filter.searchKind ? `Filter.textSearch(${JSON.stringify(filter.text)}, ${JSON.stringify(filter.searchKind)})` : `Filter.textSearch(${JSON.stringify(filter.text)})`;
184
+ case "timestamp": return `Filter.${filter.field}.${filter.operator}(${filter.value})`;
185
+ case "child-of": return `Filter.childOf([${filter.parents.map((p) => JSON.stringify(p)).join(", ")}], { transitive: ${filter.transitive} })`;
186
+ case "not": return `Filter.not(${prettyFilter(filter.filter)})`;
187
+ case "and": return `Filter.and(${filter.filters.map(prettyFilter).join(", ")})`;
188
+ case "or": return `Filter.or(${filter.filters.map(prettyFilter).join(", ")})`;
189
+ }
190
+ };
191
+ /**
192
+ * Returns a human-readable string representation of a Query AST.
193
+ */
194
+ var prettyQuery = (query) => {
195
+ switch (query.type) {
196
+ case "select": return `Query.select(${prettyFilter(query.filter)})`;
197
+ case "filter": return `${prettyQuery(query.selection)}.select(${prettyFilter(query.filter)})`;
198
+ case "reference-traversal": return `${prettyQuery(query.anchor)}.reference(${JSON.stringify(query.property)})`;
199
+ case "incoming-references": {
200
+ const args = [];
201
+ if (query.typename !== null) args.push(String(query.typename));
202
+ if (query.property !== null) args.push(JSON.stringify(query.property));
203
+ return `${prettyQuery(query.anchor)}.referencedBy(${args.join(", ")})`;
204
+ }
205
+ case "relation": {
206
+ const method = query.direction === "outgoing" ? "sourceOf" : query.direction === "incoming" ? "targetOf" : "relationOf";
207
+ const filterStr = query.filter !== void 0 ? prettyFilter(query.filter) : "";
208
+ return `${prettyQuery(query.anchor)}.${method}(${filterStr})`;
209
+ }
210
+ case "relation-traversal": return `${prettyQuery(query.anchor)}.${query.direction}()`;
211
+ case "hierarchy-traversal": return query.direction === "to-parent" ? `${prettyQuery(query.anchor)}.parent()` : `${prettyQuery(query.anchor)}.children()`;
212
+ case "union": return `Query.all(${query.queries.map(prettyQuery).join(", ")})`;
213
+ case "set-difference": return `Query.without(${prettyQuery(query.source)}, ${prettyQuery(query.exclude)})`;
214
+ case "order": {
215
+ const orders = query.order.map((o) => {
216
+ if (o.kind === "natural") return `Order.natural(${JSON.stringify(o.direction)})`;
217
+ else if (o.kind === "rank") return `Order.rank(${JSON.stringify(o.direction)})`;
218
+ else if (o.kind === "timestamp") return `Order.${o.field === "updatedAt" ? "updated" : "created"}(${JSON.stringify(o.direction)})`;
219
+ else return `Order.property(${JSON.stringify(o.property)}, ${JSON.stringify(o.direction)})`;
220
+ });
221
+ return `${prettyQuery(query.query)}.orderBy(${orders.join(", ")})`;
222
+ }
223
+ case "options": {
224
+ const opts = query.options;
225
+ const parts = [];
226
+ if (opts.deleted !== void 0) parts.push(`deleted: ${JSON.stringify(opts.deleted)}`);
227
+ if (opts.debugLabel !== void 0) parts.push(`debugLabel: ${JSON.stringify(opts.debugLabel)}`);
228
+ return `${prettyQuery(query.query)}.options({ ${parts.join(", ")} })`;
229
+ }
230
+ case "from":
231
+ if (query.from._tag === "scope") {
232
+ if (query.from.scopes.length === 0) return `${prettyQuery(query.query)}.from('all-accessible-spaces')`;
233
+ const scopeStrs = query.from.scopes.map((scope) => {
234
+ if (scope._tag === "space") return scope.includeAllFeeds ? `{ space: ${JSON.stringify(scope.spaceId)}, includeAllFeeds: true }` : `{ space: ${JSON.stringify(scope.spaceId)} }`;
235
+ if (scope._tag === "feed") return `{ feed: ${JSON.stringify(String(scope.feedUri))} }`;
236
+ return `{ registry: ${JSON.stringify(scope.location)} }`;
237
+ });
238
+ return `${prettyQuery(query.query)}.from([${scopeStrs.join(", ")}])`;
239
+ }
240
+ return `${prettyQuery(query.query)}.from(${prettyQuery(query.from.query)})`;
241
+ case "limit": return `${prettyQuery(query.query)}.limit(${query.limit})`;
242
+ case "skip": return `${prettyQuery(query.query)}.skip(${query.skip})`;
243
+ case "aggregate": {
244
+ const aggregates = query.aggregates.map((aggregate) => {
245
+ const arg = aggregate.kind === "items" ? aggregate.limit !== void 0 ? `{ limit: ${aggregate.limit} }` : "" : aggregate.kind === "count" ? "" : JSON.stringify(aggregate.property);
246
+ return `${JSON.stringify(aggregate.name)}: Aggregate.${aggregate.kind}(${arg})`;
247
+ });
248
+ return `${prettyQuery(query.query)}.aggregate({ ${aggregates.join(", ")} })`;
249
+ }
250
+ }
251
+ };
252
+ //#endregion
253
+ //#region src/internal/common/proxy/define-hidden-property.ts
254
+ /**
255
+ * Define a non-enumerable property on an object.
256
+ */
257
+ var defineHiddenProperty = (object, key, value) => {
258
+ Object.defineProperty(object, key, {
259
+ enumerable: false,
260
+ configurable: true,
261
+ value
262
+ });
263
+ };
264
+ //#endregion
265
+ //#region src/internal/Ref/strong-deps.ts
266
+ /**
267
+ * Direct strong-dependency URIs of an entity: the schema (only when stored as an object), the
268
+ * relation source/target, and the parent. Returns URIs (cross-space `echo:` EIDs and queue-item
269
+ * EIDs included); a persisted schema is an `echo:` URI, a static/registry type is a `dxn:` URI.
270
+ *
271
+ * A static/registry type (`dxn:`) is intentionally NOT a strong dep: it is always synchronously
272
+ * available through the registry, so gating on it would needlessly delay surfacing. Only a
273
+ * persisted (db-backed) schema, addressed by an `echo:` URI, must load before its instances.
274
+ */
275
+ var getStrongDependencyUris = (refs, owningSpaceId) => {
276
+ const res = [];
277
+ if (refs.type != null && EID.tryParse(refs.type) != null) res.push(qualifyToSpace(refs.type, owningSpaceId));
278
+ if (refs.kind === EntityKind.Relation) {
279
+ if (refs.source != null) res.push(qualifyToSpace(refs.source, owningSpaceId));
280
+ if (refs.target != null) res.push(qualifyToSpace(refs.target, owningSpaceId));
281
+ }
282
+ if (refs.parent != null) res.push(qualifyToSpace(refs.parent, owningSpaceId));
283
+ return res;
284
+ };
285
+ /**
286
+ * Qualifies a space-less (relative) `echo:` dependency URI with the space of the entity that owns it.
287
+ * Same-space references are persisted relative; resolution needs them absolute to route to a single
288
+ * space. Already-qualified URIs (cross-space) and non-`echo:` URIs (registry `dxn:`) pass through.
289
+ */
290
+ var qualifyToSpace = (uri, owningSpaceId) => {
291
+ if (owningSpaceId == null) return uri;
292
+ const eid = EID.tryParse(uri);
293
+ if (eid == null || !EID.isLocal(eid)) return uri;
294
+ const entityId = EID.getEntityId(eid);
295
+ return entityId != null ? EID.make({
296
+ spaceId: owningSpaceId,
297
+ entityId
298
+ }) : uri;
299
+ };
300
+ /**
301
+ * Direct strong-dependency URIs of a live (decoded) entity — a queue item, cross-space proxy, or
302
+ * snapshot. Reads the reference URIs off the entity's hidden model symbols. ECHO db cores compute
303
+ * the same set from their raw encoded references via {@link getStrongDependencyUris}.
304
+ */
305
+ var getStrongDependencies = (entity) => {
306
+ if (entity == null || typeof entity !== "object") return [];
307
+ const props = entity;
308
+ const kind = props[RelationSourceDXNId] != null || props[RelationTargetDXNId] != null ? EntityKind.Relation : EntityKind.Object;
309
+ const parent = props[ParentId];
310
+ const selfUri = getObjectEchoUri(entity);
311
+ const owningSpaceId = selfUri != null ? EID.getSpaceId(selfUri) : void 0;
312
+ return getStrongDependencyUris({
313
+ kind,
314
+ type: typeof props[TypeId] === "string" ? props[TypeId] : void 0,
315
+ source: props[RelationSourceDXNId],
316
+ target: props[RelationTargetDXNId],
317
+ parent: parent != null ? getObjectEchoUri(parent) : void 0
318
+ }, owningSpaceId);
319
+ };
320
+ //#endregion
321
+ //#region src/internal/common/proxy/json-serializer.ts
322
+ var __dxlog_file$10 = "/__w/dxos/dxos/packages/core/echo/echo/src/internal/common/proxy/json-serializer.ts";
323
+ /**
324
+ * Attaches a toJSON method to the object for typed serialization.
325
+ */
326
+ var attachTypedJsonSerializer = (obj) => {
327
+ if (Object.getOwnPropertyDescriptor(obj, "toJSON")) return;
328
+ Object.defineProperty(obj, "toJSON", {
329
+ value: typedJsonSerializer,
330
+ writable: false,
331
+ enumerable: false,
332
+ configurable: true
333
+ });
334
+ };
335
+ var typedJsonSerializer = function() {
336
+ const { id, ...rest } = this;
337
+ const result = { id };
338
+ if (this[TypeId]) result[ATTR_TYPE] = this[TypeId];
339
+ if (this[MetaId]) result[ATTR_META] = serializeMeta(this[MetaId]);
340
+ if (this[SelfURIId]) result[ATTR_SELF_URI] = this[SelfURIId];
341
+ if (this[RelationSourceDXNId]) {
342
+ const sourceDXN = this[RelationSourceDXNId];
343
+ invariant(EID.isEID(sourceDXN), void 0, {
344
+ "~LogMeta": "~LogMeta",
345
+ F: __dxlog_file$10,
346
+ L: 63,
347
+ S: this,
348
+ A: ["EID.isEID(sourceDXN)", ""]
349
+ });
350
+ result[ATTR_RELATION_SOURCE] = sourceDXN;
351
+ }
352
+ if (this[RelationTargetDXNId]) {
353
+ const targetDXN = this[RelationTargetDXNId];
354
+ invariant(EID.isEID(targetDXN), void 0, {
355
+ "~LogMeta": "~LogMeta",
356
+ F: __dxlog_file$10,
357
+ L: 68,
358
+ S: this,
359
+ A: ["EID.isEID(targetDXN)", ""]
360
+ });
361
+ result[ATTR_RELATION_TARGET] = targetDXN;
362
+ }
363
+ Object.assign(result, serializeData(rest));
364
+ return result;
365
+ };
366
+ var serializeData = (data) => {
367
+ return deepMapValues(data, (value, recurse) => {
368
+ if (Ref.isRef(value)) return value.noInline().encode();
369
+ if (value instanceof Uint8Array) return encodeUint8ArrayToJson(value);
370
+ return recurse(value);
371
+ });
372
+ };
373
+ var serializeMeta = (meta) => {
374
+ const { tags, annotations, ...rest } = meta;
375
+ return serializeData({
376
+ ...rest,
377
+ ...tags != null && tags.length > 0 ? { tags } : {},
378
+ ...annotations != null && Object.keys(annotations).length > 0 ? { annotations } : {}
379
+ });
380
+ };
381
+ //#endregion
382
+ //#region src/internal/common/proxy/event-batch.ts
383
+ /**
384
+ * Simple batching mechanism for EventId emissions.
385
+ * When batch depth > 0, events are collected instead of emitted immediately.
386
+ * When batch depth returns to 0, pending events are emitted.
387
+ */
388
+ var eventBatchDepth = 0;
389
+ var pendingEventTargets = /* @__PURE__ */ new Set();
390
+ /**
391
+ * Run a callback in a batched context for EventId emissions.
392
+ * Multiple mutations within the batch will only emit one event per target.
393
+ */
394
+ var batchEvents = (callback) => {
395
+ eventBatchDepth++;
396
+ try {
397
+ callback();
398
+ } finally {
399
+ eventBatchDepth--;
400
+ if (eventBatchDepth === 0) {
401
+ for (const target of pendingEventTargets) target[EventId]?.emit();
402
+ pendingEventTargets.clear();
403
+ }
404
+ }
405
+ };
406
+ /**
407
+ * Emit an event on a target, respecting batching.
408
+ */
409
+ var emitEvent = (target) => {
410
+ if (eventBatchDepth > 0) pendingEventTargets.add(target);
411
+ else target[EventId]?.emit();
412
+ };
413
+ //#endregion
414
+ //#region src/internal/common/proxy/change-context.ts
415
+ /**
416
+ * Generic change context tracking.
417
+ * Only one object can be in a change context at a time (synchronous changes).
418
+ *
419
+ * This module provides a unified change context mechanism used by both:
420
+ * - TypedReactiveHandler (for non-database objects, using target as key)
421
+ * - EchoReactiveHandler (for database objects, using ObjectCore as key)
422
+ */
423
+ /**
424
+ * The object currently in a change context.
425
+ * Can be a target object (for typed reactive) or ObjectCore (for database objects).
426
+ */
427
+ var currentChangeContext = null;
428
+ /**
429
+ * The primary object that has pending notifications, if any.
430
+ * This uses the contextKey (target or ObjectCore).
431
+ */
432
+ var pendingNotificationKey = null;
433
+ /**
434
+ * Additional objects (owner chain) that need notifications.
435
+ * These are separate from the primary notification because they use EventId directly.
436
+ */
437
+ var pendingOwnerNotifications = /* @__PURE__ */ new Set();
438
+ /**
439
+ * Enter a change context for the given key.
440
+ * While in a change context, mutations are allowed on the associated object.
441
+ * Nested Obj.update calls are not supported.
442
+ *
443
+ * @param key - The key to enter the change context for (target object or ObjectCore).
444
+ * @returns A cleanup function that exits the change context.
445
+ */
446
+ var enterChangeContext = (key) => {
447
+ currentChangeContext = key;
448
+ return () => {
449
+ currentChangeContext = null;
450
+ };
451
+ };
452
+ /**
453
+ * Check if the given key is currently in a change context.
454
+ *
455
+ * @param key - The key to check (target object or ObjectCore).
456
+ * @returns True if the key is in a change context, false otherwise.
457
+ */
458
+ var isInChangeContext = (key) => {
459
+ return currentChangeContext === key;
460
+ };
461
+ /**
462
+ * Queue a notification for the given key to be fired when the change context exits.
463
+ *
464
+ * @param key - The key to queue a notification for.
465
+ */
466
+ var queueNotification = (key) => {
467
+ if (currentChangeContext === key) pendingNotificationKey = key;
468
+ };
469
+ /**
470
+ * Queue an owner notification. Owner notifications are for objects in the ownership
471
+ * chain that should be notified when a nested object changes.
472
+ * These objects have EventId and emit directly.
473
+ * Skip if the target is already the current change context (to avoid duplicate notifications).
474
+ *
475
+ * @param target - The owner target that has EventId.
476
+ */
477
+ var queueOwnerNotification = (target) => {
478
+ if (currentChangeContext !== null && target !== currentChangeContext) pendingOwnerNotifications.add(target);
479
+ };
480
+ /**
481
+ * Check if there are any pending notifications for the given key.
482
+ *
483
+ * @param key - The key to check.
484
+ * @returns True if there are pending notifications, false otherwise.
485
+ */
486
+ var hasPendingNotifications = (key) => {
487
+ return pendingNotificationKey === key;
488
+ };
489
+ /**
490
+ * Clear any pending notifications for the given key.
491
+ *
492
+ * @param key - The key to clear notifications for.
493
+ */
494
+ var clearPendingNotifications = (key) => {
495
+ if (pendingNotificationKey === key) pendingNotificationKey = null;
496
+ };
497
+ /**
498
+ * Execute a callback within a change context.
499
+ * This is the shared implementation used by both TypedReactiveHandler and EchoReactiveHandler.
500
+ *
501
+ * @param contextKey - The key for the change context (target for typed, ObjectCore for db).
502
+ * @param eventTarget - The object that has the EventId for notifications.
503
+ * @param proxy - The proxy object to pass to the callback.
504
+ * @param callback - The callback to execute with mutations allowed.
505
+ */
506
+ var executeChange = (contextKey, eventTarget, proxy, callback) => {
507
+ const exitContext = enterChangeContext(contextKey);
508
+ try {
509
+ batchEvents(() => callback(proxy));
510
+ } finally {
511
+ exitContext();
512
+ if (hasPendingNotifications(contextKey)) {
513
+ clearPendingNotifications(contextKey);
514
+ eventTarget[EventId]?.emit();
515
+ }
516
+ for (const ownerTarget of pendingOwnerNotifications) ownerTarget[EventId]?.emit();
517
+ pendingOwnerNotifications.clear();
518
+ }
519
+ };
520
+ //#endregion
521
+ //#region src/internal/common/proxy/errors.ts
522
+ /**
523
+ * Error thrown when attempting to mutate an object outside of an Obj.update() context.
524
+ */
525
+ var MutationOutsideChangeContextError = class extends Error {
526
+ constructor(operation, suggestion) {
527
+ super(`Cannot ${operation} outside of Obj.update(). Use Obj.update(obj, (mutableObj) => { ${suggestion} }) instead.`);
528
+ this.name = "MutationOutsideChangeContextError";
529
+ }
530
+ };
531
+ /**
532
+ * Create an error for attempting to set a property outside of a change context.
533
+ */
534
+ var createPropertySetError = (prop) => {
535
+ return new MutationOutsideChangeContextError(`modify object property "${String(prop)}"`, `mutableObj.${String(prop)} = value;`);
536
+ };
537
+ /**
538
+ * Create an error for attempting to delete a property outside of a change context.
539
+ */
540
+ var createPropertyDeleteError = (prop) => {
541
+ return new MutationOutsideChangeContextError(`delete object property "${String(prop)}"`, `delete mutableObj.${String(prop)};`);
542
+ };
543
+ /**
544
+ * Create an error for attempting to call an array method outside of a change context.
545
+ */
546
+ var createArrayMethodError = (method) => {
547
+ return new MutationOutsideChangeContextError(`call array.${method}()`, `mutableObj.array.${method}(...);`);
548
+ };
549
+ //#endregion
550
+ //#region src/internal/common/proxy/ownership.ts
551
+ var __dxlog_file$9 = "/__w/dxos/dxos/packages/core/echo/echo/src/internal/common/proxy/ownership.ts";
552
+ /**
553
+ * Symbol to store the owning ECHO object reference on nested JS objects (records).
554
+ * Every nested record is attributed to exactly one ECHO object.
555
+ * This achieves:
556
+ * - No cycles in the object graph (cyclical Refs are still allowed).
557
+ * - No multiple inbound pointers to one record.
558
+ * - Centralized reactivity for entire ECHO object.
559
+ */
560
+ var EchoOwner = Symbol.for("@dxos/echo/Owner");
561
+ /**
562
+ * Get the raw target from a value, unwrapping proxy if needed.
563
+ */
564
+ var getRawTarget = (value) => {
565
+ return isProxy(value) ? getProxyTarget(value) : value;
566
+ };
567
+ /**
568
+ * Get the ECHO object that owns this nested record.
569
+ *
570
+ * The owner is always the raw target object (not a proxy) of the root ECHO object.
571
+ * For example, if you have `echoObject.nested.deep`, both `nested` and `deep`
572
+ * will have their owner set to the raw target of `echoObject`.
573
+ *
574
+ * @param value - The nested record to check (can be a proxy or raw target).
575
+ * @returns The raw target of the owning root ECHO object, or undefined if not owned.
576
+ */
577
+ var getOwner = (value) => {
578
+ return value?.[EchoOwner];
579
+ };
580
+ /**
581
+ * Set the owner of a meta object to its parent.
582
+ * This allows meta mutations to respect the parent's change context.
583
+ * @internal
584
+ */
585
+ var setMetaOwner = (metaTarget, parent) => {
586
+ defineHiddenProperty(metaTarget, EchoOwner, parent);
587
+ };
588
+ /**
589
+ * Set the ECHO object owner on a value and all its nested records.
590
+ * All nested JS objects point directly to the root ECHO object.
591
+ *
592
+ * @param value - The value to set ownership on (can be a proxy or raw target).
593
+ * @param owner - The raw target of the root ECHO object that will own this value.
594
+ * @param options.visited - Set of already-visited objects to avoid infinite loops.
595
+ * @param options.depth - Current recursion depth (unused, kept for debugging).
596
+ * @param options.allowedPreviousOwner - When reassigning a root ECHO object, its nested structures
597
+ * are allowed to have this as their previous owner without triggering the invariant.
598
+ */
599
+ var setOwnerRecursive = (value, owner, options = {}) => {
600
+ const { visited = /* @__PURE__ */ new Set(), depth = 0, allowedPreviousOwner } = options;
601
+ if (value == null || typeof value !== "object") return;
602
+ const actualValue = getRawTarget(value);
603
+ if (visited.has(actualValue)) return;
604
+ visited.add(actualValue);
605
+ const existingOwner = getOwner(actualValue);
606
+ const isRootEchoObject = EventId in actualValue;
607
+ let newAllowedPreviousOwner = allowedPreviousOwner;
608
+ if (isRootEchoObject && depth === 0) newAllowedPreviousOwner = actualValue;
609
+ if (!isRootEchoObject) invariant(existingOwner == null || existingOwner === owner || existingOwner === newAllowedPreviousOwner, "Cannot reassign ownership of a nested record to a different ECHO object. Use deep copy first.", {
610
+ "~LogMeta": "~LogMeta",
611
+ F: __dxlog_file$9,
612
+ L: 101,
613
+ S: void 0,
614
+ A: ["ownershipAllowed", "'Cannot reassign ownership of a nested record to a different ECHO object. Use deep copy first.'"]
615
+ });
616
+ defineHiddenProperty(actualValue, EchoOwner, owner);
617
+ const recursiveOptions = {
618
+ visited,
619
+ depth: depth + 1,
620
+ allowedPreviousOwner: newAllowedPreviousOwner
621
+ };
622
+ if (Array.isArray(actualValue)) {
623
+ for (const item of actualValue) if (isValidProxyTarget(item) || isProxy(item)) setOwnerRecursive(item, owner, recursiveOptions);
624
+ } else for (const key in actualValue) if (Object.prototype.hasOwnProperty.call(actualValue, key)) {
625
+ const nested = actualValue[key];
626
+ if (isValidProxyTarget(nested) || isProxy(nested)) setOwnerRecursive(nested, owner, recursiveOptions);
627
+ }
628
+ };
629
+ /**
630
+ * Traverse an object graph, calling the visitor on each object.
631
+ * Handles proxy unwrapping and cycle detection.
632
+ *
633
+ * @param value - The value to traverse (can be a proxy or raw target).
634
+ * @param visitor - Called for each object. Return true to stop traversal (early exit).
635
+ * @returns true if the visitor returns true for any object.
636
+ */
637
+ var traverseObjectGraph = (value, visitor, visited = /* @__PURE__ */ new Set()) => {
638
+ if (value == null || typeof value !== "object") return false;
639
+ const actualValue = getRawTarget(value);
640
+ if (visited.has(actualValue)) return false;
641
+ visited.add(actualValue);
642
+ if (visitor(actualValue)) return true;
643
+ if (Array.isArray(actualValue)) {
644
+ for (const item of actualValue) if (traverseObjectGraph(item, visitor, visited)) return true;
645
+ } else for (const key in actualValue) if (Object.prototype.hasOwnProperty.call(actualValue, key)) {
646
+ if (traverseObjectGraph(actualValue[key], visitor, visited)) return true;
647
+ }
648
+ return false;
649
+ };
650
+ /**
651
+ * Check if a value would create a cycle when assigned to a target ECHO object.
652
+ * Returns true if the value (or any nested object) IS the target root.
653
+ */
654
+ var wouldCreateCycle = (targetRoot, value) => traverseObjectGraph(value, (v) => v === targetRoot);
655
+ /**
656
+ * Check if a value or any of its nested objects has an owner different from the target.
657
+ * Used to determine if deep copy is needed during init.
658
+ */
659
+ var hasForeignOwner = (value, target) => traverseObjectGraph(value, (v) => {
660
+ const owner = getOwner(v);
661
+ if (owner != null && owner !== target) return true;
662
+ if (EventId in v && v !== target) return true;
663
+ return false;
664
+ });
665
+ /**
666
+ * Maximum depth for owner chain traversal.
667
+ * This is a defensive measure against malformed circular ownership.
668
+ * Primary cycle detection is handled by wouldCreateCycle() before assignment.
669
+ */
670
+ var MAX_OWNER_DEPTH = 100;
671
+ /**
672
+ * Get the root ECHO object for a target.
673
+ * Follows the owner chain to find the ultimate root.
674
+ * An object may have EventId (from being created standalone) but if it now
675
+ * has an owner, it's nested and we should use its owner's root instead.
676
+ * @internal
677
+ */
678
+ var getEchoRoot = (target, depth = 0) => {
679
+ invariant(depth < MAX_OWNER_DEPTH, "Owner chain too deep - possible circular ownership", {
680
+ "~LogMeta": "~LogMeta",
681
+ F: __dxlog_file$9,
682
+ L: 220,
683
+ S: void 0,
684
+ A: ["depth < MAX_OWNER_DEPTH", "'Owner chain too deep - possible circular ownership'"]
685
+ });
686
+ if ("~@dxos/echo/Kind" in target) return target;
687
+ const owner = getOwner(target);
688
+ if (owner) return getEchoRoot(owner, depth + 1);
689
+ return target;
690
+ };
691
+ /**
692
+ * Notify all owners in the ownership chain.
693
+ * When a nested object changes, its parent should also be notified.
694
+ * This handles the case where a root ECHO object is nested inside another object.
695
+ */
696
+ var notifyOwnerChain = (target) => {
697
+ const owner = getOwner(target);
698
+ if (owner) {
699
+ queueOwnerNotification(getEchoRoot(owner));
700
+ notifyOwnerChain(owner);
701
+ }
702
+ };
703
+ //#endregion
704
+ //#region src/internal/common/proxy/proxy-types.ts
705
+ /**
706
+ * For debug-dumping the data of the object.
707
+ */
708
+ var objectData = Symbol.for("@dxos/live-object/objectData");
709
+ //#endregion
710
+ //#region src/internal/common/proxy/reactive-array.ts
711
+ /**
712
+ * Check if array mutation is allowed (inside a change context).
713
+ * Throws a descriptive error if not.
714
+ */
715
+ var checkArrayMutationAllowed = (arr, method) => {
716
+ const echoRoot = getEchoRoot(isProxy(arr) ? getProxyTarget(arr) : arr);
717
+ if (!(EventId in echoRoot)) return;
718
+ if (!isInChangeContext(echoRoot)) throw createArrayMethodError(method);
719
+ };
720
+ /**
721
+ * Extends the native array to make sure that arrays methods are correctly reactive.
722
+ * Enforces that mutations only happen within Obj.update() context.
723
+ */
724
+ var ReactiveArray = class extends Array {
725
+ static get [Symbol.species]() {
726
+ return Array;
727
+ }
728
+ static {
729
+ for (const method of [
730
+ "push",
731
+ "pop",
732
+ "shift",
733
+ "unshift",
734
+ "splice",
735
+ "sort",
736
+ "reverse"
737
+ ]) Object.defineProperty(this.prototype, method, {
738
+ enumerable: false,
739
+ value: function(...args) {
740
+ checkArrayMutationAllowed(this, method);
741
+ let result;
742
+ batchEvents(() => {
743
+ result = Array.prototype[method].apply(this, args);
744
+ });
745
+ return result;
746
+ }
747
+ });
748
+ }
749
+ };
750
+ //#endregion
751
+ //#region src/internal/common/proxy/schema-validator.ts
752
+ var __dxlog_file$8 = "/__w/dxos/dxos/packages/core/echo/echo/src/internal/common/proxy/schema-validator.ts";
753
+ var SchemaValidator = class {
754
+ /**
755
+ * Recursively check that schema specifies constructions we can handle.
756
+ * Validates there are no ambiguous discriminated union types.
757
+ */
758
+ static validateSchema(schema) {
759
+ const visitAll = (nodes) => nodes.forEach((node) => this.validateSchema(Schema.make(node)));
760
+ if (SchemaAST.isUnion(schema.ast)) {
761
+ const typeAstList = schema.ast.types.filter((type) => SchemaAST.isTypeLiteral(type));
762
+ if (typeAstList.length > 1) getTypeDiscriminators(typeAstList);
763
+ visitAll(typeAstList);
764
+ } else if (SchemaAST.isTupleType(schema.ast)) visitAll(schema.ast.elements.map((t) => t.type).concat(schema.ast.rest.map((t) => t.type)));
765
+ else if (SchemaAST.isTypeLiteral(schema.ast)) visitAll(SchemaAST.getPropertySignatures(schema.ast).map((p) => p.type));
766
+ }
767
+ static hasTypeAnnotation(rootObjectSchema, property, annotation) {
768
+ try {
769
+ let type = this.getPropertySchema(rootObjectSchema, [property]);
770
+ if (SchemaAST.isTupleType(type.ast)) type = this.getPropertySchema(rootObjectSchema, [property, "0"]);
771
+ return type.ast.annotations[annotation] != null;
772
+ } catch {
773
+ return false;
774
+ }
775
+ }
776
+ static getPropertySchema(rootObjectSchema, propertyPath, getProperty = () => null) {
777
+ let schema = rootObjectSchema;
778
+ for (let i = 0; i < propertyPath.length; i++) {
779
+ const propertyName = propertyPath[i];
780
+ const tupleAst = unwrapArray(schema.ast);
781
+ if (tupleAst != null) schema = getArrayElementSchema(tupleAst, propertyName);
782
+ else {
783
+ const propertyType = getPropertyType(schema.ast, propertyName.toString(), (propertyName) => getProperty([...propertyPath.slice(0, i), propertyName]));
784
+ if (propertyType == null) {
785
+ const indexSignatureType = getIndexSignatureValueType(schema.ast);
786
+ if (indexSignatureType != null) {
787
+ schema = Schema.make(indexSignatureType).annotations(indexSignatureType.annotations);
788
+ continue;
789
+ }
790
+ throw new TypeError(`Unknown property: ${formatPropertyPath([...propertyPath.slice(0, i), propertyName])}`);
791
+ }
792
+ schema = Schema.make(propertyType).annotations(propertyType.annotations);
793
+ }
794
+ }
795
+ return schema;
796
+ }
797
+ /**
798
+ * Rejects properties not declared on the schema. Types with index signatures allow extra keys.
799
+ */
800
+ static assertExactProperties(schema, value, getProperty = () => void 0, path = []) {
801
+ if (!isPlainRecord(value)) return;
802
+ const typeLiteral = resolveTypeLiteral(schema.ast, (propertyName) => getProperty([...path, propertyName]));
803
+ if (typeLiteral == null) return;
804
+ const propertySignatures = SchemaAST.getPropertySignatures(typeLiteral);
805
+ const allowedKeys = new Set(propertySignatures.map((property) => String(property.name)));
806
+ const indexSignatureType = typeLiteral.indexSignatures[0]?.type;
807
+ for (const key of Object.keys(value)) {
808
+ const propertyPath = [...path, key];
809
+ if (!allowedKeys.has(key)) {
810
+ if (indexSignatureType == null) throw new TypeError(`Unknown property: ${formatPropertyPath(propertyPath)}`);
811
+ const indexSchema = Schema.make(indexSignatureType).annotations(indexSignatureType.annotations);
812
+ this.assertExactProperties(indexSchema, value[key], getProperty, propertyPath);
813
+ continue;
814
+ }
815
+ const propertySignature = propertySignatures.find((property) => String(property.name) === key);
816
+ invariant(propertySignature, "Property signature must exist.", {
817
+ "~LogMeta": "~LogMeta",
818
+ F: __dxlog_file$8,
819
+ L: 121,
820
+ S: this,
821
+ A: ["propertySignature", "'Property signature must exist.'"]
822
+ });
823
+ const propertySchema = Schema.make(propertySignature.type).annotations(propertySignature.type.annotations);
824
+ this.assertExactProperties(propertySchema, value[key], getProperty, propertyPath);
825
+ }
826
+ }
827
+ static getIndexedElementSchema(schema, index) {
828
+ const arrayAst = unwrapArray(schema.ast);
829
+ if (arrayAst != null) return getArrayElementSchema(arrayAst, index);
830
+ const unionAst = unwrapAst(schema.ast, (candidate) => SchemaAST.isUnion(candidate) && candidate.types.some((member) => unwrapArray(member) != null));
831
+ if (unionAst != null && SchemaAST.isUnion(unionAst)) for (const member of unionAst.types) {
832
+ const memberArrayAst = unwrapArray(member);
833
+ if (memberArrayAst != null) return getArrayElementSchema(memberArrayAst, index);
834
+ }
835
+ return null;
836
+ }
837
+ static getTargetPropertySchema(target, prop) {
838
+ const schema = target[SchemaId];
839
+ invariant(schema, "target has no schema", {
840
+ "~LogMeta": "~LogMeta",
841
+ F: __dxlog_file$8,
842
+ L: 154,
843
+ S: this,
844
+ A: ["schema", "'target has no schema'"]
845
+ });
846
+ if (Array.isArray(target)) {
847
+ if (prop === "length") return Schema.Number;
848
+ if (typeof prop !== "symbol") {
849
+ const indexedSchema = this.getIndexedElementSchema(schema, prop);
850
+ if (indexedSchema != null) return indexedSchema;
851
+ }
852
+ if (SchemaAST.isTypeLiteral(schema.ast)) return schema;
853
+ }
854
+ if (typeof prop === "number" || typeof prop === "string" && /^\d+$/.test(prop)) {
855
+ const indexedSchema = this.getIndexedElementSchema(schema, prop);
856
+ if (indexedSchema != null) return indexedSchema;
857
+ }
858
+ const arrayAst = unwrapArray(schema.ast);
859
+ if (arrayAst != null) return getArrayElementSchema(arrayAst, prop);
860
+ const propertyType = getPropertyType(schema.ast, prop.toString(), (prop) => target[prop]);
861
+ if (propertyType == null) {
862
+ const indexSignatureType = getIndexSignatureValueType(schema.ast);
863
+ if (indexSignatureType != null) return Schema.make(indexSignatureType).annotations(indexSignatureType.annotations);
864
+ throw new TypeError(`Unknown property: ${String(prop)}`);
865
+ }
866
+ return Schema.make(propertyType).annotations(propertyType.annotations);
867
+ }
868
+ };
869
+ /**
870
+ * Tuple AST is used both for:
871
+ * fixed-length tuples ([string, number]) in which case AST will be { elements: [Schema.String, Schema.Number] }
872
+ * variable-length arrays (Array<string | number>) in which case AST will be { rest: [Schema.Union(Schema.String, Schema.Number)] }
873
+ */
874
+ var getArrayElementSchema = (tupleAst, property) => {
875
+ const elementIndex = typeof property === "number" ? property : typeof property === "string" ? parseInt(property, 10) : NaN;
876
+ if (Number.isNaN(elementIndex)) {
877
+ invariant(property === "length", `invalid array property: ${String(property)}`, {
878
+ "~LogMeta": "~LogMeta",
879
+ F: __dxlog_file$8,
880
+ L: 212,
881
+ S: void 0,
882
+ A: ["property === 'length'", "`invalid array property: ${String(property)}`"]
883
+ });
884
+ return Schema.Number;
885
+ }
886
+ if (elementIndex < tupleAst.elements.length) {
887
+ const elementType = tupleAst.elements[elementIndex].type;
888
+ return Schema.make(elementType).annotations(elementType.annotations);
889
+ }
890
+ const restType = tupleAst.rest;
891
+ return Schema.make(restType[0].type).annotations(restType[0].annotations);
892
+ };
893
+ var flattenUnion = (typeAst) => SchemaAST.isUnion(typeAst) ? typeAst.types.flatMap(flattenUnion) : [typeAst];
894
+ var getProperties = (typeAst, getTargetPropertyFn) => {
895
+ const typeAstList = flattenUnion(typeAst).filter((type) => SchemaAST.isTypeLiteral(type));
896
+ if (typeAstList.length === 0) return [];
897
+ if (typeAstList.length === 1) return SchemaAST.getPropertySignatures(typeAstList[0]);
898
+ const typeDiscriminators = getTypeDiscriminators(typeAstList);
899
+ const targetPropertyValue = getTargetPropertyFn(String(typeDiscriminators[0].name));
900
+ const typeIndex = typeDiscriminators.findIndex((p) => targetPropertyValue === p.type.literal);
901
+ invariant(typeIndex !== -1, "discriminator field not set on target", {
902
+ "~LogMeta": "~LogMeta",
903
+ F: __dxlog_file$8,
904
+ L: 243,
905
+ S: void 0,
906
+ A: ["typeIndex !== -1", "'discriminator field not set on target'"]
907
+ });
908
+ return SchemaAST.getPropertySignatures(typeAstList[typeIndex]);
909
+ };
910
+ var getPropertyType = (ast, propertyName, getTargetPropertyFn) => {
911
+ if (unwrapAst(ast, (candidate) => SchemaAST.isAnyKeyword(candidate) || SchemaAST.isUnknownKeyword(candidate) || SchemaAST.isObjectKeyword(candidate)) != null) return ast;
912
+ const typeOrDiscriminatedUnion = unwrapAst(ast, (t) => {
913
+ return SchemaAST.isTypeLiteral(t) || SchemaAST.isUnion(t) && t.types.some((t) => SchemaAST.isTypeLiteral(t));
914
+ });
915
+ if (typeOrDiscriminatedUnion == null) return null;
916
+ const targetProperty = getProperties(typeOrDiscriminatedUnion, getTargetPropertyFn).find((p) => p.name === propertyName);
917
+ if (targetProperty != null) return unwrapAst(targetProperty.type);
918
+ const indexSignatureType = unwrapAst(ast, SchemaAST.isTypeLiteral);
919
+ if (indexSignatureType && SchemaAST.isTypeLiteral(indexSignatureType) && indexSignatureType.indexSignatures.length > 0) return unwrapAst(indexSignatureType.indexSignatures[0].type);
920
+ return null;
921
+ };
922
+ var getTypeDiscriminators = (typeAstList) => {
923
+ const discriminatorPropCandidates = typeAstList.flatMap(SchemaAST.getPropertySignatures).filter((p) => SchemaAST.isLiteral(p.type));
924
+ const propertyName = discriminatorPropCandidates[0].name;
925
+ const isValidDiscriminator = discriminatorPropCandidates.every((p) => p.name === propertyName && !p.isOptional);
926
+ const everyTypeHasDiscriminator = discriminatorPropCandidates.length === typeAstList.length;
927
+ invariant(isValidDiscriminator && everyTypeHasDiscriminator, "type ambiguity: every type in a union must have a single unique-literal field", {
928
+ "~LogMeta": "~LogMeta",
929
+ F: __dxlog_file$8,
930
+ L: 297,
931
+ S: void 0,
932
+ A: ["isDiscriminatedUnion", "'type ambiguity: every type in a union must have a single unique-literal field'"]
933
+ });
934
+ return discriminatorPropCandidates;
935
+ };
936
+ /**
937
+ * Used to check that rootAst is for a type matching the provided predicate.
938
+ * That's not always straightforward because types of optionality and recursive types.
939
+ * const Task = Schema.Struct({
940
+ * ...,
941
+ * previous?: Schema.optional(Schema.suspend(() => Task)),
942
+ * });
943
+ * Here the AST for `previous` field is going to be Union(Suspend(Type), Undefined).
944
+ * SchemaAST.isTypeLiteral(field) will return false, but unwrapAst(field, (ast) => SchemaAST.isTypeLiteral(ast))
945
+ * will return true.
946
+ */
947
+ var unwrapAst = (rootAst, predicate) => {
948
+ let ast = rootAst;
949
+ while (ast != null) {
950
+ if (predicate?.(ast)) return ast;
951
+ if (SchemaAST.isUnion(ast)) {
952
+ const next = ast.types.find((t) => predicate != null && predicate(t) || SchemaAST.isSuspend(t));
953
+ if (next != null) {
954
+ ast = next;
955
+ continue;
956
+ }
957
+ }
958
+ if (SchemaAST.isSuspend(ast)) ast = ast.f();
959
+ else return predicate == null ? ast : null;
960
+ }
961
+ return null;
962
+ };
963
+ var unwrapArray = (ast) => unwrapAst(ast, SchemaAST.isTupleType);
964
+ var getIndexSignatureValueType = (ast) => {
965
+ const typeLiteral = unwrapAst(ast, SchemaAST.isTypeLiteral);
966
+ if (typeLiteral == null || !SchemaAST.isTypeLiteral(typeLiteral) || typeLiteral.indexSignatures.length === 0) return null;
967
+ return unwrapAst(typeLiteral.indexSignatures[0].type);
968
+ };
969
+ var resolveTypeLiteral = (ast, getTargetPropertyFn) => {
970
+ if (unwrapAst(ast, (candidate) => SchemaAST.isAnyKeyword(candidate) || SchemaAST.isUnknownKeyword(candidate) || SchemaAST.isObjectKeyword(candidate)) != null) return null;
971
+ const typeOrDiscriminatedUnion = unwrapAst(ast, (type) => {
972
+ return SchemaAST.isTypeLiteral(type) || SchemaAST.isUnion(type) && type.types.some((member) => SchemaAST.isTypeLiteral(member));
973
+ });
974
+ if (typeOrDiscriminatedUnion == null) return null;
975
+ if (SchemaAST.isTypeLiteral(typeOrDiscriminatedUnion)) return typeOrDiscriminatedUnion;
976
+ if (!SchemaAST.isUnion(typeOrDiscriminatedUnion)) return null;
977
+ const typeAstList = typeOrDiscriminatedUnion.types.filter((type) => SchemaAST.isTypeLiteral(type));
978
+ if (typeAstList.length === 1) return typeAstList[0];
979
+ const typeDiscriminators = getTypeDiscriminators(typeAstList);
980
+ const targetPropertyValue = getTargetPropertyFn(String(typeDiscriminators[0].name));
981
+ const typeIndex = typeDiscriminators.findIndex((property) => targetPropertyValue === property.type.literal);
982
+ invariant(typeIndex !== -1, "discriminator field not set on target", {
983
+ "~LogMeta": "~LogMeta",
984
+ F: __dxlog_file$8,
985
+ L: 393,
986
+ S: void 0,
987
+ A: ["typeIndex !== -1", "'discriminator field not set on target'"]
988
+ });
989
+ return typeAstList[typeIndex];
990
+ };
991
+ var isPlainRecord = (value) => {
992
+ if (typeof value !== "object" || value === null || Array.isArray(value) || value instanceof Uint8Array) return false;
993
+ const proto = Object.getPrototypeOf(value);
994
+ return proto === Object.prototype || proto === null;
995
+ };
996
+ var formatPropertyPath = (path) => path.map(String).join(".");
997
+ var checkIdNotPresentOnSchema = (schema) => {
998
+ invariant(SchemaAST.isTypeLiteral(schema.ast), void 0, {
999
+ "~LogMeta": "~LogMeta",
1000
+ F: __dxlog_file$8,
1001
+ L: 409,
1002
+ S: void 0,
1003
+ A: ["SchemaAST.isTypeLiteral(schema.ast)", ""]
1004
+ });
1005
+ if (SchemaAST.getPropertySignatures(schema.ast).find((prop) => prop.name === "id") != null) throw new Error("\"id\" property name is reserved");
1006
+ };
1007
+ //#endregion
1008
+ //#region src/internal/common/proxy/typed-handler.ts
1009
+ var __dxlog_file$7 = "/__w/dxos/dxos/packages/core/echo/echo/src/internal/common/proxy/typed-handler.ts";
1010
+ /**
1011
+ * Deep copy a value, handling arrays and nested objects.
1012
+ * Preserves ReactiveArray type and hidden properties (SchemaId, TypeId).
1013
+ * Does not copy class instances or functions (except ReactiveArray).
1014
+ *
1015
+ * Note: Cannot use structuredClone because we need to:
1016
+ * - Unwrap proxies
1017
+ * - Preserve ReactiveArray instances
1018
+ * - Copy Symbol-keyed hidden properties (SchemaId, TypeId)
1019
+ * - Convert plain arrays to ReactiveArray
1020
+ *
1021
+ * Performance: O(n) where n is the total number of nested objects/arrays.
1022
+ * For large structures, consider using Refs for frequently reassigned subtrees.
1023
+ */
1024
+ var deepCopy = (value, visited = /* @__PURE__ */ new Map()) => {
1025
+ if (value == null || typeof value !== "object") return value;
1026
+ const actualValue = getRawTarget(value);
1027
+ if (visited.has(actualValue)) return visited.get(actualValue);
1028
+ if (actualValue instanceof ReactiveArray) {
1029
+ const copy = new ReactiveArray();
1030
+ visited.set(actualValue, copy);
1031
+ for (const item of actualValue) copy.push(deepCopy(item, visited));
1032
+ copyHiddenProperties(actualValue, copy);
1033
+ return copy;
1034
+ }
1035
+ const proto = Object.getPrototypeOf(actualValue);
1036
+ if (proto !== Array.prototype && proto !== null && !isReactiveRecord(actualValue)) return value;
1037
+ if (Array.isArray(actualValue)) {
1038
+ const copy = new ReactiveArray();
1039
+ visited.set(actualValue, copy);
1040
+ for (const item of actualValue) copy.push(deepCopy(item, visited));
1041
+ return copy;
1042
+ }
1043
+ const copy = {};
1044
+ visited.set(actualValue, copy);
1045
+ for (const key of Object.keys(actualValue)) copy[key] = deepCopy(actualValue[key], visited);
1046
+ copyHiddenProperties(actualValue, copy);
1047
+ return copy;
1048
+ };
1049
+ /**
1050
+ * Copy hidden properties (SchemaId, TypeId) from source to target.
1051
+ */
1052
+ var copyHiddenProperties = (source, target) => {
1053
+ if (SchemaId in source) defineHiddenProperty(target, SchemaId, source[SchemaId]);
1054
+ if (TypeId in source) defineHiddenProperty(target, TypeId, source[TypeId]);
1055
+ };
1056
+ /**
1057
+ * Behaviour prototype for typed reactive records. A record's per-object metadata is moved onto an
1058
+ * intermediate instance-state object whose prototype is this, so that swapping the handler that
1059
+ * backs an object (e.g. an in-memory object becoming database-backed) is a prototype re-point that
1060
+ * doesn't perturb the target's own-property shape. Marked as a reactive prototype so the "plain
1061
+ * object" gates (`isValidProxyTarget` / `deepCopy`) still treat such targets as data records.
1062
+ */
1063
+ var TypedObjectPrototype = Object.create(Object.prototype);
1064
+ defineHiddenProperty(TypedObjectPrototype, symbolReactivePrototype, true);
1065
+ Object.defineProperties(TypedObjectPrototype, {
1066
+ [objectData]: { get() {
1067
+ return toJSON(getRawTarget(this));
1068
+ } },
1069
+ [ChangeId]: { get() {
1070
+ const target = getRawTarget(this);
1071
+ if (!(EventId in target)) return;
1072
+ return (callback) => executeChange(target, target, this, callback);
1073
+ } },
1074
+ [StaticTypeSchemaSlot]: { get() {
1075
+ const target = getRawTarget(this);
1076
+ const jsonSchema = target.jsonSchema;
1077
+ if (jsonSchema == null) return;
1078
+ const rebuilt = toEffectSchema(jsonSchema);
1079
+ defineHiddenProperty(target, StaticTypeSchemaSlot, rebuilt);
1080
+ return rebuilt;
1081
+ } }
1082
+ });
1083
+ /** True if `prop` resolves to an accessor on the behaviour-prototype chain (not an own property). */
1084
+ var isBehaviourAccessor = (target, prop) => {
1085
+ let proto = Object.getPrototypeOf(target);
1086
+ while (proto != null && proto !== Object.prototype) {
1087
+ const descriptor = Object.getOwnPropertyDescriptor(proto, prop);
1088
+ if (descriptor != null) return descriptor.get != null;
1089
+ proto = Object.getPrototypeOf(proto);
1090
+ }
1091
+ return false;
1092
+ };
1093
+ /**
1094
+ * Enforce that user-data mutations only happen inside `Obj.update()`. A root object owns an
1095
+ * `EventId` once initialized; before that (and for non-root records or symbol-keyed system
1096
+ * properties) mutations pass through. Returns whether the root is initialized so callers can gate
1097
+ * change notifications.
1098
+ */
1099
+ var assertMutableWithinChange = (echoRoot, prop) => {
1100
+ const isInitialized = EventId in echoRoot;
1101
+ if (isInitialized && typeof prop !== "symbol" && !isInChangeContext(echoRoot)) throw new Error(`Cannot modify object property "${String(prop)}" outside of Obj.update(). Use Obj.update(obj, (mutableObj) => { mutableObj.property = value; }) instead.`);
1102
+ return isInitialized;
1103
+ };
1104
+ /**
1105
+ * Move a record's per-object metadata (symbol-keyed hidden properties) onto a fresh instance-state
1106
+ * object inserted between the target and {@link TypedObjectPrototype}. The target keeps only its
1107
+ * user data as own properties. Arrays are exempt — they keep their own (ReactiveArray) prototype chain.
1108
+ */
1109
+ var compactMetadataToInstanceState = (target) => {
1110
+ if (Array.isArray(target) || Object.getPrototypeOf(target) !== Object.prototype) return;
1111
+ const state = Object.create(TypedObjectPrototype);
1112
+ for (const symbol of Object.getOwnPropertySymbols(target)) {
1113
+ const descriptor = Object.getOwnPropertyDescriptor(target, symbol);
1114
+ Object.defineProperty(state, symbol, descriptor);
1115
+ if (descriptor.configurable) delete target[symbol];
1116
+ }
1117
+ Object.setPrototypeOf(target, state);
1118
+ };
1119
+ /**
1120
+ * Typed in-memory reactive store (with Schema).
1121
+ * Reactivity is based on Event subscriptions, not signals.
1122
+ */
1123
+ var TypedReactiveHandler = class TypedReactiveHandler {
1124
+ static instance = new TypedReactiveHandler();
1125
+ _proxyMap = /* @__PURE__ */ new WeakMap();
1126
+ _inSet = false;
1127
+ constructor() {}
1128
+ init(target) {
1129
+ assertArgument(typeof target === "object" && target !== null, "target");
1130
+ invariant(SchemaId in target, "Schema is not defined for the target", {
1131
+ "~LogMeta": "~LogMeta",
1132
+ F: __dxlog_file$7,
1133
+ L: 296,
1134
+ S: this,
1135
+ A: ["SchemaId in target", "'Schema is not defined for the target'"]
1136
+ });
1137
+ const hasOwner = !!getOwner(target);
1138
+ if (!(EventId in target) && !hasOwner) defineHiddenProperty(target, EventId, new Event());
1139
+ if (!(ObjectDeletedId in target)) defineHiddenProperty(target, ObjectDeletedId, false);
1140
+ if (!hasOwner) for (const key in target) {
1141
+ if (target[symbolIsProxy]) continue;
1142
+ let value = target[key];
1143
+ if (isValidProxyTarget(value) || isProxy(value)) {
1144
+ if (hasForeignOwner(value, target)) {
1145
+ value = deepCopy(value);
1146
+ target[key] = value;
1147
+ }
1148
+ setOwnerRecursive(value, target);
1149
+ }
1150
+ }
1151
+ Object.defineProperty(target, inspectCustom, {
1152
+ enumerable: false,
1153
+ configurable: true,
1154
+ value: this._inspect.bind(target)
1155
+ });
1156
+ compactMetadataToInstanceState(target);
1157
+ }
1158
+ /**
1159
+ * Hide the internal instance-state prototype so consumers see a plain object; arrays keep their
1160
+ * real (ReactiveArray) prototype.
1161
+ */
1162
+ getPrototypeOf(target) {
1163
+ return Array.isArray(target) ? Reflect.getPrototypeOf(target) : Object.prototype;
1164
+ }
1165
+ get(target, prop, receiver) {
1166
+ if (typeof prop === "symbol" && isBehaviourAccessor(target, prop)) return Reflect.get(target, prop, receiver);
1167
+ if (prop === TypeEntityId) return Reflect.get(target, prop, receiver);
1168
+ if (Object.getOwnPropertyDescriptor(target, prop)?.get) return Reflect.get(target, prop, receiver);
1169
+ const value = Reflect.get(target, prop, receiver);
1170
+ if (isValidProxyTarget(value)) return createProxy(value, this);
1171
+ return value;
1172
+ }
1173
+ set(target, prop, value, receiver) {
1174
+ const echoRoot = getEchoRoot(target);
1175
+ const isInitialized = assertMutableWithinChange(echoRoot, prop);
1176
+ let result = false;
1177
+ this._inSet = true;
1178
+ try {
1179
+ batchEvents(() => {
1180
+ const { echoRoot: _, preparedValue } = this._prepareValueForAssignment(target, prop, value);
1181
+ result = Reflect.set(target, prop, preparedValue, receiver);
1182
+ if (prop === "jsonSchema") Reflect.deleteProperty(target, StaticTypeSchemaSlot);
1183
+ if (isInitialized) {
1184
+ queueNotification(echoRoot);
1185
+ notifyOwnerChain(target);
1186
+ }
1187
+ });
1188
+ } finally {
1189
+ this._inSet = false;
1190
+ }
1191
+ return result;
1192
+ }
1193
+ ownKeys(target) {
1194
+ return Reflect.ownKeys(target);
1195
+ }
1196
+ deleteProperty(target, property) {
1197
+ const echoRoot = getEchoRoot(target);
1198
+ const isInitialized = EventId in echoRoot;
1199
+ if (isInitialized && !(typeof property === "symbol") && !isInChangeContext(echoRoot)) throw createPropertyDeleteError(property);
1200
+ const result = Reflect.deleteProperty(target, property);
1201
+ if (isInitialized) queueNotification(echoRoot);
1202
+ return result;
1203
+ }
1204
+ defineProperty(target, property, attributes) {
1205
+ const echoRoot = getEchoRoot(target);
1206
+ const isInitialized = assertMutableWithinChange(echoRoot, property);
1207
+ const { echoRoot: _, preparedValue } = this._prepareValueForAssignment(target, property, attributes.value);
1208
+ const result = Reflect.defineProperty(target, property, {
1209
+ ...attributes,
1210
+ value: preparedValue
1211
+ });
1212
+ if (!this._inSet && isInitialized) queueNotification(echoRoot);
1213
+ return result;
1214
+ }
1215
+ textUpdate(target, path, newText) {
1216
+ this._applyTextMutation(target, path, () => newText);
1217
+ }
1218
+ textSplice(target, path, start, deleteCount, insert) {
1219
+ let removed = "";
1220
+ this._applyTextMutation(target, path, (current) => {
1221
+ const range = normalizeSpliceRange(current.length, start, deleteCount);
1222
+ removed = current.slice(range.start, range.start + range.deleteCount);
1223
+ return current.slice(0, range.start) + insert + current.slice(range.start + range.deleteCount);
1224
+ });
1225
+ return removed;
1226
+ }
1227
+ /**
1228
+ * Shared read-modify-write for the in-memory string CRDT path. Mirrors the `set` trap: enforce the
1229
+ * change context, then mutate and notify through the same batched notification path so reactivity fires.
1230
+ *
1231
+ * Writes via `setDeep` on the raw target, intentionally bypassing `_prepareValueForAssignment` /
1232
+ * `_validateValue`: a string CRDT delta produces a string, and per-delta schema checks (pattern,
1233
+ * maxLength) would reject valid intermediate states during incremental edits. Such constraints are
1234
+ * enforced at the initial assignment or as application-level invariants, mirroring the Automerge path.
1235
+ */
1236
+ _applyTextMutation(target, path, compute) {
1237
+ const echoRoot = getEchoRoot(target);
1238
+ if (!isInChangeContext(echoRoot)) throw new Error(`Cannot modify text at "${path.join(".")}" outside of Obj.update(). Use Obj.update(obj, () => { Text.splice(obj, path, ...); }) instead.`);
1239
+ const keyPath = [...path];
1240
+ invariant(keyPath.length > 0, "Text path must be non-empty", {
1241
+ "~LogMeta": "~LogMeta",
1242
+ F: __dxlog_file$7,
1243
+ L: 493,
1244
+ S: this,
1245
+ A: ["keyPath.length > 0", "'Text path must be non-empty'"]
1246
+ });
1247
+ const current = getDeep(target, keyPath);
1248
+ if (typeof current !== "string") throw new TypeError(`Text mutation target at "${keyPath.join(".")}" is not a string.`);
1249
+ const next = compute(current);
1250
+ batchEvents(() => {
1251
+ setDeep(target, keyPath, next);
1252
+ queueNotification(echoRoot);
1253
+ notifyOwnerChain(target);
1254
+ });
1255
+ }
1256
+ /**
1257
+ * Prepare a value for assignment to a typed object property.
1258
+ * Handles cycle detection, copy-on-assign, array conversion, validation, and ownership.
1259
+ */
1260
+ _prepareValueForAssignment(target, prop, value) {
1261
+ const echoRoot = getEchoRoot(target);
1262
+ if (typeof prop === "symbol") return {
1263
+ echoRoot,
1264
+ preparedValue: value
1265
+ };
1266
+ if (isValidProxyTarget(value) || isProxy(value)) {
1267
+ if (wouldCreateCycle(echoRoot, value)) throw new Error("Cannot create cycles in typed object graph. Consider using Ref for circular references.");
1268
+ }
1269
+ if (isValidProxyTarget(value) || isProxy(value)) {
1270
+ if (EventId in getRawTarget(value)) throw new Error("Object references must be wrapped with `Ref.make`");
1271
+ }
1272
+ if (isValidProxyTarget(value) || isProxy(value)) {
1273
+ const existingOwner = getOwner(getRawTarget(value));
1274
+ if (existingOwner != null && existingOwner !== echoRoot) value = deepCopy(value);
1275
+ }
1276
+ if (Array.isArray(value) && !(value instanceof ReactiveArray)) value = ReactiveArray.from(value);
1277
+ const validatedValue = this._validateValue(target, prop, value);
1278
+ if (isValidProxyTarget(validatedValue) || isProxy(validatedValue)) setOwnerRecursive(validatedValue, echoRoot);
1279
+ return {
1280
+ echoRoot,
1281
+ preparedValue: validatedValue
1282
+ };
1283
+ }
1284
+ _validateValue(target, prop, value) {
1285
+ if (prop === ParentId) return value;
1286
+ const schema = SchemaValidator.getTargetPropertySchema(target, prop);
1287
+ Schema.asserts(schema)(value);
1288
+ SchemaValidator.assertExactProperties(schema, value, (path) => getDeep(value, path));
1289
+ if (isValidProxyTarget(value)) setSchemaProperties(value, schema);
1290
+ return value;
1291
+ }
1292
+ _inspect(_, options, inspectFn) {
1293
+ return `Typed ${inspectFn(this, {
1294
+ ...options,
1295
+ showHidden: false,
1296
+ customInspect: false
1297
+ })}`;
1298
+ }
1299
+ };
1300
+ /**
1301
+ * @deprecated Use `Obj.toJSON` instead.
1302
+ */
1303
+ var toJSON = (target) => {
1304
+ return {
1305
+ "@type": "TypedReactiveObject",
1306
+ ...target
1307
+ };
1308
+ };
1309
+ /**
1310
+ * Recursively set AST on all potential proxy targets.
1311
+ *
1312
+ * @param skipOwnStamp Skip stamping `TypeId`/`SchemaId` on `obj` itself (still recurses into
1313
+ * children, which always get stamped). Used for objects decoded from JSON, whose own `TypeId`/
1314
+ * `SchemaId` are already set by `setTypename`/`setSchema` as `configurable: false` — redefining
1315
+ * them here (with `configurable: true`) would throw.
1316
+ */
1317
+ var setSchemaProperties = (obj, schema, typeSource, skipOwnStamp = false) => {
1318
+ if (!skipOwnStamp) {
1319
+ const schemaType = getSchemaURI(schema);
1320
+ if (schemaType != null) defineHiddenProperty(obj, TypeId, schemaType);
1321
+ if (typeSource != null) {
1322
+ defineHiddenProperty(obj, TypeEntityId, typeSource);
1323
+ Object.defineProperty(obj, SchemaId, {
1324
+ get: () => typeSource["~@dxos/echo/Type.StaticSchema"] ?? schema,
1325
+ enumerable: false,
1326
+ configurable: true
1327
+ });
1328
+ } else defineHiddenProperty(obj, SchemaId, schema);
1329
+ }
1330
+ if (Array.isArray(obj)) {
1331
+ for (let index = 0; index < obj.length; index++) if (isValidProxyTarget(obj[index])) {
1332
+ const elementSchema = SchemaValidator.getIndexedElementSchema(schema, index) ?? Schema.Any;
1333
+ setSchemaProperties(obj[index], elementSchema);
1334
+ }
1335
+ return;
1336
+ }
1337
+ for (const key in obj) if (isValidProxyTarget(obj[key])) {
1338
+ let elementSchema;
1339
+ try {
1340
+ elementSchema = SchemaValidator.getTargetPropertySchema(obj, key);
1341
+ } catch {
1342
+ elementSchema = Schema.Any;
1343
+ }
1344
+ setSchemaProperties(obj[key], elementSchema);
1345
+ }
1346
+ };
1347
+ var prepareTypedTarget = (target, schema, typeSource) => {
1348
+ validateAndReactifyTarget(target, schema);
1349
+ setSchemaProperties(target, schema, typeSource);
1350
+ };
1351
+ /**
1352
+ * Validate a target against its schema and convert nested arrays to `ReactiveArray`. Shared by
1353
+ * {@link prepareTypedTarget} and {@link prepareDecodedTypedTarget}.
1354
+ */
1355
+ var validateAndReactifyTarget = (target, schema) => {
1356
+ if (!SchemaAST.isTypeLiteral(schema.ast)) throw new Error("schema has to describe an object type");
1357
+ SchemaValidator.validateSchema(schema);
1358
+ Schema.asserts(schema)(target);
1359
+ SchemaValidator.assertExactProperties(schema, target, (path) => getDeep(target, path));
1360
+ makeArraysReactive(target);
1361
+ };
1362
+ /**
1363
+ * Like {@link prepareTypedTarget}, for a target whose own `SchemaId`/`TypeId` are already stamped
1364
+ * and locked `configurable: false` — e.g. an object decoded from JSON via `setSchema`/`setTypename`
1365
+ * (see `objectFromJSON`). Validates and reactifies as usual, then stamps `SchemaId`/`TypeId` on
1366
+ * nested records/arrays only, leaving the target's own (locked) stamps untouched.
1367
+ */
1368
+ var prepareDecodedTypedTarget = (target, schema) => {
1369
+ validateAndReactifyTarget(target, schema);
1370
+ setSchemaProperties(target, schema, void 0, true);
1371
+ };
1372
+ var makeArraysReactive = (target) => {
1373
+ for (const key in target) {
1374
+ if (target[symbolIsProxy]) continue;
1375
+ if (Array.isArray(target[key])) target[key] = ReactiveArray.from(target[key]);
1376
+ if (typeof target[key] === "object") makeArraysReactive(target[key]);
1377
+ }
1378
+ };
1379
+ //#endregion
1380
+ //#region src/internal/common/proxy/make-object.ts
1381
+ /**
1382
+ * Creates a reactive object from a plain Javascript object.
1383
+ * Requires a TS-effect schema.
1384
+ *
1385
+ * Callers that have a `Type.Type` entity (not a raw schema) must unwrap it
1386
+ * themselves — `Obj.make` / `Relation.make` do this via `Type.getSchema(...)`
1387
+ * and pass the entity through as `typeSource` so the instance carries a
1388
+ * back-reference for `Obj.getType` and resolves the live source schema
1389
+ * uniformly via the entity's `[StaticTypeSchemaSlot]`.
1390
+ */
1391
+ var makeObject = (schema, obj, meta, typeSource) => {
1392
+ return createReactiveObject(Object.assign({}, obj), meta, schema, typeSource);
1393
+ };
1394
+ var createReactiveObject = (obj, meta, schema, typeSource) => {
1395
+ if (!isValidProxyTarget(obj)) throw new Error("Value cannot be made into a reactive object.");
1396
+ if (!schema) throw new Error("Schema is required for reactive objects. Use Atom for untyped reactive state.");
1397
+ const parent = obj[ParentId];
1398
+ if (parent !== void 0) delete obj[ParentId];
1399
+ const annotation = getTypeAnnotation(schema);
1400
+ if (annotation) {
1401
+ setIdOnTarget(obj);
1402
+ defineHiddenProperty(obj, KindId, annotation.kind);
1403
+ }
1404
+ initMeta(obj, meta);
1405
+ if (parent !== void 0) defineHiddenProperty(obj, ParentId, parent);
1406
+ prepareTypedTarget(obj, schema, typeSource);
1407
+ attachTypedJsonSerializer(obj);
1408
+ const proxy = createProxy(obj, TypedReactiveHandler.instance);
1409
+ const metaProxy = obj[MetaId];
1410
+ if (metaProxy) {
1411
+ const metaTarget = getProxyTarget(metaProxy);
1412
+ if (metaTarget) setMetaOwner(metaTarget, obj);
1413
+ }
1414
+ return proxy;
1415
+ };
1416
+ /**
1417
+ * Rewrap an object decoded from JSON (via `objectFromJSON`) into a live reactive proxy, so that
1418
+ * `Obj.update` synchronously mutates it and `Obj.subscribe`/atoms fire — the same contract as
1419
+ * automerge-backed objects. Unlike {@link makeObject}, the target already carries `SchemaId`/
1420
+ * `TypeId` stamped by `setSchema`/`setTypename` (both `configurable: false`), so this does not
1421
+ * re-derive or re-stamp them — it only validates against the schema, reactifies nested arrays,
1422
+ * rewraps `[MetaId]` as a live nested proxy, and wraps the whole object in a proxy.
1423
+ *
1424
+ * Objects whose type could not be resolved at decode time (no `SchemaId`) are returned unchanged —
1425
+ * they remain plain snapshots and `Obj.update` on them stays a no-op, since there is no schema to
1426
+ * validate mutations against.
1427
+ */
1428
+ var makeDecodedEntityLive = (obj) => {
1429
+ const schema = obj[SchemaId];
1430
+ if (!schema) return obj;
1431
+ prepareDecodedTypedTarget(obj, schema);
1432
+ const meta = obj[MetaId];
1433
+ if (meta != null && typeof meta === "object" && !isProxy(meta)) {
1434
+ prepareTypedTarget(meta, EntityMetaSchema);
1435
+ const metaProxy = createProxy(meta, TypedReactiveHandler.instance);
1436
+ defineHiddenProperty(obj, MetaId, metaProxy);
1437
+ setMetaOwner(getProxyTarget(metaProxy), obj);
1438
+ }
1439
+ attachTypedJsonSerializer(obj);
1440
+ return createProxy(obj, TypedReactiveHandler.instance);
1441
+ };
1442
+ /**
1443
+ * Set ID on ECHO object targets during creation.
1444
+ * Used for objects with schema and the ones explicitly marked as Expando.
1445
+ */
1446
+ var setIdOnTarget = (target) => {
1447
+ if ("id" in target && target.id !== void 0 && target.id !== null) {
1448
+ if (!EntityId.isValid(target.id)) throw new Error("Invalid object id format.");
1449
+ } else target.id = EntityId.random();
1450
+ };
1451
+ /**
1452
+ * Set metadata on object.
1453
+ */
1454
+ var initMeta = (obj, meta) => {
1455
+ const fullMeta = {
1456
+ ...meta,
1457
+ keys: meta?.keys ?? [],
1458
+ tags: meta?.tags ?? [],
1459
+ annotations: meta?.annotations ?? {}
1460
+ };
1461
+ prepareTypedTarget(fullMeta, EntityMetaSchema);
1462
+ defineHiddenProperty(obj, MetaId, createProxy(fullMeta, TypedReactiveHandler.instance));
1463
+ };
1464
+ //#endregion
1465
+ //#region src/internal/Entity/entity.ts
1466
+ /**
1467
+ * Identity (typename + version) of the type meta-schema — the `Type.Type` that
1468
+ * every ECHO type entity is itself an instance of. Shared by the materialisation
1469
+ * vehicle ({@link persistentEntitySchema}) and `TypeSchema` so the two cannot
1470
+ * drift on identity.
1471
+ */
1472
+ var TypeMetaSchemaDXN = DXN.make("org.dxos.type.schema", "0.1.0");
1473
+ /**
1474
+ * Effect Schema that every `Type.Type` entity is an instance of: the meta-schema
1475
+ * struct `{ name?, jsonSchema, id }` branded as a type-kind ECHO entity. This is
1476
+ * the materialisation vehicle for `makeObject` below — the canonical user-facing
1477
+ * entity is `Type/type-schema.ts`'s `TypeSchema`, which carries the same shape
1478
+ * plus UI annotations.
1479
+ *
1480
+ * Kept self-contained (no import of `TypeSchema`) to avoid a bootstrap cycle:
1481
+ * `TypeSchema` is itself produced via `makeEchoTypeSchema`, so this builder must
1482
+ * not depend on it. `jsonSchema` is declared optional here (only on the
1483
+ * materialisation vehicle — the canonical `TypeSchema` keeps it required) so the
1484
+ * construction-time `Schema.asserts` does not force the field before it is
1485
+ * attached; it is populated immediately after via a lazy accessor (see
1486
+ * `makeEchoTypeSchema`).
1487
+ */
1488
+ var persistentEntitySchema = (() => {
1489
+ const typename = DXN.getName(TypeMetaSchemaDXN);
1490
+ const version = DXN.getVersion(TypeMetaSchemaDXN);
1491
+ const struct = Schema.Struct({
1492
+ name: Schema.optional(Schema.String),
1493
+ jsonSchema: JsonSchemaType.pipe(Schema.optional),
1494
+ id: EntityId
1495
+ });
1496
+ const ast = SchemaAST.annotations(struct.ast, {
1497
+ [TypeAnnotationId]: {
1498
+ kind: EntityKind.Type,
1499
+ typename,
1500
+ version
1501
+ },
1502
+ [SchemaAST.JSONSchemaAnnotationId]: makeTypeJsonSchemaAnnotation({
1503
+ kind: EntityKind.Type,
1504
+ typename,
1505
+ version
1506
+ })
1507
+ });
1508
+ return Schema.make(ast);
1509
+ })();
1510
+ /**
1511
+ * @internal
1512
+ *
1513
+ * Build an in-memory `Type.Type` entity (the value returned by `Type.makeObject`
1514
+ * / `Type.makeRelation`). The result is a LIVE reactive `TypeSchema`
1515
+ * instance — identical in every respect to a persisted `Type.Type` except that
1516
+ * it is not yet attached to a database. It is mutable via `Type.update`, can be
1517
+ * passed to `db.add(...)` (which keeps the same proxy and swaps the handler),
1518
+ * and round-trips through `jsonSchema`.
1519
+ *
1520
+ * The source Effect Schema describing the user's type is cached on
1521
+ * `[StaticTypeSchemaSlot]` so `Type.getSchema(...)` returns it without a
1522
+ * jsonSchema round-trip; the cache is invalidated by the proxy set-trap when
1523
+ * `jsonSchema` is mutated (see `typed-handler.ts`).
1524
+ */
1525
+ var makeEchoTypeSchema = (fields, ast, typename, version, kind, computeJsonSchema, explicitId) => {
1526
+ const sourceSchema = Schema.make(ast);
1527
+ const meta = {
1528
+ keys: [],
1529
+ key: typename,
1530
+ version
1531
+ };
1532
+ const entity = makeObject(persistentEntitySchema, { id: explicitId ?? EntityId.deterministic(typename, version) }, meta);
1533
+ const target = getProxyTarget(entity);
1534
+ let memoizedJsonSchema;
1535
+ Object.defineProperty(target, "jsonSchema", {
1536
+ configurable: true,
1537
+ enumerable: true,
1538
+ get() {
1539
+ return memoizedJsonSchema ??= computeJsonSchema();
1540
+ },
1541
+ set(value) {
1542
+ memoizedJsonSchema = value;
1543
+ }
1544
+ });
1545
+ defineHiddenProperty(target, StaticTypeSchemaSlot, sourceSchema);
1546
+ defineHiddenProperty(target, SchemaKindId, kind);
1547
+ Object.defineProperty(target, "fields", {
1548
+ configurable: true,
1549
+ enumerable: false,
1550
+ get: () => fields
1551
+ });
1552
+ return entity;
1553
+ };
1554
+ //#endregion
1555
+ //#region src/internal/JsonSchema/json-schema-normalize.ts
1556
+ /**
1557
+ * Normalize schema to to draft-07 format.
1558
+ * Note: the input type does not necessarily match the {@link JsonSchemaType} type.
1559
+ */
1560
+ var normalizeSchema = (schema) => {
1561
+ const copy = structuredClone(schema);
1562
+ go(copy);
1563
+ return copy;
1564
+ };
1565
+ var go = (schema) => {
1566
+ if (typeof schema !== "object" || schema === null) return;
1567
+ if (schema.exclusiveMaximum === true) {
1568
+ schema.exclusiveMaximum = schema.maximum;
1569
+ delete schema.exclusiveMaximum;
1570
+ } else if (schema.exclusiveMaximum === false) delete schema.exclusiveMaximum;
1571
+ if (schema.exclusiveMinimum === true) {
1572
+ schema.exclusiveMinimum = schema.minimum;
1573
+ delete schema.exclusiveMinimum;
1574
+ } else if (schema.exclusiveMinimum === false) delete schema.exclusiveMinimum;
1575
+ for (const key of Object.keys(schema)) if (!JsonSchemaFields.includes(key)) delete schema[key];
1576
+ if (schema.properties) goOnRecord(schema.properties);
1577
+ if (schema.patternProperties) goOnRecord(schema.patternProperties);
1578
+ if (schema.propertyNames) go(schema.propertyNames);
1579
+ if (schema.definitions) goOnRecord(schema.definitions);
1580
+ if (schema.items) maybeGoOnArray(schema.items);
1581
+ if (schema.additionalItems) maybeGoOnArray(schema.additionalItems);
1582
+ if (schema.contains) go(schema.contains);
1583
+ if (schema.if) go(schema.if);
1584
+ if (schema.then) go(schema.then);
1585
+ if (schema.else) go(schema.else);
1586
+ if (schema.allOf) maybeGoOnArray(schema.allOf);
1587
+ if (schema.anyOf) maybeGoOnArray(schema.anyOf);
1588
+ if (schema.oneOf) maybeGoOnArray(schema.oneOf);
1589
+ if (schema.not) go(schema.not);
1590
+ if (schema.$defs) goOnRecord(schema.$defs);
1591
+ if (schema.reference) go(schema.reference.schema);
1592
+ };
1593
+ var maybeGoOnArray = (value) => {
1594
+ if (Array.isArray(value)) for (const item of value) go(item);
1595
+ else if (typeof value === "object" && value !== null) go(value);
1596
+ };
1597
+ var goOnRecord = (record) => {
1598
+ for (const key of Object.keys(record)) go(record[key]);
1599
+ };
1600
+ //#endregion
1601
+ //#region src/internal/Entity/object.ts
1602
+ var __dxlog_file$6 = "/__w/dxos/dxos/packages/core/echo/echo/src/internal/Entity/object.ts";
1603
+ /**
1604
+ * Schema for Obj entity types.
1605
+ * Pipeable function to add ECHO object annotations to a schema.
1606
+ */
1607
+ var EchoObjectSchema = (dxn, options) => {
1608
+ const typename = DXN.getName(dxn);
1609
+ const version = DXN.getVersion(dxn);
1610
+ invariant(version, `Type.makeObject requires a versioned DXN: ${dxn}`, {
1611
+ "~LogMeta": "~LogMeta",
1612
+ F: __dxlog_file$6,
1613
+ L: 40,
1614
+ S: void 0,
1615
+ A: ["version", "`Type.makeObject requires a versioned DXN: ${dxn}`"]
1616
+ });
1617
+ return (self) => {
1618
+ invariant(typeof TypeAnnotationId === "symbol", "Sanity.", {
1619
+ "~LogMeta": "~LogMeta",
1620
+ F: __dxlog_file$6,
1621
+ L: 45,
1622
+ S: void 0,
1623
+ A: ["typeof TypeAnnotationId === 'symbol'", "'Sanity.'"]
1624
+ });
1625
+ invariant(SchemaAST.isTypeLiteral(self.ast), "Schema must be a TypeLiteral.", {
1626
+ "~LogMeta": "~LogMeta",
1627
+ F: __dxlog_file$6,
1628
+ L: 46,
1629
+ S: void 0,
1630
+ A: ["SchemaAST.isTypeLiteral(self.ast)", "'Schema must be a TypeLiteral.'"]
1631
+ });
1632
+ const fields = self.fields ?? {};
1633
+ const schemaWithId = Schema.extend(self, Schema.Struct({ id: Schema.String }));
1634
+ const ast = SchemaAST.annotations(schemaWithId.ast, {
1635
+ ...self.ast.annotations,
1636
+ [TypeAnnotationId]: {
1637
+ kind: EntityKind.Object,
1638
+ typename,
1639
+ version
1640
+ },
1641
+ [SchemaAST.JSONSchemaAnnotationId]: makeTypeJsonSchemaAnnotation({
1642
+ kind: EntityKind.Object,
1643
+ typename,
1644
+ version
1645
+ })
1646
+ });
1647
+ return makeEchoTypeSchema(fields, ast, typename, version, EntityKind.Object, () => toJsonSchema(Schema.make(ast)), options?.id);
1648
+ };
1649
+ };
1650
+ var makeObjectType = (dxn, schema, options) => {
1651
+ const type = EchoObjectSchema(dxn, options)(schema);
1652
+ const constructor = function ObjectType() {};
1653
+ Object.setPrototypeOf(constructor, type);
1654
+ return constructor;
1655
+ };
1656
+ //#endregion
1657
+ //#region src/internal/Entity/relation.ts
1658
+ var __dxlog_file$5 = "/__w/dxos/dxos/packages/core/echo/echo/src/internal/Entity/relation.ts";
1659
+ /**
1660
+ * Schema for Relation entity types.
1661
+ */
1662
+ var EchoRelationSchema = ({ dxn, source, target, id: explicitId }) => {
1663
+ const sourceSchema = source != null ? getStaticTypeSchema(source) ?? source : source;
1664
+ const targetSchema = target != null ? getStaticTypeSchema(target) ?? target : target;
1665
+ assertArgument(Schema.isSchema(sourceSchema), "source");
1666
+ assertArgument(Schema.isSchema(targetSchema), "target");
1667
+ const typename = DXN.getName(dxn);
1668
+ const version = DXN.getVersion(dxn);
1669
+ invariant(version, `Type.makeRelation requires a versioned DXN: ${dxn}`, {
1670
+ "~LogMeta": "~LogMeta",
1671
+ F: __dxlog_file$5,
1672
+ L: 123,
1673
+ S: void 0,
1674
+ A: ["version", "`Type.makeRelation requires a versioned DXN: ${dxn}`"]
1675
+ });
1676
+ const sourceDXN = getDXNForRelationSchemaRef(sourceSchema);
1677
+ const targetDXN = getDXNForRelationSchemaRef(targetSchema);
1678
+ if (getEntityKind(sourceSchema) !== EntityKind.Object) raise(/* @__PURE__ */ new Error("Source schema must be an echo object schema."));
1679
+ if (getEntityKind(targetSchema) !== EntityKind.Object) raise(/* @__PURE__ */ new Error("Target schema must be an echo object schema."));
1680
+ return (self) => {
1681
+ invariant(SchemaAST.isTypeLiteral(self.ast), "Schema must be a TypeLiteral.", {
1682
+ "~LogMeta": "~LogMeta",
1683
+ F: __dxlog_file$5,
1684
+ L: 136,
1685
+ S: void 0,
1686
+ A: ["SchemaAST.isTypeLiteral(self.ast)", "'Schema must be a TypeLiteral.'"]
1687
+ });
1688
+ const fields = self.fields ?? {};
1689
+ const schemaWithId = Schema.extend(self, Schema.Struct({ id: Schema.String }));
1690
+ const ast = SchemaAST.annotations(schemaWithId.ast, {
1691
+ ...self.ast.annotations,
1692
+ [TypeAnnotationId]: {
1693
+ kind: EntityKind.Relation,
1694
+ typename,
1695
+ version,
1696
+ sourceSchema: sourceDXN,
1697
+ targetSchema: targetDXN
1698
+ },
1699
+ [SchemaAST.JSONSchemaAnnotationId]: makeTypeJsonSchemaAnnotation({
1700
+ kind: EntityKind.Relation,
1701
+ typename,
1702
+ version,
1703
+ relationSource: sourceDXN,
1704
+ relationTarget: targetDXN
1705
+ })
1706
+ });
1707
+ return makeEchoTypeSchema(fields, ast, typename, version, EntityKind.Relation, () => toJsonSchema(Schema.make(ast)), explicitId);
1708
+ };
1709
+ };
1710
+ var getDXNForRelationSchemaRef = (schema) => {
1711
+ assertArgument(Schema.isSchema(schema), "schema");
1712
+ const identifier = getTypeIdentifierAnnotation(schema);
1713
+ if (identifier) return DXN.tryMake(identifier) ?? raise(/* @__PURE__ */ new Error(`Invalid schema identifier: ${identifier}`));
1714
+ const typename = getSchemaTypename(schema);
1715
+ if (!typename) throw new Error("Schema must have a typename");
1716
+ return DXN.make(typename);
1717
+ };
1718
+ var makeRelationType = (options) => {
1719
+ const type = EchoRelationSchema({
1720
+ dxn: options.dxn,
1721
+ source: options.source,
1722
+ target: options.target,
1723
+ id: options.id
1724
+ })(options.schema);
1725
+ const constructor = function RelationType() {};
1726
+ Object.setPrototypeOf(constructor, type);
1727
+ return constructor;
1728
+ };
1729
+ //#endregion
1730
+ //#region src/internal/Entity/type-kind.ts
1731
+ var __dxlog_file$4 = "/__w/dxos/dxos/packages/core/echo/echo/src/internal/Entity/type-kind.ts";
1732
+ /**
1733
+ * Pipeable that brands a schema as a type-kind ECHO entity. Mirrors
1734
+ * {@link EchoObjectSchema} / {@link EchoRelationSchema}, but stamps the
1735
+ * resulting entity with `[SchemaKindId]: EntityKind.Type` and a matching
1736
+ * `TypeAnnotation.kind = 'type'` so meta-schemas surface uniformly through
1737
+ * `Type.isTypeKind`, `Filter.type`, etc.
1738
+ */
1739
+ var EchoTypeKindSchema = (dxn, options) => {
1740
+ const typename = DXN.getName(dxn);
1741
+ const version = DXN.getVersion(dxn);
1742
+ invariant(version, `Type-kind schemas require a versioned DXN: ${dxn}`, {
1743
+ "~LogMeta": "~LogMeta",
1744
+ F: __dxlog_file$4,
1745
+ L: 45,
1746
+ S: void 0,
1747
+ A: ["version", "`Type-kind schemas require a versioned DXN: ${dxn}`"]
1748
+ });
1749
+ return (self) => {
1750
+ invariant(SchemaAST.isTypeLiteral(self.ast), "Schema must be a TypeLiteral.", {
1751
+ "~LogMeta": "~LogMeta",
1752
+ F: __dxlog_file$4,
1753
+ L: 50,
1754
+ S: void 0,
1755
+ A: ["SchemaAST.isTypeLiteral(self.ast)", "'Schema must be a TypeLiteral.'"]
1756
+ });
1757
+ const fields = self.fields ?? {};
1758
+ const schemaWithId = Schema.extend(self, Schema.Struct({ id: Schema.String }));
1759
+ const ast = SchemaAST.annotations(schemaWithId.ast, {
1760
+ ...self.ast.annotations,
1761
+ [TypeAnnotationId]: {
1762
+ kind: EntityKind.Type,
1763
+ typename,
1764
+ version
1765
+ },
1766
+ [SchemaAST.JSONSchemaAnnotationId]: makeTypeJsonSchemaAnnotation({
1767
+ kind: EntityKind.Type,
1768
+ typename,
1769
+ version
1770
+ })
1771
+ });
1772
+ return makeEchoTypeSchema(fields, ast, typename, version, EntityKind.Type, () => toJsonSchema(Schema.make(ast)), options?.id);
1773
+ };
1774
+ };
1775
+ //#endregion
1776
+ //#region src/internal/Entity/version.ts
1777
+ var unversioned = {
1778
+ [VersionTypeId]: {},
1779
+ versioned: false
1780
+ };
1781
+ /**
1782
+ * Checks that `obj` is a version object.
1783
+ */
1784
+ var isVersion = (entity) => {
1785
+ return entity != null && typeof entity === "object" && "~@dxos/echo/VersionTypeId" in entity;
1786
+ };
1787
+ /**
1788
+ * Returns the version of an entity.
1789
+ * Accepts both reactive entities and snapshots.
1790
+ */
1791
+ var version = (entity) => {
1792
+ const ver = entity[ObjectVersionId];
1793
+ if (ver === void 0) return unversioned;
1794
+ return ver;
1795
+ };
1796
+ /**
1797
+ * Checks that `version` is a valid version object.
1798
+ */
1799
+ var versionValid = (ver) => {
1800
+ assertArgument(isVersion(ver), "version", "Invalid version object");
1801
+ return !!ver.versioned;
1802
+ };
1803
+ /**
1804
+ * Compares two versions.
1805
+ * @param version1
1806
+ * @param version2
1807
+ * @returns 'unversioned' if either entity is unversioned, 'equal' if the versions are equal, 'different' if the versions are different.
1808
+ */
1809
+ var compareVersions = (version1, version2) => {
1810
+ assertArgument(isVersion(version1), "version1", "Invalid version object");
1811
+ assertArgument(isVersion(version2), "version2", "Invalid version object");
1812
+ if (!versionValid(version1) || !versionValid(version2)) return "unversioned";
1813
+ if (version1.automergeHeads?.length !== version2.automergeHeads?.length) return "different";
1814
+ if (version1.automergeHeads?.some((head) => !version2.automergeHeads?.includes(head))) return "different";
1815
+ return "equal";
1816
+ };
1817
+ var encodeVersion = (ver) => {
1818
+ return JSON.stringify(ver);
1819
+ };
1820
+ var decodeVersion = (ver) => {
1821
+ const parsed = JSON.parse(ver);
1822
+ parsed[VersionTypeId] = {};
1823
+ return parsed;
1824
+ };
1825
+ //#endregion
1826
+ //#region src/internal/Obj/json-serializer.ts
1827
+ var __dxlog_file$3 = "/__w/dxos/dxos/packages/core/echo/echo/src/internal/Obj/json-serializer.ts";
1828
+ /**
1829
+ * Converts object to it's JSON representation.
1830
+ */
1831
+ var objectToJSON = (obj) => {
1832
+ const typename = getTypeURI(obj);
1833
+ invariant(typename && typeof typename === "string", void 0, {
1834
+ "~LogMeta": "~LogMeta",
1835
+ F: __dxlog_file$3,
1836
+ L: 68,
1837
+ S: void 0,
1838
+ A: ["typename && typeof typename === 'string'", ""]
1839
+ });
1840
+ return typedJsonSerializer.call(obj);
1841
+ };
1842
+ /**
1843
+ * Creates an object from it's json representation.
1844
+ * Performs schema validation.
1845
+ * References and schema will be resolvable if the `refResolver` is provided.
1846
+ * The function need to be async to support resolving the schema as well as the relation endpoints.
1847
+ *
1848
+ * @param jsonData - JSON representation of the object.
1849
+ * @param options.refResolver - Resolver for references.
1850
+ * @param options.uri - Override object URI.
1851
+ * @param options.database - Database to associate with the object.
1852
+ */
1853
+ var objectFromJSON = async (jsonData, { refResolver, uri, database, parent } = {}) => {
1854
+ assumeType(jsonData);
1855
+ assertArgument(typeof jsonData === "object" && jsonData !== null, "jsonData", "expect object");
1856
+ assertArgument(typeof jsonData[ATTR_TYPE] === "string", "jsonData[ATTR_TYPE]", "expected object to have a type");
1857
+ assertArgument(typeof jsonData.id === "string", "jsonData.id", "expected object to have an id");
1858
+ const type = URI.make(jsonData[ATTR_TYPE]);
1859
+ const schema = await refResolver?.resolveSchema(type);
1860
+ invariant(schema === void 0 || Schema.isSchema(schema), void 0, {
1861
+ "~LogMeta": "~LogMeta",
1862
+ F: __dxlog_file$3,
1863
+ L: 99,
1864
+ S: void 0,
1865
+ A: ["schema === undefined || Schema.isSchema(schema)", ""]
1866
+ });
1867
+ const decodedInput = restoreUint8Arrays(stripInternalJsonKeys(jsonData));
1868
+ let obj;
1869
+ if (schema != null) {
1870
+ obj = await schema.pipe(Schema.decodeUnknownPromise)(decodedInput);
1871
+ if (refResolver) setRefResolverOnData(obj, refResolver);
1872
+ } else obj = decodeGeneric(decodedInput, { refResolver });
1873
+ invariant(EntityId.isValid(obj.id), "Invalid object id", {
1874
+ "~LogMeta": "~LogMeta",
1875
+ F: __dxlog_file$3,
1876
+ L: 112,
1877
+ S: void 0,
1878
+ A: ["EntityId.isValid(obj.id)", "'Invalid object id'"]
1879
+ });
1880
+ setTypename(obj, type);
1881
+ if (schema) setSchema(obj, schema);
1882
+ if (refResolver?.resolveType) {
1883
+ const typeEntity = await refResolver.resolveType(type);
1884
+ if (typeEntity != null) setType(obj, typeEntity);
1885
+ }
1886
+ if (typeof jsonData["@relationSource"] === "string" || typeof jsonData["@relationTarget"] === "string") {
1887
+ const sourceDxn = jsonData["@relationSource"] ?? raise(/* @__PURE__ */ new TypeError("Missing relation source"));
1888
+ const targetDxn = jsonData["@relationTarget"] ?? raise(/* @__PURE__ */ new TypeError("Missing relation target"));
1889
+ const source = await refResolver?.resolveLegacy(sourceDxn);
1890
+ const target = await refResolver?.resolveLegacy(targetDxn);
1891
+ defineHiddenProperty(obj, KindId, EntityKind.Relation);
1892
+ defineHiddenProperty(obj, RelationSourceDXNId, sourceDxn);
1893
+ defineHiddenProperty(obj, RelationTargetDXNId, targetDxn);
1894
+ defineHiddenProperty(obj, RelationSourceId, source);
1895
+ defineHiddenProperty(obj, RelationTargetId, target);
1896
+ } else {
1897
+ const annotationKind = schema != null ? getTypeAnnotation(schema)?.kind : void 0;
1898
+ defineHiddenProperty(obj, KindId, annotationKind === EntityKind.Type ? EntityKind.Type : EntityKind.Object);
1899
+ }
1900
+ if (typeof jsonData["@meta"] === "object") {
1901
+ const meta = await EntityMetaSchema.pipe(Schema.decodeUnknownPromise)(normalizeMeta(jsonData[ATTR_META]));
1902
+ invariant(Array.isArray(meta.keys), void 0, {
1903
+ "~LogMeta": "~LogMeta",
1904
+ F: __dxlog_file$3,
1905
+ L: 153,
1906
+ S: void 0,
1907
+ A: ["Array.isArray(meta.keys)", ""]
1908
+ });
1909
+ defineHiddenProperty(obj, MetaId, meta);
1910
+ } else defineHiddenProperty(obj, MetaId, {
1911
+ keys: [],
1912
+ tags: [],
1913
+ annotations: {}
1914
+ });
1915
+ if (jsonData["@parent"]) {
1916
+ const parentDxn = jsonData[ATTR_PARENT];
1917
+ const resolvedParent = await refResolver?.resolveLegacy(parentDxn);
1918
+ defineHiddenProperty(obj, ParentId, resolvedParent);
1919
+ } else if (parent) defineHiddenProperty(obj, ParentId, parent);
1920
+ if (uri) defineHiddenProperty(obj, SelfURIId, uri);
1921
+ if (database) defineHiddenProperty(obj, ObjectDatabaseId, database);
1922
+ defineHiddenProperty(obj, ObjectDeletedId, jsonData[ATTR_DELETED] === true);
1923
+ assertObjectModel(obj);
1924
+ invariant(obj[ATTR_TYPE] === void 0, "Invalid object model", {
1925
+ "~LogMeta": "~LogMeta",
1926
+ F: __dxlog_file$3,
1927
+ L: 184,
1928
+ S: void 0,
1929
+ A: ["(obj as any)[ATTR_TYPE] === undefined", "'Invalid object model'"]
1930
+ });
1931
+ invariant(obj[ATTR_META] === void 0, "Invalid object model", {
1932
+ "~LogMeta": "~LogMeta",
1933
+ F: __dxlog_file$3,
1934
+ L: 185,
1935
+ S: void 0,
1936
+ A: ["(obj as any)[ATTR_META] === undefined", "'Invalid object model'"]
1937
+ });
1938
+ invariant(obj[ATTR_DELETED] === void 0, "Invalid object model", {
1939
+ "~LogMeta": "~LogMeta",
1940
+ F: __dxlog_file$3,
1941
+ L: 186,
1942
+ S: void 0,
1943
+ A: ["(obj as any)[ATTR_DELETED] === undefined", "'Invalid object model'"]
1944
+ });
1945
+ invariant(obj[ATTR_SELF_URI] === void 0, "Invalid object model", {
1946
+ "~LogMeta": "~LogMeta",
1947
+ F: __dxlog_file$3,
1948
+ L: 187,
1949
+ S: void 0,
1950
+ A: ["(obj as any)[ATTR_SELF_URI] === undefined", "'Invalid object model'"]
1951
+ });
1952
+ invariant(obj[ATTR_SELF_URI_LEGACY] === void 0, "Invalid object model", {
1953
+ "~LogMeta": "~LogMeta",
1954
+ F: __dxlog_file$3,
1955
+ L: 188,
1956
+ S: void 0,
1957
+ A: ["(obj as any)[ATTR_SELF_URI_LEGACY] === undefined", "'Invalid object model'"]
1958
+ });
1959
+ invariant(obj[ATTR_RELATION_SOURCE] === void 0, "Invalid object model", {
1960
+ "~LogMeta": "~LogMeta",
1961
+ F: __dxlog_file$3,
1962
+ L: 189,
1963
+ S: void 0,
1964
+ A: ["(obj as any)[ATTR_RELATION_SOURCE] === undefined", "'Invalid object model'"]
1965
+ });
1966
+ invariant(obj[ATTR_RELATION_TARGET] === void 0, "Invalid object model", {
1967
+ "~LogMeta": "~LogMeta",
1968
+ F: __dxlog_file$3,
1969
+ L: 190,
1970
+ S: void 0,
1971
+ A: ["(obj as any)[ATTR_RELATION_TARGET] === undefined", "'Invalid object model'"]
1972
+ });
1973
+ return obj;
1974
+ };
1975
+ /**
1976
+ * Backfills required meta fields and upgrades legacy `tags` (bare URI strings) to encoded references
1977
+ * so serialized data produced before the tags-as-refs migration still decodes.
1978
+ */
1979
+ var normalizeMeta = (meta) => {
1980
+ const tags = Array.isArray(meta?.tags) ? meta.tags.map((tag) => typeof tag === "string" ? { "/": URI.make(tag) } : tag) : [];
1981
+ return {
1982
+ ...meta,
1983
+ keys: Array.isArray(meta?.keys) ? meta.keys : [],
1984
+ tags,
1985
+ annotations: meta?.annotations ?? {}
1986
+ };
1987
+ };
1988
+ var decodeGeneric = (jsonData, options) => {
1989
+ return deepMapValues(stripInternalJsonKeys(jsonData), (value, visitor) => {
1990
+ if (isEncodedReference(value)) return refFromEncodedReference(value, options.refResolver);
1991
+ if (isEncodedUint8Array(value)) return decodeUint8ArrayFromJson(value);
1992
+ return visitor(value);
1993
+ });
1994
+ };
1995
+ /**
1996
+ * Recursively replaces encoded `Uint8Array` JSON markers with actual `Uint8Array` instances.
1997
+ * Runs before schema decoding so `Schema.Uint8ArrayFromSelf` sees real bytes.
1998
+ */
1999
+ var restoreUint8Arrays = (data) => deepMapValues(data, (value, recurse) => {
2000
+ if (isEncodedUint8Array(value)) return decodeUint8ArrayFromJson(value);
2001
+ return recurse(value);
2002
+ });
2003
+ var stripInternalJsonKeys = (jsonData) => {
2004
+ const { [ATTR_TYPE]: _type, [ATTR_META]: _meta, [ATTR_DELETED]: _deleted, [ATTR_SELF_URI]: _selfUri, [ATTR_SELF_URI_LEGACY]: _legacySelfUri, [ATTR_RELATION_SOURCE]: _relationSource, [ATTR_RELATION_TARGET]: _relationTarget, ...props } = jsonData;
2005
+ return props;
2006
+ };
2007
+ var setRefResolverOnData = (obj, refResolver) => {
2008
+ const visitor = (value) => {
2009
+ if (Ref.isRef(value)) setRefResolver(value, refResolver);
2010
+ else visitValues(value, visitor);
2011
+ };
2012
+ visitor(obj);
2013
+ };
2014
+ /**
2015
+ * Convert EntityStructure to JSON data for indexing.
2016
+ * Different from {@link objectToJSON} as it takes the internal {@link EntityStructure} representation directly
2017
+ */
2018
+ var objectStructureToJson = (objectId, structure) => {
2019
+ const typeRef = EntityStructure.getTypeReference(structure)?.["/"];
2020
+ const parent = EntityStructure.getParent(structure)?.["/"];
2021
+ const source = EntityStructure.getRelationSource(structure)?.["/"];
2022
+ const target = EntityStructure.getRelationTarget(structure)?.["/"];
2023
+ return {
2024
+ ...structure.data,
2025
+ id: objectId,
2026
+ [ATTR_TYPE]: typeRef ? URI.make(typeRef) : void 0,
2027
+ [ATTR_DELETED]: EntityStructure.isDeleted(structure),
2028
+ [ATTR_PARENT]: parent !== void 0 ? EID.tryParse(parent) : void 0,
2029
+ [ATTR_RELATION_SOURCE]: source !== void 0 ? EID.tryParse(source) : void 0,
2030
+ [ATTR_RELATION_TARGET]: target !== void 0 ? EID.tryParse(target) : void 0
2031
+ };
2032
+ };
2033
+ //#endregion
2034
+ //#region src/internal/Filter/match.ts
2035
+ /**
2036
+ * Matches a tag filter against an object's stored tags. Tags may be stored as encoded references or
2037
+ * (in legacy data) bare URI strings, and those URIs may be in legacy DXN form. Both sides are
2038
+ * normalized to the canonical EID before comparing.
2039
+ */
2040
+ var matchesTag = (tags, filterTag) => {
2041
+ const canonical = (uri) => {
2042
+ const eid = EID.tryParse(uri);
2043
+ return eid && EID.getEntityId(eid) || uri;
2044
+ };
2045
+ const normalize = (tag) => canonical(isEncodedReference(tag) ? EncodedReference.toURI(tag) : tag);
2046
+ const target = canonical(filterTag);
2047
+ return tags.some((tag) => normalize(tag) === target);
2048
+ };
2049
+ /**
2050
+ * Matches a meta `key` / `version` constraint against an object's meta `key` and `version`.
2051
+ */
2052
+ var matchMetaKey = (key, versionRange, objKey, objVersion) => {
2053
+ if (objKey !== key) return false;
2054
+ if (versionRange === void 0) return true;
2055
+ if (objVersion === void 0 || semver.valid(objVersion) === null) return false;
2056
+ if (semver.validRange(versionRange) === null) return false;
2057
+ return semver.satisfies(objVersion, versionRange, { includePrerelease: true });
2058
+ };
2059
+ /**
2060
+ * Compares a filter's type discriminator against the value stored on an object's `system.type`.
2061
+ */
2062
+ var compareTypenameStrings = (expectedStr, actualStr) => {
2063
+ const expectedEid = EID.tryParse(expectedStr);
2064
+ if (expectedEid) {
2065
+ const actualEid = EID.tryParse(actualStr);
2066
+ if (!actualEid) return false;
2067
+ if (EID.getEntityId(expectedEid) !== EID.getEntityId(actualEid)) return false;
2068
+ const expectedSpaceId = EID.getSpaceId(expectedEid);
2069
+ const actualSpaceId = EID.getSpaceId(actualEid);
2070
+ return expectedSpaceId === void 0 || actualSpaceId === void 0 || expectedSpaceId === actualSpaceId;
2071
+ }
2072
+ const expectedDxn = DXN.tryMake(expectedStr);
2073
+ if (expectedDxn) {
2074
+ const actualDxn = DXN.tryMake(actualStr);
2075
+ if (!actualDxn) return false;
2076
+ if (DXN.getName(expectedDxn) !== DXN.getName(actualDxn)) return false;
2077
+ const expectedVersion = DXN.getVersion(expectedDxn);
2078
+ const actualVersion = DXN.getVersion(actualDxn);
2079
+ return expectedVersion === void 0 || actualVersion === void 0 || expectedVersion === actualVersion;
2080
+ }
2081
+ return expectedStr === actualStr;
2082
+ };
2083
+ var structuralMatch = (filterObj, targetObj, strict = true) => {
2084
+ if (typeof filterObj !== "object" || filterObj === null) return filterObj === targetObj;
2085
+ if (typeof targetObj !== "object" || targetObj === null) return false;
2086
+ const filterKeys = Object.keys(filterObj);
2087
+ const targetKeys = Object.keys(targetObj);
2088
+ if (strict && filterKeys.length !== targetKeys.length) return false;
2089
+ return filterKeys.every((key) => {
2090
+ if (!(key in targetObj)) return false;
2091
+ const filterValue = filterObj[key];
2092
+ const targetValue = targetObj[key];
2093
+ if (typeof filterValue === "object" && filterValue !== null) return structuralMatch(filterValue, targetValue);
2094
+ return filterValue === targetValue;
2095
+ });
2096
+ };
2097
+ /** Normalizes an encoded reference to its URI string so ref-valued properties compare by identity. */
2098
+ var _normalizeInValue = (value) => isEncodedReference(value) ? EncodedReference.toURI(value) : value;
2099
+ /**
2100
+ * Memoizes a `Set` per `values` array so `Filter.in` membership is O(1) rather than
2101
+ * `Array.includes`'s O(n) — this matters most for large sets projected from a subquery
2102
+ * (`Filter.in(query.project(...))`, resolved to a literal `in` by the query executor), but
2103
+ * also speeds up ordinary literal-list `Filter.in`. Keyed by array identity: the planner and
2104
+ * executor never mutate a filter's `values` array in place, so the cache stays valid for the
2105
+ * array's lifetime.
2106
+ */
2107
+ var _inSetCache = /* @__PURE__ */ new WeakMap();
2108
+ var _getInSet = (values) => {
2109
+ let set = _inSetCache.get(values);
2110
+ if (!set) {
2111
+ set = new Set(values.map(_normalizeInValue));
2112
+ _inSetCache.set(values, set);
2113
+ }
2114
+ return set;
2115
+ };
2116
+ var filterMatchValue = (filter, value) => {
2117
+ switch (filter.type) {
2118
+ case "compare": {
2119
+ const compareValue = filter.value;
2120
+ switch (filter.operator) {
2121
+ case "eq":
2122
+ if (isEncodedReference(compareValue)) {
2123
+ if (!isEncodedReference(value)) return false;
2124
+ return EncodedReference.toURI(value) === EncodedReference.toURI(compareValue);
2125
+ }
2126
+ return value === compareValue;
2127
+ case "neq": return value !== compareValue;
2128
+ case "gt": return value > compareValue;
2129
+ case "gte": return value >= compareValue;
2130
+ case "lt": return value < compareValue;
2131
+ case "lte": return value <= compareValue;
2132
+ default: return false;
2133
+ }
2134
+ }
2135
+ case "object":
2136
+ if (typeof value !== "object" || value === null) return false;
2137
+ if (filter.props) for (const [key, valueFilter] of Object.entries(filter.props)) {
2138
+ const nestedValue = value[key];
2139
+ if (!filterMatchValue(valueFilter, nestedValue)) return false;
2140
+ }
2141
+ return true;
2142
+ case "in": return _getInSet(filter.values).has(_normalizeInValue(value));
2143
+ case "in-query": throw new Error("in-query filters must be resolved to a literal `in` by the query executor before matching.");
2144
+ case "contains":
2145
+ if (!Array.isArray(value)) return false;
2146
+ return value.some((element) => {
2147
+ if (typeof filter.value === "object" && filter.value !== null && !Array.isArray(filter.value)) return structuralMatch(filter.value, element);
2148
+ return element === filter.value;
2149
+ });
2150
+ case "range": return value >= filter.from && value <= filter.to;
2151
+ case "not": return !filterMatchValue(filter.filter, value);
2152
+ case "and": return filter.filters.every((f) => filterMatchValue(f, value));
2153
+ case "or": return filter.filters.some((f) => filterMatchValue(f, value));
2154
+ default: return false;
2155
+ }
2156
+ };
2157
+ /**
2158
+ * Matches a filter against an entity proxy without full JSON serialization when possible.
2159
+ */
2160
+ var filterMatchEntity = (filter, entity) => {
2161
+ switch (filter.type) {
2162
+ case "object": {
2163
+ if (filter.typename !== null) {
2164
+ const typeURI = getTypeURI(entity);
2165
+ if (!typeURI || !compareTypenameStrings(filter.typename, typeURI)) return false;
2166
+ }
2167
+ if (filter.id && filter.id.length > 0 && !filter.id.includes(entity.id)) return false;
2168
+ if (filter.props) {
2169
+ let json = null;
2170
+ try {
2171
+ json = objectToJSON(entity);
2172
+ } catch {}
2173
+ if (json === null) return false;
2174
+ for (const [key, valueFilter] of Object.entries(filter.props)) {
2175
+ if (key.startsWith("@")) continue;
2176
+ if (!filterMatchValue(valueFilter, json[key])) return false;
2177
+ }
2178
+ }
2179
+ const meta = getMetaChecked(entity);
2180
+ if (filter.foreignKeys && filter.foreignKeys.length > 0) {
2181
+ if (!filter.foreignKeys.some((fk) => meta.keys.some((k) => k.source === fk.source && k.id === fk.id))) return false;
2182
+ }
2183
+ if (filter.metaKey !== void 0) {
2184
+ if (!matchMetaKey(filter.metaKey, filter.metaVersion, meta.key, meta.version)) return false;
2185
+ }
2186
+ return true;
2187
+ }
2188
+ case "tag": return matchesTag(getMetaChecked(entity).tags.map((tag) => typeof tag?.encode === "function" ? tag.encode() : tag), filter.tag);
2189
+ case "text-search": return false;
2190
+ case "timestamp": throw new Error("Timestamp filters must be handled at the index level, not in-memory matching.");
2191
+ case "child-of": throw new Error("child-of filters must be handled at the executor level, not in-memory matching.");
2192
+ case "in-query": throw new Error("in-query filters must be resolved to a literal `in` by the query executor before matching.");
2193
+ case "not": return !filterMatchEntity(filter.filter, entity);
2194
+ case "and": return filter.filters.every((f) => filterMatchEntity(f, entity));
2195
+ case "or": return filter.filters.some((f) => filterMatchEntity(f, entity));
2196
+ default: return false;
2197
+ }
2198
+ };
2199
+ //#endregion
2200
+ //#region src/internal/Obj/common.ts
2201
+ var makeTypedEntityClass = (typename, version, baseSchema) => {
2202
+ return class {
2203
+ static typename = typename;
2204
+ static version = version;
2205
+ static [Schema.TypeId] = schemaVariance;
2206
+ static ast = baseSchema.ast;
2207
+ static annotations = baseSchema.annotations.bind(baseSchema);
2208
+ static pipe = baseSchema.pipe.bind(baseSchema);
2209
+ static [Symbol.hasInstance](obj) {
2210
+ return obj != null && getTypename(obj) === typename;
2211
+ }
2212
+ constructor() {
2213
+ throw new Error("Use live(Typename, { ...fields }) to instantiate an object.");
2214
+ }
2215
+ };
2216
+ };
2217
+ var schemaVariance = {
2218
+ _A: (_) => _,
2219
+ _I: (_) => _,
2220
+ _R: (_) => _
2221
+ };
2222
+ //#endregion
2223
+ //#region src/internal/Obj/inspect.ts
2224
+ var attachedTypedObjectInspector = (obj) => {
2225
+ if (Object.getOwnPropertyDescriptor(obj, inspectCustom)) return;
2226
+ Object.defineProperty(obj, inspectCustom, {
2227
+ value: typedObjectInspectFunction,
2228
+ writable: false,
2229
+ enumerable: false,
2230
+ configurable: true
2231
+ });
2232
+ };
2233
+ var typedObjectInspectFunction = function(depth, options, inspect) {
2234
+ const { id, ...props } = this;
2235
+ return inspect({
2236
+ id,
2237
+ [ATTR_TYPE]: getTypeURI(this),
2238
+ ...props,
2239
+ [ATTR_META]: this[MetaId]
2240
+ }, options);
2241
+ };
2242
+ //#endregion
2243
+ //#region src/internal/Obj/create-object.ts
2244
+ /**
2245
+ * Creates a new object instance from a schema and data, without signal reactivity.
2246
+ * This static version creates plain JavaScript objects that are not reactive/observable.
2247
+ * For reactive objects that automatically update UI when changed, use the regular live() function.
2248
+ *
2249
+ * @param schema - The Effect schema that defines the object's structure and type, piped into EchoObjectSchema
2250
+ * @param data - The data to initialize the object with. The id and @type fields are handled automatically.
2251
+ * @returns A new non-reactive object instance conforming to the schema
2252
+ * @throws {Error} If the schema is not an object schema
2253
+ * @throws {TypeError} If data contains an @type field
2254
+ *
2255
+ * @example
2256
+ * ```ts
2257
+ * class Contact extends Type.makeObject<Contact>(DXN.make('com.example.type.person', '0.1.0'))(
2258
+ * Schema.Struct({ name: Schema.String, email: Schema.String }),
2259
+ * ) {}
2260
+ *
2261
+ * const contact = createObject(Contact, {
2262
+ * name: "John",
2263
+ * email: "john@example.com",
2264
+ * })
2265
+ * ```
2266
+ */
2267
+ var createObject = (input, props) => {
2268
+ const schema = getStaticTypeSchema(input) ?? failedInvariant("Type entity is missing its source schema");
2269
+ const annotation = getTypeAnnotation(schema);
2270
+ if (!annotation) throw new Error("Schema is not an ECHO schema");
2271
+ assertArgument(!("@type" in props), "data", "@type is not allowed");
2272
+ assertArgument(!(RelationSourceDXNId in props), "data", "Relation source DXN is not allowed in the constructor");
2273
+ assertArgument(!(RelationTargetDXNId in props), "data", "Relation target DXN is not allowed in the constructor");
2274
+ assertArgument(RelationSourceId in props === RelationTargetId in props, "data", "Relation source and target must be provided together");
2275
+ const metaOverride = props[MetaId];
2276
+ if (metaOverride !== void 0) delete props[MetaId];
2277
+ const obj = {
2278
+ ...props,
2279
+ id: props.id ?? EntityId.random()
2280
+ };
2281
+ const kind = annotation.kind === EntityKind.Type ? EntityKind.Type : annotation.kind === EntityKind.Relation || RelationSourceId in props ? EntityKind.Relation : EntityKind.Object;
2282
+ defineHiddenProperty(obj, KindId, kind);
2283
+ defineHiddenProperty(obj, MetaId, {
2284
+ ...metaOverride,
2285
+ keys: metaOverride?.keys ?? [],
2286
+ tags: metaOverride?.tags ?? [],
2287
+ annotations: metaOverride?.annotations ?? {}
2288
+ });
2289
+ setSchema(obj, schema);
2290
+ if (input !== schema) setType(obj, input);
2291
+ setTypename(obj, getSchemaURI(schema) ?? failedInvariant("Missing schema URI"));
2292
+ attachTypedJsonSerializer(obj);
2293
+ attachedTypedObjectInspector(obj);
2294
+ if (kind === EntityKind.Relation) {
2295
+ const sourceDXN = getObjectEchoUri(props[RelationSourceId]) ?? raise(/* @__PURE__ */ new Error("Unresolved relation source"));
2296
+ const targetDXN = getObjectEchoUri(props[RelationTargetId]) ?? raise(/* @__PURE__ */ new Error("Unresolved relation target"));
2297
+ defineHiddenProperty(obj, RelationSourceDXNId, sourceDXN);
2298
+ defineHiddenProperty(obj, RelationTargetDXNId, targetDXN);
2299
+ }
2300
+ assertObjectModel(obj);
2301
+ return obj;
2302
+ };
2303
+ //#endregion
2304
+ //#region src/internal/Obj/deleted.ts
2305
+ /**
2306
+ * @returns `true` if the object has been marked as deleted.
2307
+ */
2308
+ var isDeleted = (obj) => {
2309
+ if (obj[ObjectDeletedId] === void 0) return false;
2310
+ return obj[ObjectDeletedId] ?? false;
2311
+ };
2312
+ //#endregion
2313
+ //#region src/internal/Obj/set-value.ts
2314
+ var __dxlog_file$2 = "/__w/dxos/dxos/packages/core/echo/echo/src/internal/Obj/set-value.ts";
2315
+ /**
2316
+ * Set a deeply nested property on an object.
2317
+ * Must be called within an Obj.update or Relation.update callback.
2318
+ */
2319
+ var setValue = (obj, path, value) => {
2320
+ invariant(path.length > 0, "Path must not be empty", {
2321
+ "~LogMeta": "~LogMeta",
2322
+ F: __dxlog_file$2,
2323
+ L: 20,
2324
+ S: void 0,
2325
+ A: ["path.length > 0", "'Path must not be empty'"]
2326
+ });
2327
+ const schema = getSchema(obj);
2328
+ invariant(schema != null, "Object must have a schema", {
2329
+ "~LogMeta": "~LogMeta",
2330
+ F: __dxlog_file$2,
2331
+ L: 23,
2332
+ S: void 0,
2333
+ A: ["schema != null", "'Object must have a schema'"]
2334
+ });
2335
+ let parent = obj;
2336
+ let currentAST = schema.ast;
2337
+ for (let i = 0; i < path.length - 1; i++) {
2338
+ const part = path[i];
2339
+ const key = typeof part === "number" ? part : String(part);
2340
+ if (parent[key] === void 0) {
2341
+ const propertyAST = getPropertyAST(currentAST, String(part));
2342
+ if (propertyAST ? SchemaEx.isArrayType(propertyAST) : false) parent[key] = [];
2343
+ else {
2344
+ const objWithDefaults = createObjectWithDefaults(propertyAST);
2345
+ parent[key] = objWithDefaults;
2346
+ }
2347
+ }
2348
+ parent = parent[key];
2349
+ currentAST = getPropertyAST(currentAST, String(part));
2350
+ }
2351
+ const finalKey = path[path.length - 1];
2352
+ parent[finalKey] = value;
2353
+ return value;
2354
+ };
2355
+ /**
2356
+ * Helper to get the AST of a nested property.
2357
+ * @param ast - Current schema AST.
2358
+ * @param propertyName - Name of the property to get.
2359
+ * @returns The AST of the nested property, or undefined if not found.
2360
+ */
2361
+ var getPropertyAST = (ast, propertyName) => {
2362
+ if (!ast) return;
2363
+ if (SchemaEx.isNestedType(ast)) {
2364
+ const property = SchemaEx.getProperties(ast).find((p) => p.name.toString() === propertyName);
2365
+ if (property) return SchemaEx.getBaseType(property).type;
2366
+ }
2367
+ if (SchemaEx.isArrayType(ast)) return SchemaEx.getArrayElementType(ast);
2368
+ };
2369
+ /**
2370
+ * Get all required properties from a schema AST.
2371
+ * A property is required if it's not optional.
2372
+ *
2373
+ * @param ast - Schema AST to inspect.
2374
+ * @returns Array of required properties with their types.
2375
+ */
2376
+ var getRequiredProperties = (ast) => {
2377
+ if (!ast) return [];
2378
+ if (!SchemaEx.isNestedType(ast)) return [];
2379
+ return SchemaEx.getProperties(ast).filter((p) => !p.isOptional);
2380
+ };
2381
+ /**
2382
+ * Get the default value for a primitive type.
2383
+ * Returns undefined for non-primitive or unsupported types.
2384
+ *
2385
+ * @param ast - Type AST.
2386
+ * @returns Default value for the type, or undefined.
2387
+ */
2388
+ var getDefaultValueForType = (ast) => {
2389
+ if (!ast) return;
2390
+ const defaultValue = SchemaAST.getDefaultAnnotation(ast);
2391
+ if (Option.isSome(defaultValue)) return defaultValue.value;
2392
+ return Match.value(ast).pipe(Match.when({ _tag: "StringKeyword" }, () => ""), Match.when({ _tag: "NumberKeyword" }, () => 0), Match.when({ _tag: "BooleanKeyword" }, () => false), Match.orElse(() => void 0));
2393
+ };
2394
+ /**
2395
+ * Create an object with default values for all required properties.
2396
+ * Handles primitive types (String, Number, Boolean) and recursively initializes required nested objects.
2397
+ *
2398
+ * @param ast - Schema AST describing the object structure.
2399
+ * @returns Object with required fields populated with defaults.
2400
+ */
2401
+ var createObjectWithDefaults = (ast) => {
2402
+ if (!ast) return {};
2403
+ const requiredProps = getRequiredProperties(ast);
2404
+ const obj = {};
2405
+ for (const prop of requiredProps) {
2406
+ const defaultValue = getDefaultValueForType(prop.type);
2407
+ if (defaultValue !== void 0) obj[prop.name] = defaultValue;
2408
+ else if (SchemaEx.isNestedType(prop.type)) obj[prop.name] = createObjectWithDefaults(prop.type);
2409
+ }
2410
+ return obj;
2411
+ };
2412
+ //#endregion
2413
+ //#region src/internal/Obj/snapshot.ts
2414
+ /**
2415
+ * Copy a Symbol-keyed property from source to target if it has a defined value.
2416
+ * Handles both plain objects (symbol in source) and proxies where get returns a value
2417
+ * but has/in returns false (e.g. ObjectDatabaseId on echo-db proxies).
2418
+ * Optional transform clones or mutates the value before assignment (e.g. for MetaId).
2419
+ */
2420
+ var copySymbolProperty = (source, target, symbol, transform) => {
2421
+ let value;
2422
+ try {
2423
+ value = source[symbol];
2424
+ } catch {
2425
+ return;
2426
+ }
2427
+ if (value !== void 0) {
2428
+ const finalValue = transform ? transform(value) : value;
2429
+ Object.defineProperty(target, symbol, {
2430
+ value: finalValue,
2431
+ writable: false,
2432
+ enumerable: false,
2433
+ configurable: false
2434
+ });
2435
+ }
2436
+ };
2437
+ /**
2438
+ * Returns an immutable snapshot of the reactive object.
2439
+ * The snapshot is branded with SnapshotKindId (not KindId).
2440
+ */
2441
+ var getSnapshot = (obj) => {
2442
+ assertArgument(typeof obj === "object" && obj !== null && "~@dxos/echo/Kind" in obj, "obj", "must be an entity");
2443
+ const snapshot = deepMapValues(obj, (value, recurse) => {
2444
+ if (typeof value === "object" && value !== null && Object.getPrototypeOf(value) !== Object.prototype && !Array.isArray(value)) return value;
2445
+ return recurse(value);
2446
+ });
2447
+ if (obj != null && typeof obj === "object" && "~@dxos/echo/Kind" in obj) snapshot[SnapshotKindId] = obj[KindId];
2448
+ const source = obj;
2449
+ copySymbolProperty(source, snapshot, TypeId);
2450
+ copySymbolProperty(source, snapshot, SchemaId);
2451
+ copySymbolProperty(source, snapshot, TypeEntityId);
2452
+ copySymbolProperty(source, snapshot, SelfURIId);
2453
+ copySymbolProperty(source, snapshot, ObjectDatabaseId);
2454
+ copySymbolProperty(source, snapshot, ObjectDeletedId);
2455
+ copySymbolProperty(source, snapshot, ParentId);
2456
+ copySymbolProperty(source, snapshot, MetaId, (meta) => ({
2457
+ keys: [...meta?.keys ?? []],
2458
+ tags: [...meta?.tags ?? []],
2459
+ ...meta?.key != null ? { key: meta.key } : {},
2460
+ ...meta?.version != null ? { version: meta.version } : {},
2461
+ ...meta?.annotations ? { annotations: { ...meta.annotations } } : {}
2462
+ }));
2463
+ copySymbolProperty(source, snapshot, RelationSourceDXNId);
2464
+ copySymbolProperty(source, snapshot, RelationTargetDXNId);
2465
+ copySymbolProperty(source, snapshot, RelationSourceId);
2466
+ copySymbolProperty(source, snapshot, RelationTargetId);
2467
+ return Object.freeze(snapshot);
2468
+ };
2469
+ //#endregion
2470
+ //#region src/internal/Obj/atoms.ts
2471
+ var isRef = (obj) => obj != null && typeof obj === "object" && RefTypeId in obj;
2472
+ var getReactiveOption = (snapshot) => Effect.gen(function* () {
2473
+ const db = getDatabase(snapshot);
2474
+ if (!db) return Option.none();
2475
+ const obj = db.getObjectById(snapshot.id);
2476
+ return obj ? Option.some(obj) : Option.none();
2477
+ });
2478
+ /**
2479
+ * Atom family for ECHO objects.
2480
+ * Uses object reference as key — same object returns same atom.
2481
+ */
2482
+ var objectFamily = Atom.family((obj) => {
2483
+ return Atom.make((get) => {
2484
+ const unsubscribe = subscribe(obj, () => {
2485
+ get.setSelf(getSnapshot(obj));
2486
+ });
2487
+ get.addFinalizer(() => unsubscribe());
2488
+ return getSnapshot(obj);
2489
+ }).pipe(Atom.keepAlive);
2490
+ });
2491
+ /**
2492
+ * Atom family for ECHO refs (snapshot version).
2493
+ * Uses ref as key — same ref returns same atom.
2494
+ * Subscribes to target object changes after loading.
2495
+ */
2496
+ var refFamily = Atom.family((ref) => {
2497
+ return Atom.make((get) => {
2498
+ let unsubscribeTarget;
2499
+ const setupTargetSubscription = (target) => {
2500
+ unsubscribeTarget?.();
2501
+ unsubscribeTarget = subscribe(target, () => {
2502
+ get.setSelf(isDeleted(target) ? void 0 : getSnapshot(target));
2503
+ });
2504
+ return isDeleted(target) ? void 0 : getSnapshot(target);
2505
+ };
2506
+ get.addFinalizer(() => {
2507
+ unsubscribeTarget?.();
2508
+ });
2509
+ return loadRefTarget(ref, get, setupTargetSubscription);
2510
+ }).pipe(Atom.keepAlive);
2511
+ });
2512
+ /**
2513
+ * Atom family for ECHO object properties.
2514
+ * Uses nested families: outer keyed by object, inner keyed by property key.
2515
+ */
2516
+ var propertyFamily = Atom.family((obj) => Atom.family((key) => {
2517
+ return Atom.make((get) => {
2518
+ let previousSnapshot = snapshotForComparison(obj[key]);
2519
+ const unsubscribe2 = subscribe(obj, () => {
2520
+ const newValue = obj[key];
2521
+ const newSnapshot = snapshotForComparison(newValue);
2522
+ if (newSnapshot !== previousSnapshot) {
2523
+ previousSnapshot = newSnapshot;
2524
+ get.setSelf(newSnapshot);
2525
+ }
2526
+ });
2527
+ get.addFinalizer(() => unsubscribe2());
2528
+ return snapshotForComparison(obj[key]);
2529
+ }).pipe(Atom.keepAlive);
2530
+ }));
2531
+ /**
2532
+ * Atom family for ECHO objects — returns the live object, not a snapshot.
2533
+ */
2534
+ var objectWithReactiveFamily = Atom.family((obj) => {
2535
+ return Atom.make((get) => {
2536
+ const unsubscribe = subscribe(obj, () => {
2537
+ get.setSelf(obj);
2538
+ });
2539
+ get.addFinalizer(() => unsubscribe());
2540
+ return obj;
2541
+ }).pipe(Atom.keepAlive);
2542
+ });
2543
+ /**
2544
+ * Atom family for ECHO refs — returns the live reactive object, not a snapshot.
2545
+ */
2546
+ var refWithReactiveFamily = Atom.family((ref) => {
2547
+ const effect = (get) => Effect.gen(function* () {
2548
+ const snapshot = get(makeAtom(ref));
2549
+ if (snapshot == null) return;
2550
+ const option = yield* getReactiveOption(snapshot);
2551
+ return Option.getOrElse(option, () => void 0);
2552
+ });
2553
+ return Function.pipe(Atom.make(effect), Atom.map((result) => Result.getOrElse(result, () => void 0)));
2554
+ });
2555
+ /**
2556
+ * Atom family for a property of a ref's target object.
2557
+ * Resolves the ref (reactively) then projects the property atom, so it fires when the ref resolves or when
2558
+ * that property changes. Yields `undefined` while the target is unresolved.
2559
+ */
2560
+ var refPropertyFamily = Atom.family((ref) => Atom.family((key) => {
2561
+ return Atom.make((get) => {
2562
+ const target = get(refWithReactiveFamily(ref));
2563
+ return target ? get(propertyFamily(target)(key)) : void 0;
2564
+ }).pipe(Atom.keepAlive);
2565
+ }));
2566
+ /**
2567
+ * Atom family for any ECHO entity (obj or relation) — returns a snapshot.
2568
+ */
2569
+ var entityFamily = Atom.family((entity) => {
2570
+ return Atom.make((get) => {
2571
+ const unsubscribe = subscribe(entity, () => {
2572
+ get.setSelf(getSnapshot(entity));
2573
+ });
2574
+ get.addFinalizer(() => unsubscribe());
2575
+ return getSnapshot(entity);
2576
+ }).pipe(Atom.keepAlive);
2577
+ });
2578
+ /**
2579
+ * Atom family for ECHO relations — returns a typed relation snapshot.
2580
+ */
2581
+ var relationFamily = Atom.family((relation) => {
2582
+ return Atom.make((get) => {
2583
+ const unsubscribe = subscribe(relation, () => {
2584
+ get.setSelf(getSnapshot(relation));
2585
+ });
2586
+ get.addFinalizer(() => unsubscribe());
2587
+ return getSnapshot(relation);
2588
+ }).pipe(Atom.keepAlive);
2589
+ });
2590
+ /**
2591
+ * Create a read-only snapshot atom for a reactive object or ref.
2592
+ * Updates automatically when the object is mutated.
2593
+ * For refs, subscribes to target object changes after loading.
2594
+ */
2595
+ var makeAtom = (objOrRef) => {
2596
+ if (isRef(objOrRef)) return refFamily(objOrRef);
2597
+ const obj = objOrRef;
2598
+ assertArgument(isEntity(obj), "obj", "Object must be a reactive object");
2599
+ return objectFamily(obj);
2600
+ };
2601
+ /**
2602
+ * Create a read-only atom for a specific property of a reactive object, or of a ref's target.
2603
+ * Only fires updates when the property value actually changes. Given a ref, the atom resolves the target
2604
+ * first and yields `undefined` until it loads.
2605
+ */
2606
+ var makeProperty = (objOrRef, key) => {
2607
+ if (isRef(objOrRef)) return refPropertyFamily(objOrRef)(key);
2608
+ const obj = objOrRef;
2609
+ assertArgument(isEntity(obj), "obj", "Object must be a reactive object");
2610
+ return propertyFamily(obj)(key);
2611
+ };
2612
+ /**
2613
+ * Like `makeAtom` but returns the live reactive object instead of a snapshot.
2614
+ * Prefer `makeAtom` (snapshot) unless you need the live Obj for generic mutations.
2615
+ */
2616
+ var makeWithReactive = (objOrRef) => {
2617
+ if (isRef(objOrRef)) return refWithReactiveFamily(objOrRef);
2618
+ const obj = objOrRef;
2619
+ assertArgument(isEntity(obj), "obj", "Object must be a reactive object");
2620
+ return objectWithReactiveFamily(obj);
2621
+ };
2622
+ /**
2623
+ * Create a read-only snapshot atom for any ECHO entity (obj or relation).
2624
+ * Updates automatically when the entity is mutated.
2625
+ */
2626
+ var makeEntity = (entity) => {
2627
+ assertArgument(isEntity(entity), "entity", "Must be a reactive ECHO entity");
2628
+ return entityFamily(entity);
2629
+ };
2630
+ /**
2631
+ * Create a read-only snapshot atom for a reactive relation.
2632
+ * Updates automatically when the relation is mutated.
2633
+ */
2634
+ var makeRelation = (relation) => {
2635
+ assertArgument(isEntity(relation), "relation", "Must be a reactive ECHO relation");
2636
+ return relationFamily(relation);
2637
+ };
2638
+ /**
2639
+ * Atom family for an entity's label string.
2640
+ * Fires only when the computed label actually changes, not on every entity mutation.
2641
+ */
2642
+ var labelAtomFamily = Atom.family((entity) => {
2643
+ return Atom.make((get) => {
2644
+ let previous = getLabel(entity);
2645
+ const unsubscribe = subscribe(entity, () => {
2646
+ const next = getLabel(entity);
2647
+ if (next !== previous) {
2648
+ previous = next;
2649
+ get.setSelf(next);
2650
+ }
2651
+ });
2652
+ get.addFinalizer(() => unsubscribe());
2653
+ return previous;
2654
+ }).pipe(Atom.keepAlive);
2655
+ });
2656
+ /**
2657
+ * Create a read-only atom for the label of a reactive ECHO entity.
2658
+ * Re-evaluates on entity mutation; only propagates when the label string changes.
2659
+ */
2660
+ var makeLabelAtom = (entity) => {
2661
+ assertArgument(isEntity(entity), "entity", "Must be a reactive ECHO entity");
2662
+ return labelAtomFamily(entity);
2663
+ };
2664
+ //#endregion
2665
+ //#region src/internal/Obj/clone.ts
2666
+ var __dxlog_file$1 = "/__w/dxos/dxos/packages/core/echo/echo/src/internal/Obj/clone.ts";
2667
+ /**
2668
+ * Clones an object or relation.
2669
+ * By default this does not clone referenced objects, only the properties in the object; pass `opts.deep`
2670
+ * to recurse into refs (see {@link Obj.CloneOptions}).
2671
+ * @returns A new object with the same schema and properties.
2672
+ */
2673
+ var clone = (obj, opts) => cloneInner(obj, opts, obj, /* @__PURE__ */ new Map(), /* @__PURE__ */ new Set());
2674
+ /**
2675
+ * Recursive clone worker threaded with two cycle-guard structures:
2676
+ * - `cache`: id → already-finished clone; reused when the same object appears more than once in a DAG.
2677
+ * - `inProgress`: ids of objects whose clone is currently being computed; a ref back into this set means
2678
+ * a true cycle — the original ref is kept rather than recursing forever.
2679
+ */
2680
+ var cloneInner = (obj, opts, root, cache, inProgress) => {
2681
+ if (cache.has(obj.id)) return cache.get(obj.id);
2682
+ inProgress.add(obj.id);
2683
+ const { id, ...data } = obj;
2684
+ const typeEntity = getType(obj);
2685
+ const schema = typeEntity != null ? getStaticTypeSchema(typeEntity) : getSchema(obj);
2686
+ invariant(schema != null, "Object should have a type or schema", {
2687
+ "~LogMeta": "~LogMeta",
2688
+ F: __dxlog_file$1,
2689
+ L: 48,
2690
+ S: void 0,
2691
+ A: ["schema != null", "'Object should have a type or schema'"]
2692
+ });
2693
+ const mapRef = (value, recurse) => {
2694
+ if (Ref.isRef(value)) {
2695
+ const target = value.target;
2696
+ if (target != null && !inProgress.has(target.id) && (opts?.deep === "all" || opts?.deep === "parent" && isChildOf(target, root))) return Ref.make(cloneInner(target, opts, root, cache, inProgress));
2697
+ return value;
2698
+ }
2699
+ return recurse(value);
2700
+ };
2701
+ const props = deepMapValues(data, mapRef);
2702
+ if (opts?.retainId) props.id = id;
2703
+ const result = makeObject(schema, props, deepMapValues(getMeta(obj), mapRef), typeEntity);
2704
+ inProgress.delete(obj.id);
2705
+ cache.set(obj.id, result);
2706
+ return result;
2707
+ };
2708
+ /**
2709
+ * Whether `entity`'s parent chain reaches `root` — i.e. it is an owned descendant that cascade-deletes with
2710
+ * the root. Walks the `ParentId` back-links (a finite tree); guarded against cycles defensively.
2711
+ */
2712
+ var isChildOf = (entity, root) => {
2713
+ const seen = /* @__PURE__ */ new Set();
2714
+ assumeType(entity);
2715
+ let parent = entity[ParentId];
2716
+ while (parent != null && !seen.has(parent)) {
2717
+ if (parent.id === root.id) return true;
2718
+ seen.add(parent);
2719
+ parent = parent[ParentId];
2720
+ }
2721
+ return false;
2722
+ };
2723
+ //#endregion
2724
+ //#region src/internal/Type/manipulation.ts
2725
+ var __dxlog_file = "/__w/dxos/dxos/packages/core/echo/echo/src/internal/Type/manipulation.ts";
2726
+ var addFieldsToSchema = (schema, fields) => {
2727
+ const schemaExtension = Schema.partial(Schema.Struct(fields));
2728
+ return Schema.extend(schema, schemaExtension).annotations(schema.ast.annotations);
2729
+ };
2730
+ var updateFieldsInSchema = (schema, fields) => {
2731
+ const ast = schema.ast;
2732
+ invariant(SchemaAST.isTypeLiteral(ast), void 0, {
2733
+ "~LogMeta": "~LogMeta",
2734
+ F: __dxlog_file,
2735
+ L: 26,
2736
+ S: void 0,
2737
+ A: ["SchemaAST.isTypeLiteral(ast)", ""]
2738
+ });
2739
+ const updatedProperties = [...ast.propertySignatures];
2740
+ const propertiesToUpdate = Schema.partial(Schema.Struct(fields)).ast.propertySignatures;
2741
+ for (const property of propertiesToUpdate) {
2742
+ const index = updatedProperties.findIndex((p) => p.name === property.name);
2743
+ if (index !== -1) updatedProperties[index] = property;
2744
+ else updatedProperties.push(property);
2745
+ }
2746
+ return Schema.make(new SchemaAST.TypeLiteral(updatedProperties, ast.indexSignatures, ast.annotations));
2747
+ };
2748
+ var removeFieldsFromSchema = (schema, fieldNames) => {
2749
+ return Schema.make(SchemaAST.omit(schema.ast, fieldNames)).annotations(schema.ast.annotations);
2750
+ };
2751
+ var updateFieldNameInSchema = (schema, { before, after }) => {
2752
+ const ast = schema.ast;
2753
+ invariant(SchemaAST.isTypeLiteral(ast), void 0, {
2754
+ "~LogMeta": "~LogMeta",
2755
+ F: __dxlog_file,
2756
+ L: 54,
2757
+ S: void 0,
2758
+ A: ["SchemaAST.isTypeLiteral(ast)", ""]
2759
+ });
2760
+ return Schema.make(new SchemaAST.TypeLiteral(ast.propertySignatures.map((p) => p.name === before ? new SchemaAST.PropertySignature(after, p.type, p.isOptional, p.isReadonly, p.annotations) : p), ast.indexSignatures, ast.annotations));
2761
+ };
2762
+ /**
2763
+ * Persistent representation of a schema.
2764
+ */
2765
+ var TypeSchema = Schema.Struct({
2766
+ name: Schema.optional(Schema.String),
2767
+ jsonSchema: JsonSchemaType
2768
+ }).pipe(LabelAnnotation.set(["name"]), IconAnnotation.set({
2769
+ icon: "ph--database--regular",
2770
+ hue: "green"
2771
+ }), EchoTypeKindSchema(TypeMetaSchemaDXN));
2772
+ //#endregion
2773
+ export { setMetaOwner as $, isVersion as A, TypeMetaSchemaDXN as B, objectFromJSON as C, sortByLabel as Ct, compareVersions as D, isProjection as Dt, setRefResolverOnData as E, ProjectionTypeId as Et, getDXNForRelationSchemaRef as F, prepareDecodedTypedTarget as G, makeDecodedEntityLive as H, makeRelationType as I, SchemaValidator as J, prepareTypedTarget as K, EchoObjectSchema as L, versionValid as M, EchoTypeKindSchema as N, decodeVersion as O, makeProjection as Ot, EchoRelationSchema as P, getEchoRoot as Q, makeObjectType as R, matchesTag as S, sort as St, objectToJSON as T, VersionTypeId as Tt, makeObject as U, makeEchoTypeSchema as V, TypedReactiveHandler as W, ReactiveArray as X, checkIdNotPresentOnSchema as Y, objectData as Z, makeTypedEntityClass as _, defineHiddenProperty as _t, updateFieldsInSchema as a, enterChangeContext as at, filterMatchValue as b, assertObjectModel as bt, makeEntity as c, isInChangeContext as ct, makeRelation as d, batchEvents as dt, MutationOutsideChangeContextError as et, makeWithReactive as f, emitEvent as ft, createObject as g, getStrongDependencyUris as gt, isDeleted as h, getStrongDependencies as ht, updateFieldNameInSchema as i, clearPendingNotifications as it, version as j, encodeVersion as k, RawObject as kt, makeLabelAtom as l, queueNotification as lt, setValue as m, typedJsonSerializer as mt, addFieldsToSchema as n, createPropertyDeleteError as nt, clone as o, executeChange as ot, getSnapshot as p, attachTypedJsonSerializer as pt, validateAndReactifyTarget as q, removeFieldsFromSchema as r, createPropertySetError as rt, makeAtom as s, hasPendingNotifications as st, TypeSchema as t, createArrayMethodError as tt, makeProperty as u, queueOwnerNotification as ut, compareTypenameStrings as v, prettyFilter as vt, objectStructureToJson as w, sortByTypename as wt, matchMetaKey as x, compare as xt, filterMatchEntity as y, prettyQuery as yt, normalizeSchema as z };
2774
+
2775
+ //# sourceMappingURL=chunk-internal.mjs.map