@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,183 @@
1
+ /**
2
+ * Data transformation utilities for converting between internal formats
3
+ * (ReadonlyMap and array) and storage object format, plus collection
4
+ * file grouping utilities.
5
+ */
6
+ /**
7
+ * Convert an array of entities with id fields to an object keyed by id.
8
+ * This provides O(1) lookups in storage files.
9
+ *
10
+ * @param items - Array of entities, each must have an 'id' field
11
+ * @returns Object keyed by entity id
12
+ *
13
+ * @example
14
+ * arrayToObject([
15
+ * { id: 'user-1', name: 'Alice' },
16
+ * { id: 'user-2', name: 'Bob' }
17
+ * ])
18
+ * // Returns: {
19
+ * // 'user-1': { id: 'user-1', name: 'Alice' },
20
+ * // 'user-2': { id: 'user-2', name: 'Bob' }
21
+ * // }
22
+ */
23
+ export declare function arrayToObject<T extends {
24
+ id: string;
25
+ }>(items: readonly T[]): Record<string, T>;
26
+ /**
27
+ * Convert an object keyed by id back to an array of entities.
28
+ *
29
+ * @param obj - Object keyed by entity id
30
+ * @returns Array of entities
31
+ *
32
+ * @example
33
+ * objectToArray({
34
+ * 'user-1': { id: 'user-1', name: 'Alice' },
35
+ * 'user-2': { id: 'user-2', name: 'Bob' }
36
+ * })
37
+ * // Returns: [
38
+ * // { id: 'user-1', name: 'Alice' },
39
+ * // { id: 'user-2', name: 'Bob' }
40
+ * // ]
41
+ */
42
+ export declare function objectToArray<T>(obj: Record<string, T>): T[];
43
+ /**
44
+ * Collection configuration that may include a file path for persistence
45
+ */
46
+ type CollectionConfig = {
47
+ readonly file?: string;
48
+ readonly [key: string]: unknown;
49
+ };
50
+ /**
51
+ * Group collections by their configured file paths.
52
+ * Collections without a file path are not included in the result.
53
+ *
54
+ * @param config - Database configuration with collection definitions
55
+ * @returns Map from file path to array of collection names that use that file
56
+ *
57
+ * @example
58
+ * groupByFile({
59
+ * users: { schema: UserSchema, file: '/data/users.json' },
60
+ * products: { schema: ProductSchema, file: '/data/db.json' },
61
+ * categories: { schema: CategorySchema, file: '/data/db.json' },
62
+ * sessions: { schema: SessionSchema } // no file = in-memory only
63
+ * })
64
+ * // Returns: Map {
65
+ * // '/data/users.json' => ['users'],
66
+ * // '/data/db.json' => ['products', 'categories']
67
+ * // }
68
+ */
69
+ export declare function groupByFile<Config extends Record<string, CollectionConfig>>(config: Config): Map<string, string[]>;
70
+ /**
71
+ * Get all unique file paths from a database configuration.
72
+ *
73
+ * @param config - Database configuration with collection definitions
74
+ * @returns Array of unique file paths used by collections
75
+ */
76
+ export declare function getConfigFilePaths<Config extends Record<string, CollectionConfig>>(config: Config): string[];
77
+ /**
78
+ * Check if a collection is configured for persistence.
79
+ *
80
+ * @param config - Database configuration
81
+ * @param collectionName - Name of the collection to check
82
+ * @returns True if the collection has a file path configured
83
+ */
84
+ export declare function isCollectionPersistent<Config extends Record<string, CollectionConfig>>(config: Config, collectionName: keyof Config): boolean;
85
+ /**
86
+ * Extract collections that should be stored in a specific file.
87
+ *
88
+ * @param data - Full dataset with all collections
89
+ * @param collectionsForFile - Array of collection names to extract
90
+ * @returns Object containing only the specified collections in object format
91
+ */
92
+ export declare function extractCollectionsForFile<T extends Record<string, unknown[]>>(data: T, collectionsForFile: readonly string[]): Record<string, Record<string, unknown>>;
93
+ /**
94
+ * Merge file data back into the main dataset.
95
+ * Converts object format back to array format for each collection.
96
+ *
97
+ * @param data - Current dataset to update
98
+ * @param fileData - Data loaded from file (in object format)
99
+ * @param collectionsFromFile - Array of collection names to update
100
+ * @returns Updated dataset with arrays
101
+ */
102
+ export declare function mergeFileDataIntoDataset<T extends Record<string, unknown[]>>(data: T, fileData: Record<string, Record<string, unknown>>, collectionsFromFile: readonly string[]): T;
103
+ /**
104
+ * Convert an array of entities to a ReadonlyMap keyed by entity ID.
105
+ *
106
+ * @param items - Array of entities, each must have an 'id' field
107
+ * @returns ReadonlyMap keyed by entity id
108
+ *
109
+ * @example
110
+ * arrayToMap([
111
+ * { id: 'user-1', name: 'Alice' },
112
+ * { id: 'user-2', name: 'Bob' }
113
+ * ])
114
+ * // Returns: Map { 'user-1' => { id: 'user-1', name: 'Alice' }, 'user-2' => { id: 'user-2', name: 'Bob' } }
115
+ */
116
+ export declare function arrayToMap<T extends {
117
+ readonly id: string;
118
+ }>(items: readonly T[]): ReadonlyMap<string, T>;
119
+ /**
120
+ * Convert a ReadonlyMap to a Record keyed by entity ID (the on-disk object format).
121
+ *
122
+ * @param map - ReadonlyMap of entities keyed by ID
123
+ * @returns Record keyed by entity id
124
+ *
125
+ * @example
126
+ * mapToObject(new Map([
127
+ * ['user-1', { id: 'user-1', name: 'Alice' }],
128
+ * ['user-2', { id: 'user-2', name: 'Bob' }],
129
+ * ]))
130
+ * // Returns: { 'user-1': { id: 'user-1', name: 'Alice' }, 'user-2': { id: 'user-2', name: 'Bob' } }
131
+ */
132
+ export declare function mapToObject<T>(map: ReadonlyMap<string, T>): Record<string, T>;
133
+ /**
134
+ * Convert a Record keyed by entity ID to a ReadonlyMap.
135
+ * Inverse of mapToObject.
136
+ *
137
+ * @param obj - Record keyed by entity id
138
+ * @returns ReadonlyMap keyed by entity id
139
+ *
140
+ * @example
141
+ * objectToMap({
142
+ * 'user-1': { id: 'user-1', name: 'Alice' },
143
+ * 'user-2': { id: 'user-2', name: 'Bob' },
144
+ * })
145
+ * // Returns: Map { 'user-1' => { id: 'user-1', name: 'Alice' }, 'user-2' => { id: 'user-2', name: 'Bob' } }
146
+ */
147
+ export declare function objectToMap<T>(obj: Readonly<Record<string, T>>): ReadonlyMap<string, T>;
148
+ /**
149
+ * Convert a ReadonlyMap to an array of its values.
150
+ *
151
+ * @param map - ReadonlyMap of entities
152
+ * @returns Array of entity values
153
+ */
154
+ export declare function mapToArray<T>(map: ReadonlyMap<string, T>): readonly T[];
155
+ /**
156
+ * Extract collections from ReadonlyMap-based state for file storage.
157
+ *
158
+ * Takes a Record of collection name → ReadonlyMap and a list of collection
159
+ * names to include, returning nested Record format suitable for serialization.
160
+ *
161
+ * @param stateMaps - Record mapping collection names to their ReadonlyMap state
162
+ * @param collectionsForFile - Collection names to extract
163
+ * @returns Nested Record: { collectionName: { id: entity, ... }, ... }
164
+ */
165
+ export declare function extractCollectionsFromMaps<T extends {
166
+ readonly id: string;
167
+ }>(stateMaps: Readonly<Record<string, ReadonlyMap<string, T>>>, collectionsForFile: readonly string[]): Record<string, Record<string, T>>;
168
+ /**
169
+ * Merge file data (nested Record format) back into ReadonlyMap-based state.
170
+ *
171
+ * Takes existing state maps, file data in Record format, and collection names,
172
+ * returning updated state maps with the file data merged in.
173
+ *
174
+ * @param stateMaps - Current state: Record of collection name → ReadonlyMap
175
+ * @param fileData - Data from file: { collectionName: { id: entity, ... }, ... }
176
+ * @param collectionsFromFile - Collection names to update from file data
177
+ * @returns Updated state maps
178
+ */
179
+ export declare function mergeFileDataIntoMaps<T extends {
180
+ readonly id: string;
181
+ }>(stateMaps: Readonly<Record<string, ReadonlyMap<string, T>>>, fileData: Readonly<Record<string, Readonly<Record<string, T>>>>, collectionsFromFile: readonly string[]): Record<string, ReadonlyMap<string, T>>;
182
+ export {};
183
+ //# sourceMappingURL=transforms.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transforms.d.ts","sourceRoot":"","sources":["../../src/storage/transforms.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,263 @@
1
+ /**
2
+ * Data transformation utilities for converting between internal formats
3
+ * (ReadonlyMap and array) and storage object format, plus collection
4
+ * file grouping utilities.
5
+ */
6
+ /**
7
+ * Convert an array of entities with id fields to an object keyed by id.
8
+ * This provides O(1) lookups in storage files.
9
+ *
10
+ * @param items - Array of entities, each must have an 'id' field
11
+ * @returns Object keyed by entity id
12
+ *
13
+ * @example
14
+ * arrayToObject([
15
+ * { id: 'user-1', name: 'Alice' },
16
+ * { id: 'user-2', name: 'Bob' }
17
+ * ])
18
+ * // Returns: {
19
+ * // 'user-1': { id: 'user-1', name: 'Alice' },
20
+ * // 'user-2': { id: 'user-2', name: 'Bob' }
21
+ * // }
22
+ */
23
+ export function arrayToObject(items) {
24
+ const result = {};
25
+ for (const item of items) {
26
+ if (typeof item.id !== "string") {
27
+ throw new Error(`Invalid entity: id must be a string, got ${typeof item.id}`);
28
+ }
29
+ result[item.id] = item;
30
+ }
31
+ return result;
32
+ }
33
+ /**
34
+ * Convert an object keyed by id back to an array of entities.
35
+ *
36
+ * @param obj - Object keyed by entity id
37
+ * @returns Array of entities
38
+ *
39
+ * @example
40
+ * objectToArray({
41
+ * 'user-1': { id: 'user-1', name: 'Alice' },
42
+ * 'user-2': { id: 'user-2', name: 'Bob' }
43
+ * })
44
+ * // Returns: [
45
+ * // { id: 'user-1', name: 'Alice' },
46
+ * // { id: 'user-2', name: 'Bob' }
47
+ * // ]
48
+ */
49
+ export function objectToArray(obj) {
50
+ return Object.values(obj);
51
+ }
52
+ /**
53
+ * Group collections by their configured file paths.
54
+ * Collections without a file path are not included in the result.
55
+ *
56
+ * @param config - Database configuration with collection definitions
57
+ * @returns Map from file path to array of collection names that use that file
58
+ *
59
+ * @example
60
+ * groupByFile({
61
+ * users: { schema: UserSchema, file: '/data/users.json' },
62
+ * products: { schema: ProductSchema, file: '/data/db.json' },
63
+ * categories: { schema: CategorySchema, file: '/data/db.json' },
64
+ * sessions: { schema: SessionSchema } // no file = in-memory only
65
+ * })
66
+ * // Returns: Map {
67
+ * // '/data/users.json' => ['users'],
68
+ * // '/data/db.json' => ['products', 'categories']
69
+ * // }
70
+ */
71
+ export function groupByFile(config) {
72
+ const fileGroups = new Map();
73
+ for (const [collectionName, collectionConfig] of Object.entries(config)) {
74
+ const filePath = collectionConfig.file;
75
+ if (filePath && typeof filePath === "string") {
76
+ const existingCollections = fileGroups.get(filePath) ?? [];
77
+ existingCollections.push(collectionName);
78
+ fileGroups.set(filePath, existingCollections);
79
+ }
80
+ }
81
+ return fileGroups;
82
+ }
83
+ /**
84
+ * Get all unique file paths from a database configuration.
85
+ *
86
+ * @param config - Database configuration with collection definitions
87
+ * @returns Array of unique file paths used by collections
88
+ */
89
+ export function getConfigFilePaths(config) {
90
+ const filePaths = new Set();
91
+ for (const collectionConfig of Object.values(config)) {
92
+ if (collectionConfig.file && typeof collectionConfig.file === "string") {
93
+ filePaths.add(collectionConfig.file);
94
+ }
95
+ }
96
+ return Array.from(filePaths);
97
+ }
98
+ /**
99
+ * Check if a collection is configured for persistence.
100
+ *
101
+ * @param config - Database configuration
102
+ * @param collectionName - Name of the collection to check
103
+ * @returns True if the collection has a file path configured
104
+ */
105
+ export function isCollectionPersistent(config, collectionName) {
106
+ const collectionConfig = config[collectionName];
107
+ return !!(collectionConfig?.file && typeof collectionConfig.file === "string");
108
+ }
109
+ /**
110
+ * Extract collections that should be stored in a specific file.
111
+ *
112
+ * @param data - Full dataset with all collections
113
+ * @param collectionsForFile - Array of collection names to extract
114
+ * @returns Object containing only the specified collections in object format
115
+ */
116
+ export function extractCollectionsForFile(data, collectionsForFile) {
117
+ const result = {};
118
+ for (const collectionName of collectionsForFile) {
119
+ const collectionData = data[collectionName];
120
+ if (Array.isArray(collectionData)) {
121
+ // Validate that all items have string id fields
122
+ const validItems = collectionData.filter((item) => {
123
+ return (typeof item === "object" &&
124
+ item !== null &&
125
+ "id" in item &&
126
+ typeof item.id === "string");
127
+ });
128
+ result[collectionName] = arrayToObject(validItems);
129
+ }
130
+ }
131
+ return result;
132
+ }
133
+ /**
134
+ * Merge file data back into the main dataset.
135
+ * Converts object format back to array format for each collection.
136
+ *
137
+ * @param data - Current dataset to update
138
+ * @param fileData - Data loaded from file (in object format)
139
+ * @param collectionsFromFile - Array of collection names to update
140
+ * @returns Updated dataset with arrays
141
+ */
142
+ export function mergeFileDataIntoDataset(data, fileData, collectionsFromFile) {
143
+ const result = { ...data };
144
+ for (const collectionName of collectionsFromFile) {
145
+ const collectionFileData = fileData[collectionName];
146
+ if (collectionFileData && typeof collectionFileData === "object") {
147
+ // Convert back to array format
148
+ const arrayData = objectToArray(collectionFileData);
149
+ // Type-safe assignment using index signature constraint
150
+ if (collectionName in result) {
151
+ result[collectionName] = arrayData;
152
+ }
153
+ }
154
+ }
155
+ return result;
156
+ }
157
+ // ============================================================================
158
+ // ReadonlyMap-aware transforms (Effect migration)
159
+ // ============================================================================
160
+ /**
161
+ * Convert an array of entities to a ReadonlyMap keyed by entity ID.
162
+ *
163
+ * @param items - Array of entities, each must have an 'id' field
164
+ * @returns ReadonlyMap keyed by entity id
165
+ *
166
+ * @example
167
+ * arrayToMap([
168
+ * { id: 'user-1', name: 'Alice' },
169
+ * { id: 'user-2', name: 'Bob' }
170
+ * ])
171
+ * // Returns: Map { 'user-1' => { id: 'user-1', name: 'Alice' }, 'user-2' => { id: 'user-2', name: 'Bob' } }
172
+ */
173
+ export function arrayToMap(items) {
174
+ return new Map(items.map((item) => [item.id, item]));
175
+ }
176
+ /**
177
+ * Convert a ReadonlyMap to a Record keyed by entity ID (the on-disk object format).
178
+ *
179
+ * @param map - ReadonlyMap of entities keyed by ID
180
+ * @returns Record keyed by entity id
181
+ *
182
+ * @example
183
+ * mapToObject(new Map([
184
+ * ['user-1', { id: 'user-1', name: 'Alice' }],
185
+ * ['user-2', { id: 'user-2', name: 'Bob' }],
186
+ * ]))
187
+ * // Returns: { 'user-1': { id: 'user-1', name: 'Alice' }, 'user-2': { id: 'user-2', name: 'Bob' } }
188
+ */
189
+ export function mapToObject(map) {
190
+ const result = {};
191
+ for (const [key, value] of map) {
192
+ result[key] = value;
193
+ }
194
+ return result;
195
+ }
196
+ /**
197
+ * Convert a Record keyed by entity ID to a ReadonlyMap.
198
+ * Inverse of mapToObject.
199
+ *
200
+ * @param obj - Record keyed by entity id
201
+ * @returns ReadonlyMap keyed by entity id
202
+ *
203
+ * @example
204
+ * objectToMap({
205
+ * 'user-1': { id: 'user-1', name: 'Alice' },
206
+ * 'user-2': { id: 'user-2', name: 'Bob' },
207
+ * })
208
+ * // Returns: Map { 'user-1' => { id: 'user-1', name: 'Alice' }, 'user-2' => { id: 'user-2', name: 'Bob' } }
209
+ */
210
+ export function objectToMap(obj) {
211
+ return new Map(Object.entries(obj));
212
+ }
213
+ /**
214
+ * Convert a ReadonlyMap to an array of its values.
215
+ *
216
+ * @param map - ReadonlyMap of entities
217
+ * @returns Array of entity values
218
+ */
219
+ export function mapToArray(map) {
220
+ return Array.from(map.values());
221
+ }
222
+ /**
223
+ * Extract collections from ReadonlyMap-based state for file storage.
224
+ *
225
+ * Takes a Record of collection name → ReadonlyMap and a list of collection
226
+ * names to include, returning nested Record format suitable for serialization.
227
+ *
228
+ * @param stateMaps - Record mapping collection names to their ReadonlyMap state
229
+ * @param collectionsForFile - Collection names to extract
230
+ * @returns Nested Record: { collectionName: { id: entity, ... }, ... }
231
+ */
232
+ export function extractCollectionsFromMaps(stateMaps, collectionsForFile) {
233
+ const result = {};
234
+ for (const collectionName of collectionsForFile) {
235
+ const collectionMap = stateMaps[collectionName];
236
+ if (collectionMap !== undefined) {
237
+ result[collectionName] = mapToObject(collectionMap);
238
+ }
239
+ }
240
+ return result;
241
+ }
242
+ /**
243
+ * Merge file data (nested Record format) back into ReadonlyMap-based state.
244
+ *
245
+ * Takes existing state maps, file data in Record format, and collection names,
246
+ * returning updated state maps with the file data merged in.
247
+ *
248
+ * @param stateMaps - Current state: Record of collection name → ReadonlyMap
249
+ * @param fileData - Data from file: { collectionName: { id: entity, ... }, ... }
250
+ * @param collectionsFromFile - Collection names to update from file data
251
+ * @returns Updated state maps
252
+ */
253
+ export function mergeFileDataIntoMaps(stateMaps, fileData, collectionsFromFile) {
254
+ const result = { ...stateMaps };
255
+ for (const collectionName of collectionsFromFile) {
256
+ const collectionFileData = fileData[collectionName];
257
+ if (collectionFileData !== undefined) {
258
+ result[collectionName] = objectToMap(collectionFileData);
259
+ }
260
+ }
261
+ return result;
262
+ }
263
+ //# sourceMappingURL=transforms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transforms.js","sourceRoot":"","sources":["../../src/storage/transforms.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Transaction support for atomic multi-collection operations.
3
+ *
4
+ * `createTransaction` returns a TransactionContext with collection accessors,
5
+ * commit/rollback methods, and mutation tracking. Mutations are visible
6
+ * immediately within the transaction (read-own-writes) and either committed
7
+ * atomically or rolled back to pre-transaction state.
8
+ *
9
+ * `$transaction` is a callback wrapper that auto-commits on success and
10
+ * auto-rolls back on failure.
11
+ */
12
+ import { Effect, PubSub, Ref } from "effect";
13
+ import { TransactionError } from "../errors/crud-errors.js";
14
+ import type { EffectCollection } from "../factories/database-effect.js";
15
+ import type { TransactionContext } from "../types/crud-types.js";
16
+ import type { ChangeEvent } from "../types/reactive-types.js";
17
+ type HasId = {
18
+ readonly id: string;
19
+ };
20
+ /**
21
+ * Internal ref map type used for cross-collection references.
22
+ */
23
+ type StateRefs = Record<string, Ref.Ref<ReadonlyMap<string, HasId>>>;
24
+ /**
25
+ * Persistence trigger interface for scheduling debounced saves.
26
+ */
27
+ interface PersistenceTrigger {
28
+ /** Schedule a debounced save for the given key */
29
+ readonly schedule: (key: string) => void;
30
+ }
31
+ /**
32
+ * Callback type for building a collection with transaction-aware afterMutation.
33
+ * The afterMutation adds the collection name to the mutation set instead of
34
+ * scheduling a persistence write.
35
+ */
36
+ type BuildCollectionForTx = (collectionName: string, addMutation: (name: string) => void) => EffectCollection<HasId>;
37
+ /**
38
+ * Create a new transaction context.
39
+ *
40
+ * Parameters:
41
+ * - stateRefs: The database's collection Refs (will be snapshotted and potentially restored)
42
+ * - transactionLock: Single-writer lock Ref (prevents concurrent transactions)
43
+ * - buildCollectionForTx: Callback to create collection accessors with transaction-aware mutations
44
+ * - persistenceTrigger: Optional trigger for scheduling saves on commit
45
+ * - changePubSub: Optional PubSub for reactive change notifications. When provided,
46
+ * individual mutation events are suppressed during the transaction and a single
47
+ * batch event is published for each mutated collection on commit.
48
+ *
49
+ * Returns an Effect that yields a TransactionContext. The context provides:
50
+ * - Collection accessors with the same interface as db.collectionName
51
+ * - commit() to finalize changes and trigger persistence
52
+ * - rollback() to restore snapshots and discard changes
53
+ * - isActive to check if transaction is still open
54
+ * - mutatedCollections to see which collections were written to
55
+ *
56
+ * On failure (e.g., lock already held), returns TransactionError.
57
+ */
58
+ export declare const createTransaction: <DB extends Record<string, EffectCollection<HasId>>>(stateRefs: StateRefs, transactionLock: Ref.Ref<boolean>, buildCollectionForTx: BuildCollectionForTx, persistenceTrigger?: PersistenceTrigger, changePubSub?: PubSub.PubSub<ChangeEvent>) => Effect.Effect<TransactionContext<DB>, TransactionError>;
59
+ /**
60
+ * Execute a callback within an atomic transaction context.
61
+ *
62
+ * All CRUD operations inside the callback operate against the live in-memory state.
63
+ * On success, changes are committed and persistence is triggered.
64
+ * On failure (error thrown or explicit rollback), all mutations are reverted.
65
+ *
66
+ * Usage:
67
+ * ```ts
68
+ * const result = await db.$transaction((ctx) =>
69
+ * Effect.gen(function* () {
70
+ * const user = yield* ctx.users.create({ name: "Alice" })
71
+ * const post = yield* ctx.posts.create({ authorId: user.id, title: "Hello" })
72
+ * return { user, post }
73
+ * })
74
+ * ).pipe(Effect.runPromise)
75
+ * ```
76
+ *
77
+ * @param stateRefs - The database's collection Refs
78
+ * @param transactionLock - Single-writer lock Ref
79
+ * @param buildCollectionForTx - Callback to create collection accessors
80
+ * @param persistenceTrigger - Optional trigger for scheduling saves on commit
81
+ * @param changePubSub - Optional PubSub for reactive change notifications
82
+ * @param fn - The callback to execute within the transaction
83
+ * @returns Effect that yields the callback result, with TransactionError in error channel
84
+ */
85
+ export declare const $transaction: <DB extends Record<string, EffectCollection<HasId>>, A, E>(stateRefs: StateRefs, transactionLock: Ref.Ref<boolean>, buildCollectionForTx: BuildCollectionForTx, persistenceTrigger: PersistenceTrigger | undefined, changePubSub: PubSub.PubSub<ChangeEvent> | undefined, fn: (ctx: TransactionContext<DB>) => Effect.Effect<A, E>) => Effect.Effect<A, E | TransactionError>;
86
+ export {};
87
+ //# sourceMappingURL=transaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../../src/transactions/transaction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAM9D,KAAK,KAAK,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAErC;;GAEG;AACH,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AAErE;;GAEG;AACH,UAAU,kBAAkB;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED;;;;GAIG;AACH,KAAK,oBAAoB,GAAG,CAC3B,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAC/B,gBAAgB,CAAC,KAAK,CAAC,CAAC;AAM7B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,iBAAiB,GAC7B,EAAE,SAAS,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAElD,WAAW,SAAS,EACpB,iBAAiB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,EACjC,sBAAsB,oBAAoB,EAC1C,qBAAqB,kBAAkB,EACvC,eAAe,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,KACvC,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,EAAE,CAAC,EAAE,gBAAgB,CAwLtD,CAAC;AAMJ;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,YAAY,GACxB,EAAE,SAAS,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAClD,CAAC,EACD,CAAC,EAED,WAAW,SAAS,EACpB,iBAAiB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,EACjC,sBAAsB,oBAAoB,EAC1C,oBAAoB,kBAAkB,GAAG,SAAS,EAClD,cAAc,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,SAAS,EACpD,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,KACtD,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,gBAAgB,CAgDrC,CAAC"}