@proseql/core 0.1.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 (342) hide show
  1. package/LICENSE +21 -0
  2. package/dist/errors/crud-errors.d.ts +98 -0
  3. package/dist/errors/crud-errors.d.ts.map +1 -0
  4. package/dist/errors/crud-errors.js +23 -0
  5. package/dist/errors/crud-errors.js.map +1 -0
  6. package/dist/errors/index.d.ts +16 -0
  7. package/dist/errors/index.d.ts.map +1 -0
  8. package/dist/errors/index.js +12 -0
  9. package/dist/errors/index.js.map +1 -0
  10. package/dist/errors/migration-errors.d.ts +22 -0
  11. package/dist/errors/migration-errors.d.ts.map +1 -0
  12. package/dist/errors/migration-errors.js +14 -0
  13. package/dist/errors/migration-errors.js.map +1 -0
  14. package/dist/errors/plugin-errors.d.ts +15 -0
  15. package/dist/errors/plugin-errors.d.ts.map +1 -0
  16. package/dist/errors/plugin-errors.js +11 -0
  17. package/dist/errors/plugin-errors.js.map +1 -0
  18. package/dist/errors/query-errors.d.ts +31 -0
  19. package/dist/errors/query-errors.d.ts.map +1 -0
  20. package/dist/errors/query-errors.js +11 -0
  21. package/dist/errors/query-errors.js.map +1 -0
  22. package/dist/errors/storage-errors.d.ts +30 -0
  23. package/dist/errors/storage-errors.d.ts.map +1 -0
  24. package/dist/errors/storage-errors.js +11 -0
  25. package/dist/errors/storage-errors.js.map +1 -0
  26. package/dist/factories/crud-factory-with-relationships.d.ts +28 -0
  27. package/dist/factories/crud-factory-with-relationships.d.ts.map +1 -0
  28. package/dist/factories/crud-factory-with-relationships.js +8 -0
  29. package/dist/factories/crud-factory-with-relationships.js.map +1 -0
  30. package/dist/factories/crud-factory.d.ts +25 -0
  31. package/dist/factories/crud-factory.d.ts.map +1 -0
  32. package/dist/factories/crud-factory.js +8 -0
  33. package/dist/factories/crud-factory.js.map +1 -0
  34. package/dist/factories/database-effect.d.ts +241 -0
  35. package/dist/factories/database-effect.d.ts.map +1 -0
  36. package/dist/factories/database-effect.js +859 -0
  37. package/dist/factories/database-effect.js.map +1 -0
  38. package/dist/hooks/hook-runner.d.ts +60 -0
  39. package/dist/hooks/hook-runner.d.ts.map +1 -0
  40. package/dist/hooks/hook-runner.js +107 -0
  41. package/dist/hooks/hook-runner.js.map +1 -0
  42. package/dist/index.d.ts +84 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +110 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/indexes/index-lookup.d.ts +33 -0
  47. package/dist/indexes/index-lookup.d.ts.map +1 -0
  48. package/dist/indexes/index-lookup.js +180 -0
  49. package/dist/indexes/index-lookup.js.map +1 -0
  50. package/dist/indexes/index-manager.d.ts +118 -0
  51. package/dist/indexes/index-manager.d.ts.map +1 -0
  52. package/dist/indexes/index-manager.js +345 -0
  53. package/dist/indexes/index-manager.js.map +1 -0
  54. package/dist/indexes/search-index.d.ts +179 -0
  55. package/dist/indexes/search-index.d.ts.map +1 -0
  56. package/dist/indexes/search-index.js +405 -0
  57. package/dist/indexes/search-index.js.map +1 -0
  58. package/dist/migrations/migration-runner.d.ts +70 -0
  59. package/dist/migrations/migration-runner.d.ts.map +1 -0
  60. package/dist/migrations/migration-runner.js +271 -0
  61. package/dist/migrations/migration-runner.js.map +1 -0
  62. package/dist/migrations/migration-types.d.ts +63 -0
  63. package/dist/migrations/migration-types.d.ts.map +1 -0
  64. package/dist/migrations/migration-types.js +5 -0
  65. package/dist/migrations/migration-types.js.map +1 -0
  66. package/dist/operations/crud/create-with-relationships.d.ts +44 -0
  67. package/dist/operations/crud/create-with-relationships.d.ts.map +1 -0
  68. package/dist/operations/crud/create-with-relationships.js +483 -0
  69. package/dist/operations/crud/create-with-relationships.js.map +1 -0
  70. package/dist/operations/crud/create.d.ts +48 -0
  71. package/dist/operations/crud/create.d.ts.map +1 -0
  72. package/dist/operations/crud/create.js +333 -0
  73. package/dist/operations/crud/create.js.map +1 -0
  74. package/dist/operations/crud/delete-with-relationships.d.ts +63 -0
  75. package/dist/operations/crud/delete-with-relationships.d.ts.map +1 -0
  76. package/dist/operations/crud/delete-with-relationships.js +395 -0
  77. package/dist/operations/crud/delete-with-relationships.js.map +1 -0
  78. package/dist/operations/crud/delete.d.ts +58 -0
  79. package/dist/operations/crud/delete.d.ts.map +1 -0
  80. package/dist/operations/crud/delete.js +267 -0
  81. package/dist/operations/crud/delete.js.map +1 -0
  82. package/dist/operations/crud/unique-check.d.ts +114 -0
  83. package/dist/operations/crud/unique-check.d.ts.map +1 -0
  84. package/dist/operations/crud/unique-check.js +383 -0
  85. package/dist/operations/crud/unique-check.js.map +1 -0
  86. package/dist/operations/crud/update-with-relationships.d.ts +45 -0
  87. package/dist/operations/crud/update-with-relationships.d.ts.map +1 -0
  88. package/dist/operations/crud/update-with-relationships.js +516 -0
  89. package/dist/operations/crud/update-with-relationships.js.map +1 -0
  90. package/dist/operations/crud/update.d.ts +91 -0
  91. package/dist/operations/crud/update.d.ts.map +1 -0
  92. package/dist/operations/crud/update.js +505 -0
  93. package/dist/operations/crud/update.js.map +1 -0
  94. package/dist/operations/crud/upsert.d.ts +52 -0
  95. package/dist/operations/crud/upsert.d.ts.map +1 -0
  96. package/dist/operations/crud/upsert.js +386 -0
  97. package/dist/operations/crud/upsert.js.map +1 -0
  98. package/dist/operations/query/aggregate.d.ts +30 -0
  99. package/dist/operations/query/aggregate.d.ts.map +1 -0
  100. package/dist/operations/query/aggregate.js +227 -0
  101. package/dist/operations/query/aggregate.js.map +1 -0
  102. package/dist/operations/query/cursor-stream.d.ts +18 -0
  103. package/dist/operations/query/cursor-stream.d.ts.map +1 -0
  104. package/dist/operations/query/cursor-stream.js +199 -0
  105. package/dist/operations/query/cursor-stream.js.map +1 -0
  106. package/dist/operations/query/filter-stream.d.ts +12 -0
  107. package/dist/operations/query/filter-stream.d.ts.map +1 -0
  108. package/dist/operations/query/filter-stream.js +167 -0
  109. package/dist/operations/query/filter-stream.js.map +1 -0
  110. package/dist/operations/query/filter.d.ts +13 -0
  111. package/dist/operations/query/filter.d.ts.map +1 -0
  112. package/dist/operations/query/filter.js +267 -0
  113. package/dist/operations/query/filter.js.map +1 -0
  114. package/dist/operations/query/paginate-stream.d.ts +11 -0
  115. package/dist/operations/query/paginate-stream.d.ts.map +1 -0
  116. package/dist/operations/query/paginate-stream.js +22 -0
  117. package/dist/operations/query/paginate-stream.js.map +1 -0
  118. package/dist/operations/query/query-helpers.d.ts +14 -0
  119. package/dist/operations/query/query-helpers.d.ts.map +1 -0
  120. package/dist/operations/query/query-helpers.js +22 -0
  121. package/dist/operations/query/query-helpers.js.map +1 -0
  122. package/dist/operations/query/resolve-computed.d.ts +142 -0
  123. package/dist/operations/query/resolve-computed.d.ts.map +1 -0
  124. package/dist/operations/query/resolve-computed.js +197 -0
  125. package/dist/operations/query/resolve-computed.js.map +1 -0
  126. package/dist/operations/query/search.d.ts +110 -0
  127. package/dist/operations/query/search.d.ts.map +1 -0
  128. package/dist/operations/query/search.js +188 -0
  129. package/dist/operations/query/search.js.map +1 -0
  130. package/dist/operations/query/select-stream.d.ts +27 -0
  131. package/dist/operations/query/select-stream.d.ts.map +1 -0
  132. package/dist/operations/query/select-stream.js +88 -0
  133. package/dist/operations/query/select-stream.js.map +1 -0
  134. package/dist/operations/query/select.d.ts +54 -0
  135. package/dist/operations/query/select.d.ts.map +1 -0
  136. package/dist/operations/query/select.js +159 -0
  137. package/dist/operations/query/select.js.map +1 -0
  138. package/dist/operations/query/sort-stream.d.ts +46 -0
  139. package/dist/operations/query/sort-stream.d.ts.map +1 -0
  140. package/dist/operations/query/sort-stream.js +158 -0
  141. package/dist/operations/query/sort-stream.js.map +1 -0
  142. package/dist/operations/query/sort.d.ts +9 -0
  143. package/dist/operations/query/sort.d.ts.map +1 -0
  144. package/dist/operations/query/sort.js +58 -0
  145. package/dist/operations/query/sort.js.map +1 -0
  146. package/dist/operations/relationships/populate-stream.d.ts +29 -0
  147. package/dist/operations/relationships/populate-stream.d.ts.map +1 -0
  148. package/dist/operations/relationships/populate-stream.js +159 -0
  149. package/dist/operations/relationships/populate-stream.js.map +1 -0
  150. package/dist/operations/relationships/populate.d.ts +15 -0
  151. package/dist/operations/relationships/populate.d.ts.map +1 -0
  152. package/dist/operations/relationships/populate.js +228 -0
  153. package/dist/operations/relationships/populate.js.map +1 -0
  154. package/dist/plugins/plugin-hooks.d.ts +25 -0
  155. package/dist/plugins/plugin-hooks.d.ts.map +1 -0
  156. package/dist/plugins/plugin-hooks.js +64 -0
  157. package/dist/plugins/plugin-hooks.js.map +1 -0
  158. package/dist/plugins/plugin-registry.d.ts +26 -0
  159. package/dist/plugins/plugin-registry.d.ts.map +1 -0
  160. package/dist/plugins/plugin-registry.js +150 -0
  161. package/dist/plugins/plugin-registry.js.map +1 -0
  162. package/dist/plugins/plugin-types.d.ts +95 -0
  163. package/dist/plugins/plugin-types.d.ts.map +1 -0
  164. package/dist/plugins/plugin-types.js +6 -0
  165. package/dist/plugins/plugin-types.js.map +1 -0
  166. package/dist/plugins/plugin-validation.d.ts +49 -0
  167. package/dist/plugins/plugin-validation.d.ts.map +1 -0
  168. package/dist/plugins/plugin-validation.js +295 -0
  169. package/dist/plugins/plugin-validation.js.map +1 -0
  170. package/dist/reactive/change-event.d.ts +44 -0
  171. package/dist/reactive/change-event.d.ts.map +1 -0
  172. package/dist/reactive/change-event.js +49 -0
  173. package/dist/reactive/change-event.js.map +1 -0
  174. package/dist/reactive/change-pubsub.d.ts +32 -0
  175. package/dist/reactive/change-pubsub.d.ts.map +1 -0
  176. package/dist/reactive/change-pubsub.js +31 -0
  177. package/dist/reactive/change-pubsub.js.map +1 -0
  178. package/dist/reactive/evaluate-query.d.ts +62 -0
  179. package/dist/reactive/evaluate-query.d.ts.map +1 -0
  180. package/dist/reactive/evaluate-query.js +57 -0
  181. package/dist/reactive/evaluate-query.js.map +1 -0
  182. package/dist/reactive/watch-by-id.d.ts +53 -0
  183. package/dist/reactive/watch-by-id.d.ts.map +1 -0
  184. package/dist/reactive/watch-by-id.js +55 -0
  185. package/dist/reactive/watch-by-id.js.map +1 -0
  186. package/dist/reactive/watch.d.ts +78 -0
  187. package/dist/reactive/watch.d.ts.map +1 -0
  188. package/dist/reactive/watch.js +133 -0
  189. package/dist/reactive/watch.js.map +1 -0
  190. package/dist/serializers/codecs/hjson.d.ts +33 -0
  191. package/dist/serializers/codecs/hjson.d.ts.map +1 -0
  192. package/dist/serializers/codecs/hjson.js +40 -0
  193. package/dist/serializers/codecs/hjson.js.map +1 -0
  194. package/dist/serializers/codecs/json.d.ts +22 -0
  195. package/dist/serializers/codecs/json.d.ts.map +1 -0
  196. package/dist/serializers/codecs/json.js +28 -0
  197. package/dist/serializers/codecs/json.js.map +1 -0
  198. package/dist/serializers/codecs/json5.d.ts +26 -0
  199. package/dist/serializers/codecs/json5.d.ts.map +1 -0
  200. package/dist/serializers/codecs/json5.js +33 -0
  201. package/dist/serializers/codecs/json5.js.map +1 -0
  202. package/dist/serializers/codecs/jsonc.d.ts +29 -0
  203. package/dist/serializers/codecs/jsonc.d.ts.map +1 -0
  204. package/dist/serializers/codecs/jsonc.js +38 -0
  205. package/dist/serializers/codecs/jsonc.js.map +1 -0
  206. package/dist/serializers/codecs/jsonl.d.ts +17 -0
  207. package/dist/serializers/codecs/jsonl.d.ts.map +1 -0
  208. package/dist/serializers/codecs/jsonl.js +31 -0
  209. package/dist/serializers/codecs/jsonl.js.map +1 -0
  210. package/dist/serializers/codecs/prose.d.ts +419 -0
  211. package/dist/serializers/codecs/prose.d.ts.map +1 -0
  212. package/dist/serializers/codecs/prose.js +1060 -0
  213. package/dist/serializers/codecs/prose.js.map +1 -0
  214. package/dist/serializers/codecs/toml.d.ts +23 -0
  215. package/dist/serializers/codecs/toml.d.ts.map +1 -0
  216. package/dist/serializers/codecs/toml.js +66 -0
  217. package/dist/serializers/codecs/toml.js.map +1 -0
  218. package/dist/serializers/codecs/toon.d.ts +20 -0
  219. package/dist/serializers/codecs/toon.d.ts.map +1 -0
  220. package/dist/serializers/codecs/toon.js +33 -0
  221. package/dist/serializers/codecs/toon.js.map +1 -0
  222. package/dist/serializers/codecs/yaml.d.ts +24 -0
  223. package/dist/serializers/codecs/yaml.d.ts.map +1 -0
  224. package/dist/serializers/codecs/yaml.js +31 -0
  225. package/dist/serializers/codecs/yaml.js.map +1 -0
  226. package/dist/serializers/format-codec.d.ts +53 -0
  227. package/dist/serializers/format-codec.d.ts.map +1 -0
  228. package/dist/serializers/format-codec.js +148 -0
  229. package/dist/serializers/format-codec.js.map +1 -0
  230. package/dist/serializers/presets.d.ts +48 -0
  231. package/dist/serializers/presets.d.ts.map +1 -0
  232. package/dist/serializers/presets.js +72 -0
  233. package/dist/serializers/presets.js.map +1 -0
  234. package/dist/serializers/serializer-service.d.ts +11 -0
  235. package/dist/serializers/serializer-service.d.ts.map +1 -0
  236. package/dist/serializers/serializer-service.js +4 -0
  237. package/dist/serializers/serializer-service.js.map +1 -0
  238. package/dist/state/collection-state.d.ts +19 -0
  239. package/dist/state/collection-state.d.ts.map +1 -0
  240. package/dist/state/collection-state.js +15 -0
  241. package/dist/state/collection-state.js.map +1 -0
  242. package/dist/state/state-operations.d.ts +38 -0
  243. package/dist/state/state-operations.d.ts.map +1 -0
  244. package/dist/state/state-operations.js +65 -0
  245. package/dist/state/state-operations.js.map +1 -0
  246. package/dist/storage/in-memory-adapter-layer.d.ts +16 -0
  247. package/dist/storage/in-memory-adapter-layer.d.ts.map +1 -0
  248. package/dist/storage/in-memory-adapter-layer.js +81 -0
  249. package/dist/storage/in-memory-adapter-layer.js.map +1 -0
  250. package/dist/storage/persistence-effect.d.ts +244 -0
  251. package/dist/storage/persistence-effect.d.ts.map +1 -0
  252. package/dist/storage/persistence-effect.js +551 -0
  253. package/dist/storage/persistence-effect.js.map +1 -0
  254. package/dist/storage/storage-service.d.ts +22 -0
  255. package/dist/storage/storage-service.d.ts.map +1 -0
  256. package/dist/storage/storage-service.js +4 -0
  257. package/dist/storage/storage-service.js.map +1 -0
  258. package/dist/storage/transforms.d.ts +183 -0
  259. package/dist/storage/transforms.d.ts.map +1 -0
  260. package/dist/storage/transforms.js +263 -0
  261. package/dist/storage/transforms.js.map +1 -0
  262. package/dist/transactions/transaction.d.ts +87 -0
  263. package/dist/transactions/transaction.d.ts.map +1 -0
  264. package/dist/transactions/transaction.js +240 -0
  265. package/dist/transactions/transaction.js.map +1 -0
  266. package/dist/types/aggregate-types.d.ts +73 -0
  267. package/dist/types/aggregate-types.d.ts.map +1 -0
  268. package/dist/types/aggregate-types.js +14 -0
  269. package/dist/types/aggregate-types.js.map +1 -0
  270. package/dist/types/computed-types.d.ts +71 -0
  271. package/dist/types/computed-types.d.ts.map +1 -0
  272. package/dist/types/computed-types.js +8 -0
  273. package/dist/types/computed-types.js.map +1 -0
  274. package/dist/types/crud-relationship-types.d.ts +180 -0
  275. package/dist/types/crud-relationship-types.d.ts.map +1 -0
  276. package/dist/types/crud-relationship-types.js +17 -0
  277. package/dist/types/crud-relationship-types.js.map +1 -0
  278. package/dist/types/crud-types.d.ts +343 -0
  279. package/dist/types/crud-types.d.ts.map +1 -0
  280. package/dist/types/crud-types.js +43 -0
  281. package/dist/types/crud-types.js.map +1 -0
  282. package/dist/types/cursor-types.d.ts +52 -0
  283. package/dist/types/cursor-types.d.ts.map +1 -0
  284. package/dist/types/cursor-types.js +2 -0
  285. package/dist/types/cursor-types.js.map +1 -0
  286. package/dist/types/database-config-types.d.ts +196 -0
  287. package/dist/types/database-config-types.d.ts.map +1 -0
  288. package/dist/types/database-config-types.js +11 -0
  289. package/dist/types/database-config-types.js.map +1 -0
  290. package/dist/types/hook-types.d.ts +158 -0
  291. package/dist/types/hook-types.d.ts.map +1 -0
  292. package/dist/types/hook-types.js +6 -0
  293. package/dist/types/hook-types.js.map +1 -0
  294. package/dist/types/index-types.d.ts +42 -0
  295. package/dist/types/index-types.d.ts.map +1 -0
  296. package/dist/types/index-types.js +8 -0
  297. package/dist/types/index-types.js.map +1 -0
  298. package/dist/types/operators.d.ts +5 -0
  299. package/dist/types/operators.d.ts.map +1 -0
  300. package/dist/types/operators.js +297 -0
  301. package/dist/types/operators.js.map +1 -0
  302. package/dist/types/query-overloads.d.ts +54 -0
  303. package/dist/types/query-overloads.d.ts.map +1 -0
  304. package/dist/types/query-overloads.js +3 -0
  305. package/dist/types/query-overloads.js.map +1 -0
  306. package/dist/types/reactive-types.d.ts +75 -0
  307. package/dist/types/reactive-types.d.ts.map +1 -0
  308. package/dist/types/reactive-types.js +7 -0
  309. package/dist/types/reactive-types.js.map +1 -0
  310. package/dist/types/schema-types.d.ts +56 -0
  311. package/dist/types/schema-types.d.ts.map +1 -0
  312. package/dist/types/schema-types.js +8 -0
  313. package/dist/types/schema-types.js.map +1 -0
  314. package/dist/types/search-types.d.ts +82 -0
  315. package/dist/types/search-types.d.ts.map +1 -0
  316. package/dist/types/search-types.js +110 -0
  317. package/dist/types/search-types.js.map +1 -0
  318. package/dist/types/types.d.ts +286 -0
  319. package/dist/types/types.d.ts.map +1 -0
  320. package/dist/types/types.js +2 -0
  321. package/dist/types/types.js.map +1 -0
  322. package/dist/utils/id-generator.d.ts +97 -0
  323. package/dist/utils/id-generator.d.ts.map +1 -0
  324. package/dist/utils/id-generator.js +247 -0
  325. package/dist/utils/id-generator.js.map +1 -0
  326. package/dist/utils/nested-path.d.ts +56 -0
  327. package/dist/utils/nested-path.d.ts.map +1 -0
  328. package/dist/utils/nested-path.js +119 -0
  329. package/dist/utils/nested-path.js.map +1 -0
  330. package/dist/utils/path.d.ts +16 -0
  331. package/dist/utils/path.d.ts.map +1 -0
  332. package/dist/utils/path.js +24 -0
  333. package/dist/utils/path.js.map +1 -0
  334. package/dist/validators/foreign-key.d.ts +49 -0
  335. package/dist/validators/foreign-key.d.ts.map +1 -0
  336. package/dist/validators/foreign-key.js +153 -0
  337. package/dist/validators/foreign-key.js.map +1 -0
  338. package/dist/validators/schema-validator.d.ts +19 -0
  339. package/dist/validators/schema-validator.d.ts.map +1 -0
  340. package/dist/validators/schema-validator.js +34 -0
  341. package/dist/validators/schema-validator.js.map +1 -0
  342. package/package.json +57 -0
@@ -0,0 +1,516 @@
1
+ /**
2
+ * Effect-based update operations with relationship support.
3
+ *
4
+ * Uses Ref<ReadonlyMap> for atomic state mutation, Effect Schema for validation,
5
+ * and typed errors. Supports $disconnect, $connect, $update, $delete, and $set
6
+ * operations for both ref (single) and inverse (many) relationship types.
7
+ */
8
+ import { Effect, PubSub, Ref } from "effect";
9
+ import { ForeignKeyError, NotFoundError, ValidationError, } from "../../errors/crud-errors.js";
10
+ import { isRelationshipOperation } from "../../types/crud-relationship-types.js";
11
+ import { validateForeignKeysEffect } from "../../validators/foreign-key.js";
12
+ import { validateEntity } from "../../validators/schema-validator.js";
13
+ // ============================================================================
14
+ // Helpers
15
+ // ============================================================================
16
+ const getTargetCollection = (rel) => rel.target || rel.__targetCollection;
17
+ /**
18
+ * Resolve a connect input to a target entity's ID by looking up the Ref state.
19
+ */
20
+ const resolveConnectInput = (input, targetCollection, stateRefs) => Effect.gen(function* () {
21
+ const targetRef = stateRefs[targetCollection];
22
+ if (targetRef === undefined) {
23
+ return yield* Effect.fail(new ForeignKeyError({
24
+ collection: targetCollection,
25
+ field: "",
26
+ value: "",
27
+ targetCollection,
28
+ message: `Target collection '${targetCollection}' not found`,
29
+ }));
30
+ }
31
+ const targetMap = yield* Ref.get(targetRef);
32
+ // If input has id, use it directly
33
+ if ("id" in input &&
34
+ typeof input.id === "string") {
35
+ const id = input.id;
36
+ if (targetMap.has(id)) {
37
+ return id;
38
+ }
39
+ return yield* Effect.fail(new ForeignKeyError({
40
+ collection: targetCollection,
41
+ field: "id",
42
+ value: id,
43
+ targetCollection,
44
+ message: `Entity with ID '${id}' not found in '${targetCollection}'`,
45
+ }));
46
+ }
47
+ // Otherwise, find by matching fields
48
+ const inputEntries = Object.entries(input);
49
+ for (const [, entity] of targetMap) {
50
+ const entityRecord = entity;
51
+ const matches = inputEntries.every(([key, value]) => entityRecord[key] === value);
52
+ if (matches) {
53
+ return entity.id;
54
+ }
55
+ }
56
+ return yield* Effect.fail(new ForeignKeyError({
57
+ collection: targetCollection,
58
+ field: "",
59
+ value: JSON.stringify(input),
60
+ targetCollection,
61
+ message: `No matching entity found in '${targetCollection}'`,
62
+ }));
63
+ });
64
+ /**
65
+ * Find the inverse relationship field name in the target collection
66
+ * that points back to the source collection.
67
+ */
68
+ const findInverseRelationship = (sourceCollection, targetRelationships) => {
69
+ for (const [field, rel] of Object.entries(targetRelationships)) {
70
+ const target = getTargetCollection(rel);
71
+ if (target === sourceCollection) {
72
+ return field;
73
+ }
74
+ }
75
+ return null;
76
+ };
77
+ // ============================================================================
78
+ // Relationship Processing
79
+ // ============================================================================
80
+ /**
81
+ * Process a single (ref) relationship update input into operations.
82
+ */
83
+ const processSingleRelationshipUpdate = (field, value, targetCollection, stateRefs) => Effect.gen(function* () {
84
+ const disconnect = [];
85
+ const connect = [];
86
+ const update = [];
87
+ const del = [];
88
+ const set = [];
89
+ // Direct connect (shorthand syntax)
90
+ if (!isRelationshipOperation(value)) {
91
+ const targetId = yield* resolveConnectInput(value, targetCollection, stateRefs);
92
+ connect.push({ field, targetId, targetCollection });
93
+ return { disconnect, connect, update, delete: del, set };
94
+ }
95
+ const ops = value;
96
+ if (ops.$disconnect) {
97
+ disconnect.push({ field, targetCollection });
98
+ }
99
+ if (ops.$connect) {
100
+ const targetId = yield* resolveConnectInput(ops.$connect, targetCollection, stateRefs);
101
+ connect.push({ field, targetId, targetCollection });
102
+ }
103
+ if (ops.$update) {
104
+ update.push({ field, data: ops.$update, targetCollection });
105
+ }
106
+ if (ops.$delete) {
107
+ del.push({ field, targetCollection });
108
+ }
109
+ return { disconnect, connect, update, delete: del, set };
110
+ });
111
+ /**
112
+ * Process a many (inverse) relationship update input into operations.
113
+ */
114
+ const processManyRelationshipUpdate = (field, value, targetCollection, stateRefs) => Effect.gen(function* () {
115
+ const disconnect = [];
116
+ const connect = [];
117
+ const update = [];
118
+ const del = [];
119
+ const set = [];
120
+ // Process $set (replace all) — takes priority over other operations
121
+ if (value.$set) {
122
+ const targetIds = [];
123
+ for (const item of value.$set) {
124
+ const targetId = yield* resolveConnectInput(item, targetCollection, stateRefs);
125
+ targetIds.push(targetId);
126
+ }
127
+ set.push({ field, targetIds, targetCollection });
128
+ return { disconnect, connect, update, delete: del, set };
129
+ }
130
+ // Process $disconnect
131
+ if (value.$disconnect) {
132
+ if (value.$disconnect === true) {
133
+ disconnect.push({ field, targetCollection });
134
+ }
135
+ else {
136
+ const disconnects = Array.isArray(value.$disconnect)
137
+ ? value.$disconnect
138
+ : [value.$disconnect];
139
+ for (const disc of disconnects) {
140
+ const targetId = yield* resolveConnectInput(disc, targetCollection, stateRefs).pipe(Effect.catchTag("ForeignKeyError", () => Effect.succeed("")));
141
+ if (targetId) {
142
+ del.push({ field, targetId, targetCollection });
143
+ }
144
+ }
145
+ }
146
+ }
147
+ // Process $connect
148
+ if (value.$connect) {
149
+ const connects = Array.isArray(value.$connect)
150
+ ? value.$connect
151
+ : [value.$connect];
152
+ for (const conn of connects) {
153
+ const targetId = yield* resolveConnectInput(conn, targetCollection, stateRefs);
154
+ connect.push({ field, targetId, targetCollection });
155
+ }
156
+ }
157
+ // Process $update
158
+ if (value.$update) {
159
+ const updates = Array.isArray(value.$update)
160
+ ? value.$update
161
+ : [value.$update];
162
+ for (const u of updates) {
163
+ const targetId = yield* resolveConnectInput(u.where, targetCollection, stateRefs).pipe(Effect.catchTag("ForeignKeyError", () => Effect.succeed("")));
164
+ if (targetId) {
165
+ update.push({ field, data: u.data, targetCollection, targetId });
166
+ }
167
+ }
168
+ }
169
+ // Process $delete
170
+ if (value.$delete) {
171
+ const deletes = Array.isArray(value.$delete)
172
+ ? value.$delete
173
+ : [value.$delete];
174
+ for (const d of deletes) {
175
+ const targetId = yield* resolveConnectInput(d, targetCollection, stateRefs).pipe(Effect.catchTag("ForeignKeyError", () => Effect.succeed("")));
176
+ if (targetId) {
177
+ del.push({ field, targetId, targetCollection });
178
+ }
179
+ }
180
+ }
181
+ return { disconnect, connect, update, delete: del, set };
182
+ });
183
+ /**
184
+ * Process all relationship operations from the update input.
185
+ */
186
+ const processRelationshipOperations = (input, relationships, stateRefs) => Effect.gen(function* () {
187
+ const allDisconnect = [];
188
+ const allConnect = [];
189
+ const allUpdate = [];
190
+ const allDelete = [];
191
+ const allSet = [];
192
+ for (const [field, value] of Object.entries(input)) {
193
+ const rel = relationships[field];
194
+ if (!rel || value === undefined || value === null)
195
+ continue;
196
+ const targetCollection = getTargetCollection(rel);
197
+ if (!targetCollection)
198
+ continue;
199
+ let ops;
200
+ if (rel.type === "ref") {
201
+ ops = yield* processSingleRelationshipUpdate(field, value, targetCollection, stateRefs);
202
+ }
203
+ else {
204
+ ops = yield* processManyRelationshipUpdate(field, value, targetCollection, stateRefs);
205
+ }
206
+ allDisconnect.push(...ops.disconnect);
207
+ allConnect.push(...ops.connect);
208
+ allUpdate.push(...ops.update);
209
+ allDelete.push(...ops.delete);
210
+ allSet.push(...ops.set);
211
+ }
212
+ return {
213
+ disconnect: allDisconnect,
214
+ connect: allConnect,
215
+ update: allUpdate,
216
+ delete: allDelete,
217
+ set: allSet,
218
+ };
219
+ });
220
+ // ============================================================================
221
+ // Computed Field Stripping
222
+ // ============================================================================
223
+ /**
224
+ * Strip computed field keys from an input object.
225
+ * Used to remove computed field names from update input before schema validation.
226
+ *
227
+ * @param input - The input object (possibly with computed field keys)
228
+ * @param computed - The computed fields configuration that defines which keys to strip
229
+ * @returns A new object with computed field keys removed
230
+ */
231
+ const stripComputedFromInput = (input, computed) => {
232
+ if (computed === undefined || Object.keys(computed).length === 0) {
233
+ return input;
234
+ }
235
+ const computedKeys = new Set(Object.keys(computed));
236
+ const result = {};
237
+ for (const key of Object.keys(input)) {
238
+ if (!computedKeys.has(key)) {
239
+ result[key] = input[key];
240
+ }
241
+ }
242
+ return result;
243
+ };
244
+ // ============================================================================
245
+ // Update with Relationships
246
+ // ============================================================================
247
+ /**
248
+ * Update a single entity with relationship support.
249
+ *
250
+ * Steps:
251
+ * 1. Strip computed field keys from input (they are derived, not stored)
252
+ * 2. Look up existing entity by ID
253
+ * 3. Parse relationship operations from input
254
+ * 4. Extract base entity updates (non-relationship fields)
255
+ * 5. Process $disconnect: set FK to null (ref) or update inverse entities
256
+ * 6. Process $connect: set FK (ref) or update inverse entity FKs
257
+ * 7. Process $update: update related entities in target collections
258
+ * 8. Process $delete: disconnect specific inverse entities
259
+ * 9. Process $set: replace all inverse relationships
260
+ * 10. Merge base updates, validate, and update the entity
261
+ */
262
+ export const updateWithRelationships = (collectionName, schema, relationships, ref, stateRefs, dbConfig, computed, changePubSub) => (id, input) => Effect.gen(function* () {
263
+ // 1. Strip computed field keys from input (they are derived, not stored)
264
+ const sanitizedInput = stripComputedFromInput(input, computed);
265
+ // 2. Look up existing entity
266
+ const currentMap = yield* Ref.get(ref);
267
+ const existing = currentMap.get(id);
268
+ if (existing === undefined) {
269
+ return yield* Effect.fail(new NotFoundError({
270
+ collection: collectionName,
271
+ id,
272
+ message: `Entity '${id}' not found in collection '${collectionName}'`,
273
+ }));
274
+ }
275
+ const now = new Date().toISOString();
276
+ // 3. Process relationship operations
277
+ const relationshipOps = yield* processRelationshipOperations(sanitizedInput, relationships, stateRefs);
278
+ // 4. Extract base entity updates (non-relationship fields)
279
+ const baseUpdate = {};
280
+ for (const [key, value] of Object.entries(sanitizedInput)) {
281
+ if (!(key in relationships)) {
282
+ baseUpdate[key] = value;
283
+ }
284
+ }
285
+ // Start with a copy of existing entity
286
+ const updatedEntity = {
287
+ ...existing,
288
+ };
289
+ // 5. Process disconnects
290
+ for (const op of relationshipOps.disconnect) {
291
+ const relationship = relationships[op.field];
292
+ if (!relationship)
293
+ continue;
294
+ if (relationship.type === "ref") {
295
+ // Set FK to null on the entity being updated
296
+ const foreignKey = relationship.foreignKey || `${op.field}Id`;
297
+ updatedEntity[foreignKey] = null;
298
+ }
299
+ else if (relationship.type === "inverse") {
300
+ // Update inverse entities: set their FK to null
301
+ const targetConfig = dbConfig[op.targetCollection];
302
+ if (!targetConfig)
303
+ continue;
304
+ const inverseField = findInverseRelationship(collectionName, targetConfig.relationships);
305
+ if (!inverseField)
306
+ continue;
307
+ const inverseRel = targetConfig.relationships[inverseField];
308
+ if (!inverseRel)
309
+ continue;
310
+ const foreignKey = inverseRel.foreignKey || `${inverseField}Id`;
311
+ const targetRef = stateRefs[op.targetCollection];
312
+ if (!targetRef)
313
+ continue;
314
+ yield* Ref.update(targetRef, (map) => {
315
+ const next = new Map(map);
316
+ for (const [entityId, entity] of map) {
317
+ if (entity[foreignKey] === id) {
318
+ next.set(entityId, {
319
+ ...entity,
320
+ [foreignKey]: null,
321
+ updatedAt: now,
322
+ });
323
+ }
324
+ }
325
+ return next;
326
+ });
327
+ }
328
+ }
329
+ // 6. Process connects
330
+ for (const op of relationshipOps.connect) {
331
+ const relationship = relationships[op.field];
332
+ if (!relationship)
333
+ continue;
334
+ if (relationship.type === "ref") {
335
+ // Set FK on the entity being updated
336
+ const foreignKey = relationship.foreignKey || `${op.field}Id`;
337
+ updatedEntity[foreignKey] = op.targetId;
338
+ }
339
+ else if (relationship.type === "inverse") {
340
+ // Update the target entity's FK to point to this entity
341
+ const targetConfig = dbConfig[op.targetCollection];
342
+ if (!targetConfig)
343
+ continue;
344
+ const inverseField = findInverseRelationship(collectionName, targetConfig.relationships);
345
+ if (!inverseField)
346
+ continue;
347
+ const inverseRel = targetConfig.relationships[inverseField];
348
+ if (!inverseRel)
349
+ continue;
350
+ const foreignKey = inverseRel.foreignKey || `${inverseField}Id`;
351
+ const targetRef = stateRefs[op.targetCollection];
352
+ if (!targetRef)
353
+ continue;
354
+ yield* Ref.update(targetRef, (map) => {
355
+ const target = map.get(op.targetId);
356
+ if (!target)
357
+ return map;
358
+ const next = new Map(map);
359
+ next.set(op.targetId, {
360
+ ...target,
361
+ [foreignKey]: id,
362
+ updatedAt: now,
363
+ });
364
+ return next;
365
+ });
366
+ }
367
+ }
368
+ // 7. Process nested updates on related entities
369
+ for (const op of relationshipOps.update) {
370
+ const targetRef = stateRefs[op.targetCollection];
371
+ if (!targetRef)
372
+ continue;
373
+ const targetConfig = dbConfig[op.targetCollection];
374
+ if (!targetConfig)
375
+ continue;
376
+ // Determine which target entity to update
377
+ let targetId = op.targetId;
378
+ if (!targetId) {
379
+ // For ref relationships, look up the FK on the current entity
380
+ const relationship = relationships[op.field];
381
+ if (relationship && relationship.type === "ref") {
382
+ const foreignKey = relationship.foreignKey || `${op.field}Id`;
383
+ const fkValue = updatedEntity[foreignKey];
384
+ if (typeof fkValue === "string") {
385
+ targetId = fkValue;
386
+ }
387
+ }
388
+ }
389
+ if (!targetId)
390
+ continue;
391
+ // Capture targetId for closure (TypeScript narrowing)
392
+ const validTargetId = targetId;
393
+ const targetMap = yield* Ref.get(targetRef);
394
+ const targetEntity = targetMap.get(validTargetId);
395
+ if (!targetEntity)
396
+ continue;
397
+ const updateData = op.data;
398
+ const updatedTarget = {
399
+ ...targetEntity,
400
+ ...updateData,
401
+ updatedAt: now,
402
+ };
403
+ // Validate updated target
404
+ const validated = yield* validateEntity(targetConfig.schema, updatedTarget).pipe(Effect.mapError((ve) => new ValidationError({
405
+ message: `Nested update in '${op.targetCollection}' failed: ${ve.message}`,
406
+ issues: ve.issues,
407
+ })));
408
+ yield* Ref.update(targetRef, (map) => {
409
+ const next = new Map(map);
410
+ next.set(validTargetId, validated);
411
+ return next;
412
+ });
413
+ }
414
+ // 8. Process delete operations (disconnect specific inverse entities)
415
+ for (const op of relationshipOps.delete) {
416
+ const relationship = relationships[op.field];
417
+ if (!relationship || relationship.type !== "inverse")
418
+ continue;
419
+ const targetConfig = dbConfig[op.targetCollection];
420
+ if (!targetConfig)
421
+ continue;
422
+ const inverseField = findInverseRelationship(collectionName, targetConfig.relationships);
423
+ if (!inverseField)
424
+ continue;
425
+ const inverseRel = targetConfig.relationships[inverseField];
426
+ if (!inverseRel)
427
+ continue;
428
+ const foreignKey = inverseRel.foreignKey || `${inverseField}Id`;
429
+ if (!op.targetId)
430
+ continue;
431
+ // Capture targetId for closure (TypeScript narrowing)
432
+ const deleteTargetId = op.targetId;
433
+ const targetRef = stateRefs[op.targetCollection];
434
+ if (!targetRef)
435
+ continue;
436
+ yield* Ref.update(targetRef, (map) => {
437
+ const target = map.get(deleteTargetId);
438
+ if (!target)
439
+ return map;
440
+ if (target[foreignKey] !== id)
441
+ return map;
442
+ const next = new Map(map);
443
+ next.set(deleteTargetId, {
444
+ ...target,
445
+ [foreignKey]: null,
446
+ updatedAt: now,
447
+ });
448
+ return next;
449
+ });
450
+ }
451
+ // 9. Process set operations (replace all inverse relationships)
452
+ for (const op of relationshipOps.set) {
453
+ const relationship = relationships[op.field];
454
+ if (!relationship || relationship.type !== "inverse")
455
+ continue;
456
+ const targetConfig = dbConfig[op.targetCollection];
457
+ if (!targetConfig)
458
+ continue;
459
+ const inverseField = findInverseRelationship(collectionName, targetConfig.relationships);
460
+ if (!inverseField)
461
+ continue;
462
+ const inverseRel = targetConfig.relationships[inverseField];
463
+ if (!inverseRel)
464
+ continue;
465
+ const foreignKey = inverseRel.foreignKey || `${inverseField}Id`;
466
+ const targetRef = stateRefs[op.targetCollection];
467
+ if (!targetRef)
468
+ continue;
469
+ const targetIdsSet = new Set(op.targetIds);
470
+ yield* Ref.update(targetRef, (map) => {
471
+ const next = new Map(map);
472
+ for (const [entityId, entity] of map) {
473
+ const entityRecord = entity;
474
+ if (entityRecord[foreignKey] === id &&
475
+ !targetIdsSet.has(entityId)) {
476
+ // Remove current relationship
477
+ next.set(entityId, {
478
+ ...entity,
479
+ [foreignKey]: null,
480
+ updatedAt: now,
481
+ });
482
+ }
483
+ else if (targetIdsSet.has(entityId)) {
484
+ // Set new relationship
485
+ next.set(entityId, {
486
+ ...entity,
487
+ [foreignKey]: id,
488
+ updatedAt: now,
489
+ });
490
+ }
491
+ }
492
+ return next;
493
+ });
494
+ }
495
+ // 10. Merge base updates, validate, and update
496
+ Object.assign(updatedEntity, baseUpdate);
497
+ updatedEntity.updatedAt = now;
498
+ const validated = yield* validateEntity(schema, updatedEntity);
499
+ // Validate foreign keys
500
+ yield* validateForeignKeysEffect(validated, collectionName, relationships, stateRefs);
501
+ // Atomically update in state
502
+ yield* Ref.update(ref, (map) => {
503
+ const next = new Map(map);
504
+ next.set(id, validated);
505
+ return next;
506
+ });
507
+ // Publish change event for reactive query subscribers
508
+ if (changePubSub) {
509
+ yield* PubSub.publish(changePubSub, {
510
+ collection: collectionName,
511
+ operation: "update",
512
+ });
513
+ }
514
+ return validated;
515
+ });
516
+ //# sourceMappingURL=update-with-relationships.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-with-relationships.js","sourceRoot":"","sources":["../../../src/operations/crud/update-with-relationships.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Effect-based update operations for entities.
3
+ *
4
+ * Uses Ref<ReadonlyMap> for atomic state mutation, Effect Schema for validation,
5
+ * and typed errors (ValidationError, NotFoundError, ForeignKeyError).
6
+ *
7
+ * Preserves all update operators: $increment, $decrement, $multiply,
8
+ * $append, $prepend, $remove, $toggle, $set.
9
+ */
10
+ import { Effect, PubSub, Ref, type Schema } from "effect";
11
+ import { type ForeignKeyError, type HookError, NotFoundError, type UniqueConstraintError, ValidationError } from "../../errors/crud-errors.js";
12
+ import type { ComputedFieldsConfig } from "../../types/computed-types.js";
13
+ import type { MinimalEntity, UpdateManyResult, UpdateWithOperators } from "../../types/crud-types.js";
14
+ import type { HooksConfig } from "../../types/hook-types.js";
15
+ import type { CollectionIndexes } from "../../types/index-types.js";
16
+ import type { ChangeEvent } from "../../types/reactive-types.js";
17
+ import type { SearchIndexMap } from "../../types/search-types.js";
18
+ import { type NormalizedConstraints } from "./unique-check.js";
19
+ type HasId = {
20
+ readonly id: string;
21
+ };
22
+ type RelationshipConfig = {
23
+ readonly type: "ref" | "inverse";
24
+ readonly target: string;
25
+ readonly foreignKey?: string;
26
+ };
27
+ /**
28
+ * Deep merge an update object into a current object, handling operators at any level.
29
+ *
30
+ * Rules:
31
+ * 1. If update value has $-prefixed keys → it's an operator, apply to current value
32
+ * 2. If update value is a plain object with no $-keys AND current value is also a plain object → recurse
33
+ * 3. Otherwise → direct assignment (replace current value with update value)
34
+ *
35
+ * This allows nested updates like:
36
+ * - `{ metadata: { views: 500 } }` → merges into metadata, preserving other fields
37
+ * - `{ metadata: { views: { $increment: 1 } } }` → applies operator to metadata.views
38
+ * - `{ metadata: { $set: { views: 0 } } }` → replaces entire metadata
39
+ *
40
+ * @param current - The current object to merge into
41
+ * @param updates - The update object containing values and/or operators
42
+ * @returns A new object with updates applied
43
+ */
44
+ export declare function deepMergeUpdates(current: Record<string, unknown>, updates: Record<string, unknown>): Record<string, unknown>;
45
+ /**
46
+ * Apply update operations to an entity.
47
+ * Handles both direct value assignments and operator objects at any nesting level.
48
+ * Uses deepMergeUpdates for nested object merging with operator support.
49
+ * Automatically sets updatedAt timestamp.
50
+ */
51
+ export declare function applyUpdates<T extends MinimalEntity>(entity: T, updates: UpdateWithOperators<T>): T;
52
+ /**
53
+ * Validate that an update doesn't violate immutable fields (id, createdAt).
54
+ */
55
+ export declare function validateImmutableFields<T extends MinimalEntity>(updates: UpdateWithOperators<T>): {
56
+ readonly valid: boolean;
57
+ readonly field?: string;
58
+ };
59
+ /**
60
+ * Update a single entity by ID with validation, hooks, and foreign key checks.
61
+ *
62
+ * Steps:
63
+ * 1. Validate immutable fields are not being modified
64
+ * 2. Look up entity by ID in Ref state (O(1)) - capture as previous
65
+ * 3. Run beforeUpdate hooks (can transform update payload)
66
+ * 4. Apply update operators to produce new entity
67
+ * 5. Validate through Effect Schema
68
+ * 6. Validate foreign key constraints if relationship fields changed
69
+ * 7. Atomically update in Ref state
70
+ * 8. Update indexes if provided
71
+ */
72
+ export declare const update: <T extends HasId, I = T>(collectionName: string, schema: Schema.Schema<T, I>, relationships: Record<string, RelationshipConfig>, ref: Ref.Ref<ReadonlyMap<string, T>>, stateRefs: Record<string, Ref.Ref<ReadonlyMap<string, HasId>>>, indexes?: CollectionIndexes, hooks?: HooksConfig<T>, uniqueFields?: NormalizedConstraints, computed?: ComputedFieldsConfig<unknown>, searchIndexRef?: Ref.Ref<SearchIndexMap>, searchIndexFields?: ReadonlyArray<string>, changePubSub?: PubSub.PubSub<ChangeEvent>) => (id: string, updates: UpdateWithOperators<T & MinimalEntity>) => Effect.Effect<T, ValidationError | NotFoundError | ForeignKeyError | HookError | UniqueConstraintError>;
73
+ /**
74
+ * Update multiple entities matching a filter predicate.
75
+ *
76
+ * Uses a predicate function to select which entities to update.
77
+ * The caller (database factory) can use the Stream-based filter pipeline
78
+ * to build the predicate from a WhereClause.
79
+ *
80
+ * Runs hooks per entity: beforeUpdate can transform the update payload,
81
+ * afterUpdate and onChange run after state mutation.
82
+ *
83
+ * All matching entities are updated atomically in a single Ref.update call.
84
+ */
85
+ export declare const updateMany: <T extends HasId, I = T>(collectionName: string, schema: Schema.Schema<T, I>, relationships: Record<string, RelationshipConfig>, ref: Ref.Ref<ReadonlyMap<string, T>>, stateRefs: Record<string, Ref.Ref<ReadonlyMap<string, HasId>>>, indexes?: CollectionIndexes, hooks?: HooksConfig<T>, uniqueFields?: NormalizedConstraints, computed?: ComputedFieldsConfig<unknown>, searchIndexRef?: Ref.Ref<SearchIndexMap>, searchIndexFields?: ReadonlyArray<string>, changePubSub?: PubSub.PubSub<ChangeEvent>) => (predicate: (entity: T) => boolean, updates: UpdateWithOperators<T & MinimalEntity>) => Effect.Effect<UpdateManyResult<T>, ValidationError | ForeignKeyError | HookError | UniqueConstraintError>;
86
+ /**
87
+ * Extract fields that were actually changed between two entity versions.
88
+ */
89
+ export declare function getChangedFields<T extends MinimalEntity>(original: T, updated: T): string[];
90
+ export {};
91
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/operations/crud/update.ts"],"names":[],"mappings":"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"}