@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,159 @@
1
+ import { Effect, Ref, Stream } from "effect";
2
+ import { DanglingReferenceError } from "../../errors/query-errors.js";
3
+ /**
4
+ * Maximum recursion depth for nested population (mirrors PopulateConfig type depth limit).
5
+ */
6
+ const MAX_POPULATE_DEPTH = 5;
7
+ /**
8
+ * Type guard: is value a non-null, non-array object?
9
+ */
10
+ function isRecord(value) {
11
+ return typeof value === "object" && value !== null && !Array.isArray(value);
12
+ }
13
+ /**
14
+ * Type guard for populate config objects.
15
+ */
16
+ function isPopulateConfig(value) {
17
+ return isRecord(value);
18
+ }
19
+ /**
20
+ * Derive the foreign key field for an inverse relationship.
21
+ *
22
+ * Priority:
23
+ * 1. Explicit `foreignKey` on the inverse relationship definition
24
+ * 2. Explicit `foreignKey` on the corresponding ref relationship in the target collection
25
+ * 3. Default naming convention: singularize source collection name + "Id"
26
+ */
27
+ function resolveInverseForeignKey(relationship, collectionName, dbConfig) {
28
+ if (relationship.foreignKey) {
29
+ return relationship.foreignKey;
30
+ }
31
+ const targetConfig = dbConfig[relationship.target];
32
+ if (targetConfig) {
33
+ const reverseRel = Object.entries(targetConfig.relationships).find(([, rel]) => rel.type === "ref" && rel.target === collectionName);
34
+ if (reverseRel?.[1].foreignKey) {
35
+ return reverseRel[1].foreignKey;
36
+ }
37
+ }
38
+ // Default: singularize collection name + "Id"
39
+ const singularName = collectionName.endsWith("ies")
40
+ ? `${collectionName.slice(0, -3)}y`
41
+ : collectionName.replace(/s$/, "");
42
+ return `${singularName}Id`;
43
+ }
44
+ /**
45
+ * Populate a single item's relationships recursively.
46
+ *
47
+ * For each relationship key in the populate config:
48
+ * - `ref`: look up a single entity in the target collection by foreign key
49
+ * - `inverse`: find all entities whose foreign key points back to this item
50
+ *
51
+ * When the populate value is a nested config object (not just `true`),
52
+ * recursively populate the related entity's relationships using the
53
+ * target collection's relationship definitions.
54
+ *
55
+ * Recursion stops at MAX_POPULATE_DEPTH (5) to prevent infinite loops
56
+ * in circular relationship graphs.
57
+ */
58
+ function populateItem(item, populateConfig, stateRefs, dbConfig, collectionName, depth) {
59
+ return Effect.gen(function* () {
60
+ const sourceConfig = dbConfig[collectionName];
61
+ if (!sourceConfig)
62
+ return item;
63
+ const relationships = sourceConfig.relationships;
64
+ const populateEntries = Object.entries(populateConfig).filter(([key]) => relationships[key] !== undefined);
65
+ if (populateEntries.length === 0)
66
+ return item;
67
+ const populated = { ...item };
68
+ for (const [key, value] of populateEntries) {
69
+ const relationship = relationships[key];
70
+ const targetRef = stateRefs[relationship.target];
71
+ if (!targetRef)
72
+ continue;
73
+ const targetMap = yield* Ref.get(targetRef);
74
+ if (relationship.type === "ref") {
75
+ const foreignKeyField = relationship.foreignKey || `${key}Id`;
76
+ const foreignKeyValue = item[foreignKeyField];
77
+ if (typeof foreignKeyValue === "string") {
78
+ const related = targetMap.get(foreignKeyValue);
79
+ if (related) {
80
+ populated[key] = yield* maybeRecurse(related, value, relationship.target, stateRefs, dbConfig, depth);
81
+ }
82
+ else {
83
+ yield* new DanglingReferenceError({
84
+ collection: relationship.target,
85
+ field: foreignKeyField,
86
+ targetId: foreignKeyValue,
87
+ message: `Entity in "${collectionName}" references missing "${relationship.target}" with ${foreignKeyField}="${foreignKeyValue}"`,
88
+ });
89
+ }
90
+ }
91
+ else {
92
+ populated[key] = undefined;
93
+ }
94
+ }
95
+ else if (relationship.type === "inverse") {
96
+ const foreignKeyField = resolveInverseForeignKey(relationship, collectionName, dbConfig);
97
+ const relatedItems = [];
98
+ for (const entity of targetMap.values()) {
99
+ if (entity[foreignKeyField] === item.id) {
100
+ relatedItems.push(entity);
101
+ }
102
+ }
103
+ if (value === true || !isRecord(value)) {
104
+ populated[key] = relatedItems;
105
+ }
106
+ else {
107
+ const populatedRelated = [];
108
+ for (const relItem of relatedItems) {
109
+ populatedRelated.push(yield* maybeRecurse(relItem, value, relationship.target, stateRefs, dbConfig, depth));
110
+ }
111
+ populated[key] = populatedRelated;
112
+ }
113
+ }
114
+ }
115
+ return populated;
116
+ });
117
+ }
118
+ /**
119
+ * If the populate value is a nested config and we haven't hit the depth limit,
120
+ * recursively populate the related entity. Otherwise return the entity as-is.
121
+ */
122
+ function maybeRecurse(entity, value, targetCollectionName, stateRefs, dbConfig, depth) {
123
+ if (value === true ||
124
+ !isPopulateConfig(value) ||
125
+ depth >= MAX_POPULATE_DEPTH) {
126
+ return Effect.succeed(entity);
127
+ }
128
+ return populateItem(entity, value, stateRefs, dbConfig, targetCollectionName, depth + 1);
129
+ }
130
+ /**
131
+ * Apply relationship population as a Stream combinator.
132
+ *
133
+ * For each item in the stream, resolves relationships by reading related
134
+ * entities from collection Refs. Supports nested population recursively
135
+ * up to a depth of 5.
136
+ *
137
+ * - `ref` relationships: look up a single entity in the target collection
138
+ * using the foreign key field (default: `<relationName>Id`)
139
+ * - `inverse` relationships: find all entities in the target collection
140
+ * whose foreign key points back to this item's `id`
141
+ *
142
+ * @param populateConfig - Which relationships to populate (e.g. `{ company: true }`)
143
+ * @param stateRefs - Map of collection name → Ref<ReadonlyMap<string, entity>>
144
+ * @param dbConfig - Full database config with relationship definitions
145
+ * @param collectionName - Name of the source collection being queried
146
+ */
147
+ export const applyPopulate = (populateConfig, stateRefs, dbConfig, collectionName) => (stream) => {
148
+ if (!populateConfig || !isPopulateConfig(populateConfig))
149
+ return stream;
150
+ const sourceConfig = dbConfig[collectionName];
151
+ if (!sourceConfig)
152
+ return stream;
153
+ const relationships = sourceConfig.relationships;
154
+ const populateEntries = Object.entries(populateConfig).filter(([key]) => relationships[key] !== undefined);
155
+ if (populateEntries.length === 0)
156
+ return stream;
157
+ return Stream.mapEffect(stream, (item) => populateItem(item, populateConfig, stateRefs, dbConfig, collectionName, 0));
158
+ };
159
+ //# sourceMappingURL=populate-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"populate-stream.js","sourceRoot":"","sources":["../../../src/operations/relationships/populate-stream.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ type RelationshipType = "ref" | "inverse";
2
+ interface Relationship {
3
+ type: RelationshipType;
4
+ target: string;
5
+ foreignKey?: string;
6
+ }
7
+ interface CollectionConfig {
8
+ relationships: Record<string, Relationship>;
9
+ }
10
+ export type PopulateValue = boolean | Record<string, unknown>;
11
+ export declare function isPopulateConfig(value: unknown): value is Record<string, PopulateValue>;
12
+ export declare function applyPopulate<T extends Record<string, unknown>>(item: T, populateConfig: Record<string, PopulateValue>, allData: Record<string, unknown[]>, relationships: Record<string, Relationship>, collectionName: string, config: Record<string, CollectionConfig>): T;
13
+ export declare function populateRelationships<T extends Record<string, unknown>>(items: T[], populateConfig: Record<string, PopulateValue> | undefined, allData: Record<string, unknown[]>, relationships: Record<string, Relationship>, collectionName: string, config: Record<string, CollectionConfig>): T[];
14
+ export {};
15
+ //# sourceMappingURL=populate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"populate.d.ts","sourceRoot":"","sources":["../../../src/operations/relationships/populate.ts"],"names":[],"mappings":"AAIA,KAAK,gBAAgB,GAAG,KAAK,GAAG,SAAS,CAAC;AAE1C,UAAU,YAAY;IACrB,IAAI,EAAE,gBAAgB,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,gBAAgB;IACzB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CAC5C;AAED,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAG9D,wBAAgB,gBAAgB,CAC/B,KAAK,EAAE,OAAO,GACZ,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAExC;AAwFD,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9D,IAAI,EAAE,CAAC,EACP,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,EAC7C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,EAClC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,EAC3C,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GACtC,CAAC,CA2MH;AAGD,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACtE,KAAK,EAAE,CAAC,EAAE,EACV,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,SAAS,EACzD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,EAClC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,EAC3C,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GACtC,CAAC,EAAE,CAaL"}
@@ -0,0 +1,228 @@
1
+ import { isValidWhereClause } from "../query/filter.js";
2
+ import { applyObjectSelection } from "../query/select.js";
3
+ // Type guard for populate config objects
4
+ export function isPopulateConfig(value) {
5
+ return value !== null && typeof value === "object" && !Array.isArray(value);
6
+ }
7
+ // Type guard to check if value is a record
8
+ function isRecord(value) {
9
+ return typeof value === "object" && value !== null && !Array.isArray(value);
10
+ }
11
+ // Type guard for string arrays
12
+ function isStringArray(value) {
13
+ return (Array.isArray(value) && value.every((item) => typeof item === "string"));
14
+ }
15
+ function isSelectionConfig(value) {
16
+ return isStringArray(value) || isRecord(value);
17
+ }
18
+ // Safe extraction of nested populate configuration
19
+ function extractNestedConfig(value) {
20
+ const { select, populate, ...otherProps } = value;
21
+ const validNestedPopulate = {};
22
+ // Safely copy otherProps that are valid PopulateValue types
23
+ for (const [key, value] of Object.entries(otherProps)) {
24
+ if (typeof value === "boolean" || isRecord(value)) {
25
+ validNestedPopulate[key] = value;
26
+ }
27
+ }
28
+ // Safely merge populate if it's valid
29
+ if (isPopulateConfig(populate)) {
30
+ for (const [key, value] of Object.entries(populate)) {
31
+ if (typeof value === "boolean" || isRecord(value)) {
32
+ validNestedPopulate[key] = value;
33
+ }
34
+ }
35
+ }
36
+ const result = {
37
+ nestedPopulate: validNestedPopulate,
38
+ };
39
+ if (isSelectionConfig(select)) {
40
+ result.select = select;
41
+ }
42
+ return result;
43
+ }
44
+ // Helper function to find a single related item
45
+ function findRelatedItem(item, foreignKeyField, targetData) {
46
+ if (!targetData || !isValidWhereClause(item))
47
+ return undefined;
48
+ return targetData.find((target) => {
49
+ if (!isValidWhereClause(target))
50
+ return false;
51
+ return target.id === item[foreignKeyField];
52
+ });
53
+ }
54
+ // Helper function to find multiple related items
55
+ function findRelatedItems(item, foreignKeyField, targetData) {
56
+ if (!targetData || !isValidWhereClause(item))
57
+ return [];
58
+ return targetData.filter((target) => {
59
+ if (!isValidWhereClause(target))
60
+ return false;
61
+ return target[foreignKeyField] === item.id;
62
+ });
63
+ }
64
+ // Helper function to apply populate configuration recursively
65
+ export function applyPopulate(item, populateConfig, allData, relationships, collectionName, config) {
66
+ const populated = { ...item };
67
+ for (const [key, value] of Object.entries(populateConfig)) {
68
+ const relationship = relationships[key];
69
+ if (!relationship)
70
+ continue;
71
+ const targetData = allData[relationship.target];
72
+ if (relationship.type === "ref") {
73
+ // Handle ref relationships
74
+ const foreignKeyField = relationship.foreignKey || `${key}Id`;
75
+ const relatedItem = findRelatedItem(populated, foreignKeyField, targetData);
76
+ if (relatedItem && value === true) {
77
+ Object.assign(populated, { [key]: relatedItem });
78
+ }
79
+ else if (relatedItem && isPopulateConfig(value)) {
80
+ // Recursively populate nested config
81
+ const targetConfig = config[relationship.target];
82
+ if (targetConfig) {
83
+ // Extract nested populate config and select from value safely
84
+ const { select, nestedPopulate } = extractNestedConfig(value);
85
+ // Apply nested population first
86
+ let populatedRelated = relatedItem;
87
+ if (Object.keys(nestedPopulate).length > 0) {
88
+ populatedRelated = applyPopulate(relatedItem, nestedPopulate, allData, targetConfig.relationships, relationship.target, config);
89
+ }
90
+ // Apply field selection if specified (supports both array and object-based)
91
+ if (select) {
92
+ let selectedFields;
93
+ if (isStringArray(select)) {
94
+ // Convert array to object format
95
+ const objectSelect = {};
96
+ for (const field of select) {
97
+ objectSelect[field] = true;
98
+ }
99
+ selectedFields = applyObjectSelection(populatedRelated, objectSelect);
100
+ }
101
+ else if (isRecord(select)) {
102
+ selectedFields = applyObjectSelection(populatedRelated, select);
103
+ }
104
+ else {
105
+ // Invalid select format, skip selection
106
+ selectedFields = populatedRelated;
107
+ }
108
+ // For object-based selection, the nested fields are already handled by applyObjectSelection
109
+ // For array-based selection, preserve any populated fields that are defined in relationships
110
+ let finalResult = selectedFields;
111
+ if (isStringArray(select)) {
112
+ // Only for array-based selection, we need to preserve populated relationships
113
+ finalResult = { ...selectedFields };
114
+ // Check relationships in the target config to know which fields are populated
115
+ for (const [relKey, _relDef] of Object.entries(targetConfig.relationships)) {
116
+ if (nestedPopulate[relKey] && relKey in populatedRelated) {
117
+ finalResult[relKey] = populatedRelated[relKey];
118
+ }
119
+ }
120
+ }
121
+ populatedRelated = finalResult;
122
+ }
123
+ Object.assign(populated, { [key]: populatedRelated });
124
+ }
125
+ }
126
+ else {
127
+ Object.assign(populated, { [key]: undefined });
128
+ }
129
+ }
130
+ else if (relationship.type === "inverse") {
131
+ // Handle inverse relationships
132
+ // For inverse relationships, we need to find items in the target collection
133
+ // that have a foreign key pointing back to this collection
134
+ // First, check if there's a specific foreignKey configured
135
+ let foreignKeyField;
136
+ if (relationship.foreignKey) {
137
+ foreignKeyField = relationship.foreignKey;
138
+ }
139
+ else {
140
+ // Look for the corresponding ref relationship in the target collection
141
+ const targetConfig = config[relationship.target];
142
+ if (targetConfig) {
143
+ // Find the relationship that points back to our collection
144
+ const reverseRelationship = Object.entries(targetConfig.relationships).find(([, rel]) => rel.type === "ref" && rel.target === collectionName);
145
+ if (reverseRelationship?.[1].foreignKey) {
146
+ foreignKeyField = reverseRelationship[1].foreignKey;
147
+ }
148
+ else {
149
+ // Fall back to the default naming convention
150
+ const singularName = collectionName.endsWith("ies")
151
+ ? `${collectionName.slice(0, -3)}y` // companies -> company, industries -> industry
152
+ : collectionName.replace(/s$/, ""); // users -> user, posts -> post
153
+ foreignKeyField = `${singularName}Id`;
154
+ }
155
+ }
156
+ else {
157
+ // Fall back to the default naming convention
158
+ const singularName = collectionName.endsWith("ies")
159
+ ? `${collectionName.slice(0, -3)}y` // companies -> company, industries -> industry
160
+ : collectionName.replace(/s$/, ""); // users -> user, posts -> post
161
+ foreignKeyField = `${singularName}Id`;
162
+ }
163
+ }
164
+ const relatedItems = findRelatedItems(populated, foreignKeyField, targetData);
165
+ if (value === true) {
166
+ Object.assign(populated, { [key]: relatedItems });
167
+ }
168
+ else if (isPopulateConfig(value)) {
169
+ // Recursively populate each item in the array
170
+ const targetConfig = config[relationship.target];
171
+ if (targetConfig) {
172
+ // Extract nested populate config and select from value safely
173
+ const { select, nestedPopulate } = extractNestedConfig(value);
174
+ const populatedItems = relatedItems.map((relItem) => {
175
+ // Apply nested population first
176
+ let populatedItem = relItem;
177
+ if (Object.keys(nestedPopulate).length > 0) {
178
+ populatedItem = applyPopulate(relItem, nestedPopulate, allData, targetConfig.relationships, relationship.target, config);
179
+ }
180
+ // Apply field selection if specified (supports both array and object-based)
181
+ if (select) {
182
+ let selectedFields;
183
+ if (isStringArray(select)) {
184
+ // Convert array to object format
185
+ const objectSelect = {};
186
+ for (const field of select) {
187
+ objectSelect[field] = true;
188
+ }
189
+ selectedFields = applyObjectSelection(populatedItem, objectSelect);
190
+ }
191
+ else if (isRecord(select)) {
192
+ selectedFields = applyObjectSelection(populatedItem, select);
193
+ }
194
+ else {
195
+ // Invalid select format, skip selection
196
+ selectedFields = populatedItem;
197
+ }
198
+ // For object-based selection, the nested fields are already handled by applyObjectSelection
199
+ // For array-based selection, preserve any populated fields that are defined in relationships
200
+ let finalResult = selectedFields;
201
+ if (isStringArray(select)) {
202
+ // Only for array-based selection, we need to preserve populated relationships
203
+ finalResult = { ...selectedFields };
204
+ // Check relationships in the target config to know which fields are populated
205
+ for (const [relKey, _relDef] of Object.entries(targetConfig.relationships)) {
206
+ if (nestedPopulate[relKey] && relKey in populatedItem) {
207
+ finalResult[relKey] = populatedItem[relKey];
208
+ }
209
+ }
210
+ }
211
+ populatedItem = finalResult;
212
+ }
213
+ return populatedItem;
214
+ });
215
+ Object.assign(populated, { [key]: populatedItems });
216
+ }
217
+ }
218
+ }
219
+ }
220
+ return populated;
221
+ }
222
+ // Helper function to populate relationships
223
+ export function populateRelationships(items, populateConfig, allData, relationships, collectionName, config) {
224
+ if (!populateConfig || !isPopulateConfig(populateConfig))
225
+ return items;
226
+ return items.map((item) => applyPopulate(item, populateConfig, allData, relationships, collectionName, config));
227
+ }
228
+ //# sourceMappingURL=populate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"populate.js","sourceRoot":"","sources":["../../../src/operations/relationships/populate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Plugin hooks utilities for merging global hooks with collection hooks.
3
+ *
4
+ * Global plugin hooks run before collection-specific hooks because they represent
5
+ * cross-cutting concerns (audit logging, encryption) that should see data before
6
+ * collection-specific transformations.
7
+ */
8
+ import type { HooksConfig } from "../types/hook-types.js";
9
+ import type { GlobalHooksConfig } from "./plugin-types.js";
10
+ /**
11
+ * Merges global plugin hooks with collection-specific hooks.
12
+ *
13
+ * For each hook type, global hooks are prepended before collection hooks.
14
+ * This ensures global hooks (cross-cutting concerns) run first.
15
+ *
16
+ * Type narrowing: Global hooks are `HooksConfig<Record<string, unknown>>`,
17
+ * collection hooks are `HooksConfig<T>`. The merged result is `HooksConfig<T>`
18
+ * with global hooks cast appropriately.
19
+ *
20
+ * @param globalHooks - Global hooks from plugin registry (may be empty/undefined)
21
+ * @param collectionHooks - Collection-specific hooks (may be empty/undefined)
22
+ * @returns Merged hooks config with global hooks first
23
+ */
24
+ export declare const mergeGlobalHooks: <T extends Record<string, unknown>>(globalHooks: GlobalHooksConfig | undefined, collectionHooks: HooksConfig<T> | undefined) => HooksConfig<T>;
25
+ //# sourceMappingURL=plugin-hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-hooks.d.ts","sourceRoot":"","sources":["../../src/plugins/plugin-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjE,aAAa,iBAAiB,GAAG,SAAS,EAC1C,iBAAiB,WAAW,CAAC,CAAC,CAAC,GAAG,SAAS,KACzC,WAAW,CAAC,CAAC,CA6Cf,CAAC"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Plugin hooks utilities for merging global hooks with collection hooks.
3
+ *
4
+ * Global plugin hooks run before collection-specific hooks because they represent
5
+ * cross-cutting concerns (audit logging, encryption) that should see data before
6
+ * collection-specific transformations.
7
+ */
8
+ /**
9
+ * Merges global plugin hooks with collection-specific hooks.
10
+ *
11
+ * For each hook type, global hooks are prepended before collection hooks.
12
+ * This ensures global hooks (cross-cutting concerns) run first.
13
+ *
14
+ * Type narrowing: Global hooks are `HooksConfig<Record<string, unknown>>`,
15
+ * collection hooks are `HooksConfig<T>`. The merged result is `HooksConfig<T>`
16
+ * with global hooks cast appropriately.
17
+ *
18
+ * @param globalHooks - Global hooks from plugin registry (may be empty/undefined)
19
+ * @param collectionHooks - Collection-specific hooks (may be empty/undefined)
20
+ * @returns Merged hooks config with global hooks first
21
+ */
22
+ export const mergeGlobalHooks = (globalHooks, collectionHooks) => {
23
+ // If no global hooks, return collection hooks as-is (or empty object)
24
+ if (!globalHooks) {
25
+ return collectionHooks ?? {};
26
+ }
27
+ // If no collection hooks, cast global hooks to the collection type
28
+ if (!collectionHooks) {
29
+ return globalHooks;
30
+ }
31
+ // Merge each hook array: global first, then collection
32
+ // Note: Global hooks have Record<string, unknown> type and need casting
33
+ // to the specific collection type T. This is safe because global hooks
34
+ // operate on any entity shape and T extends Record<string, unknown>.
35
+ return {
36
+ beforeCreate: mergeHookArrays(globalHooks.beforeCreate, collectionHooks.beforeCreate),
37
+ afterCreate: mergeHookArrays(globalHooks.afterCreate, collectionHooks.afterCreate),
38
+ beforeUpdate: mergeHookArrays(globalHooks.beforeUpdate, collectionHooks.beforeUpdate),
39
+ afterUpdate: mergeHookArrays(globalHooks.afterUpdate, collectionHooks.afterUpdate),
40
+ beforeDelete: mergeHookArrays(globalHooks.beforeDelete, collectionHooks.beforeDelete),
41
+ afterDelete: mergeHookArrays(globalHooks.afterDelete, collectionHooks.afterDelete),
42
+ onChange: mergeHookArrays(globalHooks.onChange, collectionHooks.onChange),
43
+ };
44
+ };
45
+ /**
46
+ * Helper to merge two optional hook arrays.
47
+ * Global hooks come first, then collection hooks.
48
+ * Returns undefined if both are empty/undefined.
49
+ */
50
+ const mergeHookArrays = (global, collection) => {
51
+ const hasGlobal = global && global.length > 0;
52
+ const hasCollection = collection && collection.length > 0;
53
+ if (!hasGlobal && !hasCollection) {
54
+ return undefined;
55
+ }
56
+ if (!hasGlobal) {
57
+ return collection;
58
+ }
59
+ if (!hasCollection) {
60
+ return global;
61
+ }
62
+ return [...global, ...collection];
63
+ };
64
+ //# sourceMappingURL=plugin-hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-hooks.js","sourceRoot":"","sources":["../../src/plugins/plugin-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC/B,WAA0C,EAC1C,eAA2C,EAC1B,EAAE;IACnB,sEAAsE;IACtE,IAAI,CAAC,WAAW,EAAE,CAAC;QAClB,OAAO,eAAe,IAAI,EAAE,CAAC;IAC9B,CAAC;IAED,mEAAmE;IACnE,IAAI,CAAC,eAAe,EAAE,CAAC;QACtB,OAAO,WAA6B,CAAC;IACtC,CAAC;IAED,uDAAuD;IACvD,wEAAwE;IACxE,uEAAuE;IACvE,qEAAqE;IACrE,OAAO;QACN,YAAY,EAAE,eAAe,CAC5B,WAAW,CAAC,YAA8C,EAC1D,eAAe,CAAC,YAAY,CAC5B;QACD,WAAW,EAAE,eAAe,CAC3B,WAAW,CAAC,WAA4C,EACxD,eAAe,CAAC,WAAW,CAC3B;QACD,YAAY,EAAE,eAAe,CAC5B,WAAW,CAAC,YAA8C,EAC1D,eAAe,CAAC,YAAY,CAC5B;QACD,WAAW,EAAE,eAAe,CAC3B,WAAW,CAAC,WAA4C,EACxD,eAAe,CAAC,WAAW,CAC3B;QACD,YAAY,EAAE,eAAe,CAC5B,WAAW,CAAC,YAA8C,EAC1D,eAAe,CAAC,YAAY,CAC5B;QACD,WAAW,EAAE,eAAe,CAC3B,WAAW,CAAC,WAA4C,EACxD,eAAe,CAAC,WAAW,CAC3B;QACD,QAAQ,EAAE,eAAe,CACxB,WAAW,CAAC,QAAsC,EAClD,eAAe,CAAC,QAAQ,CACxB;KACiB,CAAC;AACrB,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,eAAe,GAAG,CACvB,MAAoC,EACpC,UAAwC,EACT,EAAE;IACjC,MAAM,SAAS,GAAG,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IAC9C,MAAM,aAAa,GAAG,UAAU,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;IAE1D,IAAI,CAAC,SAAS,IAAI,CAAC,aAAa,EAAE,CAAC;QAClC,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,SAAS,EAAE,CAAC;QAChB,OAAO,UAAU,CAAC;IACnB,CAAC;IAED,IAAI,CAAC,aAAa,EAAE,CAAC;QACpB,OAAO,MAAM,CAAC;IACf,CAAC;IAED,OAAO,CAAC,GAAG,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC;AACnC,CAAC,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Plugin registry builder.
3
+ * Validates plugins and merges their contributions into a single registry.
4
+ */
5
+ import { Effect } from "effect";
6
+ import type { PluginError } from "../errors/plugin-errors.js";
7
+ import type { PluginRegistry, ProseQLPlugin } from "./plugin-types.js";
8
+ /**
9
+ * Builds a PluginRegistry from an array of plugins.
10
+ *
11
+ * This function:
12
+ * 1. Validates each plugin individually (structure, codecs, operators, generators)
13
+ * 2. Validates operator conflicts (between plugins and with built-in operators)
14
+ * 3. Validates dependencies (all declared dependencies must exist)
15
+ * 4. Merges codecs (append in registration order)
16
+ * 5. Merges operators into a Map (O(1) lookup)
17
+ * 6. Merges ID generators into a Map (O(1) lookup)
18
+ * 7. Merges global hooks (concatenate arrays in registration order)
19
+ *
20
+ * If plugins is undefined or empty, returns an empty registry.
21
+ *
22
+ * @param plugins - Array of plugins to validate and merge (optional)
23
+ * @returns Effect<PluginRegistry, PluginError> - The merged registry or validation error
24
+ */
25
+ export declare const buildPluginRegistry: (plugins?: ReadonlyArray<ProseQLPlugin>) => Effect.Effect<PluginRegistry, PluginError>;
26
+ //# sourceMappingURL=plugin-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-registry.d.ts","sourceRoot":"","sources":["../../src/plugins/plugin-registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAIX,cAAc,EACd,aAAa,EACb,MAAM,mBAAmB,CAAC;AA0B3B;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,mBAAmB,GAC/B,UAAU,aAAa,CAAC,aAAa,CAAC,KACpC,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,WAAW,CAmD3C,CAAC"}