@dxos/echo 0.8.4-main.dedc0f3 → 0.8.4-main.e8ec1fe

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 (312) hide show
  1. package/dist/lib/browser/chunk-BIDAASFK.mjs +3727 -0
  2. package/dist/lib/browser/chunk-BIDAASFK.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-ZDLCWGEW.mjs +410 -0
  4. package/dist/lib/browser/chunk-ZDLCWGEW.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-ZFRJKT4A.mjs +585 -0
  6. package/dist/lib/browser/chunk-ZFRJKT4A.mjs.map +7 -0
  7. package/dist/lib/browser/index.mjs +14 -5
  8. package/dist/lib/browser/internal/index.mjs +336 -0
  9. package/dist/lib/browser/internal/index.mjs.map +7 -0
  10. package/dist/lib/browser/meta.json +1 -1
  11. package/dist/lib/browser/query/index.mjs +13 -0
  12. package/dist/lib/browser/query/index.mjs.map +7 -0
  13. package/dist/lib/browser/testing/index.mjs +231 -34
  14. package/dist/lib/browser/testing/index.mjs.map +4 -4
  15. package/dist/lib/node-esm/chunk-3SVRRCUU.mjs +3727 -0
  16. package/dist/lib/node-esm/chunk-3SVRRCUU.mjs.map +7 -0
  17. package/dist/lib/node-esm/chunk-CGDHRZWH.mjs +585 -0
  18. package/dist/lib/node-esm/chunk-CGDHRZWH.mjs.map +7 -0
  19. package/dist/lib/node-esm/chunk-HWS6VBQC.mjs +410 -0
  20. package/dist/lib/node-esm/chunk-HWS6VBQC.mjs.map +7 -0
  21. package/dist/lib/node-esm/index.mjs +14 -5
  22. package/dist/lib/node-esm/internal/index.mjs +336 -0
  23. package/dist/lib/node-esm/internal/index.mjs.map +7 -0
  24. package/dist/lib/node-esm/meta.json +1 -1
  25. package/dist/lib/node-esm/query/index.mjs +13 -0
  26. package/dist/lib/node-esm/query/index.mjs.map +7 -0
  27. package/dist/lib/node-esm/testing/index.mjs +231 -34
  28. package/dist/lib/node-esm/testing/index.mjs.map +4 -4
  29. package/dist/types/src/Obj.d.ts +26 -7
  30. package/dist/types/src/Obj.d.ts.map +1 -1
  31. package/dist/types/src/Ref.d.ts +1 -1
  32. package/dist/types/src/Ref.d.ts.map +1 -1
  33. package/dist/types/src/Relation.d.ts +5 -4
  34. package/dist/types/src/Relation.d.ts.map +1 -1
  35. package/dist/types/src/Tag.d.ts +17 -0
  36. package/dist/types/src/Tag.d.ts.map +1 -0
  37. package/dist/types/src/Type.d.ts +16 -17
  38. package/dist/types/src/Type.d.ts.map +1 -1
  39. package/dist/types/src/errors.d.ts +68 -0
  40. package/dist/types/src/errors.d.ts.map +1 -0
  41. package/dist/types/src/index.d.ts +4 -2
  42. package/dist/types/src/index.d.ts.map +1 -1
  43. package/dist/types/src/internal/ast/annotation-helper.d.ts +8 -0
  44. package/dist/types/src/internal/ast/annotation-helper.d.ts.map +1 -0
  45. package/dist/types/src/internal/ast/annotations.d.ts +131 -0
  46. package/dist/types/src/internal/ast/annotations.d.ts.map +1 -0
  47. package/dist/types/src/internal/ast/annotations.test.d.ts +2 -0
  48. package/dist/types/src/internal/ast/annotations.test.d.ts.map +1 -0
  49. package/dist/types/src/internal/ast/entity-kind.d.ts +10 -0
  50. package/dist/types/src/internal/ast/entity-kind.d.ts.map +1 -0
  51. package/dist/types/src/internal/ast/index.d.ts +5 -0
  52. package/dist/types/src/internal/ast/index.d.ts.map +1 -0
  53. package/dist/types/src/internal/ast/types.d.ts +6 -0
  54. package/dist/types/src/internal/ast/types.d.ts.map +1 -0
  55. package/dist/types/src/internal/formats/date.d.ts +63 -0
  56. package/dist/types/src/internal/formats/date.d.ts.map +1 -0
  57. package/dist/types/src/internal/formats/date.test.d.ts +2 -0
  58. package/dist/types/src/internal/formats/date.test.d.ts.map +1 -0
  59. package/dist/types/src/internal/formats/format.d.ts +30 -0
  60. package/dist/types/src/internal/formats/format.d.ts.map +1 -0
  61. package/dist/types/src/internal/formats/format.test.d.ts +2 -0
  62. package/dist/types/src/internal/formats/format.test.d.ts.map +1 -0
  63. package/dist/types/src/internal/formats/index.d.ts +8 -0
  64. package/dist/types/src/internal/formats/index.d.ts.map +1 -0
  65. package/dist/types/src/internal/formats/number.d.ts +31 -0
  66. package/dist/types/src/internal/formats/number.d.ts.map +1 -0
  67. package/dist/types/src/internal/formats/object.d.ts +35 -0
  68. package/dist/types/src/internal/formats/object.d.ts.map +1 -0
  69. package/dist/types/src/internal/formats/select.d.ts +11 -0
  70. package/dist/types/src/internal/formats/select.d.ts.map +1 -0
  71. package/dist/types/src/internal/formats/string.d.ts +38 -0
  72. package/dist/types/src/internal/formats/string.d.ts.map +1 -0
  73. package/dist/types/src/internal/formats/types.d.ts +68 -0
  74. package/dist/types/src/internal/formats/types.d.ts.map +1 -0
  75. package/dist/types/src/internal/index.d.ts +15 -0
  76. package/dist/types/src/internal/index.d.ts.map +1 -0
  77. package/dist/types/src/internal/json/annotations.d.ts +19 -0
  78. package/dist/types/src/internal/json/annotations.d.ts.map +1 -0
  79. package/dist/types/src/internal/json/effect-schema.test.d.ts +2 -0
  80. package/dist/types/src/internal/json/effect-schema.test.d.ts.map +1 -0
  81. package/dist/types/src/internal/json/index.d.ts +2 -0
  82. package/dist/types/src/internal/json/index.d.ts.map +1 -0
  83. package/dist/types/src/internal/json/json-schema.d.ts +28 -0
  84. package/dist/types/src/internal/json/json-schema.d.ts.map +1 -0
  85. package/dist/types/src/internal/json/json-schema.test.d.ts +2 -0
  86. package/dist/types/src/internal/json/json-schema.test.d.ts.map +1 -0
  87. package/dist/types/src/internal/json-schema/index.d.ts +3 -0
  88. package/dist/types/src/internal/json-schema/index.d.ts.map +1 -0
  89. package/dist/types/src/internal/json-schema/json-schema-normalize.d.ts +7 -0
  90. package/dist/types/src/internal/json-schema/json-schema-normalize.d.ts.map +1 -0
  91. package/dist/types/src/internal/json-schema/json-schema-type.d.ts +250 -0
  92. package/dist/types/src/internal/json-schema/json-schema-type.d.ts.map +1 -0
  93. package/dist/types/src/internal/object/accessors.d.ts +37 -0
  94. package/dist/types/src/internal/object/accessors.d.ts.map +1 -0
  95. package/dist/types/src/internal/object/common.d.ts +18 -0
  96. package/dist/types/src/internal/object/common.d.ts.map +1 -0
  97. package/dist/types/src/internal/object/create.d.ts +40 -0
  98. package/dist/types/src/internal/object/create.d.ts.map +1 -0
  99. package/dist/types/src/internal/object/create.test.d.ts +2 -0
  100. package/dist/types/src/internal/object/create.test.d.ts.map +1 -0
  101. package/dist/types/src/internal/object/deleted.d.ts +6 -0
  102. package/dist/types/src/internal/object/deleted.d.ts.map +1 -0
  103. package/dist/types/src/internal/object/entity.d.ts +33 -0
  104. package/dist/types/src/internal/object/entity.d.ts.map +1 -0
  105. package/dist/types/src/internal/object/expando.d.ts +14 -0
  106. package/dist/types/src/internal/object/expando.d.ts.map +1 -0
  107. package/dist/types/src/internal/object/ids.d.ts +6 -0
  108. package/dist/types/src/internal/object/ids.d.ts.map +1 -0
  109. package/dist/types/src/internal/object/index.d.ts +16 -0
  110. package/dist/types/src/internal/object/index.d.ts.map +1 -0
  111. package/dist/types/src/internal/object/inspect.d.ts +2 -0
  112. package/dist/types/src/internal/object/inspect.d.ts.map +1 -0
  113. package/dist/types/src/internal/object/json-serializer.d.ts +32 -0
  114. package/dist/types/src/internal/object/json-serializer.d.ts.map +1 -0
  115. package/dist/types/src/internal/object/json-serializer.test.d.ts +2 -0
  116. package/dist/types/src/internal/object/json-serializer.test.d.ts.map +1 -0
  117. package/dist/types/src/internal/object/meta.d.ts +31 -0
  118. package/dist/types/src/internal/object/meta.d.ts.map +1 -0
  119. package/dist/types/src/internal/object/model.d.ts +117 -0
  120. package/dist/types/src/internal/object/model.d.ts.map +1 -0
  121. package/dist/types/src/internal/object/relation.d.ts +17 -0
  122. package/dist/types/src/internal/object/relation.d.ts.map +1 -0
  123. package/dist/types/src/internal/object/schema-validator.d.ts +15 -0
  124. package/dist/types/src/internal/object/schema-validator.d.ts.map +1 -0
  125. package/dist/types/src/internal/object/schema-validator.test.d.ts +2 -0
  126. package/dist/types/src/internal/object/schema-validator.test.d.ts.map +1 -0
  127. package/dist/types/src/internal/object/typed-object.d.ts +31 -0
  128. package/dist/types/src/internal/object/typed-object.d.ts.map +1 -0
  129. package/dist/types/src/internal/object/typed-object.test.d.ts +2 -0
  130. package/dist/types/src/internal/object/typed-object.test.d.ts.map +1 -0
  131. package/dist/types/src/internal/object/typename.d.ts +15 -0
  132. package/dist/types/src/internal/object/typename.d.ts.map +1 -0
  133. package/dist/types/src/internal/object/version.d.ts +14 -0
  134. package/dist/types/src/internal/object/version.d.ts.map +1 -0
  135. package/dist/types/src/internal/projection/compose.d.ts +6 -0
  136. package/dist/types/src/internal/projection/compose.d.ts.map +1 -0
  137. package/dist/types/src/internal/projection/compose.test.d.ts +2 -0
  138. package/dist/types/src/internal/projection/compose.test.d.ts.map +1 -0
  139. package/dist/types/src/internal/projection/index.d.ts +2 -0
  140. package/dist/types/src/internal/projection/index.d.ts.map +1 -0
  141. package/dist/types/src/internal/proxy/handler.test.d.ts +2 -0
  142. package/dist/types/src/internal/proxy/handler.test.d.ts.map +1 -0
  143. package/dist/types/src/internal/proxy/reactive-object.d.ts +15 -0
  144. package/dist/types/src/internal/proxy/reactive-object.d.ts.map +1 -0
  145. package/dist/types/src/internal/proxy/schema.test.d.ts +2 -0
  146. package/dist/types/src/internal/proxy/schema.test.d.ts.map +1 -0
  147. package/dist/types/src/internal/proxy/typed-handler.d.ts +44 -0
  148. package/dist/types/src/internal/proxy/typed-handler.d.ts.map +1 -0
  149. package/dist/types/src/internal/proxy/typed-handler.test.d.ts +2 -0
  150. package/dist/types/src/internal/proxy/typed-handler.test.d.ts.map +1 -0
  151. package/dist/types/src/internal/proxy/typed-object.test.d.ts +2 -0
  152. package/dist/types/src/internal/proxy/typed-object.test.d.ts.map +1 -0
  153. package/dist/types/src/internal/query/index.d.ts +2 -0
  154. package/dist/types/src/internal/query/index.d.ts.map +1 -0
  155. package/dist/types/src/internal/query/query.d.ts +17 -0
  156. package/dist/types/src/internal/query/query.d.ts.map +1 -0
  157. package/dist/types/src/internal/ref/index.d.ts +3 -0
  158. package/dist/types/src/internal/ref/index.d.ts.map +1 -0
  159. package/dist/types/src/internal/ref/ref-array.d.ts +21 -0
  160. package/dist/types/src/internal/ref/ref-array.d.ts.map +1 -0
  161. package/dist/types/src/internal/ref/ref.d.ts +206 -0
  162. package/dist/types/src/internal/ref/ref.d.ts.map +1 -0
  163. package/dist/types/src/internal/ref/ref.test.d.ts +2 -0
  164. package/dist/types/src/internal/ref/ref.test.d.ts.map +1 -0
  165. package/dist/types/src/internal/schema/echo-schema.d.ts +168 -0
  166. package/dist/types/src/internal/schema/echo-schema.d.ts.map +1 -0
  167. package/dist/types/src/internal/schema/index.d.ts +7 -0
  168. package/dist/types/src/internal/schema/index.d.ts.map +1 -0
  169. package/dist/types/src/internal/schema/manipulation.d.ts +10 -0
  170. package/dist/types/src/internal/schema/manipulation.d.ts.map +1 -0
  171. package/dist/types/src/internal/schema/runtime-schema-registry.d.ts +18 -0
  172. package/dist/types/src/internal/schema/runtime-schema-registry.d.ts.map +1 -0
  173. package/dist/types/src/internal/schema/snapshot.d.ts +6 -0
  174. package/dist/types/src/internal/schema/snapshot.d.ts.map +1 -0
  175. package/dist/types/src/internal/schema/stored-schema.d.ts +13 -0
  176. package/dist/types/src/internal/schema/stored-schema.d.ts.map +1 -0
  177. package/dist/types/src/internal/testing/index.d.ts +3 -0
  178. package/dist/types/src/internal/testing/index.d.ts.map +1 -0
  179. package/dist/types/src/internal/testing/types.d.ts +381 -0
  180. package/dist/types/src/internal/testing/types.d.ts.map +1 -0
  181. package/dist/types/src/internal/testing/utils.d.ts +10 -0
  182. package/dist/types/src/internal/testing/utils.d.ts.map +1 -0
  183. package/dist/types/src/internal/types/index.d.ts +3 -0
  184. package/dist/types/src/internal/types/index.d.ts.map +1 -0
  185. package/dist/types/src/internal/types/types.d.ts +79 -0
  186. package/dist/types/src/internal/types/types.d.ts.map +1 -0
  187. package/dist/types/src/internal/types/types.test.d.ts +2 -0
  188. package/dist/types/src/internal/types/types.test.d.ts.map +1 -0
  189. package/dist/types/src/internal/types/util.d.ts +5 -0
  190. package/dist/types/src/internal/types/util.d.ts.map +1 -0
  191. package/dist/types/src/query/index.d.ts +1 -1
  192. package/dist/types/src/query/index.d.ts.map +1 -1
  193. package/dist/types/src/query/{dsl.d.ts → query.d.ts} +34 -24
  194. package/dist/types/src/query/query.d.ts.map +1 -0
  195. package/dist/types/src/query/query.test.d.ts +2 -0
  196. package/dist/types/src/query/query.test.d.ts.map +1 -0
  197. package/dist/types/src/testing/echo-schema.d.ts +7 -0
  198. package/dist/types/src/testing/echo-schema.d.ts.map +1 -0
  199. package/dist/types/src/testing/index.d.ts +2 -0
  200. package/dist/types/src/testing/index.d.ts.map +1 -1
  201. package/dist/types/src/testing/types.d.ts +170 -55
  202. package/dist/types/src/testing/types.d.ts.map +1 -1
  203. package/dist/types/tsconfig.tsbuildinfo +1 -1
  204. package/package.json +29 -17
  205. package/src/Obj.ts +98 -14
  206. package/src/Ref.ts +1 -2
  207. package/src/Relation.ts +15 -5
  208. package/src/Tag.ts +39 -0
  209. package/src/Type.ts +29 -30
  210. package/src/errors.ts +18 -0
  211. package/src/index.ts +5 -2
  212. package/src/internal/ast/annotation-helper.ts +22 -0
  213. package/src/internal/ast/annotations.test.ts +98 -0
  214. package/src/internal/ast/annotations.ts +226 -0
  215. package/src/internal/ast/entity-kind.ts +15 -0
  216. package/src/internal/ast/index.ts +8 -0
  217. package/src/internal/ast/types.ts +17 -0
  218. package/src/internal/formats/date.test.ts +56 -0
  219. package/src/internal/formats/date.ts +217 -0
  220. package/src/internal/formats/format.test.ts +77 -0
  221. package/src/internal/formats/format.ts +52 -0
  222. package/src/internal/formats/index.ts +12 -0
  223. package/src/internal/formats/number.ts +89 -0
  224. package/src/internal/formats/object.ts +80 -0
  225. package/src/internal/formats/select.ts +16 -0
  226. package/src/internal/formats/string.ts +76 -0
  227. package/src/internal/formats/types.ts +175 -0
  228. package/src/internal/index.ts +22 -0
  229. package/src/internal/json/annotations.ts +50 -0
  230. package/src/internal/json/effect-schema.test.ts +143 -0
  231. package/src/internal/json/index.ts +5 -0
  232. package/src/internal/json/json-schema.test.ts +849 -0
  233. package/src/internal/json/json-schema.ts +519 -0
  234. package/src/internal/json-schema/index.ts +6 -0
  235. package/src/internal/json-schema/json-schema-normalize.ts +109 -0
  236. package/src/internal/json-schema/json-schema-type.ts +403 -0
  237. package/src/internal/object/accessors.ts +153 -0
  238. package/src/internal/object/common.ts +76 -0
  239. package/src/internal/object/create.test.ts +118 -0
  240. package/src/internal/object/create.ts +96 -0
  241. package/src/internal/object/deleted.ts +19 -0
  242. package/src/internal/object/entity.ts +248 -0
  243. package/src/internal/object/expando.ts +21 -0
  244. package/src/internal/object/ids.ts +12 -0
  245. package/src/internal/object/index.ts +19 -0
  246. package/src/internal/object/inspect.ts +48 -0
  247. package/src/internal/object/json-serializer.test.ts +99 -0
  248. package/src/internal/object/json-serializer.ts +225 -0
  249. package/src/internal/object/meta.ts +61 -0
  250. package/src/internal/object/model.ts +170 -0
  251. package/src/internal/object/relation.ts +24 -0
  252. package/src/internal/object/schema-validator.test.ts +186 -0
  253. package/src/internal/object/schema-validator.ts +241 -0
  254. package/src/internal/object/typed-object.test.ts +34 -0
  255. package/src/internal/object/typed-object.ts +88 -0
  256. package/src/internal/object/typename.ts +61 -0
  257. package/src/internal/object/version.ts +22 -0
  258. package/src/internal/projection/compose.test.ts +43 -0
  259. package/src/internal/projection/compose.ts +36 -0
  260. package/src/internal/projection/index.ts +5 -0
  261. package/src/internal/proxy/handler.test.ts +163 -0
  262. package/src/internal/proxy/reactive-object.ts +108 -0
  263. package/src/internal/proxy/schema.test.ts +136 -0
  264. package/src/internal/proxy/typed-handler.test.ts +102 -0
  265. package/src/internal/proxy/typed-handler.ts +228 -0
  266. package/src/internal/proxy/typed-object.test.ts +100 -0
  267. package/src/internal/query/index.ts +5 -0
  268. package/src/internal/query/query.ts +23 -0
  269. package/src/internal/ref/index.ts +6 -0
  270. package/src/internal/ref/ref-array.ts +39 -0
  271. package/src/internal/ref/ref.test.ts +100 -0
  272. package/src/internal/ref/ref.ts +521 -0
  273. package/src/internal/schema/echo-schema.ts +383 -0
  274. package/src/internal/schema/index.ts +10 -0
  275. package/src/internal/schema/manipulation.ts +92 -0
  276. package/src/internal/schema/runtime-schema-registry.ts +78 -0
  277. package/src/internal/schema/snapshot.ts +25 -0
  278. package/src/internal/schema/stored-schema.ts +26 -0
  279. package/src/internal/testing/index.ts +6 -0
  280. package/src/internal/testing/types.ts +144 -0
  281. package/src/internal/testing/utils.ts +54 -0
  282. package/src/internal/types/index.ts +6 -0
  283. package/src/internal/types/types.test.ts +48 -0
  284. package/src/internal/types/types.ts +176 -0
  285. package/src/internal/types/util.ts +9 -0
  286. package/src/query/index.ts +2 -1
  287. package/src/query/query.test.ts +401 -0
  288. package/src/query/{dsl.ts → query.ts} +131 -46
  289. package/src/test/api.test.ts +9 -9
  290. package/src/testing/echo-schema.ts +39 -0
  291. package/src/testing/index.ts +2 -0
  292. package/src/testing/types.ts +40 -23
  293. package/dist/lib/browser/chunk-MTR3E5S2.mjs +0 -786
  294. package/dist/lib/browser/chunk-MTR3E5S2.mjs.map +0 -7
  295. package/dist/lib/node-esm/chunk-MYZLAJSR.mjs +0 -786
  296. package/dist/lib/node-esm/chunk-MYZLAJSR.mjs.map +0 -7
  297. package/dist/types/src/experimental/database.d.ts +0 -8
  298. package/dist/types/src/experimental/database.d.ts.map +0 -1
  299. package/dist/types/src/experimental/index.d.ts +0 -1
  300. package/dist/types/src/experimental/index.d.ts.map +0 -1
  301. package/dist/types/src/experimental/queue.d.ts +0 -8
  302. package/dist/types/src/experimental/queue.d.ts.map +0 -1
  303. package/dist/types/src/experimental/space.d.ts +0 -8
  304. package/dist/types/src/experimental/space.d.ts.map +0 -1
  305. package/dist/types/src/query/dsl.d.ts.map +0 -1
  306. package/dist/types/src/query/dsl.test.d.ts +0 -2
  307. package/dist/types/src/query/dsl.test.d.ts.map +0 -1
  308. package/src/experimental/database.ts +0 -11
  309. package/src/experimental/index.ts +0 -7
  310. package/src/experimental/queue.ts +0 -11
  311. package/src/experimental/space.ts +0 -11
  312. package/src/query/dsl.test.ts +0 -332
@@ -0,0 +1,849 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ import * as Option from 'effect/Option';
6
+ import * as Schema from 'effect/Schema';
7
+ import * as SchemaAST from 'effect/SchemaAST';
8
+ import { describe, expect, test } from 'vitest';
9
+
10
+ import { type JsonProp, findAnnotation } from '@dxos/effect';
11
+ import { ObjectId } from '@dxos/keys';
12
+ import { log } from '@dxos/log';
13
+
14
+ import { Type } from '../..';
15
+ import { Testing, prepareAstForCompare } from '../../testing';
16
+ import {
17
+ EntityKind,
18
+ FieldLookupAnnotationId,
19
+ GeneratorAnnotation,
20
+ LabelAnnotation,
21
+ PropertyMeta,
22
+ getTypeAnnotation,
23
+ getTypeIdentifierAnnotation,
24
+ } from '../ast';
25
+ import { Email, FormatAnnotation, FormatEnum } from '../formats';
26
+ import { JsonSchemaType, getNormalizedEchoAnnotations, getSchemaProperty, setSchemaProperty } from '../json-schema';
27
+ import { EchoObject } from '../object';
28
+ import { Ref, createSchemaReference, getReferenceAst, getSchemaReference } from '../ref';
29
+ import { StoredSchema } from '../schema';
30
+
31
+ import { toEffectSchema, toJsonSchema } from './json-schema';
32
+
33
+ const EXAMPLE_NAMESPACE = '@example';
34
+
35
+ describe('effect-to-json', () => {
36
+ test('type annotation', () => {
37
+ const Test = Schema.Struct({ name: Schema.String }).pipe(
38
+ Type.Obj({
39
+ typename: 'example.com/type/Test',
40
+ version: '0.1.0',
41
+ }),
42
+ );
43
+ const jsonSchema = toJsonSchema(Test);
44
+ expect((jsonSchema as any).$id).toEqual('dxn:type:example.com/type/Test');
45
+ expect((jsonSchema as any).version).toEqual('0.1.0');
46
+ });
47
+
48
+ test('property meta annotation', () => {
49
+ const meta = { maxLength: 0 };
50
+ const Test = Schema.Struct({
51
+ name: Schema.String.pipe(PropertyMeta(EXAMPLE_NAMESPACE, meta)),
52
+ }).pipe(
53
+ Type.Obj({
54
+ typename: 'example.com/type/Test',
55
+ version: '0.1.0',
56
+ }),
57
+ );
58
+ const jsonSchema = toJsonSchema(Test);
59
+ expect(getNormalizedEchoAnnotations(jsonSchema.properties!.name!)!.meta![EXAMPLE_NAMESPACE]).to.deep.eq(meta);
60
+ });
61
+
62
+ test('reference annotation', () => {
63
+ const Nested = Schema.Struct({
64
+ name: Schema.String,
65
+ }).pipe(
66
+ Type.Obj({
67
+ typename: 'example.com/type/TestNested',
68
+ version: '0.1.0',
69
+ }),
70
+ );
71
+ const Test = Schema.Struct({
72
+ name: Ref(Nested),
73
+ }).pipe(
74
+ Type.Obj({
75
+ typename: 'example.com/type/Test',
76
+ version: '0.1.0',
77
+ }),
78
+ );
79
+ const jsonSchema = toJsonSchema(Test);
80
+ // log.info('schema', { jsonSchema });
81
+ const nested = jsonSchema.properties!.name;
82
+ expectReferenceAnnotation(nested);
83
+ });
84
+
85
+ // TODO(ZaymonFC): @dmaretskyi we still need to fix this.
86
+ // TODO(dmaretskyi): Remove FieldLookupAnnotationId.
87
+ test.skip('reference annotation with lookup property', () => {
88
+ const Nested = Schema.Struct({
89
+ name: Schema.String,
90
+ }).pipe(
91
+ Type.Obj({
92
+ typename: 'example.com/type/TestNested',
93
+ version: '0.1.0',
94
+ }),
95
+ );
96
+ const Test = Schema.Struct({
97
+ name: Ref(Nested).annotations({ [FieldLookupAnnotationId]: 'name' }),
98
+ }).pipe(
99
+ Type.Obj({
100
+ typename: 'example.com/type/Test',
101
+ version: '0.1.0',
102
+ }),
103
+ );
104
+ const jsonSchema = toJsonSchema(Test);
105
+ const effectSchema = toEffectSchema(jsonSchema);
106
+
107
+ const annotation = findAnnotation<string>(effectSchema.ast, FieldLookupAnnotationId);
108
+ expect(annotation).to.not.toBeUndefined();
109
+ });
110
+
111
+ test('array of references', () => {
112
+ const Nested = Schema.Struct({
113
+ name: Schema.String,
114
+ }).pipe(
115
+ Type.Obj({
116
+ typename: 'example.com/type/TestNested',
117
+ version: '0.1.0',
118
+ }),
119
+ );
120
+ const Test = Schema.Struct({
121
+ name: Schema.Array(Ref(Nested)),
122
+ }).pipe(
123
+ Type.Obj({
124
+ typename: 'example.com/type/Test',
125
+ version: '0.1.0',
126
+ }),
127
+ );
128
+
129
+ const jsonSchema = toJsonSchema(Test);
130
+ expectReferenceAnnotation((jsonSchema.properties!.name as any).items);
131
+ });
132
+
133
+ test('optional references', () => {
134
+ const Nested = Schema.Struct({
135
+ name: Schema.String,
136
+ }).pipe(
137
+ Type.Obj({
138
+ typename: 'example.com/type/TestNested',
139
+ version: '0.1.0',
140
+ }),
141
+ );
142
+ const Test = Schema.Struct({
143
+ name: Schema.optional(Ref(Nested)),
144
+ }).pipe(
145
+ Type.Obj({
146
+ typename: 'example.com/type/Test',
147
+ version: '0.1.0',
148
+ }),
149
+ );
150
+ const jsonSchema = toJsonSchema(Test);
151
+ expectReferenceAnnotation(jsonSchema.properties!.name);
152
+ });
153
+
154
+ test('regular objects are not annotated', () => {
155
+ const object = Schema.Struct({ name: Schema.Struct({ name: Schema.String }) });
156
+ const jsonSchema = toJsonSchema(object);
157
+ expect(getNormalizedEchoAnnotations(jsonSchema)).to.be.undefined;
158
+ expect(getNormalizedEchoAnnotations(jsonSchema.properties!.name!)).to.be.undefined;
159
+ });
160
+
161
+ test('annotations', () => {
162
+ const TestSchema = Schema.Struct({
163
+ name: Schema.String.annotations({ description: 'Person name', title: 'Name' }),
164
+ email: Schema.String.pipe(FormatAnnotation.set(FormatEnum.Email)).annotations({
165
+ description: 'Email address',
166
+ }),
167
+ }).pipe(
168
+ Type.Obj({
169
+ typename: 'example.com/type/Person',
170
+ version: '0.1.0',
171
+ }),
172
+ );
173
+ const jsonSchema = toJsonSchema(TestSchema);
174
+ expect(jsonSchema).to.deep.eq({
175
+ $schema: 'http://json-schema.org/draft-07/schema#',
176
+ $id: 'dxn:type:example.com/type/Person',
177
+
178
+ entityKind: EntityKind.Object,
179
+ typename: 'example.com/type/Person',
180
+ version: '0.1.0',
181
+
182
+ type: 'object',
183
+ required: ['name', 'email', 'id'],
184
+ properties: {
185
+ id: { type: 'string' },
186
+ name: { type: 'string', title: 'Name', description: 'Person name' },
187
+ email: {
188
+ type: 'string',
189
+
190
+ description: 'Email address',
191
+ format: 'email',
192
+ },
193
+ },
194
+ propertyOrder: ['name', 'email', 'id'],
195
+ additionalProperties: false,
196
+ });
197
+ });
198
+
199
+ test('handles suspend -- Contact schema serialization', () => {
200
+ const schema = toJsonSchema(Testing.Person);
201
+ expect(Object.keys(schema.properties!)).toEqual(['id', 'name', 'username', 'email', 'tasks', 'address']);
202
+ });
203
+
204
+ test('reference property by ref', () => {
205
+ const Organization = Schema.Struct({
206
+ field: Schema.String,
207
+ }).pipe(
208
+ Type.Obj({
209
+ typename: 'example.com/type/Organization',
210
+ version: '0.1.0',
211
+ }),
212
+ );
213
+
214
+ const Contact = Schema.Struct({
215
+ name: Schema.String,
216
+ organization: Ref(Organization).annotations({ description: 'Contact organization' }),
217
+ }).pipe(
218
+ Type.Obj({
219
+ typename: 'example.com/type/Person',
220
+ version: '0.1.0',
221
+ }),
222
+ );
223
+
224
+ // log.info('Contact', { ast: Contact.ast });
225
+
226
+ const jsonSchema = toJsonSchema(Contact);
227
+ expect(jsonSchema).toEqual({
228
+ $schema: 'http://json-schema.org/draft-07/schema#',
229
+ $id: 'dxn:type:example.com/type/Person',
230
+
231
+ entityKind: EntityKind.Object,
232
+ typename: 'example.com/type/Person',
233
+ version: '0.1.0',
234
+
235
+ type: 'object',
236
+ additionalProperties: false,
237
+
238
+ properties: {
239
+ id: {
240
+ type: 'string',
241
+ },
242
+ name: {
243
+ type: 'string',
244
+ },
245
+ organization: {
246
+ allOf: [
247
+ {
248
+ $id: '/schemas/echo/ref',
249
+ $ref: '/schemas/echo/ref',
250
+ reference: {
251
+ schema: {
252
+ $ref: 'dxn:type:example.com/type/Organization',
253
+ },
254
+ schemaVersion: '0.1.0',
255
+ },
256
+ },
257
+ ],
258
+ description: 'Contact organization',
259
+ },
260
+ },
261
+ required: ['name', 'organization', 'id'],
262
+ propertyOrder: ['name', 'organization', 'id'],
263
+ });
264
+ });
265
+
266
+ test('add reference property', () => {
267
+ const Organization = Schema.Struct({
268
+ field: Schema.String,
269
+ }).pipe(
270
+ Type.Obj({
271
+ typename: 'example.com/type/Organization',
272
+ version: '0.1.0',
273
+ }),
274
+ );
275
+
276
+ const Contact = Schema.Struct({
277
+ name: Schema.String,
278
+ organization: Ref(Organization).annotations({ description: 'Contact organization' }),
279
+ }).pipe(
280
+ Type.Obj({
281
+ typename: 'example.com/type/Person',
282
+ version: '0.1.0',
283
+ }),
284
+ );
285
+
286
+ const jsonSchema = toJsonSchema(Contact);
287
+ setSchemaProperty(jsonSchema, 'organization' as JsonProp, createSchemaReference(Organization.typename));
288
+ const { typename } = getSchemaReference(getSchemaProperty(jsonSchema, 'organization' as JsonProp) ?? {}) ?? {};
289
+ expect(typename).to.eq(Organization.typename);
290
+ });
291
+
292
+ test('serialize circular schema (StoredSchema)', () => {
293
+ const jsonSchema = toJsonSchema(StoredSchema);
294
+ expect(Object.keys(jsonSchema.properties!).length).toBeGreaterThan(0);
295
+
296
+ // TODO(dmaretskyi): Currently unable to deserialize.
297
+ // const effectSchema = toEffectSchema(jsonSchema);
298
+ log('schema', { jsonSchema });
299
+ });
300
+
301
+ test('tuple schema with description', () => {
302
+ const schema = Schema.Struct({
303
+ args: Schema.Tuple(
304
+ Schema.String.annotations({ description: 'The source currency' }),
305
+ Schema.String.annotations({ description: 'The target currency' }),
306
+ ),
307
+ });
308
+ const jsonSchema = toJsonSchema(schema);
309
+ log('schema', { jsonSchema });
310
+
311
+ (Schema.asserts(JsonSchemaType) as any)(jsonSchema);
312
+ });
313
+
314
+ test('reference with title annotation', () => {
315
+ const schema = Schema.Struct({
316
+ contact: Ref(Testing.Person).annotations({ title: 'Custom Title' }),
317
+ });
318
+
319
+ // log.info('schema before', { ast: schema.ast });
320
+
321
+ const jsonSchema = toJsonSchema(schema);
322
+ // log.info('json schema', { jsonSchema });
323
+
324
+ const effectSchema = toEffectSchema(jsonSchema);
325
+ // log.info('effect schema', { ast: effectSchema.ast });
326
+
327
+ expect(
328
+ effectSchema.pipe(
329
+ Schema.pluck('contact'),
330
+ Schema.typeSchema,
331
+ (s) => s.ast,
332
+ SchemaAST.getAnnotation(SchemaAST.TitleAnnotationId),
333
+ Option.getOrUndefined,
334
+ ),
335
+ ).to.eq('Custom Title');
336
+ });
337
+
338
+ test('relation schema', () => {
339
+ const schema = Testing.HasManager;
340
+ const jsonSchema = toJsonSchema(schema);
341
+ expect(jsonSchema).toEqual({
342
+ $id: 'dxn:type:example.com/type/HasManager',
343
+ $schema: 'http://json-schema.org/draft-07/schema#',
344
+ entityKind: 'relation',
345
+ typename: 'example.com/type/HasManager',
346
+ version: '0.1.0',
347
+ relationSource: {
348
+ // TODO(dmaretskyi): Should those point to specific schema version?
349
+ $ref: 'dxn:type:example.com/type/Person',
350
+ },
351
+ relationTarget: {
352
+ // TODO(dmaretskyi): Should those point to specific schema version?
353
+ $ref: 'dxn:type:example.com/type/Person',
354
+ },
355
+ type: 'object',
356
+ properties: {
357
+ id: {
358
+ type: 'string',
359
+ },
360
+ since: {
361
+ type: 'string',
362
+ },
363
+ },
364
+ propertyOrder: ['since', 'id'],
365
+ required: ['id'],
366
+ additionalProperties: false,
367
+ });
368
+ });
369
+
370
+ test('label prop', () => {
371
+ const Organization = Schema.Struct({
372
+ id: ObjectId,
373
+ name: Schema.String,
374
+ }).pipe(
375
+ EchoObject({
376
+ typename: 'example.com/type/Organization',
377
+ version: '0.1.0',
378
+ }),
379
+ LabelAnnotation.set(['name']),
380
+ );
381
+
382
+ const jsonSchema = toJsonSchema(Organization);
383
+ expect(jsonSchema).toEqual({
384
+ $id: 'dxn:type:example.com/type/Organization',
385
+ $schema: 'http://json-schema.org/draft-07/schema#',
386
+ typename: 'example.com/type/Organization',
387
+ version: '0.1.0',
388
+ entityKind: 'object',
389
+ type: 'object',
390
+ properties: {
391
+ id: {
392
+ type: 'string',
393
+ pattern: '^[0-7][0-9A-HJKMNP-TV-Z]{25}$',
394
+ description: 'A Universally Unique Lexicographically Sortable Identifier',
395
+ },
396
+ name: {
397
+ type: 'string',
398
+ },
399
+ },
400
+ annotations: {
401
+ labelProp: ['name'],
402
+ },
403
+ propertyOrder: ['id', 'name'],
404
+ required: ['id', 'name'],
405
+ additionalProperties: false,
406
+ });
407
+ });
408
+
409
+ test('object id with description', () => {
410
+ const schema = Schema.Struct({
411
+ id: ObjectId.annotations({ description: 'The id' }),
412
+ });
413
+ // log.info('schema', { schema: ObjectId.ast });
414
+ const jsonSchema = toJsonSchema(schema);
415
+ expect(jsonSchema).toMatchInlineSnapshot(`
416
+ {
417
+ "$schema": "http://json-schema.org/draft-07/schema#",
418
+ "additionalProperties": false,
419
+ "properties": {
420
+ "id": {
421
+ "description": "The id",
422
+ "pattern": "^[0-7][0-9A-HJKMNP-TV-Z]{25}$",
423
+ "type": "string",
424
+ },
425
+ },
426
+ "propertyOrder": [
427
+ "id",
428
+ ],
429
+ "required": [
430
+ "id",
431
+ ],
432
+ "type": "object",
433
+ }
434
+ `);
435
+ });
436
+
437
+ test('email schema', () => {
438
+ const schema = Email;
439
+ const jsonSchema = toJsonSchema(schema);
440
+ expect(jsonSchema).toMatchInlineSnapshot(`
441
+ {
442
+ "$schema": "http://json-schema.org/draft-07/schema#",
443
+ "description": "Email address",
444
+ "format": "email",
445
+ "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
446
+ "title": "Email",
447
+ "type": "string",
448
+ }
449
+ `);
450
+ const effectSchema = toEffectSchema(jsonSchema);
451
+ expect(prepareAstForCompare(effectSchema.ast)).to.deep.eq(prepareAstForCompare(schema.ast));
452
+ });
453
+
454
+ const expectReferenceAnnotation = (object: JsonSchemaType) => {
455
+ expect(object.reference).to.deep.eq({
456
+ schema: {
457
+ $ref: 'dxn:type:example.com/type/TestNested',
458
+ },
459
+ schemaVersion: '0.1.0',
460
+ });
461
+ };
462
+ });
463
+
464
+ describe('json-to-effect', () => {
465
+ describe('field schema', () => {
466
+ test('email', () => {
467
+ const schema = Email;
468
+ expect(toJsonSchema(schema)).to.deep.eq({
469
+ $schema: 'http://json-schema.org/draft-07/schema#',
470
+ type: 'string',
471
+ format: 'email',
472
+ title: 'Email',
473
+ description: 'Email address',
474
+ // TODO(dmaretskyi): omit pattern.
475
+ pattern: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$',
476
+ });
477
+ });
478
+ });
479
+
480
+ for (const partial of [false, true]) {
481
+ test(`deserialized equals original ${partial ? 'with partial' : ''}`, () => {
482
+ const Organization = Schema.Struct({
483
+ field: Schema.String,
484
+ }).pipe(
485
+ Type.Obj({
486
+ typename: 'example.com/type/Organization',
487
+ version: '0.1.0',
488
+ }),
489
+ );
490
+
491
+ const fields = {
492
+ string: Schema.String,
493
+ number: Schema.Number.pipe(PropertyMeta(EXAMPLE_NAMESPACE, { is_date: true })),
494
+ boolean: Schema.Boolean,
495
+ array: Schema.Array(Schema.String),
496
+ twoDArray: Schema.Array(Schema.Array(Schema.String)),
497
+ record: Schema.Record({ key: Schema.String, value: Schema.Number }),
498
+ object: Schema.Struct({ id: Schema.String, field: Ref(Organization) }),
499
+ echoObject: Ref(Organization),
500
+ echoObjectArray: Schema.Array(Ref(Organization)),
501
+ email: Schema.String.pipe(FormatAnnotation.set(FormatEnum.Email)),
502
+ null: Schema.Null,
503
+ } as const;
504
+
505
+ const Test = (partial ? Schema.partial(Schema.Struct(fields)) : Schema.Struct(fields)).pipe(
506
+ Type.Obj({
507
+ typename: 'example.com/type/Test',
508
+ version: '0.1.0',
509
+ }),
510
+ );
511
+
512
+ const jsonSchema = toJsonSchema(Test);
513
+ // log.info('schema', { jsonSchema });
514
+
515
+ const schema = toEffectSchema(jsonSchema);
516
+
517
+ expect(() => expect(schema.ast).to.deep.eq(Test.ast)).to.throw();
518
+ expect(() => expect(prepareAstForCompare(Test.ast)).to.deep.eq(Test.ast)).to.throw();
519
+ expect(() => expect(schema.ast).to.deep.eq(prepareAstForCompare(Test.ast))).to.throw();
520
+ // log.info('', { original: prepareAstForCompare(Schema.ast), deserialized: prepareAstForCompare(schema.ast) });
521
+ expect(prepareAstForCompare(schema.ast)).to.deep.eq(prepareAstForCompare(Test.ast));
522
+
523
+ // TODO(dmaretskyi): Fix.
524
+ // expect(
525
+ // SchemaAST.getPropertySignatures(schema.ast).find((prop) => prop.name === 'email')!.type.annotations[
526
+ // FormatAnnotationId
527
+ // ],
528
+ // ).toEqual('email');
529
+ });
530
+ }
531
+
532
+ test('legacy schema with dxn:type $id gets decoded', () => {
533
+ const jsonSchema: JsonSchemaType = {
534
+ $id: 'dxn:type:example.com/type/Project',
535
+ $schema: 'http://json-schema.org/draft-07/schema#',
536
+ additionalProperties: false,
537
+ echo: {
538
+ type: {
539
+ schemaId: '01JERV1HQCQZDQ4NVCJ42QB38F',
540
+ typename: 'example.com/type/Project',
541
+ version: '0.1.0',
542
+ },
543
+ },
544
+ properties: {
545
+ description: {
546
+ type: 'string',
547
+ },
548
+ id: {
549
+ type: 'string',
550
+ },
551
+ name: {
552
+ echo: {
553
+ generator: 'commerce.productName',
554
+ },
555
+ type: 'string',
556
+ },
557
+ },
558
+ required: ['id'],
559
+ type: 'object',
560
+ version: '0.1.0',
561
+ };
562
+
563
+ const schema = toEffectSchema(jsonSchema);
564
+ expect(getTypeAnnotation(schema)).to.deep.eq({
565
+ kind: EntityKind.Object,
566
+ typename: 'example.com/type/Project',
567
+ version: '0.1.0',
568
+ });
569
+ expect(getTypeIdentifierAnnotation(schema)).to.deep.eq('dxn:echo:@:01JERV1HQCQZDQ4NVCJ42QB38F');
570
+ });
571
+
572
+ test('symbol annotations get compared', () => {
573
+ const schema1 = Schema.String.pipe(FormatAnnotation.set(FormatEnum.Email));
574
+ const schema2 = Schema.String.pipe(FormatAnnotation.set(FormatEnum.Currency));
575
+ expect(prepareAstForCompare(schema1.ast)).not.to.deep.eq(prepareAstForCompare(schema2.ast));
576
+ });
577
+
578
+ test('description gets preserved', () => {
579
+ const schema = Schema.Struct({
580
+ name: Schema.String.annotations({ description: 'Name' }),
581
+ });
582
+ const jsonSchema = toJsonSchema(schema);
583
+ const effectSchema = toEffectSchema(jsonSchema);
584
+ const jsonSchema2 = toJsonSchema(effectSchema);
585
+ expect(jsonSchema2.properties!.name.description).to.eq('Name');
586
+ });
587
+
588
+ test('relation schema roundtrip', () => {
589
+ const schema = Testing.HasManager;
590
+ const jsonSchema = toJsonSchema(schema);
591
+ const effectSchema = toEffectSchema(jsonSchema);
592
+ expect(prepareAstForCompare(effectSchema.ast)).to.deep.eq(prepareAstForCompare(schema.ast));
593
+ });
594
+
595
+ test('generator annotation', () => {
596
+ const schema = Schema.Struct({
597
+ name: Schema.String.pipe(GeneratorAnnotation.set('commerce.productName')),
598
+ });
599
+ const jsonSchema = toJsonSchema(schema);
600
+ expect(jsonSchema).toMatchInlineSnapshot(`
601
+ {
602
+ "$schema": "http://json-schema.org/draft-07/schema#",
603
+ "additionalProperties": false,
604
+ "properties": {
605
+ "name": {
606
+ "annotations": {
607
+ "generator": "commerce.productName",
608
+ },
609
+ "type": "string",
610
+ },
611
+ },
612
+ "propertyOrder": [
613
+ "name",
614
+ ],
615
+ "required": [
616
+ "name",
617
+ ],
618
+ "type": "object",
619
+ }
620
+ `);
621
+ });
622
+
623
+ // test('generator annotation on object', () => {
624
+ // const schema = Schema.Struct({
625
+ // });
626
+ // const jsonSchema = toJsonSchema(schema);
627
+ // expect(jsonSchema).toMatchInlineSnapshot();
628
+ // });
629
+
630
+ test('default annotation ', () => {
631
+ const schema = Schema.Struct({
632
+ str: Schema.String.annotations({
633
+ default: 'foo',
634
+ }),
635
+ arr: Schema.Array(Schema.String).annotations({
636
+ default: [],
637
+ }),
638
+ obj: Schema.Struct({
639
+ foo: Schema.optional(Schema.String).annotations({
640
+ default: 'bar',
641
+ }),
642
+ }),
643
+ });
644
+ const jsonSchema = toJsonSchema(schema);
645
+ expect(jsonSchema).toMatchInlineSnapshot(`
646
+ {
647
+ "$schema": "http://json-schema.org/draft-07/schema#",
648
+ "additionalProperties": false,
649
+ "properties": {
650
+ "arr": {
651
+ "default": [],
652
+ "items": {
653
+ "type": "string",
654
+ },
655
+ "type": "array",
656
+ },
657
+ "obj": {
658
+ "additionalProperties": false,
659
+ "properties": {
660
+ "foo": {
661
+ "default": "bar",
662
+ "type": "string",
663
+ },
664
+ },
665
+ "propertyOrder": [
666
+ "foo",
667
+ ],
668
+ "required": [],
669
+ "type": "object",
670
+ },
671
+ "str": {
672
+ "default": "foo",
673
+ "type": "string",
674
+ },
675
+ },
676
+ "propertyOrder": [
677
+ "str",
678
+ "arr",
679
+ "obj",
680
+ ],
681
+ "required": [
682
+ "str",
683
+ "arr",
684
+ "obj",
685
+ ],
686
+ "type": "object",
687
+ }
688
+ `);
689
+ });
690
+
691
+ test('schema with optional referece', () => {
692
+ const TestSchema = Schema.Struct({
693
+ contact: Schema.optional(Ref(Testing.Person)),
694
+ });
695
+ const jsonSchema = toJsonSchema(TestSchema);
696
+ expect(jsonSchema).toMatchInlineSnapshot(`
697
+ {
698
+ "$schema": "http://json-schema.org/draft-07/schema#",
699
+ "additionalProperties": false,
700
+ "properties": {
701
+ "contact": {
702
+ "$id": "/schemas/echo/ref",
703
+ "$ref": "/schemas/echo/ref",
704
+ "reference": {
705
+ "schema": {
706
+ "$ref": "dxn:type:example.com/type/Person",
707
+ },
708
+ "schemaVersion": "0.1.0",
709
+ },
710
+ },
711
+ },
712
+ "propertyOrder": [
713
+ "contact",
714
+ ],
715
+ "required": [],
716
+ "type": "object",
717
+ }
718
+ `);
719
+
720
+ const effectSchema = toEffectSchema(jsonSchema);
721
+ expect(prepareAstForCompare(effectSchema.ast)).to.deep.eq(prepareAstForCompare(TestSchema.ast));
722
+ });
723
+
724
+ test('object nested inside another struct', () => {
725
+ const Contact = Schema.Struct({
726
+ name: Schema.String,
727
+ }).pipe(EchoObject({ typename: 'example.com/type/Person', version: '0.1.0' }));
728
+ const input = Schema.Struct({
729
+ contact: Contact,
730
+ });
731
+ const jsonSchema = toJsonSchema(input);
732
+ expect(jsonSchema).toMatchInlineSnapshot(`
733
+ {
734
+ "$schema": "http://json-schema.org/draft-07/schema#",
735
+ "additionalProperties": false,
736
+ "properties": {
737
+ "contact": {
738
+ "$id": "dxn:type:example.com/type/Person",
739
+ "additionalProperties": false,
740
+ "entityKind": "object",
741
+ "properties": {
742
+ "id": {
743
+ "type": "string",
744
+ },
745
+ "name": {
746
+ "type": "string",
747
+ },
748
+ },
749
+ "propertyOrder": [
750
+ "name",
751
+ "id",
752
+ ],
753
+ "required": [
754
+ "name",
755
+ "id",
756
+ ],
757
+ "type": "object",
758
+ "typename": "example.com/type/Person",
759
+ "version": "0.1.0",
760
+ },
761
+ },
762
+ "propertyOrder": [
763
+ "contact",
764
+ ],
765
+ "required": [
766
+ "contact",
767
+ ],
768
+ "type": "object",
769
+ }
770
+ `);
771
+
772
+ const effectSchema = toEffectSchema(jsonSchema);
773
+ expect(prepareAstForCompare(effectSchema.ast)).to.deep.eq(prepareAstForCompare(input.ast));
774
+ });
775
+ });
776
+
777
+ describe('reference', () => {
778
+ test('reference annotation', () => {
779
+ const schema = Ref(Testing.Person);
780
+ const jsonSchema = toJsonSchema(schema);
781
+ expect(jsonSchema).toEqual({
782
+ $id: '/schemas/echo/ref',
783
+ $ref: '/schemas/echo/ref',
784
+ $schema: 'http://json-schema.org/draft-07/schema#',
785
+ reference: {
786
+ schema: {
787
+ $ref: 'dxn:type:example.com/type/Person',
788
+ },
789
+ schemaVersion: '0.1.0',
790
+ },
791
+ });
792
+ });
793
+
794
+ test('title annotation', () => {
795
+ const schema = Ref(Testing.Person).annotations({ title: 'My custom title' });
796
+ const jsonSchema = toJsonSchema(schema);
797
+ expect(jsonSchema).toEqual({
798
+ $schema: 'http://json-schema.org/draft-07/schema#',
799
+ allOf: [
800
+ {
801
+ $id: '/schemas/echo/ref',
802
+ $ref: '/schemas/echo/ref',
803
+ reference: {
804
+ schema: {
805
+ $ref: 'dxn:type:example.com/type/Person',
806
+ },
807
+ schemaVersion: '0.1.0',
808
+ },
809
+ },
810
+ ],
811
+ title: 'My custom title',
812
+ });
813
+ });
814
+
815
+ test('description annotation', () => {
816
+ const schema = Ref(Testing.Person).annotations({ description: 'My custom description' });
817
+ const jsonSchema = toJsonSchema(schema);
818
+ expect(jsonSchema).toEqual({
819
+ $schema: 'http://json-schema.org/draft-07/schema#',
820
+ allOf: [
821
+ {
822
+ $id: '/schemas/echo/ref',
823
+ $ref: '/schemas/echo/ref',
824
+ reference: {
825
+ schema: {
826
+ $ref: 'dxn:type:example.com/type/Person',
827
+ },
828
+ schemaVersion: '0.1.0',
829
+ },
830
+ },
831
+ ],
832
+ description: 'My custom description',
833
+ });
834
+
835
+ const effectSchema = toEffectSchema(jsonSchema);
836
+ expect(prepareAstForCompare(effectSchema.ast)).to.deep.eq(prepareAstForCompare(schema.ast));
837
+ });
838
+
839
+ test('serialize and deserialize', () => {
840
+ const schema = Ref(Testing.Person);
841
+ const jsonSchema = toJsonSchema(schema);
842
+ const deserializedSchema = toEffectSchema(jsonSchema);
843
+ const refAst = getReferenceAst(deserializedSchema.ast);
844
+ expect(refAst).toEqual({
845
+ typename: Testing.Person.typename,
846
+ version: Testing.Person.version,
847
+ });
848
+ });
849
+ });