@dxos/echo 0.9.0 → 0.9.1-staging.ee54ba693a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/dist/lib/neutral/Annotation.mjs +30 -8
  2. package/dist/lib/neutral/Database.mjs +7 -3
  3. package/dist/lib/neutral/Entity.mjs +15 -11
  4. package/dist/lib/neutral/Err.mjs +7 -3
  5. package/dist/lib/neutral/Feed.mjs +15 -19
  6. package/dist/lib/neutral/Filter.mjs +13 -11
  7. package/dist/lib/neutral/Format.mjs +3 -7
  8. package/dist/lib/neutral/JsonSchema.mjs +7 -7
  9. package/dist/lib/neutral/Migration.mjs +11 -11
  10. package/dist/lib/neutral/Obj.mjs +19 -13
  11. package/dist/lib/neutral/Order.mjs +1 -1
  12. package/dist/lib/neutral/Query.mjs +17 -17
  13. package/dist/lib/neutral/QueryResult.mjs +1 -1
  14. package/dist/lib/neutral/Ref.mjs +6 -6
  15. package/dist/lib/neutral/Registry.mjs +1 -1
  16. package/dist/lib/neutral/Relation.mjs +12 -12
  17. package/dist/lib/neutral/Tag.mjs +15 -15
  18. package/dist/lib/neutral/Text.mjs +25 -0
  19. package/dist/lib/neutral/Text.mjs.map +7 -0
  20. package/dist/lib/neutral/Type.mjs +10 -10
  21. package/dist/lib/neutral/chunk-2HKGAQM4.mjs +1394 -0
  22. package/dist/lib/neutral/chunk-2HKGAQM4.mjs.map +7 -0
  23. package/dist/lib/neutral/{chunk-O6BH7EPN.mjs → chunk-2ZHECXUR.mjs} +5 -4
  24. package/dist/lib/neutral/chunk-2ZHECXUR.mjs.map +7 -0
  25. package/dist/lib/neutral/{chunk-QQIYS74I.mjs → chunk-3KTE2Y7Q.mjs} +20 -20
  26. package/dist/lib/neutral/chunk-3KTE2Y7Q.mjs.map +7 -0
  27. package/dist/lib/neutral/{chunk-R5W6DXR4.mjs → chunk-3TN2VMI4.mjs} +72 -36
  28. package/dist/lib/neutral/chunk-3TN2VMI4.mjs.map +7 -0
  29. package/dist/lib/neutral/{chunk-5SMDBFVB.mjs → chunk-42L4HJ3Z.mjs} +11 -15
  30. package/dist/lib/neutral/chunk-42L4HJ3Z.mjs.map +7 -0
  31. package/dist/lib/neutral/{chunk-7PI7C4EF.mjs → chunk-4A2NWKRJ.mjs} +5 -5
  32. package/dist/lib/neutral/chunk-ACFAOTKJ.mjs +1531 -0
  33. package/dist/lib/neutral/chunk-ACFAOTKJ.mjs.map +7 -0
  34. package/dist/lib/neutral/{chunk-SBVFRTST.mjs → chunk-BEFR7LEA.mjs} +20 -10
  35. package/dist/lib/neutral/chunk-BEFR7LEA.mjs.map +7 -0
  36. package/dist/lib/neutral/{chunk-6M2Z6WBH.mjs → chunk-BXIKXT7Q.mjs} +2 -6
  37. package/dist/lib/neutral/{chunk-6M2Z6WBH.mjs.map → chunk-BXIKXT7Q.mjs.map} +1 -1
  38. package/dist/lib/neutral/{chunk-UUP46KUQ.mjs → chunk-C57XMMBY.mjs} +21 -20
  39. package/dist/lib/neutral/chunk-C57XMMBY.mjs.map +7 -0
  40. package/dist/lib/neutral/chunk-C62JYFAD.mjs +183 -0
  41. package/dist/lib/neutral/chunk-C62JYFAD.mjs.map +7 -0
  42. package/dist/lib/neutral/{chunk-MZ7K3MLL.mjs → chunk-FSGX2R62.mjs} +3 -3
  43. package/dist/lib/neutral/chunk-FSGX2R62.mjs.map +7 -0
  44. package/dist/lib/neutral/{chunk-TYGKCRMK.mjs → chunk-HBXT3GSB.mjs} +37 -15
  45. package/dist/lib/neutral/chunk-HBXT3GSB.mjs.map +7 -0
  46. package/dist/lib/neutral/{chunk-WU3GIANS.mjs → chunk-IQR45HAD.mjs} +1 -1
  47. package/dist/lib/neutral/chunk-IQR45HAD.mjs.map +7 -0
  48. package/dist/lib/neutral/{chunk-TFEWTY5A.mjs → chunk-KCBW4BR6.mjs} +4 -8
  49. package/dist/lib/neutral/chunk-KCBW4BR6.mjs.map +7 -0
  50. package/dist/lib/neutral/{chunk-WTQJHC75.mjs → chunk-L3E5IXAE.mjs} +225 -45
  51. package/dist/lib/neutral/chunk-L3E5IXAE.mjs.map +7 -0
  52. package/dist/lib/neutral/{chunk-EVK6XBXO.mjs → chunk-PRC4FEKJ.mjs} +2 -2
  53. package/dist/lib/neutral/chunk-PRC4FEKJ.mjs.map +7 -0
  54. package/dist/lib/neutral/{chunk-6YDI3J37.mjs → chunk-SCT6FFCR.mjs} +9 -4
  55. package/dist/lib/neutral/chunk-SCT6FFCR.mjs.map +7 -0
  56. package/dist/lib/neutral/{chunk-BBFJWWAV.mjs → chunk-TOCVVFK2.mjs} +26 -2
  57. package/dist/lib/neutral/chunk-TOCVVFK2.mjs.map +7 -0
  58. package/dist/lib/neutral/{chunk-RIVWNMSF.mjs → chunk-U53LSQQA.mjs} +3 -3
  59. package/dist/lib/neutral/{chunk-RIVWNMSF.mjs.map → chunk-U53LSQQA.mjs.map} +1 -1
  60. package/dist/lib/neutral/{chunk-IGK6FN65.mjs → chunk-UGFFV2FR.mjs} +2 -2
  61. package/dist/lib/neutral/{chunk-35INCYOE.mjs → chunk-UWLP4RFM.mjs} +1 -1
  62. package/dist/lib/neutral/chunk-UWLP4RFM.mjs.map +7 -0
  63. package/dist/lib/neutral/{chunk-LWXVKPPW.mjs → chunk-UZHCQ6NI.mjs} +13 -11
  64. package/dist/lib/neutral/{chunk-LWXVKPPW.mjs.map → chunk-UZHCQ6NI.mjs.map} +3 -3
  65. package/dist/lib/neutral/{chunk-5SUJPHAE.mjs → chunk-WKIT2YY5.mjs} +2 -2
  66. package/dist/lib/neutral/{chunk-T6E37YIP.mjs → chunk-XB6ISRAO.mjs} +38 -18
  67. package/dist/lib/neutral/chunk-XB6ISRAO.mjs.map +7 -0
  68. package/dist/lib/neutral/chunk-XXL42WCB.mjs +84 -0
  69. package/dist/lib/neutral/chunk-XXL42WCB.mjs.map +7 -0
  70. package/dist/lib/neutral/{chunk-ZGNNFYHS.mjs → chunk-XXWK4J53.mjs} +27 -42
  71. package/dist/lib/neutral/chunk-XXWK4J53.mjs.map +7 -0
  72. package/dist/lib/neutral/index.mjs +30 -26
  73. package/dist/lib/neutral/internal/index.mjs +111 -69
  74. package/dist/lib/neutral/meta.json +1 -1
  75. package/dist/lib/neutral/testing/index.mjs +79 -60
  76. package/dist/lib/neutral/testing/index.mjs.map +3 -3
  77. package/dist/types/src/Annotation.d.ts +35 -1
  78. package/dist/types/src/Annotation.d.ts.map +1 -1
  79. package/dist/types/src/Collection.d.ts +9 -8
  80. package/dist/types/src/Collection.d.ts.map +1 -1
  81. package/dist/types/src/Database.d.ts +38 -0
  82. package/dist/types/src/Database.d.ts.map +1 -1
  83. package/dist/types/src/Dataset.d.ts +1 -16
  84. package/dist/types/src/Dataset.d.ts.map +1 -1
  85. package/dist/types/src/Entity.d.ts +2 -0
  86. package/dist/types/src/Entity.d.ts.map +1 -1
  87. package/dist/types/src/Err.d.ts +67 -0
  88. package/dist/types/src/Err.d.ts.map +1 -1
  89. package/dist/types/src/Feed.d.ts +59 -80
  90. package/dist/types/src/Feed.d.ts.map +1 -1
  91. package/dist/types/src/Filter.d.ts +9 -1
  92. package/dist/types/src/Filter.d.ts.map +1 -1
  93. package/dist/types/src/Hypergraph.d.ts +2 -9
  94. package/dist/types/src/Hypergraph.d.ts.map +1 -1
  95. package/dist/types/src/Migration.d.ts +1 -1
  96. package/dist/types/src/Migration.d.ts.map +1 -1
  97. package/dist/types/src/Obj.d.ts +33 -6
  98. package/dist/types/src/Obj.d.ts.map +1 -1
  99. package/dist/types/src/Order.d.ts +1 -1
  100. package/dist/types/src/Order.d.ts.map +1 -1
  101. package/dist/types/src/Query.d.ts +1 -1
  102. package/dist/types/src/Query.d.ts.map +1 -1
  103. package/dist/types/src/QueryResult.d.ts +2 -2
  104. package/dist/types/src/QueryResult.d.ts.map +1 -1
  105. package/dist/types/src/Ref.d.ts +10 -6
  106. package/dist/types/src/Ref.d.ts.map +1 -1
  107. package/dist/types/src/Registry.d.ts +1 -1
  108. package/dist/types/src/Relation.d.ts.map +1 -1
  109. package/dist/types/src/Tag.d.ts +11 -13
  110. package/dist/types/src/Tag.d.ts.map +1 -1
  111. package/dist/types/src/Text.d.ts +41 -0
  112. package/dist/types/src/Text.d.ts.map +1 -0
  113. package/dist/types/src/Text.test.d.ts +2 -0
  114. package/dist/types/src/Text.test.d.ts.map +1 -0
  115. package/dist/types/src/Type.d.ts +38 -21
  116. package/dist/types/src/Type.d.ts.map +1 -1
  117. package/dist/types/src/View.d.ts +8 -9
  118. package/dist/types/src/View.d.ts.map +1 -1
  119. package/dist/types/src/index.d.ts +1 -0
  120. package/dist/types/src/index.d.ts.map +1 -1
  121. package/dist/types/src/internal/Annotation/annotations.d.ts +50 -0
  122. package/dist/types/src/internal/Annotation/annotations.d.ts.map +1 -1
  123. package/dist/types/src/internal/Annotation/atoms.d.ts +14 -0
  124. package/dist/types/src/internal/Annotation/atoms.d.ts.map +1 -0
  125. package/dist/types/src/internal/Annotation/entity-dictionary.d.ts +13 -0
  126. package/dist/types/src/internal/Annotation/entity-dictionary.d.ts.map +1 -1
  127. package/dist/types/src/internal/Entity/api.d.ts.map +1 -1
  128. package/dist/types/src/internal/Entity/guard.d.ts.map +1 -1
  129. package/dist/types/src/internal/Entity/model.d.ts +1 -1
  130. package/dist/types/src/internal/Entity/model.d.ts.map +1 -1
  131. package/dist/types/src/internal/Entity/object.d.ts +5 -1
  132. package/dist/types/src/internal/Entity/object.d.ts.map +1 -1
  133. package/dist/types/src/internal/Entity/relation.d.ts +7 -0
  134. package/dist/types/src/internal/Entity/relation.d.ts.map +1 -1
  135. package/dist/types/src/internal/Entity/type-uri.d.ts.map +1 -1
  136. package/dist/types/src/internal/Filter/index.d.ts +2 -0
  137. package/dist/types/src/internal/Filter/index.d.ts.map +1 -0
  138. package/dist/types/src/internal/Filter/match.d.ts +22 -0
  139. package/dist/types/src/internal/Filter/match.d.ts.map +1 -0
  140. package/dist/types/src/internal/Format/format.d.ts +0 -2
  141. package/dist/types/src/internal/Format/format.d.ts.map +1 -1
  142. package/dist/types/src/internal/Format/index.d.ts +2 -2
  143. package/dist/types/src/internal/Format/index.d.ts.map +1 -1
  144. package/dist/types/src/internal/Format/string.d.ts +0 -8
  145. package/dist/types/src/internal/Format/string.d.ts.map +1 -1
  146. package/dist/types/src/internal/Format/types.d.ts +2 -1
  147. package/dist/types/src/internal/Format/types.d.ts.map +1 -1
  148. package/dist/types/src/internal/Obj/atoms.d.ts +12 -3
  149. package/dist/types/src/internal/Obj/atoms.d.ts.map +1 -1
  150. package/dist/types/src/internal/Obj/clone.d.ts +2 -1
  151. package/dist/types/src/internal/Obj/clone.d.ts.map +1 -1
  152. package/dist/types/src/internal/Obj/create-object.d.ts +3 -4
  153. package/dist/types/src/internal/Obj/create-object.d.ts.map +1 -1
  154. package/dist/types/src/internal/Obj/json-serializer.d.ts.map +1 -1
  155. package/dist/types/src/internal/Query/index.d.ts +1 -0
  156. package/dist/types/src/internal/Query/index.d.ts.map +1 -1
  157. package/dist/types/src/internal/Query/query-result-effect.d.ts +9 -0
  158. package/dist/types/src/internal/Query/query-result-effect.d.ts.map +1 -0
  159. package/dist/types/src/internal/Ref/atoms.d.ts +1 -2
  160. package/dist/types/src/internal/Ref/atoms.d.ts.map +1 -1
  161. package/dist/types/src/internal/Ref/index.d.ts +1 -0
  162. package/dist/types/src/internal/Ref/index.d.ts.map +1 -1
  163. package/dist/types/src/internal/Ref/ref.d.ts +79 -8
  164. package/dist/types/src/internal/Ref/ref.d.ts.map +1 -1
  165. package/dist/types/src/internal/Ref/strong-deps.d.ts +35 -0
  166. package/dist/types/src/internal/Ref/strong-deps.d.ts.map +1 -0
  167. package/dist/types/src/internal/common/atom-snapshot.d.ts +8 -0
  168. package/dist/types/src/internal/common/atom-snapshot.d.ts.map +1 -0
  169. package/dist/types/src/internal/common/proxy/make-object.d.ts.map +1 -1
  170. package/dist/types/src/internal/common/proxy/proxy-types.d.ts +12 -0
  171. package/dist/types/src/internal/common/proxy/proxy-types.d.ts.map +1 -1
  172. package/dist/types/src/internal/common/proxy/proxy-utils.d.ts +25 -0
  173. package/dist/types/src/internal/common/proxy/proxy-utils.d.ts.map +1 -1
  174. package/dist/types/src/internal/common/proxy/schema-validator.d.ts +5 -0
  175. package/dist/types/src/internal/common/proxy/schema-validator.d.ts.map +1 -1
  176. package/dist/types/src/internal/common/proxy/typed-handler.d.ts +17 -0
  177. package/dist/types/src/internal/common/proxy/typed-handler.d.ts.map +1 -1
  178. package/dist/types/src/internal/common/types/entity.d.ts +4 -4
  179. package/dist/types/src/internal/common/types/entity.d.ts.map +1 -1
  180. package/dist/types/src/internal/common/types/meta.d.ts +2 -4
  181. package/dist/types/src/internal/common/types/meta.d.ts.map +1 -1
  182. package/dist/types/src/internal/index.d.ts +1 -0
  183. package/dist/types/src/internal/index.d.ts.map +1 -1
  184. package/dist/types/src/testing/test-schema.d.ts +42 -171
  185. package/dist/types/src/testing/test-schema.d.ts.map +1 -1
  186. package/dist/types/tsconfig.tsbuildinfo +1 -1
  187. package/package.json +20 -13
  188. package/src/Annotation.test.ts +257 -10
  189. package/src/Annotation.ts +58 -4
  190. package/src/Collection.ts +10 -12
  191. package/src/Database.ts +55 -21
  192. package/src/Entity.ts +3 -1
  193. package/src/Err.ts +22 -0
  194. package/src/Feed.ts +117 -141
  195. package/src/Filter.test.ts +38 -0
  196. package/src/Filter.ts +17 -3
  197. package/src/Hypergraph.ts +2 -11
  198. package/src/Migration.ts +1 -1
  199. package/src/Obj.test.ts +92 -12
  200. package/src/Obj.ts +38 -5
  201. package/src/Order.ts +3 -3
  202. package/src/Query.test.ts +2 -2
  203. package/src/Query.ts +16 -16
  204. package/src/QueryResult.ts +2 -2
  205. package/src/Ref.ts +14 -6
  206. package/src/Registry.ts +1 -1
  207. package/src/Relation.ts +1 -1
  208. package/src/Tag.ts +13 -16
  209. package/src/Text.test.ts +186 -0
  210. package/src/Text.ts +116 -0
  211. package/src/Type.test.ts +52 -24
  212. package/src/Type.ts +85 -33
  213. package/src/View.ts +22 -30
  214. package/src/index.ts +1 -1
  215. package/src/internal/Annotation/annotations.ts +71 -2
  216. package/src/internal/Annotation/atoms.ts +107 -0
  217. package/src/internal/Annotation/entity-dictionary.ts +40 -37
  218. package/src/internal/Entity/api.ts +1 -1
  219. package/src/internal/Entity/guard.ts +2 -1
  220. package/src/internal/Entity/model.ts +2 -2
  221. package/src/internal/Entity/object.ts +14 -1
  222. package/src/internal/Entity/relation.ts +19 -0
  223. package/src/internal/Entity/type-uri.ts +3 -1
  224. package/src/internal/Filter/index.ts +5 -0
  225. package/src/internal/Filter/match.ts +284 -0
  226. package/src/internal/Format/format.ts +0 -2
  227. package/src/internal/Format/index.ts +2 -2
  228. package/src/internal/Format/string.ts +0 -12
  229. package/src/internal/Format/types.ts +4 -2
  230. package/src/internal/JsonSchema/json-schema.test.ts +82 -54
  231. package/src/internal/Obj/atoms.ts +62 -18
  232. package/src/internal/Obj/clone.ts +61 -20
  233. package/src/internal/Obj/create-object.test.ts +3 -3
  234. package/src/internal/Obj/create-object.ts +3 -4
  235. package/src/internal/Obj/inspect.ts +1 -1
  236. package/src/internal/Obj/json-serializer.test.ts +7 -5
  237. package/src/internal/Obj/json-serializer.ts +4 -4
  238. package/src/internal/Obj/schema-validator.test.ts +53 -0
  239. package/src/internal/Obj/set-value.test.ts +29 -19
  240. package/src/internal/Query/index.ts +1 -0
  241. package/src/internal/Query/query-result-effect.ts +35 -0
  242. package/src/internal/Ref/atoms.ts +23 -3
  243. package/src/internal/Ref/index.ts +1 -0
  244. package/src/internal/Ref/ref.test.ts +8 -8
  245. package/src/internal/Ref/ref.ts +122 -39
  246. package/src/internal/Ref/strong-deps.ts +107 -0
  247. package/src/internal/common/atom-snapshot.ts +19 -0
  248. package/src/internal/common/proxy/make-object.ts +1 -1
  249. package/src/internal/common/proxy/proxy-types.ts +20 -0
  250. package/src/internal/common/proxy/proxy-utils.ts +37 -1
  251. package/src/internal/common/proxy/reactive-array.ts +3 -3
  252. package/src/internal/common/proxy/reactive.test.ts +1 -1
  253. package/src/internal/common/proxy/schema-validator.ts +181 -8
  254. package/src/internal/common/proxy/typed-handler.ts +254 -76
  255. package/src/internal/common/types/entity.ts +15 -7
  256. package/src/internal/index.ts +1 -0
  257. package/src/testing/test-schema.ts +75 -90
  258. package/dist/lib/neutral/chunk-35INCYOE.mjs.map +0 -7
  259. package/dist/lib/neutral/chunk-3PBP4V4O.mjs +0 -101
  260. package/dist/lib/neutral/chunk-3PBP4V4O.mjs.map +0 -7
  261. package/dist/lib/neutral/chunk-4ZUHOTCG.mjs +0 -184
  262. package/dist/lib/neutral/chunk-4ZUHOTCG.mjs.map +0 -7
  263. package/dist/lib/neutral/chunk-5SMDBFVB.mjs.map +0 -7
  264. package/dist/lib/neutral/chunk-6YDI3J37.mjs.map +0 -7
  265. package/dist/lib/neutral/chunk-7FPIAJIV.mjs +0 -2279
  266. package/dist/lib/neutral/chunk-7FPIAJIV.mjs.map +0 -7
  267. package/dist/lib/neutral/chunk-BBFJWWAV.mjs.map +0 -7
  268. package/dist/lib/neutral/chunk-EVK6XBXO.mjs.map +0 -7
  269. package/dist/lib/neutral/chunk-MZ7K3MLL.mjs.map +0 -7
  270. package/dist/lib/neutral/chunk-O6BH7EPN.mjs.map +0 -7
  271. package/dist/lib/neutral/chunk-QQIYS74I.mjs.map +0 -7
  272. package/dist/lib/neutral/chunk-R5W6DXR4.mjs.map +0 -7
  273. package/dist/lib/neutral/chunk-SBVFRTST.mjs.map +0 -7
  274. package/dist/lib/neutral/chunk-T6E37YIP.mjs.map +0 -7
  275. package/dist/lib/neutral/chunk-TFEWTY5A.mjs.map +0 -7
  276. package/dist/lib/neutral/chunk-TYGKCRMK.mjs.map +0 -7
  277. package/dist/lib/neutral/chunk-UUP46KUQ.mjs.map +0 -7
  278. package/dist/lib/neutral/chunk-WTQJHC75.mjs.map +0 -7
  279. package/dist/lib/neutral/chunk-WU3GIANS.mjs.map +0 -7
  280. package/dist/lib/neutral/chunk-ZGNNFYHS.mjs.map +0 -7
  281. package/dist/types/src/exemplars.test.d.ts +0 -2
  282. package/dist/types/src/exemplars.test.d.ts.map +0 -1
  283. package/dist/types/src/hierarchy.test.d.ts +0 -2
  284. package/dist/types/src/hierarchy.test.d.ts.map +0 -1
  285. package/src/exemplars.test.ts +0 -21
  286. package/src/hierarchy.test.ts +0 -33
  287. /package/dist/lib/neutral/{chunk-7PI7C4EF.mjs.map → chunk-4A2NWKRJ.mjs.map} +0 -0
  288. /package/dist/lib/neutral/{chunk-IGK6FN65.mjs.map → chunk-UGFFV2FR.mjs.map} +0 -0
  289. /package/dist/lib/neutral/{chunk-5SUJPHAE.mjs.map → chunk-WKIT2YY5.mjs.map} +0 -0
@@ -0,0 +1,284 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import * as semver from 'semver';
6
+
7
+ import { EncodedReference, type QueryAST, isEncodedReference } from '@dxos/echo-protocol';
8
+ import { DXN, EID } from '@dxos/keys';
9
+
10
+ import { getTypeURI } from '../Annotation/annotations';
11
+ import { getMetaChecked } from '../common/api/meta';
12
+ import { type AnyEntity } from '../common/types';
13
+ import { objectToJSON } from '../Obj/json-serializer';
14
+
15
+ /**
16
+ * Matches a tag filter against an object's stored tags. Tags may be stored as encoded references or
17
+ * (in legacy data) bare URI strings, and those URIs may be in legacy DXN form. Both sides are
18
+ * normalized to the canonical EID before comparing.
19
+ */
20
+ export const matchesTag = (tags: readonly unknown[], filterTag: string): boolean => {
21
+ const canonical = (uri: string): string => {
22
+ const eid = EID.tryParse(uri);
23
+ return (eid && EID.getEntityId(eid)) || uri;
24
+ };
25
+ const normalize = (tag: unknown): string =>
26
+ canonical(isEncodedReference(tag) ? EncodedReference.toURI(tag) : (tag as string));
27
+ const target = canonical(filterTag);
28
+ return tags.some((tag) => normalize(tag) === target);
29
+ };
30
+
31
+ /**
32
+ * Matches a meta `key` / `version` constraint against an object's meta `key` and `version`.
33
+ */
34
+ export const matchMetaKey = (
35
+ key: string,
36
+ versionRange: string | undefined,
37
+ objKey: string | undefined,
38
+ objVersion: string | undefined,
39
+ ): boolean => {
40
+ if (objKey !== key) {
41
+ return false;
42
+ }
43
+ if (versionRange === undefined) {
44
+ return true;
45
+ }
46
+ if (objVersion === undefined || semver.valid(objVersion) === null) {
47
+ return false;
48
+ }
49
+ if (semver.validRange(versionRange) === null) {
50
+ return false;
51
+ }
52
+ return semver.satisfies(objVersion, versionRange, { includePrerelease: true });
53
+ };
54
+
55
+ /**
56
+ * Compares a filter's type discriminator against the value stored on an object's `system.type`.
57
+ */
58
+ export const compareTypenameStrings = (expectedStr: string, actualStr: string): boolean => {
59
+ const expectedEid = EID.tryParse(expectedStr);
60
+ if (expectedEid) {
61
+ const actualEid = EID.tryParse(actualStr);
62
+ if (!actualEid) {
63
+ return false;
64
+ }
65
+ if (EID.getEntityId(expectedEid) !== EID.getEntityId(actualEid)) {
66
+ return false;
67
+ }
68
+ const expectedSpaceId = EID.getSpaceId(expectedEid);
69
+ const actualSpaceId = EID.getSpaceId(actualEid);
70
+ return expectedSpaceId === undefined || actualSpaceId === undefined || expectedSpaceId === actualSpaceId;
71
+ }
72
+
73
+ const expectedDxn = DXN.tryMake(expectedStr);
74
+ if (expectedDxn) {
75
+ const actualDxn = DXN.tryMake(actualStr);
76
+ if (!actualDxn) {
77
+ return false;
78
+ }
79
+ if (DXN.getName(expectedDxn) !== DXN.getName(actualDxn)) {
80
+ return false;
81
+ }
82
+ const expectedVersion = DXN.getVersion(expectedDxn);
83
+ const actualVersion = DXN.getVersion(actualDxn);
84
+ return expectedVersion === undefined || actualVersion === undefined || expectedVersion === actualVersion;
85
+ }
86
+
87
+ return expectedStr === actualStr;
88
+ };
89
+
90
+ const structuralMatch = (filterObj: any, targetObj: any, strict = true): boolean => {
91
+ if (typeof filterObj !== 'object' || filterObj === null) {
92
+ return filterObj === targetObj;
93
+ }
94
+
95
+ if (typeof targetObj !== 'object' || targetObj === null) {
96
+ return false;
97
+ }
98
+
99
+ const filterKeys = Object.keys(filterObj);
100
+ const targetKeys = Object.keys(targetObj);
101
+ if (strict && filterKeys.length !== targetKeys.length) {
102
+ return false;
103
+ }
104
+
105
+ return filterKeys.every((key) => {
106
+ if (!(key in targetObj)) {
107
+ return false;
108
+ }
109
+ const filterValue = filterObj[key];
110
+ const targetValue = targetObj[key];
111
+
112
+ if (typeof filterValue === 'object' && filterValue !== null) {
113
+ return structuralMatch(filterValue, targetValue);
114
+ }
115
+
116
+ return filterValue === targetValue;
117
+ });
118
+ };
119
+
120
+ export const filterMatchValue = (filter: QueryAST.Filter, value: unknown): boolean => {
121
+ switch (filter.type) {
122
+ case 'compare': {
123
+ const compareValue = filter.value as any;
124
+ switch (filter.operator) {
125
+ case 'eq':
126
+ if (isEncodedReference(compareValue)) {
127
+ if (!isEncodedReference(value)) {
128
+ return false;
129
+ }
130
+ return EncodedReference.toURI(value) === EncodedReference.toURI(compareValue);
131
+ }
132
+ return value === compareValue;
133
+ case 'neq':
134
+ return value !== compareValue;
135
+ case 'gt':
136
+ return (value as any) > compareValue;
137
+ case 'gte':
138
+ return (value as any) >= compareValue;
139
+ case 'lt':
140
+ return (value as any) < compareValue;
141
+ case 'lte':
142
+ return (value as any) <= compareValue;
143
+ default:
144
+ return false;
145
+ }
146
+ }
147
+ case 'object': {
148
+ if (typeof value !== 'object' || value === null) {
149
+ return false;
150
+ }
151
+
152
+ if (filter.props) {
153
+ for (const [key, valueFilter] of Object.entries(filter.props)) {
154
+ const nestedValue = (value as any)[key];
155
+ if (!filterMatchValue(valueFilter, nestedValue)) {
156
+ return false;
157
+ }
158
+ }
159
+ }
160
+
161
+ return true;
162
+ }
163
+ case 'in': {
164
+ return filter.values.includes(value);
165
+ }
166
+ case 'contains': {
167
+ if (!Array.isArray(value)) {
168
+ return false;
169
+ }
170
+
171
+ return value.some((element) => {
172
+ if (typeof filter.value === 'object' && filter.value !== null && !Array.isArray(filter.value)) {
173
+ return structuralMatch(filter.value, element);
174
+ }
175
+
176
+ return element === filter.value;
177
+ });
178
+ }
179
+ case 'range': {
180
+ return (value as any) >= filter.from && (value as any) <= filter.to;
181
+ }
182
+ case 'not': {
183
+ return !filterMatchValue(filter.filter, value);
184
+ }
185
+ case 'and': {
186
+ return filter.filters.every((f) => filterMatchValue(f, value));
187
+ }
188
+ case 'or': {
189
+ return filter.filters.some((f) => filterMatchValue(f, value));
190
+ }
191
+ default:
192
+ return false;
193
+ }
194
+ };
195
+
196
+ /**
197
+ * Matches a filter against an entity proxy without full JSON serialization when possible.
198
+ */
199
+ export const filterMatchEntity = (filter: QueryAST.Filter, entity: AnyEntity): boolean => {
200
+ switch (filter.type) {
201
+ case 'object': {
202
+ if (filter.typename !== null) {
203
+ const typeURI = getTypeURI(entity);
204
+ if (!typeURI || !compareTypenameStrings(filter.typename, typeURI)) {
205
+ return false;
206
+ }
207
+ }
208
+
209
+ if (filter.id && filter.id.length > 0 && !filter.id.includes(entity.id)) {
210
+ return false;
211
+ }
212
+
213
+ if (filter.props) {
214
+ let json: ReturnType<typeof objectToJSON> | null = null;
215
+ try {
216
+ json = objectToJSON(entity);
217
+ } catch {
218
+ // Serialization of complex static-type entities may throw.
219
+ }
220
+ if (json === null) {
221
+ return false;
222
+ }
223
+ for (const [key, valueFilter] of Object.entries(filter.props)) {
224
+ if (key.startsWith('@')) {
225
+ continue;
226
+ }
227
+ if (!filterMatchValue(valueFilter, (json as any)[key])) {
228
+ return false;
229
+ }
230
+ }
231
+ }
232
+
233
+ const meta = getMetaChecked(entity);
234
+
235
+ if (filter.foreignKeys && filter.foreignKeys.length > 0) {
236
+ const hasKey = filter.foreignKeys.some((fk) => meta.keys.some((k) => k.source === fk.source && k.id === fk.id));
237
+ if (!hasKey) {
238
+ return false;
239
+ }
240
+ }
241
+
242
+ if (filter.metaKey !== undefined) {
243
+ if (!matchMetaKey(filter.metaKey, filter.metaVersion, meta.key, meta.version)) {
244
+ return false;
245
+ }
246
+ }
247
+
248
+ return true;
249
+ }
250
+
251
+ case 'tag': {
252
+ const rawTags = getMetaChecked(entity).tags;
253
+ const tags = rawTags.map((tag: any) => (typeof tag?.encode === 'function' ? tag.encode() : tag));
254
+ return matchesTag(tags, filter.tag);
255
+ }
256
+
257
+ case 'text-search': {
258
+ return false;
259
+ }
260
+
261
+ case 'timestamp': {
262
+ throw new Error('Timestamp filters must be handled at the index level, not in-memory matching.');
263
+ }
264
+
265
+ case 'child-of': {
266
+ throw new Error('child-of filters must be handled at the executor level, not in-memory matching.');
267
+ }
268
+
269
+ case 'not': {
270
+ return !filterMatchEntity(filter.filter, entity);
271
+ }
272
+
273
+ case 'and': {
274
+ return filter.filters.every((f) => filterMatchEntity(f, entity));
275
+ }
276
+
277
+ case 'or': {
278
+ return filter.filters.some((f) => filterMatchEntity(f, entity));
279
+ }
280
+
281
+ default:
282
+ return false;
283
+ }
284
+ };
@@ -29,8 +29,6 @@ export namespace Format {
29
29
  export const Email = StringUtil.Email;
30
30
  export const Formula = StringUtil.Formula;
31
31
  export const Hostname = StringUtil.Hostname;
32
- export const JSON = StringUtil.JSON;
33
- export const Markdown = StringUtil.Markdown;
34
32
  export const Regex = StringUtil.Regex;
35
33
  export const URL = StringUtil.URL;
36
34
  export const UUID = Schema.UUID;
@@ -4,8 +4,8 @@
4
4
 
5
5
  export * from './date';
6
6
  export * from './format';
7
- export { CurrencyAnnotationId, DecimalPrecision, Currency } from './number';
8
- export { GeoPoint, GeoLocation } from './object';
7
+ export { Currency, CurrencyAnnotationId, DecimalPrecision } from './number';
8
+ export { GeoLocation, GeoPoint } from './object';
9
9
  export * from './select';
10
10
  export * from './string';
11
11
  export * from './types';
@@ -32,18 +32,6 @@ export const Formula = Schema.String.pipe(FormatAnnotation.set(TypeFormat.Formul
32
32
  // TODO(burdon): Implement.
33
33
  export const Hostname = Schema.String.pipe(FormatAnnotation.set(TypeFormat.Hostname));
34
34
 
35
- /**
36
- *
37
- */
38
- // TODO(burdon): Implement.
39
- export const JSON = Schema.String.pipe(FormatAnnotation.set(TypeFormat.JSON));
40
-
41
- /**
42
- *
43
- */
44
- // TODO(burdon): Implement.
45
- export const Markdown = Schema.String.pipe(FormatAnnotation.set(TypeFormat.Markdown));
46
-
47
35
  /**
48
36
  * Regex
49
37
  * https://json-schema.org/understanding-json-schema/reference/regular_expressions
@@ -7,7 +7,7 @@ import type * as JSONSchema from 'effect/JSONSchema';
7
7
  import * as Option from 'effect/Option';
8
8
  import * as SchemaAST from 'effect/SchemaAST';
9
9
 
10
- import { createAnnotationHelper } from '../Annotation/util';
10
+ import { createAnnotationHelper } from '../Annotation';
11
11
  import { type JsonSchemaType } from '../JsonSchema';
12
12
 
13
13
  // TODO(burdon): Rename PropertyType.
@@ -79,10 +79,11 @@ export enum TypeFormat {
79
79
  DID = 'did', // Users, etc.
80
80
  DXN = 'dxn',
81
81
  Email = 'email',
82
- Formula = 'formula', // Spreadsheet formula.
82
+ Formula = 'formula', // Spreadsheet (Excel, Google Sheets, etc.) formula.
83
83
  Hostname = 'hostname',
84
84
  JSON = 'json',
85
85
  Markdown = 'markdown',
86
+ Password = 'password',
86
87
  Regex = 'regex',
87
88
  SingleSelect = 'single-select',
88
89
  Text = 'text',
@@ -149,6 +150,7 @@ export const formatToType: Record<TypeFormat, TypeEnum> = {
149
150
  [TypeFormat.Hostname]: TypeEnum.String,
150
151
  [TypeFormat.JSON]: TypeEnum.String,
151
152
  [TypeFormat.Markdown]: TypeEnum.String,
153
+ [TypeFormat.Password]: TypeEnum.String,
152
154
  [TypeFormat.Regex]: TypeEnum.String,
153
155
  [TypeFormat.URL]: TypeEnum.String,
154
156
  [TypeFormat.UUID]: TypeEnum.String,
@@ -33,9 +33,7 @@ const EXAMPLE_NAMESPACE = '@example';
33
33
 
34
34
  describe('effect-to-json', () => {
35
35
  test('type annotation', () => {
36
- const Test = Schema.Struct({ name: Schema.String }).pipe(
37
- Type.makeObject(DXN.make('com.example.type.test', '0.1.0')),
38
- );
36
+ const Test = Type.makeObject(DXN.make('com.example.type.test', '0.1.0'))(Schema.Struct({ name: Schema.String }));
39
37
  const jsonSchema = toJsonSchema(Test);
40
38
  expect(jsonSchema.$id).toEqual('dxn:com.example.type.test:0.1.0');
41
39
  expect(jsonSchema.version).toEqual('0.1.0');
@@ -43,20 +41,26 @@ describe('effect-to-json', () => {
43
41
 
44
42
  test('property meta annotation', () => {
45
43
  const meta = { maxLength: 0 };
46
- const Test = Schema.Struct({
47
- name: Schema.String.pipe(PropertyMeta(EXAMPLE_NAMESPACE, meta)),
48
- }).pipe(Type.makeObject(DXN.make('com.example.type.test', '0.1.0')));
44
+ const Test = Type.makeObject(DXN.make('com.example.type.test', '0.1.0'))(
45
+ Schema.Struct({
46
+ name: Schema.String.pipe(PropertyMeta(EXAMPLE_NAMESPACE, meta)),
47
+ }),
48
+ );
49
49
  const jsonSchema = toJsonSchema(Test);
50
50
  expect(getNormalizedEchoAnnotations(jsonSchema.properties!.name!)!.meta![EXAMPLE_NAMESPACE]).to.deep.eq(meta);
51
51
  });
52
52
 
53
53
  test('reference annotation', () => {
54
- const Nested = Schema.Struct({
55
- name: Schema.String,
56
- }).pipe(Type.makeObject(DXN.make('com.example.type.testNested', '0.1.0')));
57
- const Test = Schema.Struct({
58
- name: Ref(Nested),
59
- }).pipe(Type.makeObject(DXN.make('com.example.type.test', '0.1.0')));
54
+ const Nested = Type.makeObject(DXN.make('com.example.type.testNested', '0.1.0'))(
55
+ Schema.Struct({
56
+ name: Schema.String,
57
+ }),
58
+ );
59
+ const Test = Type.makeObject(DXN.make('com.example.type.test', '0.1.0'))(
60
+ Schema.Struct({
61
+ name: Ref(Nested),
62
+ }),
63
+ );
60
64
  const jsonSchema = toJsonSchema(Test);
61
65
  // log.info('schema', { jsonSchema });
62
66
  const nested = jsonSchema.properties!.name;
@@ -66,12 +70,16 @@ describe('effect-to-json', () => {
66
70
  // TODO(ZaymonFC): @dmaretskyi we still need to fix this.
67
71
  // TODO(dmaretskyi): Remove FieldLookupAnnotationId.
68
72
  test.skip('reference annotation with lookup property', () => {
69
- const Nested = Schema.Struct({
70
- name: Schema.String,
71
- }).pipe(Type.makeObject(DXN.make('com.example.type.testNested', '0.1.0')));
72
- const Test = Schema.Struct({
73
- name: Ref(Nested).annotations({ [FieldLookupAnnotationId]: 'name' }),
74
- }).pipe(Type.makeObject(DXN.make('com.example.type.test', '0.1.0')));
73
+ const Nested = Type.makeObject(DXN.make('com.example.type.testNested', '0.1.0'))(
74
+ Schema.Struct({
75
+ name: Schema.String,
76
+ }),
77
+ );
78
+ const Test = Type.makeObject(DXN.make('com.example.type.test', '0.1.0'))(
79
+ Schema.Struct({
80
+ name: Ref(Nested).annotations({ [FieldLookupAnnotationId]: 'name' }),
81
+ }),
82
+ );
75
83
  const jsonSchema = toJsonSchema(Test);
76
84
  const effectSchema = toEffectSchema(jsonSchema);
77
85
 
@@ -80,24 +88,32 @@ describe('effect-to-json', () => {
80
88
  });
81
89
 
82
90
  test('array of references', () => {
83
- const Nested = Schema.Struct({
84
- name: Schema.String,
85
- }).pipe(Type.makeObject(DXN.make('com.example.type.testNested', '0.1.0')));
86
- const Test = Schema.Struct({
87
- name: Schema.Array(Ref(Nested)),
88
- }).pipe(Type.makeObject(DXN.make('com.example.type.test', '0.1.0')));
91
+ const Nested = Type.makeObject(DXN.make('com.example.type.testNested', '0.1.0'))(
92
+ Schema.Struct({
93
+ name: Schema.String,
94
+ }),
95
+ );
96
+ const Test = Type.makeObject(DXN.make('com.example.type.test', '0.1.0'))(
97
+ Schema.Struct({
98
+ name: Schema.Array(Ref(Nested)),
99
+ }),
100
+ );
89
101
 
90
102
  const jsonSchema = toJsonSchema(Test);
91
103
  expectReferenceAnnotation((jsonSchema.properties!.name as any).items);
92
104
  });
93
105
 
94
106
  test('optional references', () => {
95
- const Nested = Schema.Struct({
96
- name: Schema.String,
97
- }).pipe(Type.makeObject(DXN.make('com.example.type.testNested', '0.1.0')));
98
- const Test = Schema.Struct({
99
- name: Schema.optional(Ref(Nested)),
100
- }).pipe(Type.makeObject(DXN.make('com.example.type.test', '0.1.0')));
107
+ const Nested = Type.makeObject(DXN.make('com.example.type.testNested', '0.1.0'))(
108
+ Schema.Struct({
109
+ name: Schema.String,
110
+ }),
111
+ );
112
+ const Test = Type.makeObject(DXN.make('com.example.type.test', '0.1.0'))(
113
+ Schema.Struct({
114
+ name: Schema.optional(Ref(Nested)),
115
+ }),
116
+ );
101
117
  const jsonSchema = toJsonSchema(Test);
102
118
  expectReferenceAnnotation(jsonSchema.properties!.name);
103
119
  });
@@ -110,12 +126,14 @@ describe('effect-to-json', () => {
110
126
  });
111
127
 
112
128
  test('annotations', () => {
113
- const TempSchema = Schema.Struct({
114
- name: Schema.String.annotations({ description: 'Person name', title: 'Name' }),
115
- email: Schema.String.pipe(FormatAnnotation.set(TypeFormat.Email)).annotations({
116
- description: 'Email address',
129
+ const TempSchema = Type.makeObject(DXN.make('com.example.type.person', '0.1.0'))(
130
+ Schema.Struct({
131
+ name: Schema.String.annotations({ description: 'Person name', title: 'Name' }),
132
+ email: Schema.String.pipe(FormatAnnotation.set(TypeFormat.Email)).annotations({
133
+ description: 'Email address',
134
+ }),
117
135
  }),
118
- }).pipe(Type.makeObject(DXN.make('com.example.type.person', '0.1.0')));
136
+ );
119
137
 
120
138
  const jsonSchema = toJsonSchema(TempSchema);
121
139
  expect(jsonSchema).to.deep.eq({
@@ -159,14 +177,18 @@ describe('effect-to-json', () => {
159
177
  });
160
178
 
161
179
  test('reference property by ref', () => {
162
- const Organization = Schema.Struct({
163
- field: Schema.String,
164
- }).pipe(Type.makeObject(DXN.make('com.example.type.organization', '0.1.0')));
180
+ const Organization = Type.makeObject(DXN.make('com.example.type.organization', '0.1.0'))(
181
+ Schema.Struct({
182
+ field: Schema.String,
183
+ }),
184
+ );
165
185
 
166
- const Contact = Schema.Struct({
167
- name: Schema.String,
168
- organization: Ref(Organization).annotations({ description: 'Contact organization' }),
169
- }).pipe(Type.makeObject(DXN.make('com.example.type.person', '0.1.0')));
186
+ const Contact = Type.makeObject(DXN.make('com.example.type.person', '0.1.0'))(
187
+ Schema.Struct({
188
+ name: Schema.String,
189
+ organization: Ref(Organization).annotations({ description: 'Contact organization' }),
190
+ }),
191
+ );
170
192
 
171
193
  // log.info('Contact', { ast: Contact.ast });
172
194
 
@@ -211,14 +233,18 @@ describe('effect-to-json', () => {
211
233
  });
212
234
 
213
235
  test('add reference property', () => {
214
- const Organization = Schema.Struct({
215
- field: Schema.String,
216
- }).pipe(Type.makeObject(DXN.make('com.example.type.organization', '0.1.0')));
236
+ const Organization = Type.makeObject(DXN.make('com.example.type.organization', '0.1.0'))(
237
+ Schema.Struct({
238
+ field: Schema.String,
239
+ }),
240
+ );
217
241
 
218
- const Contact = Schema.Struct({
219
- name: Schema.String,
220
- organization: Ref(Organization).annotations({ description: 'Contact organization' }),
221
- }).pipe(Type.makeObject(DXN.make('com.example.type.person', '0.1.0')));
242
+ const Contact = Type.makeObject(DXN.make('com.example.type.person', '0.1.0'))(
243
+ Schema.Struct({
244
+ name: Schema.String,
245
+ organization: Ref(Organization).annotations({ description: 'Contact organization' }),
246
+ }),
247
+ );
222
248
 
223
249
  const jsonSchema = toJsonSchema(Contact);
224
250
  setSchemaProperty(
@@ -418,9 +444,11 @@ describe('json-to-effect', () => {
418
444
 
419
445
  for (const partial of [false, true]) {
420
446
  test(`deserialized equals original ${partial ? 'with partial' : ''}`, () => {
421
- const Organization = Schema.Struct({
422
- field: Schema.String,
423
- }).pipe(Type.makeObject(DXN.make('com.example.type.organization', '0.1.0')));
447
+ const Organization = Type.makeObject(DXN.make('com.example.type.organization', '0.1.0'))(
448
+ Schema.Struct({
449
+ field: Schema.String,
450
+ }),
451
+ );
424
452
 
425
453
  const fields = {
426
454
  string: Schema.String,
@@ -436,8 +464,8 @@ describe('json-to-effect', () => {
436
464
  null: Schema.Null,
437
465
  } as const;
438
466
 
439
- const Test = (partial ? Schema.partial(Schema.Struct(fields)) : Schema.Struct(fields)).pipe(
440
- Type.makeObject(DXN.make('com.example.type.test', '0.1.0')),
467
+ const Test = Type.makeObject(DXN.make('com.example.type.test', '0.1.0'))(
468
+ partial ? Schema.partial(Schema.Struct(fields)) : Schema.Struct(fields),
441
469
  );
442
470
 
443
471
  const jsonSchema = toJsonSchema(Test);