@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,153 @@
1
+ /**
2
+ * Foreign key validation system.
3
+ *
4
+ * Effect-based validators use Ref<ReadonlyMap> for O(1) lookups.
5
+ */
6
+ import { Effect, Ref } from "effect";
7
+ import { ForeignKeyError } from "../errors/crud-errors.js";
8
+ // ============================================================================
9
+ // Foreign Key Config Extraction (pure, shared by legacy and Effect paths)
10
+ // ============================================================================
11
+ /**
12
+ * Extract foreign key configurations from relationships
13
+ */
14
+ export function extractForeignKeyConfigs(relationships) {
15
+ const configs = [];
16
+ for (const [field, rel] of Object.entries(relationships)) {
17
+ if (rel.type === "ref") {
18
+ const targetCollection = rel.target ||
19
+ rel
20
+ .__targetCollection ||
21
+ field;
22
+ configs.push({
23
+ field,
24
+ foreignKey: rel.foreignKey || `${field}Id`,
25
+ targetCollection,
26
+ optional: false,
27
+ });
28
+ }
29
+ }
30
+ return configs;
31
+ }
32
+ // ============================================================================
33
+ // Effect-based Foreign Key Validation
34
+ // ============================================================================
35
+ /**
36
+ * Validate foreign keys for an entity using Ref-based state.
37
+ * Returns Effect that fails with ForeignKeyError if a violation is found.
38
+ *
39
+ * Uses ReadonlyMap for O(1) lookups instead of legacy array scanning.
40
+ */
41
+ export const validateForeignKeysEffect = (entity, collectionName, relationships, stateRefs) => {
42
+ const configs = extractForeignKeyConfigs(relationships);
43
+ if (configs.length === 0) {
44
+ return Effect.void;
45
+ }
46
+ return Effect.forEach(configs, (config) => {
47
+ const value = entity[config.foreignKey];
48
+ if (value === undefined || value === null) {
49
+ return Effect.void;
50
+ }
51
+ const targetRef = stateRefs[config.targetCollection];
52
+ if (targetRef === undefined) {
53
+ return Effect.fail(new ForeignKeyError({
54
+ collection: collectionName,
55
+ field: config.foreignKey,
56
+ value: String(value),
57
+ targetCollection: config.targetCollection,
58
+ message: `Foreign key constraint violated: '${config.foreignKey}' references non-existent collection '${config.targetCollection}'`,
59
+ }));
60
+ }
61
+ return Ref.get(targetRef).pipe(Effect.flatMap((targetMap) => {
62
+ if (targetMap.has(String(value))) {
63
+ return Effect.void;
64
+ }
65
+ return Effect.fail(new ForeignKeyError({
66
+ collection: collectionName,
67
+ field: config.foreignKey,
68
+ value: String(value),
69
+ targetCollection: config.targetCollection,
70
+ message: `Foreign key constraint violated: '${config.foreignKey}' references non-existent ${config.targetCollection} '${value}'`,
71
+ }));
72
+ }));
73
+ }, { discard: true });
74
+ };
75
+ /**
76
+ * Check if deleting an entity would violate foreign key constraints.
77
+ * Scans all collections for "ref" relationships targeting this collection
78
+ * whose foreign key field references the entity being deleted.
79
+ *
80
+ * Returns Effect that fails with ForeignKeyError if violations exist.
81
+ */
82
+ export const checkDeleteConstraintsEffect = (entityId, collectionName, allRelationships, stateRefs) => Effect.gen(function* () {
83
+ for (const [otherCollection, relationships] of Object.entries(allRelationships)) {
84
+ for (const [field, rel] of Object.entries(relationships)) {
85
+ if (rel.type === "ref" && rel.target === collectionName) {
86
+ const foreignKey = rel.foreignKey || `${field}Id`;
87
+ const otherRef = stateRefs[otherCollection];
88
+ if (otherRef === undefined)
89
+ continue;
90
+ const otherMap = yield* Ref.get(otherRef);
91
+ let refCount = 0;
92
+ for (const entity of otherMap.values()) {
93
+ if (entity[foreignKey] === entityId) {
94
+ refCount++;
95
+ }
96
+ }
97
+ if (refCount > 0) {
98
+ return yield* Effect.fail(new ForeignKeyError({
99
+ collection: collectionName,
100
+ field: foreignKey,
101
+ value: entityId,
102
+ targetCollection: otherCollection,
103
+ message: `Cannot delete: ${refCount} ${otherCollection} entities reference this ${collectionName}`,
104
+ }));
105
+ }
106
+ }
107
+ }
108
+ }
109
+ });
110
+ /**
111
+ * Check referential integrity for an entire database using Ref-based state.
112
+ * Returns Effect with a list of violations.
113
+ */
114
+ export const checkReferentialIntegrityEffect = (allRelationships, stateRefs) => Effect.gen(function* () {
115
+ const violations = [];
116
+ for (const [collection, relationships] of Object.entries(allRelationships)) {
117
+ const collectionRef = stateRefs[collection];
118
+ if (collectionRef === undefined)
119
+ continue;
120
+ const collectionMap = yield* Ref.get(collectionRef);
121
+ const foreignKeyConfigs = extractForeignKeyConfigs(relationships);
122
+ for (const [entityId, entity] of collectionMap.entries()) {
123
+ for (const config of foreignKeyConfigs) {
124
+ const value = entity[config.foreignKey];
125
+ if (value === null || value === undefined)
126
+ continue;
127
+ const targetRef = stateRefs[config.targetCollection];
128
+ if (targetRef === undefined) {
129
+ violations.push({
130
+ collection,
131
+ entityId,
132
+ field: config.field,
133
+ invalidReference: value,
134
+ targetCollection: config.targetCollection,
135
+ });
136
+ continue;
137
+ }
138
+ const targetMap = yield* Ref.get(targetRef);
139
+ if (!targetMap.has(String(value))) {
140
+ violations.push({
141
+ collection,
142
+ entityId,
143
+ field: config.field,
144
+ invalidReference: value,
145
+ targetCollection: config.targetCollection,
146
+ });
147
+ }
148
+ }
149
+ }
150
+ }
151
+ return violations;
152
+ });
153
+ //# sourceMappingURL=foreign-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"foreign-key.js","sourceRoot":"","sources":["../../src/validators/foreign-key.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Effect Schema decode/encode wrappers that map ParseError to ValidationError.
3
+ *
4
+ * These functions bridge Effect Schema's parse errors into the database's
5
+ * ValidationError type for consistent error handling across CRUD operations.
6
+ */
7
+ import { Effect, Schema } from "effect";
8
+ import { ValidationError } from "../errors/index.js";
9
+ /**
10
+ * Decode unknown data through an Effect Schema, producing a typed entity.
11
+ * Maps Schema ParseError to the database's ValidationError.
12
+ */
13
+ export declare const validateEntity: <A, I, R>(schema: Schema.Schema<A, I, R>, data: unknown) => Effect.Effect<A, ValidationError, R>;
14
+ /**
15
+ * Encode a typed entity through an Effect Schema, producing the encoded (on-disk) form.
16
+ * Maps Schema ParseError to the database's ValidationError.
17
+ */
18
+ export declare const encodeEntity: <A, I, R>(schema: Schema.Schema<A, I, R>, entity: A) => Effect.Effect<I, ValidationError, R>;
19
+ //# sourceMappingURL=schema-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-validator.d.ts","sourceRoot":"","sources":["../../src/validators/schema-validator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAe,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EACrC,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC9B,MAAM,OAAO,KACX,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,CAGpC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EACnC,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC9B,QAAQ,CAAC,KACP,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,CAGpC,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Effect Schema decode/encode wrappers that map ParseError to ValidationError.
3
+ *
4
+ * These functions bridge Effect Schema's parse errors into the database's
5
+ * ValidationError type for consistent error handling across CRUD operations.
6
+ */
7
+ import { Effect, ParseResult, Schema } from "effect";
8
+ import { ValidationError } from "../errors/index.js";
9
+ /**
10
+ * Decode unknown data through an Effect Schema, producing a typed entity.
11
+ * Maps Schema ParseError to the database's ValidationError.
12
+ */
13
+ export const validateEntity = (schema, data) => Schema.decodeUnknown(schema)(data).pipe(Effect.mapError((parseError) => parseErrorToValidationError(parseError)));
14
+ /**
15
+ * Encode a typed entity through an Effect Schema, producing the encoded (on-disk) form.
16
+ * Maps Schema ParseError to the database's ValidationError.
17
+ */
18
+ export const encodeEntity = (schema, entity) => Schema.encode(schema)(entity).pipe(Effect.mapError((parseError) => parseErrorToValidationError(parseError)));
19
+ /**
20
+ * Convert an Effect Schema ParseError into our ValidationError,
21
+ * extracting structured issue details via ArrayFormatter.
22
+ */
23
+ const parseErrorToValidationError = (parseError) => {
24
+ const arrayIssues = ParseResult.ArrayFormatter.formatErrorSync(parseError);
25
+ const message = ParseResult.TreeFormatter.formatErrorSync(parseError);
26
+ return new ValidationError({
27
+ message,
28
+ issues: arrayIssues.map((issue) => ({
29
+ field: issue.path.map(String).join(".") || "(root)",
30
+ message: issue.message,
31
+ })),
32
+ });
33
+ };
34
+ //# sourceMappingURL=schema-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-validator.js","sourceRoot":"","sources":["../../src/validators/schema-validator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAC7B,MAA8B,EAC9B,IAAa,EAC0B,EAAE,CACzC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CACtC,MAAM,CAAC,QAAQ,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,2BAA2B,CAAC,UAAU,CAAC,CAAC,CACxE,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC3B,MAA8B,EAC9B,MAAS,EAC8B,EAAE,CACzC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CACjC,MAAM,CAAC,QAAQ,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,2BAA2B,CAAC,UAAU,CAAC,CAAC,CACxE,CAAC;AAEH;;;GAGG;AACH,MAAM,2BAA2B,GAAG,CACnC,UAAkC,EAChB,EAAE;IACpB,MAAM,WAAW,GAAG,WAAW,CAAC,cAAc,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;IAC3E,MAAM,OAAO,GAAG,WAAW,CAAC,aAAa,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;IAEtE,OAAO,IAAI,eAAe,CAAC;QAC1B,OAAO;QACP,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACnC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ;YACnD,OAAO,EAAE,KAAK,CAAC,OAAO;SACtB,CAAC,CAAC;KACH,CAAC,CAAC;AACJ,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@proseql/core",
3
+ "version": "0.1.0",
4
+ "description": "Type-safe in-memory database that persists to plain text files (JSON, YAML, TOML), built on Effect",
5
+ "type": "module",
6
+ "scripts": {
7
+ "build": "bunx tsc --build",
8
+ "clean": "rm -rf dist *.tsbuildinfo",
9
+ "prepublishOnly": "bun run build && bun test"
10
+ },
11
+ "main": "dist/index.js",
12
+ "types": "dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "LICENSE",
22
+ "README.md"
23
+ ],
24
+ "license": "MIT",
25
+ "author": "Simon W. Jackson",
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/simonwjackson/proseql.git",
32
+ "directory": "packages/core"
33
+ },
34
+ "keywords": [
35
+ "database",
36
+ "typescript",
37
+ "effect",
38
+ "yaml",
39
+ "json",
40
+ "plain-text",
41
+ "type-safe",
42
+ "in-memory"
43
+ ],
44
+ "engines": {
45
+ "node": ">=18"
46
+ },
47
+ "sideEffects": false,
48
+ "dependencies": {
49
+ "effect": "^3.15.2",
50
+ "yaml": "^2.3.4",
51
+ "json5": "^2.2.3",
52
+ "jsonc-parser": "^3.3.1",
53
+ "smol-toml": "^1.6.0",
54
+ "@toon-format/toon": "^2.1.0",
55
+ "hjson": "^3.2.2"
56
+ }
57
+ }