boltstore 0.5.1 → 0.6.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 (423) hide show
  1. package/README.md +65 -23
  2. package/dist/admin/api-keys.d.ts +87 -0
  3. package/dist/admin/api-keys.d.ts.map +1 -0
  4. package/dist/admin/api-keys.js +267 -0
  5. package/dist/admin/api-keys.js.map +1 -0
  6. package/dist/admin/backup.d.ts +76 -0
  7. package/dist/admin/backup.d.ts.map +1 -0
  8. package/dist/admin/backup.js +255 -0
  9. package/dist/admin/backup.js.map +1 -0
  10. package/dist/admin/import-export/csv.d.ts +4 -0
  11. package/dist/admin/import-export/csv.d.ts.map +1 -0
  12. package/dist/admin/import-export/csv.js +123 -0
  13. package/dist/admin/import-export/csv.js.map +1 -0
  14. package/dist/admin/import-export/export.d.ts +4 -0
  15. package/dist/admin/import-export/export.d.ts.map +1 -0
  16. package/dist/admin/import-export/export.js +66 -0
  17. package/dist/admin/import-export/export.js.map +1 -0
  18. package/dist/admin/import-export/import.d.ts +4 -0
  19. package/dist/admin/import-export/import.d.ts.map +1 -0
  20. package/dist/admin/import-export/import.js +253 -0
  21. package/dist/admin/import-export/import.js.map +1 -0
  22. package/dist/admin/import-export/index.d.ts +7 -0
  23. package/dist/admin/import-export/index.d.ts.map +1 -0
  24. package/dist/admin/import-export/index.js +7 -0
  25. package/dist/admin/import-export/index.js.map +1 -0
  26. package/dist/admin/import-export/json-input.d.ts +2 -0
  27. package/dist/admin/import-export/json-input.d.ts.map +1 -0
  28. package/dist/admin/import-export/json-input.js +42 -0
  29. package/dist/admin/import-export/json-input.js.map +1 -0
  30. package/dist/admin/import-export/schema-inference.d.ts +6 -0
  31. package/dist/admin/import-export/schema-inference.d.ts.map +1 -0
  32. package/dist/admin/import-export/schema-inference.js +34 -0
  33. package/dist/admin/import-export/schema-inference.js.map +1 -0
  34. package/dist/admin/import-export/types.d.ts +40 -0
  35. package/dist/admin/import-export/types.d.ts.map +1 -0
  36. package/dist/admin/import-export/types.js +2 -0
  37. package/dist/admin/import-export/types.js.map +1 -0
  38. package/dist/admin/oauth/github.d.ts +12 -0
  39. package/dist/admin/oauth/github.d.ts.map +1 -0
  40. package/dist/admin/oauth/github.js +78 -0
  41. package/dist/admin/oauth/github.js.map +1 -0
  42. package/dist/admin/oauth/google.d.ts +12 -0
  43. package/dist/admin/oauth/google.d.ts.map +1 -0
  44. package/dist/admin/oauth/google.js +55 -0
  45. package/dist/admin/oauth/google.js.map +1 -0
  46. package/dist/admin/oauth/handler.d.ts +5 -0
  47. package/dist/admin/oauth/handler.d.ts.map +1 -0
  48. package/dist/admin/oauth/handler.js +37 -0
  49. package/dist/admin/oauth/handler.js.map +1 -0
  50. package/dist/admin/oauth/index.d.ts +5 -0
  51. package/dist/admin/oauth/index.d.ts.map +1 -0
  52. package/dist/admin/oauth/index.js +5 -0
  53. package/dist/admin/oauth/index.js.map +1 -0
  54. package/dist/admin/oauth/registry.d.ts +16 -0
  55. package/dist/admin/oauth/registry.d.ts.map +1 -0
  56. package/dist/admin/oauth/registry.js +37 -0
  57. package/dist/admin/oauth/registry.js.map +1 -0
  58. package/dist/admin/oauth/types.d.ts +14 -0
  59. package/dist/admin/oauth/types.d.ts.map +1 -0
  60. package/dist/admin/oauth/types.js +2 -0
  61. package/dist/admin/oauth/types.js.map +1 -0
  62. package/dist/admin/oauth/user.d.ts +12 -0
  63. package/dist/admin/oauth/user.d.ts.map +1 -0
  64. package/dist/admin/oauth/user.js +28 -0
  65. package/dist/admin/oauth/user.js.map +1 -0
  66. package/dist/admin/query.d.ts +54 -0
  67. package/dist/admin/query.d.ts.map +1 -0
  68. package/dist/admin/query.js +168 -0
  69. package/dist/admin/query.js.map +1 -0
  70. package/dist/admin/transaction.d.ts +46 -0
  71. package/dist/admin/transaction.d.ts.map +1 -0
  72. package/dist/admin/transaction.js +52 -0
  73. package/dist/admin/transaction.js.map +1 -0
  74. package/dist/admin/views.d.ts +64 -0
  75. package/dist/admin/views.d.ts.map +1 -0
  76. package/dist/admin/views.js +197 -0
  77. package/dist/admin/views.js.map +1 -0
  78. package/dist/audit.d.ts +36 -0
  79. package/dist/audit.d.ts.map +1 -0
  80. package/dist/audit.js +92 -0
  81. package/dist/audit.js.map +1 -0
  82. package/dist/auth/jwt.d.ts +8 -0
  83. package/dist/auth/jwt.d.ts.map +1 -0
  84. package/dist/auth/jwt.js +81 -0
  85. package/dist/auth/jwt.js.map +1 -0
  86. package/dist/auth/password.d.ts +4 -0
  87. package/dist/auth/password.d.ts.map +1 -0
  88. package/dist/auth/password.js +15 -0
  89. package/dist/auth/password.js.map +1 -0
  90. package/dist/auth/tables.d.ts +5 -0
  91. package/dist/auth/tables.d.ts.map +1 -0
  92. package/dist/auth/tables.js +65 -0
  93. package/dist/auth/tables.js.map +1 -0
  94. package/dist/auth/tokens.d.ts +16 -0
  95. package/dist/auth/tokens.d.ts.map +1 -0
  96. package/dist/auth/tokens.js +126 -0
  97. package/dist/auth/tokens.js.map +1 -0
  98. package/dist/auth/types.d.ts +36 -0
  99. package/dist/auth/types.d.ts.map +1 -0
  100. package/dist/auth/types.js +2 -0
  101. package/dist/auth/types.js.map +1 -0
  102. package/dist/auth/users.d.ts +9 -0
  103. package/dist/auth/users.d.ts.map +1 -0
  104. package/dist/auth/users.js +83 -0
  105. package/dist/auth/users.js.map +1 -0
  106. package/dist/auth/validation.d.ts +5 -0
  107. package/dist/auth/validation.d.ts.map +1 -0
  108. package/dist/auth/validation.js +25 -0
  109. package/dist/auth/validation.js.map +1 -0
  110. package/dist/auth.d.ts +9 -0
  111. package/dist/auth.d.ts.map +1 -0
  112. package/dist/auth.js +9 -0
  113. package/dist/auth.js.map +1 -0
  114. package/dist/cli.d.ts +12 -0
  115. package/dist/cli.d.ts.map +1 -0
  116. package/dist/cli.js +322 -0
  117. package/dist/cli.js.map +1 -0
  118. package/dist/collections/ddl.d.ts +25 -0
  119. package/dist/collections/ddl.d.ts.map +1 -0
  120. package/dist/collections/ddl.js +83 -0
  121. package/dist/collections/ddl.js.map +1 -0
  122. package/dist/collections/management.d.ts +57 -0
  123. package/dist/collections/management.d.ts.map +1 -0
  124. package/dist/collections/management.js +289 -0
  125. package/dist/collections/management.js.map +1 -0
  126. package/dist/collections.d.ts +3 -0
  127. package/dist/collections.d.ts.map +1 -0
  128. package/dist/collections.js +3 -0
  129. package/dist/collections.js.map +1 -0
  130. package/dist/config.d.ts +47 -0
  131. package/dist/config.d.ts.map +1 -0
  132. package/dist/config.js +274 -0
  133. package/dist/config.js.map +1 -0
  134. package/dist/db/cast.d.ts +15 -0
  135. package/dist/db/cast.d.ts.map +1 -0
  136. package/dist/db/cast.js +16 -0
  137. package/dist/db/cast.js.map +1 -0
  138. package/dist/db/manager.d.ts +93 -0
  139. package/dist/db/manager.d.ts.map +1 -0
  140. package/dist/db/manager.js +209 -0
  141. package/dist/db/manager.js.map +1 -0
  142. package/dist/db/pool.d.ts +99 -0
  143. package/dist/db/pool.d.ts.map +1 -0
  144. package/dist/db/pool.js +232 -0
  145. package/dist/db/pool.js.map +1 -0
  146. package/dist/entry.d.ts +11 -0
  147. package/dist/entry.d.ts.map +1 -0
  148. package/dist/entry.js +80 -0
  149. package/dist/entry.js.map +1 -0
  150. package/dist/index.d.ts +10 -0
  151. package/dist/index.d.ts.map +1 -0
  152. package/dist/index.js +47 -0
  153. package/dist/index.js.map +1 -0
  154. package/dist/indexes.d.ts +61 -0
  155. package/dist/indexes.d.ts.map +1 -0
  156. package/dist/indexes.js +174 -0
  157. package/dist/indexes.js.map +1 -0
  158. package/dist/logger.d.ts +40 -0
  159. package/dist/logger.d.ts.map +1 -0
  160. package/dist/logger.js +147 -0
  161. package/dist/logger.js.map +1 -0
  162. package/dist/middleware/auth.d.ts +43 -0
  163. package/dist/middleware/auth.d.ts.map +1 -0
  164. package/dist/middleware/auth.js +87 -0
  165. package/dist/middleware/auth.js.map +1 -0
  166. package/dist/middleware/cors.d.ts +28 -0
  167. package/dist/middleware/cors.d.ts.map +1 -0
  168. package/dist/middleware/cors.js +71 -0
  169. package/dist/middleware/cors.js.map +1 -0
  170. package/dist/middleware/proxy.d.ts +10 -0
  171. package/dist/middleware/proxy.d.ts.map +1 -0
  172. package/dist/middleware/proxy.js +31 -0
  173. package/dist/middleware/proxy.js.map +1 -0
  174. package/dist/middleware/rate-limit.d.ts +64 -0
  175. package/dist/middleware/rate-limit.d.ts.map +1 -0
  176. package/dist/middleware/rate-limit.js +130 -0
  177. package/dist/middleware/rate-limit.js.map +1 -0
  178. package/dist/migrations.d.ts +56 -0
  179. package/dist/migrations.d.ts.map +1 -0
  180. package/dist/migrations.js +133 -0
  181. package/dist/migrations.js.map +1 -0
  182. package/dist/query/builder.d.ts +6 -0
  183. package/dist/query/builder.d.ts.map +1 -0
  184. package/dist/query/builder.js +97 -0
  185. package/dist/query/builder.js.map +1 -0
  186. package/dist/query/executor.d.ts +3 -0
  187. package/dist/query/executor.d.ts.map +1 -0
  188. package/dist/query/executor.js +64 -0
  189. package/dist/query/executor.js.map +1 -0
  190. package/dist/query/filter-builder.d.ts +8 -0
  191. package/dist/query/filter-builder.d.ts.map +1 -0
  192. package/dist/query/filter-builder.js +128 -0
  193. package/dist/query/filter-builder.js.map +1 -0
  194. package/dist/query/search.d.ts +4 -0
  195. package/dist/query/search.d.ts.map +1 -0
  196. package/dist/query/search.js +28 -0
  197. package/dist/query/search.js.map +1 -0
  198. package/dist/query/types.d.ts +45 -0
  199. package/dist/query/types.d.ts.map +1 -0
  200. package/dist/query/types.js +2 -0
  201. package/dist/query/types.js.map +1 -0
  202. package/dist/query.d.ts +6 -0
  203. package/dist/query.d.ts.map +1 -0
  204. package/dist/query.js +6 -0
  205. package/dist/query.js.map +1 -0
  206. package/dist/records/batch.d.ts +13 -0
  207. package/dist/records/batch.d.ts.map +1 -0
  208. package/dist/records/batch.js +113 -0
  209. package/dist/records/batch.js.map +1 -0
  210. package/dist/records/count.d.ts +5 -0
  211. package/dist/records/count.d.ts.map +1 -0
  212. package/dist/records/count.js +34 -0
  213. package/dist/records/count.js.map +1 -0
  214. package/dist/records/crud.d.ts +8 -0
  215. package/dist/records/crud.d.ts.map +1 -0
  216. package/dist/records/crud.js +121 -0
  217. package/dist/records/crud.js.map +1 -0
  218. package/dist/records/distinct.d.ts +5 -0
  219. package/dist/records/distinct.d.ts.map +1 -0
  220. package/dist/records/distinct.js +22 -0
  221. package/dist/records/distinct.js.map +1 -0
  222. package/dist/records/helpers.d.ts +4 -0
  223. package/dist/records/helpers.d.ts.map +1 -0
  224. package/dist/records/helpers.js +9 -0
  225. package/dist/records/helpers.js.map +1 -0
  226. package/dist/records/list.d.ts +44 -0
  227. package/dist/records/list.d.ts.map +1 -0
  228. package/dist/records/list.js +133 -0
  229. package/dist/records/list.js.map +1 -0
  230. package/dist/records/schema-cache.d.ts +8 -0
  231. package/dist/records/schema-cache.d.ts.map +1 -0
  232. package/dist/records/schema-cache.js +64 -0
  233. package/dist/records/schema-cache.js.map +1 -0
  234. package/dist/records.d.ts +8 -0
  235. package/dist/records.d.ts.map +1 -0
  236. package/dist/records.js +8 -0
  237. package/dist/records.js.map +1 -0
  238. package/dist/relations.d.ts +50 -0
  239. package/dist/relations.d.ts.map +1 -0
  240. package/dist/relations.js +179 -0
  241. package/dist/relations.js.map +1 -0
  242. package/dist/rls.d.ts +63 -0
  243. package/dist/rls.d.ts.map +1 -0
  244. package/dist/rls.js +146 -0
  245. package/dist/rls.js.map +1 -0
  246. package/dist/router.d.ts +53 -0
  247. package/dist/router.d.ts.map +1 -0
  248. package/dist/router.js +104 -0
  249. package/dist/router.js.map +1 -0
  250. package/dist/routes/admin-query.d.ts +5 -0
  251. package/dist/routes/admin-query.d.ts.map +1 -0
  252. package/dist/routes/admin-query.js +57 -0
  253. package/dist/routes/admin-query.js.map +1 -0
  254. package/dist/routes/api-keys.d.ts +12 -0
  255. package/dist/routes/api-keys.d.ts.map +1 -0
  256. package/dist/routes/api-keys.js +114 -0
  257. package/dist/routes/api-keys.js.map +1 -0
  258. package/dist/routes/auth.d.ts +10 -0
  259. package/dist/routes/auth.d.ts.map +1 -0
  260. package/dist/routes/auth.js +116 -0
  261. package/dist/routes/auth.js.map +1 -0
  262. package/dist/routes/backup.d.ts +5 -0
  263. package/dist/routes/backup.d.ts.map +1 -0
  264. package/dist/routes/backup.js +88 -0
  265. package/dist/routes/backup.js.map +1 -0
  266. package/dist/routes/collections.d.ts +5 -0
  267. package/dist/routes/collections.d.ts.map +1 -0
  268. package/dist/routes/collections.js +110 -0
  269. package/dist/routes/collections.js.map +1 -0
  270. package/dist/routes/databases.d.ts +5 -0
  271. package/dist/routes/databases.d.ts.map +1 -0
  272. package/dist/routes/databases.js +90 -0
  273. package/dist/routes/databases.js.map +1 -0
  274. package/dist/routes/health.d.ts +9 -0
  275. package/dist/routes/health.d.ts.map +1 -0
  276. package/dist/routes/health.js +34 -0
  277. package/dist/routes/health.js.map +1 -0
  278. package/dist/routes/import-export.d.ts +8 -0
  279. package/dist/routes/import-export.d.ts.map +1 -0
  280. package/dist/routes/import-export.js +173 -0
  281. package/dist/routes/import-export.js.map +1 -0
  282. package/dist/routes/indexes.d.ts +5 -0
  283. package/dist/routes/indexes.d.ts.map +1 -0
  284. package/dist/routes/indexes.js +94 -0
  285. package/dist/routes/indexes.js.map +1 -0
  286. package/dist/routes/migrations.d.ts +5 -0
  287. package/dist/routes/migrations.d.ts.map +1 -0
  288. package/dist/routes/migrations.js +87 -0
  289. package/dist/routes/migrations.js.map +1 -0
  290. package/dist/routes/oauth.d.ts +5 -0
  291. package/dist/routes/oauth.d.ts.map +1 -0
  292. package/dist/routes/oauth.js +35 -0
  293. package/dist/routes/oauth.js.map +1 -0
  294. package/dist/routes/query.d.ts +5 -0
  295. package/dist/routes/query.d.ts.map +1 -0
  296. package/dist/routes/query.js +36 -0
  297. package/dist/routes/query.js.map +1 -0
  298. package/dist/routes/records.d.ts +5 -0
  299. package/dist/routes/records.d.ts.map +1 -0
  300. package/dist/routes/records.js +181 -0
  301. package/dist/routes/records.js.map +1 -0
  302. package/dist/routes/transactions.d.ts +5 -0
  303. package/dist/routes/transactions.d.ts.map +1 -0
  304. package/dist/routes/transactions.js +43 -0
  305. package/dist/routes/transactions.js.map +1 -0
  306. package/dist/routes/views.d.ts +5 -0
  307. package/dist/routes/views.d.ts.map +1 -0
  308. package/dist/routes/views.js +123 -0
  309. package/dist/routes/views.js.map +1 -0
  310. package/dist/server.d.ts +80 -0
  311. package/dist/server.d.ts.map +1 -0
  312. package/dist/server.js +271 -0
  313. package/dist/server.js.map +1 -0
  314. package/package.json +20 -40
  315. package/bin/cli.ts +0 -185
  316. package/src/admin/assets.ts +0 -134
  317. package/src/admin/serve.ts +0 -447
  318. package/src/admin-ui/App.vue +0 -71
  319. package/src/admin-ui/api/client.ts +0 -179
  320. package/src/admin-ui/components/Icon.vue +0 -85
  321. package/src/admin-ui/components/Sidebar.vue +0 -275
  322. package/src/admin-ui/components/StatCard.vue +0 -40
  323. package/src/admin-ui/dist/assets/ApiKeys.css +0 -1
  324. package/src/admin-ui/dist/assets/ApiKeys.js +0 -1
  325. package/src/admin-ui/dist/assets/AppDashboard.css +0 -1
  326. package/src/admin-ui/dist/assets/AppDashboard.js +0 -1
  327. package/src/admin-ui/dist/assets/Backups.js +0 -1
  328. package/src/admin-ui/dist/assets/Dashboard.css +0 -1
  329. package/src/admin-ui/dist/assets/Dashboard.js +0 -3
  330. package/src/admin-ui/dist/assets/DataBrowser.css +0 -1
  331. package/src/admin-ui/dist/assets/DataBrowser.js +0 -1
  332. package/src/admin-ui/dist/assets/Docs.css +0 -1
  333. package/src/admin-ui/dist/assets/Docs.js +0 -1
  334. package/src/admin-ui/dist/assets/FileBrowser.css +0 -1
  335. package/src/admin-ui/dist/assets/FileBrowser.js +0 -1
  336. package/src/admin-ui/dist/assets/HookEditor.css +0 -1
  337. package/src/admin-ui/dist/assets/HookEditor.js +0 -2
  338. package/src/admin-ui/dist/assets/LogViewer.css +0 -1
  339. package/src/admin-ui/dist/assets/LogViewer.js +0 -1
  340. package/src/admin-ui/dist/assets/Login.css +0 -1
  341. package/src/admin-ui/dist/assets/Login.js +0 -1
  342. package/src/admin-ui/dist/assets/SchemaBuilder.css +0 -1
  343. package/src/admin-ui/dist/assets/SchemaBuilder.js +0 -1
  344. package/src/admin-ui/dist/assets/Settings.js +0 -1
  345. package/src/admin-ui/dist/assets/Setup.css +0 -1
  346. package/src/admin-ui/dist/assets/Setup.js +0 -1
  347. package/src/admin-ui/dist/assets/StatCard.css +0 -1
  348. package/src/admin-ui/dist/assets/StatCard.js +0 -1
  349. package/src/admin-ui/dist/assets/main.css +0 -1
  350. package/src/admin-ui/dist/assets/main.js +0 -30
  351. package/src/admin-ui/dist/index.html +0 -49
  352. package/src/admin-ui/index.html +0 -48
  353. package/src/admin-ui/main.ts +0 -25
  354. package/src/admin-ui/pages/ApiKeys.vue +0 -198
  355. package/src/admin-ui/pages/AppDashboard.vue +0 -274
  356. package/src/admin-ui/pages/Applications.vue +0 -123
  357. package/src/admin-ui/pages/Backups.vue +0 -140
  358. package/src/admin-ui/pages/Dashboard.vue +0 -293
  359. package/src/admin-ui/pages/DataBrowser.vue +0 -310
  360. package/src/admin-ui/pages/Docs.vue +0 -40
  361. package/src/admin-ui/pages/FileBrowser.vue +0 -587
  362. package/src/admin-ui/pages/HookEditor.vue +0 -258
  363. package/src/admin-ui/pages/LogViewer.vue +0 -109
  364. package/src/admin-ui/pages/Login.vue +0 -229
  365. package/src/admin-ui/pages/SchemaBuilder.vue +0 -501
  366. package/src/admin-ui/pages/Settings.vue +0 -251
  367. package/src/admin-ui/pages/Setup.vue +0 -275
  368. package/src/admin-ui/router.ts +0 -169
  369. package/src/admin-ui/stores/application.ts +0 -68
  370. package/src/admin-ui/stores/auth.ts +0 -109
  371. package/src/admin-ui/style.css +0 -530
  372. package/src/admin-ui/tsconfig.json +0 -21
  373. package/src/admin-ui/version.ts +0 -3
  374. package/src/admin-ui/vite.config.ts +0 -35
  375. package/src/api/admin-config.ts +0 -596
  376. package/src/api/admin.ts +0 -8
  377. package/src/api/aggregate.ts +0 -104
  378. package/src/api/applications.ts +0 -148
  379. package/src/api/auth.ts +0 -690
  380. package/src/api/backups.ts +0 -173
  381. package/src/api/batch.ts +0 -135
  382. package/src/api/collections.ts +0 -354
  383. package/src/api/files.ts +0 -801
  384. package/src/api/health.ts +0 -48
  385. package/src/api/helpers.ts +0 -86
  386. package/src/api/middleware/auth.ts +0 -202
  387. package/src/api/middleware/cors.ts +0 -37
  388. package/src/api/middleware/logging.ts +0 -27
  389. package/src/api/middleware/ratelimit.ts +0 -142
  390. package/src/api/middleware/rls.ts +0 -37
  391. package/src/api/records.ts +0 -563
  392. package/src/api/router.ts +0 -296
  393. package/src/app.ts +0 -617
  394. package/src/auth/apikey.ts +0 -73
  395. package/src/auth/jwt.ts +0 -210
  396. package/src/auth/oauth2.ts +0 -144
  397. package/src/auth/password.ts +0 -68
  398. package/src/backup/manager.ts +0 -227
  399. package/src/config/yaml.ts +0 -78
  400. package/src/config.ts +0 -240
  401. package/src/db/application-migrations.ts +0 -112
  402. package/src/db/application-schema.ts +0 -297
  403. package/src/db/migrations.ts +0 -54
  404. package/src/db/pool.ts +0 -143
  405. package/src/db/system-schema.ts +0 -153
  406. package/src/hooks/api.ts +0 -157
  407. package/src/hooks/loader.ts +0 -263
  408. package/src/hooks/runner.ts +0 -76
  409. package/src/index.ts +0 -17
  410. package/src/logging/logger.ts +0 -131
  411. package/src/realtime/broadcast.ts +0 -132
  412. package/src/realtime/subscriptions.ts +0 -124
  413. package/src/security/rls-engine.ts +0 -183
  414. package/src/security/sanitizer.ts +0 -72
  415. package/src/storage/interface.ts +0 -48
  416. package/src/storage/local.ts +0 -189
  417. package/src/storage/mime-types.ts +0 -32
  418. package/src/storage/s3.ts +0 -213
  419. package/src/sync/changelog.ts +0 -247
  420. package/src/sync/engine.ts +0 -159
  421. package/src/sync/lamport.ts +0 -48
  422. package/src/sync/protocol.ts +0 -234
  423. package/src/version.ts +0 -2
@@ -0,0 +1,22 @@
1
+ import { validateIdentifier } from "@boltstore/utils";
2
+ import { toBindings } from "../db/cast";
3
+ import { applyRLS, toRLSContext } from "../rls";
4
+ import { getColumnNames } from "./schema-cache";
5
+ function distinctValues(pool, collection, field, auth) {
6
+ validateIdentifier(field, "field name");
7
+ getColumnNames(pool, collection);
8
+ const db = pool.read();
9
+ const rlsCtx = auth ? toRLSContext(auth) : null;
10
+ const rls = rlsCtx ? applyRLS(pool, collection, "read", rlsCtx) : null;
11
+ let sql = `SELECT DISTINCT "${field}" FROM "${collection}"`;
12
+ const params = [];
13
+ if (rls?.whereClause) {
14
+ sql += ` WHERE ${rls.whereClause}`;
15
+ params.push(...rls.params);
16
+ }
17
+ sql += ` ORDER BY "${field}"`;
18
+ const rows = db.query(sql).all(...toBindings(params));
19
+ return rows.map((r) => r[field]);
20
+ }
21
+ export { distinctValues };
22
+ //# sourceMappingURL=distinct.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distinct.js","sourceRoot":"","sources":["../../src/records/distinct.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAmB,MAAM,QAAQ,CAAC;AAEjE,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,SAAS,cAAc,CACrB,IAAkB,EAClB,UAAkB,EAClB,KAAa,EACb,IAAkB;IAElB,kBAAkB,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IACxC,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACjC,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAEvB,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAChD,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAEvE,IAAI,GAAG,GAAG,oBAAoB,KAAK,WAAW,UAAU,GAAG,CAAC;IAC5D,MAAM,MAAM,GAAc,EAAE,CAAC;IAC7B,IAAI,GAAG,EAAE,WAAW,EAAE,CAAC;QACrB,GAAG,IAAI,UAAU,GAAG,CAAC,WAAW,EAAE,CAAC;QACnC,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;IACD,GAAG,IAAI,cAAc,KAAK,GAAG,CAAC;IAE9B,MAAM,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,CAA8B,CAAC;IAEnF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ declare function generateId(): string;
2
+ declare function now(): string;
3
+ export { generateId, now };
4
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/records/helpers.ts"],"names":[],"mappings":"AAEA,iBAAS,UAAU,IAAI,MAAM,CAE5B;AAED,iBAAS,GAAG,IAAI,MAAM,CAErB;AAED,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { generateSecureId } from "@boltstore/utils";
2
+ function generateId() {
3
+ return generateSecureId("rec");
4
+ }
5
+ function now() {
6
+ return new Date().toISOString();
7
+ }
8
+ export { generateId, now };
9
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/records/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,SAAS,UAAU;IACjB,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,GAAG;IACV,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { DatabasePool } from "../db/pool";
2
+ import type { AuthContext } from "../middleware/auth";
3
+ interface ListRecordsResult {
4
+ records: Record<string, unknown>[];
5
+ meta: {
6
+ total?: number;
7
+ page?: number;
8
+ per_page?: number;
9
+ total_pages?: number;
10
+ next_cursor?: string | null;
11
+ };
12
+ }
13
+ interface PaginationMetaOptions {
14
+ page: number;
15
+ perPage: number;
16
+ filter?: Record<string, unknown>;
17
+ sort?: string;
18
+ }
19
+ declare function listRecords(pool: DatabasePool, collection: string, options?: {
20
+ filter?: Record<string, unknown>;
21
+ sort?: string;
22
+ direction?: "asc" | "desc";
23
+ limit?: number;
24
+ offset?: number;
25
+ page?: number;
26
+ perPage?: number;
27
+ cursor?: string;
28
+ fields?: string[];
29
+ }, auth?: AuthContext): Record<string, unknown>[];
30
+ declare function buildListSql(collection: string, options?: {
31
+ filter?: Record<string, unknown>;
32
+ sort?: string;
33
+ direction?: "asc" | "desc";
34
+ limit?: number;
35
+ offset?: number;
36
+ cursor?: string;
37
+ fields?: string[];
38
+ }): {
39
+ sql: string;
40
+ params: unknown[];
41
+ };
42
+ declare function buildPaginationMeta(pool: DatabasePool, collection: string, options: PaginationMetaOptions, auth?: AuthContext, lastRecord?: Record<string, unknown>): ListRecordsResult["meta"];
43
+ export { listRecords, buildListSql, buildPaginationMeta, ListRecordsResult, PaginationMetaOptions };
44
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/records/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAItD,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACnC,IAAI,EAAE;QACJ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC7B,CAAC;CACH;AAED,UAAU,qBAAqB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,iBAAS,WAAW,CAClB,IAAI,EAAE,YAAY,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE;IACR,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB,EACD,IAAI,CAAC,EAAE,WAAW,GACjB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CA2E3B;AAED,iBAAS,YAAY,CACnB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE;IACR,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB,GACA;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAA;CAAE,CAkDpC;AAED,iBAAS,mBAAmB,CAC1B,IAAI,EAAE,YAAY,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,qBAAqB,EAC9B,IAAI,CAAC,EAAE,WAAW,EAClB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,iBAAiB,CAAC,MAAM,CAAC,CAa3B;AAED,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,CAAC"}
@@ -0,0 +1,133 @@
1
+ import { validateIdentifier } from "@boltstore/utils";
2
+ import { toBindings } from "../db/cast";
3
+ import { applyRLS, toRLSContext } from "../rls";
4
+ import { getColumnNames, MAX_LIMIT, MAX_OFFSET } from "./schema-cache";
5
+ import { countRecords } from "./count";
6
+ function listRecords(pool, collection, options, auth) {
7
+ getColumnNames(pool, collection);
8
+ const db = pool.read();
9
+ let limit = options?.limit;
10
+ let offset = options?.offset;
11
+ let page;
12
+ let perPage;
13
+ if (options?.page !== undefined && options?.perPage !== undefined) {
14
+ page = options.page;
15
+ perPage = options.perPage;
16
+ limit = perPage;
17
+ offset = (page - 1) * perPage;
18
+ }
19
+ if (limit !== undefined) {
20
+ limit = Math.max(1, Math.min(limit, MAX_LIMIT));
21
+ }
22
+ if (offset !== undefined) {
23
+ offset = Math.max(0, Math.min(offset, MAX_OFFSET));
24
+ }
25
+ const selectCols = options?.fields?.length
26
+ ? options.fields.map((f) => `"${f}"`).join(", ")
27
+ : "*";
28
+ let sql = `SELECT ${selectCols} FROM "${collection}"`;
29
+ const params = [];
30
+ const conditions = [];
31
+ const rlsCtx = auth ? toRLSContext(auth) : null;
32
+ const rls = rlsCtx ? applyRLS(pool, collection, "read", rlsCtx) : null;
33
+ if (rls?.whereClause) {
34
+ conditions.push(rls.whereClause);
35
+ params.push(...rls.params);
36
+ }
37
+ if (options?.filter) {
38
+ for (const [key, value] of Object.entries(options.filter)) {
39
+ if (value === null || value === undefined)
40
+ continue;
41
+ if (typeof value === "object" && !Array.isArray(value)) {
42
+ throw Object.assign(new Error(`Filter value for "${key}" must be a scalar or array.`), { status: 400 });
43
+ }
44
+ validateIdentifier(key, "filter field");
45
+ conditions.push(`"${key}" = ?`);
46
+ params.push(value);
47
+ }
48
+ }
49
+ const sortField = options?.sort || "created_at";
50
+ validateIdentifier(sortField, "sort field");
51
+ if (options?.cursor) {
52
+ const op = options.direction === "asc" ? ">" : "<";
53
+ conditions.push(`"${sortField}" ${op} ?`);
54
+ params.push(options.cursor);
55
+ }
56
+ if (conditions.length > 0) {
57
+ sql += " WHERE " + conditions.join(" AND ");
58
+ }
59
+ const direction = options?.direction === "asc" ? "ASC" : "DESC";
60
+ sql += ` ORDER BY "${sortField}" ${direction}`;
61
+ if (limit !== undefined) {
62
+ sql += ` LIMIT ?`;
63
+ params.push(limit);
64
+ }
65
+ if (offset !== undefined) {
66
+ sql += ` OFFSET ?`;
67
+ params.push(offset);
68
+ }
69
+ const records = db.query(sql).all(...toBindings(params));
70
+ return records;
71
+ }
72
+ function buildListSql(collection, options) {
73
+ validateIdentifier(collection, "collection name");
74
+ const selectCols = options?.fields?.length
75
+ ? options.fields.map((f) => `"${f}"`).join(", ")
76
+ : "*";
77
+ let sql = `SELECT ${selectCols} FROM "${collection}"`;
78
+ const params = [];
79
+ const conditions = [];
80
+ if (options?.filter) {
81
+ for (const [key, value] of Object.entries(options.filter)) {
82
+ if (value === null || value === undefined)
83
+ continue;
84
+ if (typeof value === "object" && !Array.isArray(value)) {
85
+ throw Object.assign(new Error(`Filter value for "${key}" must be a scalar or array.`), { status: 400 });
86
+ }
87
+ validateIdentifier(key, "filter field");
88
+ conditions.push(`"${key}" = ?`);
89
+ params.push(value);
90
+ }
91
+ }
92
+ const sortField = options?.sort || "created_at";
93
+ validateIdentifier(sortField, "sort field");
94
+ if (options?.cursor) {
95
+ const op = options.direction === "asc" ? ">" : "<";
96
+ conditions.push(`"${sortField}" ${op} ?`);
97
+ params.push(options.cursor);
98
+ }
99
+ if (conditions.length > 0) {
100
+ sql += " WHERE " + conditions.join(" AND ");
101
+ }
102
+ const direction = options?.direction === "asc" ? "ASC" : "DESC";
103
+ sql += ` ORDER BY "${sortField}" ${direction}`;
104
+ let limit = options?.limit;
105
+ let offset = options?.offset;
106
+ if (limit !== undefined) {
107
+ limit = Math.max(1, Math.min(limit, MAX_LIMIT));
108
+ sql += ` LIMIT ?`;
109
+ params.push(limit);
110
+ }
111
+ if (offset !== undefined) {
112
+ offset = Math.max(0, Math.min(offset, MAX_OFFSET));
113
+ sql += ` OFFSET ?`;
114
+ params.push(offset);
115
+ }
116
+ return { sql, params };
117
+ }
118
+ function buildPaginationMeta(pool, collection, options, auth, lastRecord) {
119
+ const total = countRecords(pool, collection, options.filter, auth);
120
+ const meta = {
121
+ total,
122
+ page: options.page,
123
+ per_page: options.perPage,
124
+ total_pages: Math.ceil(total / options.perPage),
125
+ };
126
+ if (lastRecord) {
127
+ const key = options.sort || "created_at";
128
+ meta.next_cursor = lastRecord[key];
129
+ }
130
+ return meta;
131
+ }
132
+ export { listRecords, buildListSql, buildPaginationMeta };
133
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/records/list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { DatabasePool } from "../db/pool";
2
+ declare const MAX_LIMIT = 1000;
3
+ declare const MAX_OFFSET = 100000;
4
+ declare function getColumnNames(pool: DatabasePool, collection: string): string[];
5
+ declare function invalidateSchemaCache(pool: DatabasePool, collection?: string): void;
6
+ declare function collectionExists(pool: DatabasePool, collection: string): boolean;
7
+ export { invalidateSchemaCache, getColumnNames, collectionExists, MAX_LIMIT, MAX_OFFSET };
8
+ //# sourceMappingURL=schema-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-cache.d.ts","sourceRoot":"","sources":["../../src/records/schema-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1C,QAAA,MAAM,SAAS,OAAO,CAAC;AACvB,QAAA,MAAM,UAAU,SAAS,CAAC;AAiC1B,iBAAS,cAAc,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAqBxE;AAED,iBAAS,qBAAqB,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAQ5E;AAED,iBAAS,gBAAgB,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CASzE;AAED,OAAO,EAAE,qBAAqB,EAAE,cAAc,EAAE,gBAAgB,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC"}
@@ -0,0 +1,64 @@
1
+ import { validateIdentifier } from "@boltstore/utils";
2
+ const MAX_LIMIT = 1000;
3
+ const MAX_OFFSET = 100000;
4
+ const schemaCache = new WeakMap();
5
+ const SCHEMA_CACHE_TTL_MS = 30000;
6
+ function getPoolCache(pool) {
7
+ let cache = schemaCache.get(pool);
8
+ if (!cache) {
9
+ cache = new Map();
10
+ schemaCache.set(pool, cache);
11
+ }
12
+ return cache;
13
+ }
14
+ function fetchColumns(pool, collection) {
15
+ validateIdentifier(collection, "collection name");
16
+ const db = pool.read();
17
+ const existsRow = db
18
+ .query("SELECT 1 FROM sqlite_master WHERE type='table' AND name=? LIMIT 1")
19
+ .get(collection);
20
+ if (!existsRow) {
21
+ return { columns: [], exists: false, fetchedAt: Date.now() };
22
+ }
23
+ const rows = db.query(`PRAGMA table_info("${collection}")`).all();
24
+ return { columns: rows.map((r) => r.name), exists: true, fetchedAt: Date.now() };
25
+ }
26
+ function getColumnNames(pool, collection) {
27
+ const cache = getPoolCache(pool);
28
+ const entry = cache.get(collection);
29
+ if (entry && Date.now() - entry.fetchedAt < SCHEMA_CACHE_TTL_MS) {
30
+ if (!entry.exists) {
31
+ throw Object.assign(new Error(`Collection "${collection}" not found.`), { status: 404 });
32
+ }
33
+ return entry.columns;
34
+ }
35
+ const fresh = fetchColumns(pool, collection);
36
+ cache.set(collection, fresh);
37
+ if (!fresh.exists) {
38
+ throw Object.assign(new Error(`Collection "${collection}" not found.`), { status: 404 });
39
+ }
40
+ return fresh.columns;
41
+ }
42
+ function invalidateSchemaCache(pool, collection) {
43
+ const cache = schemaCache.get(pool);
44
+ if (!cache)
45
+ return;
46
+ if (collection) {
47
+ cache.delete(collection);
48
+ }
49
+ else {
50
+ cache.clear();
51
+ }
52
+ }
53
+ function collectionExists(pool, collection) {
54
+ const cache = getPoolCache(pool);
55
+ const entry = cache.get(collection);
56
+ if (entry && Date.now() - entry.fetchedAt < SCHEMA_CACHE_TTL_MS) {
57
+ return entry.exists;
58
+ }
59
+ const fresh = fetchColumns(pool, collection);
60
+ cache.set(collection, fresh);
61
+ return fresh.exists;
62
+ }
63
+ export { invalidateSchemaCache, getColumnNames, collectionExists, MAX_LIMIT, MAX_OFFSET };
64
+ //# sourceMappingURL=schema-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-cache.js","sourceRoot":"","sources":["../../src/records/schema-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export * from "./records/schema-cache";
2
+ export * from "./records/crud";
3
+ export * from "./records/list";
4
+ export * from "./records/count";
5
+ export * from "./records/distinct";
6
+ export * from "./records/batch";
7
+ export * from "./records/helpers";
8
+ //# sourceMappingURL=records.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"records.d.ts","sourceRoot":"","sources":["../src/records.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,8 @@
1
+ export * from "./records/schema-cache";
2
+ export * from "./records/crud";
3
+ export * from "./records/list";
4
+ export * from "./records/count";
5
+ export * from "./records/distinct";
6
+ export * from "./records/batch";
7
+ export * from "./records/helpers";
8
+ //# sourceMappingURL=records.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"records.js","sourceRoot":"","sources":["../src/records.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Relations / References — lightweight foreign key relations for Boltstore.
3
+ *
4
+ * Adds support for:
5
+ * - `expand` parameter to fetch related records by foreign key
6
+ * - Reference field type in schema with optional cascade delete
7
+ *
8
+ * @module boltstore/relations
9
+ */
10
+ import { DatabasePool } from "./db/pool";
11
+ import type { AuthContext } from "./middleware/auth";
12
+ /** Metadata for a single relation field. */
13
+ export interface RelationDefinition {
14
+ /** The column in this collection that holds the foreign key. */
15
+ field: string;
16
+ /** The target collection (table) that records reference. */
17
+ foreignCollection: string;
18
+ /** Whether deleting a record in this collection cascades to children (Phase 1 feature). */
19
+ cascadeDelete?: boolean;
20
+ }
21
+ /** Load explicit relation definitions for a collection from metadata. */
22
+ export declare function getRelations(pool: DatabasePool, collection: string): Record<string, RelationDefinition>;
23
+ /** Persist explicit relation definitions for a collection. */
24
+ export declare function setRelations(pool: DatabasePool, collection: string, relations: Record<string, RelationDefinition>): void;
25
+ /**
26
+ * Expand related records for a list of parent records.
27
+ *
28
+ * For each record, if it has a field whose name is provided in `expandFields`,
29
+ * the function fetches the related record from the target collection and nests
30
+ * it under the key `{field}_expanded`.
31
+ *
32
+ * Example:
33
+ * ```
34
+ * GET /api/myapp/collections/posts/records?expand=author
35
+ * ```
36
+ * If `posts` has an `author` column storing user IDs, the returned records
37
+ * will include `author_expanded: { id, name, ... }`.
38
+ */
39
+ export declare function expandRecords(pool: DatabasePool, parentCollection: string, records: Record<string, unknown>[], expandFields: string[], _depth?: number): Record<string, unknown>[];
40
+ /**
41
+ * Cascade delete: when a parent record is deleted, also delete child records
42
+ * that reference it via a foreign key field.
43
+ *
44
+ * Checks all collections in the database for a field matching `{parentCollection}_id`
45
+ * and deletes records where that field equals the deleted `parentId`.
46
+ */
47
+ export declare function cascadeDelete(pool: DatabasePool, parentCollection: string, parentId: string, _auth?: AuthContext): {
48
+ deleted: string[];
49
+ };
50
+ //# sourceMappingURL=relations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relations.d.ts","sourceRoot":"","sources":["../src/relations.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAKrD,4CAA4C;AAC5C,MAAM,WAAW,kBAAkB;IACjC,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,2FAA2F;IAC3F,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAoCD,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAavG;AAED,8DAA8D;AAC9D,wBAAgB,YAAY,CAC1B,IAAI,EAAE,YAAY,EAClB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAC5C,IAAI,CAQN;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,YAAY,EAClB,gBAAgB,EAAE,MAAM,EACxB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAClC,YAAY,EAAE,MAAM,EAAE,EACtB,MAAM,SAAI,GACT,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAgE3B;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,YAAY,EAClB,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,WAAW,GAClB;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CA6BvB"}
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Relations / References — lightweight foreign key relations for Boltstore.
3
+ *
4
+ * Adds support for:
5
+ * - `expand` parameter to fetch related records by foreign key
6
+ * - Reference field type in schema with optional cascade delete
7
+ *
8
+ * @module boltstore/relations
9
+ */
10
+ import { validateIdentifier } from "@boltstore/utils";
11
+ /** Maximum recursion depth for nested expansion. */
12
+ const MAX_EXPAND_DEPTH = 2;
13
+ /** Resolve a target collection for an expand field using relation metadata first, then heuristic. */
14
+ function resolveTargetCollection(pool, parentCollection, field) {
15
+ // 1. Try explicit relation metadata stored in _collections
16
+ try {
17
+ const db = pool.read();
18
+ const meta = db
19
+ .query("SELECT relations_json FROM _collections WHERE name = ?")
20
+ .get(parentCollection);
21
+ if (meta?.relations_json) {
22
+ const relations = JSON.parse(meta.relations_json);
23
+ if (relations[field]?.foreignCollection) {
24
+ return relations[field].foreignCollection;
25
+ }
26
+ }
27
+ }
28
+ catch {
29
+ // _collections may not exist yet; fall through to heuristic.
30
+ }
31
+ // 2. Heuristic pluralization
32
+ let targetCollection = `${field}s`;
33
+ if (field.endsWith("y")) {
34
+ targetCollection = field.slice(0, -1) + "ies";
35
+ }
36
+ else if (field.endsWith("s") || field.endsWith("x") || field.endsWith("ch") || field.endsWith("sh")) {
37
+ targetCollection = field + "es";
38
+ }
39
+ try {
40
+ validateIdentifier(targetCollection, "target collection");
41
+ return targetCollection;
42
+ }
43
+ catch {
44
+ return null;
45
+ }
46
+ }
47
+ /** Load explicit relation definitions for a collection from metadata. */
48
+ export function getRelations(pool, collection) {
49
+ try {
50
+ const db = pool.read();
51
+ const meta = db
52
+ .query("SELECT relations_json FROM _collections WHERE name = ?")
53
+ .get(collection);
54
+ if (meta?.relations_json) {
55
+ return JSON.parse(meta.relations_json);
56
+ }
57
+ }
58
+ catch {
59
+ // ignore
60
+ }
61
+ return {};
62
+ }
63
+ /** Persist explicit relation definitions for a collection. */
64
+ export function setRelations(pool, collection, relations) {
65
+ const db = pool.write();
66
+ try {
67
+ db.run("ALTER TABLE _collections ADD COLUMN relations_json TEXT");
68
+ }
69
+ catch {
70
+ // Column may already exist.
71
+ }
72
+ db.run("UPDATE _collections SET relations_json = ? WHERE name = ?", [JSON.stringify(relations), collection]);
73
+ }
74
+ /**
75
+ * Expand related records for a list of parent records.
76
+ *
77
+ * For each record, if it has a field whose name is provided in `expandFields`,
78
+ * the function fetches the related record from the target collection and nests
79
+ * it under the key `{field}_expanded`.
80
+ *
81
+ * Example:
82
+ * ```
83
+ * GET /api/myapp/collections/posts/records?expand=author
84
+ * ```
85
+ * If `posts` has an `author` column storing user IDs, the returned records
86
+ * will include `author_expanded: { id, name, ... }`.
87
+ */
88
+ export function expandRecords(pool, parentCollection, records, expandFields, _depth = 0) {
89
+ if (!Array.isArray(records) || records.length === 0)
90
+ return records;
91
+ if (!Array.isArray(expandFields) || expandFields.length === 0)
92
+ return records;
93
+ if (_depth >= MAX_EXPAND_DEPTH)
94
+ return records;
95
+ const expanded = records.map((r) => ({ ...r }));
96
+ for (const field of expandFields) {
97
+ validateIdentifier(field, "field name");
98
+ const targetCollection = resolveTargetCollection(pool, parentCollection, field);
99
+ if (!targetCollection)
100
+ continue;
101
+ // Group parent IDs to fetch in batch
102
+ const foreignIds = new Set();
103
+ for (const record of records) {
104
+ const foreignId = record[field];
105
+ if (foreignId !== null && foreignId !== undefined && typeof foreignId === "string") {
106
+ foreignIds.add(foreignId);
107
+ }
108
+ }
109
+ if (foreignIds.size === 0)
110
+ continue;
111
+ // Fetch related records
112
+ const db = pool.read();
113
+ // Check if the target collection exists
114
+ const tableExists = db
115
+ .query("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?")
116
+ .get(targetCollection);
117
+ if (!tableExists) {
118
+ // Still set explicit null for non-existent heuristic targets so callers see a deterministic key.
119
+ for (const record of expanded) {
120
+ record[`${field}_expanded`] = null;
121
+ }
122
+ continue;
123
+ }
124
+ // Build batch query
125
+ const placeholders = Array.from(foreignIds).map(() => "?").join(", ");
126
+ const relatedRows = db
127
+ .query(`SELECT * FROM "${targetCollection}" WHERE id IN (${placeholders})`)
128
+ .all(...Array.from(foreignIds));
129
+ // Build a map for O(1) lookup
130
+ const relatedMap = new Map();
131
+ for (const row of relatedRows) {
132
+ relatedMap.set(row.id, row);
133
+ }
134
+ // Attach expanded data
135
+ for (const record of expanded) {
136
+ const foreignId = record[field];
137
+ const expandKey = `${field}_expanded`;
138
+ if (foreignId && relatedMap.has(foreignId)) {
139
+ record[expandKey] = relatedMap.get(foreignId);
140
+ }
141
+ else {
142
+ record[expandKey] = null;
143
+ }
144
+ }
145
+ }
146
+ return expanded;
147
+ }
148
+ /**
149
+ * Cascade delete: when a parent record is deleted, also delete child records
150
+ * that reference it via a foreign key field.
151
+ *
152
+ * Checks all collections in the database for a field matching `{parentCollection}_id`
153
+ * and deletes records where that field equals the deleted `parentId`.
154
+ */
155
+ export function cascadeDelete(pool, parentCollection, parentId, _auth) {
156
+ validateIdentifier(parentCollection, "collection name");
157
+ const deleted = [];
158
+ pool.writeTransaction(() => {
159
+ const db = pool.write();
160
+ // Find all tables that have a column named {parentCollection}_id
161
+ const allTables = db
162
+ .query("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'")
163
+ .all();
164
+ for (const table of allTables) {
165
+ const foreignKey = `${parentCollection}_id`;
166
+ // Check if this table has the foreign key column via PRAGMA
167
+ const columns = db
168
+ .query(`PRAGMA table_info("${table.name}")`)
169
+ .all();
170
+ const hasColumn = columns.some((c) => c.name === foreignKey);
171
+ if (hasColumn) {
172
+ db.run(`DELETE FROM "${table.name}" WHERE "${foreignKey}" = ?`, [parentId]);
173
+ deleted.push(table.name);
174
+ }
175
+ }
176
+ });
177
+ return { deleted };
178
+ }
179
+ //# sourceMappingURL=relations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relations.js","sourceRoot":"","sources":["../src/relations.ts"],"names":[],"mappings":"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"}