@gettersethya/mira 0.1.0-alpha.2

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 (338) hide show
  1. package/LICENSE +21 -0
  2. package/dist/src/app/app.d.ts +96 -0
  3. package/dist/src/app/app.d.ts.map +1 -0
  4. package/dist/src/app/app.js +139 -0
  5. package/dist/src/app/app.js.map +1 -0
  6. package/dist/src/app/builder.d.ts +106 -0
  7. package/dist/src/app/builder.d.ts.map +1 -0
  8. package/dist/src/app/builder.js +122 -0
  9. package/dist/src/app/builder.js.map +1 -0
  10. package/dist/src/app/index.d.ts +31 -0
  11. package/dist/src/app/index.d.ts.map +1 -0
  12. package/dist/src/app/index.js +29 -0
  13. package/dist/src/app/index.js.map +1 -0
  14. package/dist/src/app/types.d.ts +55 -0
  15. package/dist/src/app/types.d.ts.map +1 -0
  16. package/dist/src/app/types.js +2 -0
  17. package/dist/src/app/types.js.map +1 -0
  18. package/dist/src/cache/cached-collection.d.ts +30 -0
  19. package/dist/src/cache/cached-collection.d.ts.map +1 -0
  20. package/dist/src/cache/cached-collection.js +107 -0
  21. package/dist/src/cache/cached-collection.js.map +1 -0
  22. package/dist/src/cache/collection-cache.d.ts +17 -0
  23. package/dist/src/cache/collection-cache.d.ts.map +1 -0
  24. package/dist/src/cache/collection-cache.js +37 -0
  25. package/dist/src/cache/collection-cache.js.map +1 -0
  26. package/dist/src/cache/index.d.ts +4 -0
  27. package/dist/src/cache/index.d.ts.map +1 -0
  28. package/dist/src/cache/index.js +3 -0
  29. package/dist/src/cache/index.js.map +1 -0
  30. package/dist/src/cache/types.d.ts +12 -0
  31. package/dist/src/cache/types.d.ts.map +1 -0
  32. package/dist/src/cache/types.js +2 -0
  33. package/dist/src/cache/types.js.map +1 -0
  34. package/dist/src/collection-service/collection-service.d.ts +62 -0
  35. package/dist/src/collection-service/collection-service.d.ts.map +1 -0
  36. package/dist/src/collection-service/collection-service.js +267 -0
  37. package/dist/src/collection-service/collection-service.js.map +1 -0
  38. package/dist/src/collection-service/context.d.ts +17 -0
  39. package/dist/src/collection-service/context.d.ts.map +1 -0
  40. package/dist/src/collection-service/context.js +2 -0
  41. package/dist/src/collection-service/context.js.map +1 -0
  42. package/dist/src/collection-service/decode.d.ts +6 -0
  43. package/dist/src/collection-service/decode.d.ts.map +1 -0
  44. package/dist/src/collection-service/decode.js +26 -0
  45. package/dist/src/collection-service/decode.js.map +1 -0
  46. package/dist/src/collection-service/errors.d.ts +67 -0
  47. package/dist/src/collection-service/errors.d.ts.map +1 -0
  48. package/dist/src/collection-service/errors.js +43 -0
  49. package/dist/src/collection-service/errors.js.map +1 -0
  50. package/dist/src/collection-service/index.d.ts +5 -0
  51. package/dist/src/collection-service/index.d.ts.map +1 -0
  52. package/dist/src/collection-service/index.js +3 -0
  53. package/dist/src/collection-service/index.js.map +1 -0
  54. package/dist/src/collection-service/input-schema.d.ts +10 -0
  55. package/dist/src/collection-service/input-schema.d.ts.map +1 -0
  56. package/dist/src/collection-service/input-schema.js +109 -0
  57. package/dist/src/collection-service/input-schema.js.map +1 -0
  58. package/dist/src/collection-service/where.d.ts +35 -0
  59. package/dist/src/collection-service/where.d.ts.map +1 -0
  60. package/dist/src/collection-service/where.js +88 -0
  61. package/dist/src/collection-service/where.js.map +1 -0
  62. package/dist/src/config/config.d.ts +44 -0
  63. package/dist/src/config/config.d.ts.map +1 -0
  64. package/dist/src/config/config.js +89 -0
  65. package/dist/src/config/config.js.map +1 -0
  66. package/dist/src/config/index.d.ts +3 -0
  67. package/dist/src/config/index.d.ts.map +1 -0
  68. package/dist/src/config/index.js +2 -0
  69. package/dist/src/config/index.js.map +1 -0
  70. package/dist/src/config/types.d.ts +29 -0
  71. package/dist/src/config/types.d.ts.map +1 -0
  72. package/dist/src/config/types.js +2 -0
  73. package/dist/src/config/types.js.map +1 -0
  74. package/dist/src/crypto/crypto.d.ts +11 -0
  75. package/dist/src/crypto/crypto.d.ts.map +1 -0
  76. package/dist/src/crypto/crypto.js +4 -0
  77. package/dist/src/crypto/crypto.js.map +1 -0
  78. package/dist/src/crypto/index.d.ts +3 -0
  79. package/dist/src/crypto/index.d.ts.map +1 -0
  80. package/dist/src/crypto/index.js +3 -0
  81. package/dist/src/crypto/index.js.map +1 -0
  82. package/dist/src/crypto/node.d.ts +4 -0
  83. package/dist/src/crypto/node.d.ts.map +1 -0
  84. package/dist/src/crypto/node.js +9 -0
  85. package/dist/src/crypto/node.js.map +1 -0
  86. package/dist/src/databases/index.d.ts +2 -0
  87. package/dist/src/databases/index.d.ts.map +1 -0
  88. package/dist/src/databases/index.js +2 -0
  89. package/dist/src/databases/index.js.map +1 -0
  90. package/dist/src/databases/sqlite.d.ts +24 -0
  91. package/dist/src/databases/sqlite.d.ts.map +1 -0
  92. package/dist/src/databases/sqlite.js +27 -0
  93. package/dist/src/databases/sqlite.js.map +1 -0
  94. package/dist/src/http/auth-node.d.ts +4 -0
  95. package/dist/src/http/auth-node.d.ts.map +1 -0
  96. package/dist/src/http/auth-node.js +34 -0
  97. package/dist/src/http/auth-node.js.map +1 -0
  98. package/dist/src/http/auth.d.ts +38 -0
  99. package/dist/src/http/auth.d.ts.map +1 -0
  100. package/dist/src/http/auth.js +66 -0
  101. package/dist/src/http/auth.js.map +1 -0
  102. package/dist/src/http/errors.d.ts +31 -0
  103. package/dist/src/http/errors.d.ts.map +1 -0
  104. package/dist/src/http/errors.js +36 -0
  105. package/dist/src/http/errors.js.map +1 -0
  106. package/dist/src/http/file-serve.d.ts +10 -0
  107. package/dist/src/http/file-serve.d.ts.map +1 -0
  108. package/dist/src/http/file-serve.js +159 -0
  109. package/dist/src/http/file-serve.js.map +1 -0
  110. package/dist/src/http/file-token.d.ts +7 -0
  111. package/dist/src/http/file-token.d.ts.map +1 -0
  112. package/dist/src/http/file-token.js +55 -0
  113. package/dist/src/http/file-token.js.map +1 -0
  114. package/dist/src/http/files.d.ts +11 -0
  115. package/dist/src/http/files.d.ts.map +1 -0
  116. package/dist/src/http/files.js +85 -0
  117. package/dist/src/http/files.js.map +1 -0
  118. package/dist/src/http/index.d.ts +10 -0
  119. package/dist/src/http/index.d.ts.map +1 -0
  120. package/dist/src/http/index.js +8 -0
  121. package/dist/src/http/index.js.map +1 -0
  122. package/dist/src/http/ip-middleware.d.ts +4 -0
  123. package/dist/src/http/ip-middleware.d.ts.map +1 -0
  124. package/dist/src/http/ip-middleware.js +21 -0
  125. package/dist/src/http/ip-middleware.js.map +1 -0
  126. package/dist/src/http/params.d.ts +15 -0
  127. package/dist/src/http/params.d.ts.map +1 -0
  128. package/dist/src/http/params.js +48 -0
  129. package/dist/src/http/params.js.map +1 -0
  130. package/dist/src/http/router.d.ts +11 -0
  131. package/dist/src/http/router.d.ts.map +1 -0
  132. package/dist/src/http/router.js +216 -0
  133. package/dist/src/http/router.js.map +1 -0
  134. package/dist/src/http/server-factory-node.d.ts +4 -0
  135. package/dist/src/http/server-factory-node.d.ts.map +1 -0
  136. package/dist/src/http/server-factory-node.js +8 -0
  137. package/dist/src/http/server-factory-node.js.map +1 -0
  138. package/dist/src/http/server-factory.d.ts +11 -0
  139. package/dist/src/http/server-factory.d.ts.map +1 -0
  140. package/dist/src/http/server-factory.js +4 -0
  141. package/dist/src/http/server-factory.js.map +1 -0
  142. package/dist/src/index.d.ts +8 -0
  143. package/dist/src/index.d.ts.map +1 -0
  144. package/dist/src/index.js +10 -0
  145. package/dist/src/index.js.map +1 -0
  146. package/dist/src/migrator/dialect-sqlite.d.ts +9 -0
  147. package/dist/src/migrator/dialect-sqlite.d.ts.map +1 -0
  148. package/dist/src/migrator/dialect-sqlite.js +102 -0
  149. package/dist/src/migrator/dialect-sqlite.js.map +1 -0
  150. package/dist/src/migrator/dialect.d.ts +24 -0
  151. package/dist/src/migrator/dialect.d.ts.map +1 -0
  152. package/dist/src/migrator/dialect.js +5 -0
  153. package/dist/src/migrator/dialect.js.map +1 -0
  154. package/dist/src/migrator/index.d.ts +8 -0
  155. package/dist/src/migrator/index.d.ts.map +1 -0
  156. package/dist/src/migrator/index.js +6 -0
  157. package/dist/src/migrator/index.js.map +1 -0
  158. package/dist/src/migrator/migrator.d.ts +36 -0
  159. package/dist/src/migrator/migrator.d.ts.map +1 -0
  160. package/dist/src/migrator/migrator.js +200 -0
  161. package/dist/src/migrator/migrator.js.map +1 -0
  162. package/dist/src/migrator/schema-diff.d.ts +25 -0
  163. package/dist/src/migrator/schema-diff.d.ts.map +1 -0
  164. package/dist/src/migrator/schema-diff.js +157 -0
  165. package/dist/src/migrator/schema-diff.js.map +1 -0
  166. package/dist/src/migrator/types.d.ts +91 -0
  167. package/dist/src/migrator/types.d.ts.map +1 -0
  168. package/dist/src/migrator/types.js +13 -0
  169. package/dist/src/migrator/types.js.map +1 -0
  170. package/dist/src/platforms/node.d.ts +40 -0
  171. package/dist/src/platforms/node.d.ts.map +1 -0
  172. package/dist/src/platforms/node.js +45 -0
  173. package/dist/src/platforms/node.js.map +1 -0
  174. package/dist/src/repository/id.d.ts +5 -0
  175. package/dist/src/repository/id.d.ts.map +1 -0
  176. package/dist/src/repository/id.js +9 -0
  177. package/dist/src/repository/id.js.map +1 -0
  178. package/dist/src/repository/index.d.ts +3 -0
  179. package/dist/src/repository/index.d.ts.map +1 -0
  180. package/dist/src/repository/index.js +2 -0
  181. package/dist/src/repository/index.js.map +1 -0
  182. package/dist/src/repository/repository.d.ts +53 -0
  183. package/dist/src/repository/repository.d.ts.map +1 -0
  184. package/dist/src/repository/repository.js +150 -0
  185. package/dist/src/repository/repository.js.map +1 -0
  186. package/dist/src/repository/types.d.ts +42 -0
  187. package/dist/src/repository/types.d.ts.map +1 -0
  188. package/dist/src/repository/types.js +2 -0
  189. package/dist/src/repository/types.js.map +1 -0
  190. package/dist/src/rule/compiler.d.ts +52 -0
  191. package/dist/src/rule/compiler.d.ts.map +1 -0
  192. package/dist/src/rule/compiler.js +113 -0
  193. package/dist/src/rule/compiler.js.map +1 -0
  194. package/dist/src/rule/enforcer.d.ts +47 -0
  195. package/dist/src/rule/enforcer.d.ts.map +1 -0
  196. package/dist/src/rule/enforcer.js +60 -0
  197. package/dist/src/rule/enforcer.js.map +1 -0
  198. package/dist/src/rule/index.d.ts +3 -0
  199. package/dist/src/rule/index.d.ts.map +1 -0
  200. package/dist/src/rule/index.js +3 -0
  201. package/dist/src/rule/index.js.map +1 -0
  202. package/dist/src/storage/index.d.ts +3 -0
  203. package/dist/src/storage/index.d.ts.map +1 -0
  204. package/dist/src/storage/index.js +3 -0
  205. package/dist/src/storage/index.js.map +1 -0
  206. package/dist/src/storage/local-preset.d.ts +21 -0
  207. package/dist/src/storage/local-preset.d.ts.map +1 -0
  208. package/dist/src/storage/local-preset.js +21 -0
  209. package/dist/src/storage/local-preset.js.map +1 -0
  210. package/dist/src/storage/storage.d.ts +83 -0
  211. package/dist/src/storage/storage.d.ts.map +1 -0
  212. package/dist/src/storage/storage.js +120 -0
  213. package/dist/src/storage/storage.js.map +1 -0
  214. package/dist/src/telemetry/index.d.ts +6 -0
  215. package/dist/src/telemetry/index.d.ts.map +1 -0
  216. package/dist/src/telemetry/index.js +7 -0
  217. package/dist/src/telemetry/index.js.map +1 -0
  218. package/dist/src/telemetry/logger.d.ts +4 -0
  219. package/dist/src/telemetry/logger.d.ts.map +1 -0
  220. package/dist/src/telemetry/logger.js +27 -0
  221. package/dist/src/telemetry/logger.js.map +1 -0
  222. package/dist/src/telemetry/tracer.d.ts +16 -0
  223. package/dist/src/telemetry/tracer.d.ts.map +1 -0
  224. package/dist/src/telemetry/tracer.js +106 -0
  225. package/dist/src/telemetry/tracer.js.map +1 -0
  226. package/dist/src/thumbnail/index.d.ts +4 -0
  227. package/dist/src/thumbnail/index.d.ts.map +1 -0
  228. package/dist/src/thumbnail/index.js +3 -0
  229. package/dist/src/thumbnail/index.js.map +1 -0
  230. package/dist/src/thumbnail/photon.d.ts +9 -0
  231. package/dist/src/thumbnail/photon.d.ts.map +1 -0
  232. package/dist/src/thumbnail/photon.js +73 -0
  233. package/dist/src/thumbnail/photon.js.map +1 -0
  234. package/dist/src/thumbnail/types.d.ts +23 -0
  235. package/dist/src/thumbnail/types.d.ts.map +1 -0
  236. package/dist/src/thumbnail/types.js +22 -0
  237. package/dist/src/thumbnail/types.js.map +1 -0
  238. package/dist/tests/app/app.test.d.ts +2 -0
  239. package/dist/tests/app/app.test.d.ts.map +1 -0
  240. package/dist/tests/app/app.test.js +78 -0
  241. package/dist/tests/app/app.test.js.map +1 -0
  242. package/dist/tests/app/builder.test.d.ts +2 -0
  243. package/dist/tests/app/builder.test.d.ts.map +1 -0
  244. package/dist/tests/app/builder.test.js +69 -0
  245. package/dist/tests/app/builder.test.js.map +1 -0
  246. package/dist/tests/cache/cached-collection.test.d.ts +2 -0
  247. package/dist/tests/cache/cached-collection.test.d.ts.map +1 -0
  248. package/dist/tests/cache/cached-collection.test.js +244 -0
  249. package/dist/tests/cache/cached-collection.test.js.map +1 -0
  250. package/dist/tests/cache/collection-cache.test.d.ts +2 -0
  251. package/dist/tests/cache/collection-cache.test.d.ts.map +1 -0
  252. package/dist/tests/cache/collection-cache.test.js +73 -0
  253. package/dist/tests/cache/collection-cache.test.js.map +1 -0
  254. package/dist/tests/collection-service/collection-service.test.d.ts +2 -0
  255. package/dist/tests/collection-service/collection-service.test.d.ts.map +1 -0
  256. package/dist/tests/collection-service/collection-service.test.js +805 -0
  257. package/dist/tests/collection-service/collection-service.test.js.map +1 -0
  258. package/dist/tests/collection-service/input-schema.test.d.ts +2 -0
  259. package/dist/tests/collection-service/input-schema.test.d.ts.map +1 -0
  260. package/dist/tests/collection-service/input-schema.test.js +260 -0
  261. package/dist/tests/collection-service/input-schema.test.js.map +1 -0
  262. package/dist/tests/config/config.test.d.ts +2 -0
  263. package/dist/tests/config/config.test.d.ts.map +1 -0
  264. package/dist/tests/config/config.test.js +84 -0
  265. package/dist/tests/config/config.test.js.map +1 -0
  266. package/dist/tests/crypto/crypto.test.d.ts +2 -0
  267. package/dist/tests/crypto/crypto.test.d.ts.map +1 -0
  268. package/dist/tests/crypto/crypto.test.js +56 -0
  269. package/dist/tests/crypto/crypto.test.js.map +1 -0
  270. package/dist/tests/http/file-serve.test.d.ts +2 -0
  271. package/dist/tests/http/file-serve.test.d.ts.map +1 -0
  272. package/dist/tests/http/file-serve.test.js +210 -0
  273. package/dist/tests/http/file-serve.test.js.map +1 -0
  274. package/dist/tests/http/file-token.test.d.ts +2 -0
  275. package/dist/tests/http/file-token.test.d.ts.map +1 -0
  276. package/dist/tests/http/file-token.test.js +155 -0
  277. package/dist/tests/http/file-token.test.js.map +1 -0
  278. package/dist/tests/http/ip-middleware.test.d.ts +2 -0
  279. package/dist/tests/http/ip-middleware.test.d.ts.map +1 -0
  280. package/dist/tests/http/ip-middleware.test.js +58 -0
  281. package/dist/tests/http/ip-middleware.test.js.map +1 -0
  282. package/dist/tests/http/router.test.d.ts +2 -0
  283. package/dist/tests/http/router.test.d.ts.map +1 -0
  284. package/dist/tests/http/router.test.js +252 -0
  285. package/dist/tests/http/router.test.js.map +1 -0
  286. package/dist/tests/migrator/dialect-sqlite.test.d.ts +2 -0
  287. package/dist/tests/migrator/dialect-sqlite.test.d.ts.map +1 -0
  288. package/dist/tests/migrator/dialect-sqlite.test.js +90 -0
  289. package/dist/tests/migrator/dialect-sqlite.test.js.map +1 -0
  290. package/dist/tests/migrator/integration.test.d.ts +2 -0
  291. package/dist/tests/migrator/integration.test.d.ts.map +1 -0
  292. package/dist/tests/migrator/integration.test.js +180 -0
  293. package/dist/tests/migrator/integration.test.js.map +1 -0
  294. package/dist/tests/migrator/migrator.test.d.ts +2 -0
  295. package/dist/tests/migrator/migrator.test.d.ts.map +1 -0
  296. package/dist/tests/migrator/migrator.test.js +225 -0
  297. package/dist/tests/migrator/migrator.test.js.map +1 -0
  298. package/dist/tests/migrator/schema-diff.test.d.ts +2 -0
  299. package/dist/tests/migrator/schema-diff.test.d.ts.map +1 -0
  300. package/dist/tests/migrator/schema-diff.test.js +323 -0
  301. package/dist/tests/migrator/schema-diff.test.js.map +1 -0
  302. package/dist/tests/repository/repository.test.d.ts +2 -0
  303. package/dist/tests/repository/repository.test.d.ts.map +1 -0
  304. package/dist/tests/repository/repository.test.js +255 -0
  305. package/dist/tests/repository/repository.test.js.map +1 -0
  306. package/dist/tests/rule/compiler.test.d.ts +2 -0
  307. package/dist/tests/rule/compiler.test.d.ts.map +1 -0
  308. package/dist/tests/rule/compiler.test.js +226 -0
  309. package/dist/tests/rule/compiler.test.js.map +1 -0
  310. package/dist/tests/rule/enforcer.test.d.ts +2 -0
  311. package/dist/tests/rule/enforcer.test.d.ts.map +1 -0
  312. package/dist/tests/rule/enforcer.test.js +190 -0
  313. package/dist/tests/rule/enforcer.test.js.map +1 -0
  314. package/dist/tests/storage/storage.test.d.ts +2 -0
  315. package/dist/tests/storage/storage.test.d.ts.map +1 -0
  316. package/dist/tests/storage/storage.test.js +76 -0
  317. package/dist/tests/storage/storage.test.js.map +1 -0
  318. package/dist/tests/telemetry/instrumentation.test.d.ts +2 -0
  319. package/dist/tests/telemetry/instrumentation.test.d.ts.map +1 -0
  320. package/dist/tests/telemetry/instrumentation.test.js +226 -0
  321. package/dist/tests/telemetry/instrumentation.test.js.map +1 -0
  322. package/dist/tests/telemetry/logger.test.d.ts +2 -0
  323. package/dist/tests/telemetry/logger.test.d.ts.map +1 -0
  324. package/dist/tests/telemetry/logger.test.js +56 -0
  325. package/dist/tests/telemetry/logger.test.js.map +1 -0
  326. package/dist/tests/telemetry/tracer.test.d.ts +2 -0
  327. package/dist/tests/telemetry/tracer.test.d.ts.map +1 -0
  328. package/dist/tests/telemetry/tracer.test.js +63 -0
  329. package/dist/tests/telemetry/tracer.test.js.map +1 -0
  330. package/dist/tests/thumbnail/photon.test.d.ts +2 -0
  331. package/dist/tests/thumbnail/photon.test.d.ts.map +1 -0
  332. package/dist/tests/thumbnail/photon.test.js +478 -0
  333. package/dist/tests/thumbnail/photon.test.js.map +1 -0
  334. package/dist/tests/thumbnail/thumbnail.test.d.ts +2 -0
  335. package/dist/tests/thumbnail/thumbnail.test.d.ts.map +1 -0
  336. package/dist/tests/thumbnail/thumbnail.test.js +35 -0
  337. package/dist/tests/thumbnail/thumbnail.test.js.map +1 -0
  338. package/package.json +46 -0
@@ -0,0 +1,17 @@
1
+ import type { RepoRecord } from "../repository/types.js";
2
+ /** Auth-resolved request context. JWT parsing is not done here — the route handler provides this. */
3
+ export type RequestCtx = {
4
+ auth?: {
5
+ collection: string;
6
+ record: RepoRecord;
7
+ };
8
+ headers: Record<string, string>;
9
+ query: Record<string, string | ReadonlyArray<string>>;
10
+ };
11
+ /** Paginated result — cursor-based via seqId. Used for all collection kinds. */
12
+ export type CursorPage = {
13
+ items: ReadonlyArray<RepoRecord>;
14
+ /** seqId of the last item. Pass as `after` to fetch the next page. null = no more pages. */
15
+ nextCursor: number | null;
16
+ };
17
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/collection-service/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAEvD,qGAAqG;AACrG,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,CAAA;IACjD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAA;CACtD,CAAA;AAED,gFAAgF;AAChF,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,aAAa,CAAC,UAAU,CAAC,CAAA;IAChC,4FAA4F;IAC5F,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/collection-service/context.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ import { Effect } from "effect";
2
+ import type { CollectionSchema } from "@gettersethya/mira-client";
3
+ import type { RepoRecord } from "../repository/types.js";
4
+ export type RowDecoder = (record: RepoRecord) => Effect.Effect<RepoRecord>;
5
+ export declare function makeRowDecoder(colSchema: CollectionSchema): RowDecoder;
6
+ //# sourceMappingURL=decode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode.d.ts","sourceRoot":"","sources":["../../../src/collection-service/decode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAA;AACvC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AACjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAIvD,MAAM,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,UAAU,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;AAE1E,wBAAgB,cAAc,CAAC,SAAS,EAAE,gBAAgB,GAAG,UAAU,CAsBtE"}
@@ -0,0 +1,26 @@
1
+ import { Effect, Schema } from "effect";
2
+ const RecordSchema = Schema.Record({ key: Schema.String, value: Schema.Unknown });
3
+ export function makeRowDecoder(colSchema) {
4
+ const boolKeys = new Set();
5
+ for (const [key, prop] of Object.entries(colSchema.properties)) {
6
+ if (prop.type === "boolean")
7
+ boolKeys.add(key);
8
+ }
9
+ if (boolKeys.size === 0)
10
+ return Effect.succeed;
11
+ const RowSchema = Schema.transform(RecordSchema, RecordSchema, {
12
+ decode: (record) => {
13
+ const result = { ...record };
14
+ for (const key of boolKeys) {
15
+ const v = result[key];
16
+ if (v === 0 || v === 1)
17
+ result[key] = v === 1;
18
+ }
19
+ return result;
20
+ },
21
+ encode: (v) => v
22
+ });
23
+ const decode = Schema.decodeUnknown(RowSchema);
24
+ return (record) => decode(record).pipe(Effect.orDie, Effect.map((r) => r));
25
+ }
26
+ //# sourceMappingURL=decode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode.js","sourceRoot":"","sources":["../../../src/collection-service/decode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAIvC,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAA;AAIjF,MAAM,UAAU,cAAc,CAAC,SAA2B;IACxD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAA;IAClC,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/D,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;YAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAChD,CAAC;IAED,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,OAAO,CAAA;IAE9C,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,YAAY,EAAE,YAAY,EAAE;QAC7D,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;YACjB,MAAM,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,CAAA;YAC5B,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;gBACrB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;oBAAE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YAC/C,CAAC;YACD,OAAO,MAAM,CAAA;QACf,CAAC;QACD,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;KACjB,CAAC,CAAA;IAEF,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAA;IAC9C,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAe,CAAC,CAAC,CAAA;AAC1F,CAAC"}
@@ -0,0 +1,67 @@
1
+ import type { SqlError } from "@effect/sql";
2
+ import { ValidationError } from "@gettersethya/mira-client";
3
+ export { ValidationError };
4
+ declare const NotFoundError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
5
+ readonly _tag: "NotFoundError";
6
+ } & Readonly<A>;
7
+ /**
8
+ * Error raised when a requested record is not found.
9
+ * Contains the collection name and the requested record ID.
10
+ *
11
+ * The server returns HTTP 404 when this error propagates to the HTTP layer.
12
+ *
13
+ * @example
14
+ * new NotFoundError({ collection: "posts", id: "abc123" })
15
+ *
16
+ * @see CollectionService — raises this error on getOne/update/delete for missing records
17
+ */
18
+ export declare class NotFoundError extends NotFoundError_base<{
19
+ collection: string;
20
+ id: string;
21
+ }> {
22
+ }
23
+ declare const ForbiddenError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
24
+ readonly _tag: "ForbiddenError";
25
+ } & Readonly<A>;
26
+ /**
27
+ * Error raised when an action is forbidden by access rules.
28
+ * Contains the collection name and the attempted action.
29
+ *
30
+ * The server returns HTTP 403 when this error propagates to the HTTP layer.
31
+ *
32
+ * @example
33
+ * new ForbiddenError({ collection: "posts", action: "update" })
34
+ *
35
+ * @see CollectionService — raises this error when rules deny an action
36
+ */
37
+ export declare class ForbiddenError extends ForbiddenError_base<{
38
+ collection: string;
39
+ action: string;
40
+ }> {
41
+ }
42
+ declare const ReadOnlyError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
43
+ readonly _tag: "ReadOnlyError";
44
+ } & Readonly<A>;
45
+ /**
46
+ * Error raised when a write operation is attempted on a read-only collection.
47
+ * View collections always raise this on create/update/delete.
48
+ *
49
+ * The server returns HTTP 405 (Method Not Allowed) when this error propagates.
50
+ *
51
+ * @example
52
+ * new ReadOnlyError({ collection: "active_posts" })
53
+ *
54
+ * @see ViewCollection — view collections are read-only
55
+ */
56
+ export declare class ReadOnlyError extends ReadOnlyError_base<{
57
+ collection: string;
58
+ }> {
59
+ }
60
+ /**
61
+ * Union of all errors that can be raised by CollectionService operations.
62
+ * Includes NotFoundError, ForbiddenError, ValidationError, ReadOnlyError, and SqlError.
63
+ *
64
+ * @see CollectionService — all methods fail with CollectionError
65
+ */
66
+ export type CollectionError = NotFoundError | ForbiddenError | ValidationError | ReadOnlyError | SqlError.SqlError;
67
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/collection-service/errors.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAE3D,OAAO,EAAE,eAAe,EAAE,CAAA;;;;AAE1B;;;;;;;;;;GAUG;AACH,qBAAa,aAAc,SAAQ,mBAAkC;IACnE,UAAU,EAAE,MAAM,CAAA;IAClB,EAAE,EAAE,MAAM,CAAA;CACX,CAAC;CAAG;;;;AAEL;;;;;;;;;;GAUG;AACH,qBAAa,cAAe,SAAQ,oBAAmC;IACrE,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;CACf,CAAC;CAAG;;;;AAEL;;;;;;;;;;GAUG;AACH,qBAAa,aAAc,SAAQ,mBAAkC;IACnE,UAAU,EAAE,MAAM,CAAA;CACnB,CAAC;CAAG;AAEL;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GACvB,aAAa,GACb,cAAc,GACd,eAAe,GACf,aAAa,GACb,QAAQ,CAAC,QAAQ,CAAA"}
@@ -0,0 +1,43 @@
1
+ import { Data } from "effect";
2
+ import { ValidationError } from "@gettersethya/mira-client";
3
+ export { ValidationError };
4
+ /**
5
+ * Error raised when a requested record is not found.
6
+ * Contains the collection name and the requested record ID.
7
+ *
8
+ * The server returns HTTP 404 when this error propagates to the HTTP layer.
9
+ *
10
+ * @example
11
+ * new NotFoundError({ collection: "posts", id: "abc123" })
12
+ *
13
+ * @see CollectionService — raises this error on getOne/update/delete for missing records
14
+ */
15
+ export class NotFoundError extends Data.TaggedError("NotFoundError") {
16
+ }
17
+ /**
18
+ * Error raised when an action is forbidden by access rules.
19
+ * Contains the collection name and the attempted action.
20
+ *
21
+ * The server returns HTTP 403 when this error propagates to the HTTP layer.
22
+ *
23
+ * @example
24
+ * new ForbiddenError({ collection: "posts", action: "update" })
25
+ *
26
+ * @see CollectionService — raises this error when rules deny an action
27
+ */
28
+ export class ForbiddenError extends Data.TaggedError("ForbiddenError") {
29
+ }
30
+ /**
31
+ * Error raised when a write operation is attempted on a read-only collection.
32
+ * View collections always raise this on create/update/delete.
33
+ *
34
+ * The server returns HTTP 405 (Method Not Allowed) when this error propagates.
35
+ *
36
+ * @example
37
+ * new ReadOnlyError({ collection: "active_posts" })
38
+ *
39
+ * @see ViewCollection — view collections are read-only
40
+ */
41
+ export class ReadOnlyError extends Data.TaggedError("ReadOnlyError") {
42
+ }
43
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/collection-service/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAE7B,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAE3D,OAAO,EAAE,eAAe,EAAE,CAAA;AAE1B;;;;;;;;;;GAUG;AACH,MAAM,OAAO,aAAc,SAAQ,IAAI,CAAC,WAAW,CAAC,eAAe,CAGjE;CAAG;AAEL;;;;;;;;;;GAUG;AACH,MAAM,OAAO,cAAe,SAAQ,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAGnE;CAAG;AAEL;;;;;;;;;;GAUG;AACH,MAAM,OAAO,aAAc,SAAQ,IAAI,CAAC,WAAW,CAAC,eAAe,CAEjE;CAAG"}
@@ -0,0 +1,5 @@
1
+ export { CollectionService, CollectionServiceLive, makeCollectionServiceLayer } from "./collection-service.js";
2
+ export type { CollectionError } from "./errors.js";
3
+ export { ForbiddenError, NotFoundError, ReadOnlyError, ValidationError } from "./errors.js";
4
+ export type { CursorPage, RequestCtx } from "./context.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/collection-service/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAA;AAC9G,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC3F,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA"}
@@ -0,0 +1,3 @@
1
+ export { CollectionService, CollectionServiceLive, makeCollectionServiceLayer } from "./collection-service.js";
2
+ export { ForbiddenError, NotFoundError, ReadOnlyError, ValidationError } from "./errors.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/collection-service/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAA;AAE9G,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA"}
@@ -0,0 +1,10 @@
1
+ import { ParseResult, Schema } from "effect";
2
+ import type { AnyCollectionDef } from "@gettersethya/mira-client";
3
+ import { ValidationError } from "./errors.js";
4
+ export type InputSchemas = {
5
+ create: Schema.Schema<any, any, never>;
6
+ update: Schema.Schema<any, any, never>;
7
+ };
8
+ export declare function buildInputSchemas(colDef: AnyCollectionDef): InputSchemas;
9
+ export declare function parseErrToValidationError(collection: string): (err: ParseResult.ParseError) => ValidationError;
10
+ //# sourceMappingURL=input-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-schema.d.ts","sourceRoot":"","sources":["../../../src/collection-service/input-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC5C,OAAO,KAAK,EAAE,gBAAgB,EAAgD,MAAM,2BAA2B,CAAA;AAC/G,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAI7C,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;IACtC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;CACvC,CAAA;AAgFD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,GAAG,YAAY,CAiCxE;AAED,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,IAClD,KAAK,WAAW,CAAC,UAAU,KAAG,eAAe,CAOtD"}
@@ -0,0 +1,109 @@
1
+ import { ParseResult, Schema } from "effect";
2
+ import { ValidationError } from "./errors.js";
3
+ const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
4
+ function filterAnnotations(kind, errorFn) {
5
+ if (errorFn === undefined)
6
+ return undefined;
7
+ const msg = errorFn(kind);
8
+ if (msg === undefined)
9
+ return undefined;
10
+ return { message: () => msg };
11
+ }
12
+ function propertyToSchema(prop, fieldDef) {
13
+ const errorFn = fieldDef?.error;
14
+ if (prop["x-kind"] === "json")
15
+ return Schema.Unknown;
16
+ if (prop["x-kind"] === "date" ||
17
+ prop["x-kind"] === "relation" ||
18
+ prop["x-kind"] === "file")
19
+ return Schema.String;
20
+ if (prop.type === "string") {
21
+ const typeMsg = errorFn?.("type");
22
+ const base = typeMsg !== undefined
23
+ ? Schema.String.annotations({ message: () => typeMsg })
24
+ : Schema.String;
25
+ let s = base;
26
+ if (prop.format === "email") {
27
+ s = s.pipe(Schema.pattern(EMAIL_RE, filterAnnotations("email", errorFn)));
28
+ }
29
+ if (prop.minLength !== undefined) {
30
+ s = s.pipe(Schema.minLength(prop.minLength, filterAnnotations("minLength", errorFn)));
31
+ }
32
+ if (prop.maxLength !== undefined) {
33
+ s = s.pipe(Schema.maxLength(prop.maxLength, filterAnnotations("maxLength", errorFn)));
34
+ }
35
+ return s;
36
+ }
37
+ if (prop.type === "integer") {
38
+ const typeMsg = errorFn?.("type");
39
+ const base = typeMsg !== undefined
40
+ ? Schema.Number.annotations({ message: () => typeMsg })
41
+ : Schema.Number;
42
+ let s = base.pipe(Schema.int(filterAnnotations("int", errorFn)));
43
+ if (prop.minimum !== undefined) {
44
+ s = s.pipe(Schema.greaterThanOrEqualTo(prop.minimum, filterAnnotations("minimum", errorFn)));
45
+ }
46
+ if (prop.maximum !== undefined) {
47
+ s = s.pipe(Schema.lessThanOrEqualTo(prop.maximum, filterAnnotations("maximum", errorFn)));
48
+ }
49
+ return s;
50
+ }
51
+ if (prop.type === "number") {
52
+ const typeMsg = errorFn?.("type");
53
+ const base = typeMsg !== undefined
54
+ ? Schema.Number.annotations({ message: () => typeMsg })
55
+ : Schema.Number;
56
+ let s = base;
57
+ if (prop.minimum !== undefined) {
58
+ s = s.pipe(Schema.greaterThanOrEqualTo(prop.minimum, filterAnnotations("minimum", errorFn)));
59
+ }
60
+ if (prop.maximum !== undefined) {
61
+ s = s.pipe(Schema.lessThanOrEqualTo(prop.maximum, filterAnnotations("maximum", errorFn)));
62
+ }
63
+ return s;
64
+ }
65
+ if (prop.type === "boolean") {
66
+ const typeMsg = errorFn?.("type");
67
+ return typeMsg !== undefined
68
+ ? Schema.Boolean.annotations({ message: () => typeMsg })
69
+ : Schema.Boolean;
70
+ }
71
+ return Schema.Unknown;
72
+ }
73
+ export function buildInputSchemas(colDef) {
74
+ const schema = colDef.schema;
75
+ const required = new Set(schema.required ?? []);
76
+ const createFields = {};
77
+ const updateFields = {};
78
+ for (const [key, prop] of Object.entries(schema.properties)) {
79
+ if (prop["x-system"] === true)
80
+ continue;
81
+ const fieldDef = colDef.fields[key];
82
+ const errorFn = fieldDef?.error;
83
+ const base = propertyToSchema(prop, fieldDef);
84
+ if (required.has(key)) {
85
+ const requiredMsg = errorFn?.("required");
86
+ createFields[key] = requiredMsg !== undefined
87
+ ? Schema.propertySignature(base).annotations({ missingMessage: () => requiredMsg })
88
+ : base;
89
+ }
90
+ else {
91
+ createFields[key] = Schema.optional(base);
92
+ }
93
+ updateFields[key] = Schema.optional(base);
94
+ }
95
+ return {
96
+ create: Schema.Struct(createFields),
97
+ update: Schema.Struct(updateFields)
98
+ };
99
+ }
100
+ export function parseErrToValidationError(collection) {
101
+ return (err) => {
102
+ const issues = ParseResult.ArrayFormatter.formatIssueSync(err.issue).map((i) => {
103
+ const prefix = i.path.length > 0 ? `${i.path.join(".")}: ` : "";
104
+ return `${prefix}${i.message}`;
105
+ });
106
+ return new ValidationError({ collection, issues });
107
+ };
108
+ }
109
+ //# sourceMappingURL=input-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-schema.js","sourceRoot":"","sources":["../../../src/collection-service/input-schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { Effect } from "effect";
2
+ import type { CollectionSchema } from "@gettersethya/mira-client";
3
+ import type { EnforceResult } from "../rule/enforcer.js";
4
+ import type { RepoRecord, SortOrder, WhereClause } from "../repository/types.js";
5
+ import type { RequestCtx } from "./context.js";
6
+ import { ForbiddenError } from "./errors.js";
7
+ /** Combines two WHERE clauses with AND. Both inputs are trusted internal code. */
8
+ export declare function andWhere(a: WhereClause, b: WhereClause): WhereClause;
9
+ /** Produces a WHERE clause that matches a single record by id. */
10
+ export declare function idClause(id: string): WhereClause;
11
+ /** Produces a WHERE clause for cursor pagination: seqId strictly after the given cursor. */
12
+ export declare function cursorClause(after: number): WhereClause;
13
+ /**
14
+ * Resolves `@auth_<field>` and `@request_<source>_<key>` placeholders produced by the
15
+ * rule compiler into positional `?` params bound from `RequestCtx`.
16
+ *
17
+ * The replacement is done in a single left-to-right pass so that the param array stays
18
+ * in the same order as the `?` placeholders in the resulting SQL.
19
+ *
20
+ * Returns `ForbiddenError` if the rule references auth but `ctx.auth` is absent.
21
+ */
22
+ export declare function resolveCtxPlaceholders(result: EnforceResult, ctx: RequestCtx, collection: string, action: string): Effect.Effect<{
23
+ sql: string;
24
+ params: unknown[];
25
+ }, ForbiddenError, never>;
26
+ /**
27
+ * Replaces `t.<fieldName>` column references in a WHERE clause with `?` params
28
+ * bound to the corresponding values in `record`.
29
+ *
30
+ * Used for the `create` permission pre-check: `SELECT 1 WHERE <rule>` without a FROM.
31
+ * The replacement is done left-to-right to preserve param ordering with existing `?`.
32
+ */
33
+ export declare function resolveFieldRefs(clause: WhereClause, record: RepoRecord): WhereClause;
34
+ export declare function buildUserSort(query: RequestCtx["query"], schema: CollectionSchema): SortOrder | null;
35
+ //# sourceMappingURL=where.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"where.d.ts","sourceRoot":"","sources":["../../../src/collection-service/where.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAC/E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAE5C,kFAAkF;AAClF,wBAAgB,QAAQ,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,WAAW,GAAG,WAAW,CAKpE;AAED,kEAAkE;AAClE,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,CAEhD;AAED,4FAA4F;AAC5F,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAEvD;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;;;0BA+BhH;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,GAAG,WAAW,CAgBrF;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,EAC1B,MAAM,EAAE,gBAAgB,GACvB,SAAS,GAAG,IAAI,CAMlB"}
@@ -0,0 +1,88 @@
1
+ import { Effect } from "effect";
2
+ import { ForbiddenError } from "./errors.js";
3
+ /** Combines two WHERE clauses with AND. Both inputs are trusted internal code. */
4
+ export function andWhere(a, b) {
5
+ return {
6
+ sql: `(${a.sql}) AND (${b.sql})`,
7
+ params: [...a.params, ...b.params]
8
+ };
9
+ }
10
+ /** Produces a WHERE clause that matches a single record by id. */
11
+ export function idClause(id) {
12
+ return { sql: "t.id = ?", params: [id] };
13
+ }
14
+ /** Produces a WHERE clause for cursor pagination: seqId strictly after the given cursor. */
15
+ export function cursorClause(after) {
16
+ return { sql: "t.seqId > ?", params: [after] };
17
+ }
18
+ /**
19
+ * Resolves `@auth_<field>` and `@request_<source>_<key>` placeholders produced by the
20
+ * rule compiler into positional `?` params bound from `RequestCtx`.
21
+ *
22
+ * The replacement is done in a single left-to-right pass so that the param array stays
23
+ * in the same order as the `?` placeholders in the resulting SQL.
24
+ *
25
+ * Returns `ForbiddenError` if the rule references auth but `ctx.auth` is absent.
26
+ */
27
+ export function resolveCtxPlaceholders(result, ctx, collection, action) {
28
+ return Effect.gen(function* () {
29
+ const needsAuth = /@auth_\w+/.test(result.sql);
30
+ if (needsAuth && ctx.auth === undefined) {
31
+ return yield* new ForbiddenError({ collection, action });
32
+ }
33
+ const resolved = [];
34
+ let pIdx = 0;
35
+ const { params } = result;
36
+ // Single-pass left-to-right replacement preserves param ordering.
37
+ // Groups: (1) @auth field, (2) @request source, (3) @request key
38
+ const newSql = result.sql.replace(/\?|@auth_(\w+)|@request_(\w+)_(\w+)/g, (match, g1, g2, g3) => {
39
+ const authField = typeof g1 === "string" ? g1 : undefined;
40
+ const reqSource = typeof g2 === "string" ? g2 : undefined;
41
+ const reqKey = typeof g3 === "string" ? g3 : undefined;
42
+ if (match === "?") {
43
+ resolved.push(params[pIdx++]);
44
+ }
45
+ else if (authField !== undefined) {
46
+ resolved.push(ctx.auth?.record[authField] ?? null);
47
+ }
48
+ else if (reqSource !== undefined && reqKey !== undefined) {
49
+ const val = reqSource === "query" ? ctx.query[reqKey] : ctx.headers[reqKey];
50
+ resolved.push(Array.isArray(val) ? val[0] : (val ?? null));
51
+ }
52
+ return "?";
53
+ });
54
+ return yield* Effect.succeed({ sql: newSql, params: resolved });
55
+ });
56
+ }
57
+ /**
58
+ * Replaces `t.<fieldName>` column references in a WHERE clause with `?` params
59
+ * bound to the corresponding values in `record`.
60
+ *
61
+ * Used for the `create` permission pre-check: `SELECT 1 WHERE <rule>` without a FROM.
62
+ * The replacement is done left-to-right to preserve param ordering with existing `?`.
63
+ */
64
+ export function resolveFieldRefs(clause, record) {
65
+ const resolved = [];
66
+ let pIdx = 0;
67
+ const { params } = clause;
68
+ const newSql = clause.sql.replace(/\?|\bt\.(\w+)\b/g, (_, g1) => {
69
+ const field = typeof g1 === "string" ? g1 : undefined;
70
+ if (field !== undefined) {
71
+ resolved.push(record[field] ?? null);
72
+ }
73
+ else {
74
+ resolved.push(params[pIdx++]);
75
+ }
76
+ return "?";
77
+ });
78
+ return { sql: newSql, params: resolved };
79
+ }
80
+ export function buildUserSort(query, schema) {
81
+ const sortField = typeof query["sort"] === "string" ? query["sort"] : null;
82
+ if (sortField === null || !schema.properties[sortField])
83
+ return null;
84
+ const rawOrder = typeof query["order"] === "string" ? query["order"] : null;
85
+ const direction = rawOrder === "desc" ? "desc" : "asc";
86
+ return { field: sortField, direction };
87
+ }
88
+ //# sourceMappingURL=where.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"where.js","sourceRoot":"","sources":["../../../src/collection-service/where.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import { SqlClient } from "@effect/sql";
2
+ import { CryptoService } from "../crypto/index.js";
3
+ import { Context, Layer } from "effect";
4
+ import type { AppConfigShape } from "./types.js";
5
+ declare const AppConfig_base: Context.TagClass<AppConfig, "AppConfig", AppConfigShape>;
6
+ /**
7
+ * Application configuration tag, backed by the `_config` table in the database.
8
+ *
9
+ * On first boot, seeds default values (including an auto-generated `jwt_secret`)
10
+ * into the `_config` table. Runtime reads go through the database — no env vars
11
+ * or config files are needed for basic operation.
12
+ *
13
+ * Provides access to:
14
+ * - `appName`, `port`, `applicationUrl` — basic server configuration
15
+ * - `jwtSecret` — Redacted JWT signing secret (auto-generated)
16
+ * - `useS3`, `s3Config` — optional S3 storage configuration
17
+ *
18
+ * @example
19
+ * import { AppConfig } from "@gettersethya/mira"
20
+ *
21
+ * Effect.gen(function* () {
22
+ * const cfg = yield* AppConfig
23
+ * console.log(cfg.appName, cfg.port)
24
+ * const secret = cfg.jwtSecret // Redacted<string>
25
+ * })
26
+ *
27
+ * @see AppConfigLive — the live layer implementation
28
+ * @see AppConfigShape — the full config shape
29
+ */
30
+ export declare class AppConfig extends AppConfig_base {
31
+ }
32
+ /**
33
+ * Live layer for `AppConfig`.
34
+ * Seeds the `_config` table on first boot with sensible defaults
35
+ * (including auto-generating `jwt_secret` via CryptoService).
36
+ *
37
+ * @example
38
+ * Layer.provideMerge(AppConfigLive)
39
+ *
40
+ * @see AppConfig — the service tag
41
+ */
42
+ export declare const AppConfigLive: Layer.Layer<AppConfig, import("effect/ParseResult").ParseError | import("@effect/sql/SqlError").SqlError, CryptoService | SqlClient.SqlClient>;
43
+ export {};
44
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/config/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAa,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,EAAE,OAAO,EAAU,KAAK,EAA4B,MAAM,QAAQ,CAAA;AACzE,OAAO,KAAK,EAAE,cAAc,EAAY,MAAM,YAAY,CAAA;;AAO1D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,SAAU,SAAQ,cAAqD;CAAG;AAEvF;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,gJA8DzB,CAAA"}
@@ -0,0 +1,89 @@
1
+ import { SqlClient, SqlSchema } from "@effect/sql";
2
+ import { CryptoService } from "../crypto/index.js";
3
+ import { Context, Effect, Layer, Option, Redacted, Schema } from "effect";
4
+ const ConfigRowSchema = Schema.Struct({
5
+ key: Schema.String,
6
+ value: Schema.String
7
+ });
8
+ /**
9
+ * Application configuration tag, backed by the `_config` table in the database.
10
+ *
11
+ * On first boot, seeds default values (including an auto-generated `jwt_secret`)
12
+ * into the `_config` table. Runtime reads go through the database — no env vars
13
+ * or config files are needed for basic operation.
14
+ *
15
+ * Provides access to:
16
+ * - `appName`, `port`, `applicationUrl` — basic server configuration
17
+ * - `jwtSecret` — Redacted JWT signing secret (auto-generated)
18
+ * - `useS3`, `s3Config` — optional S3 storage configuration
19
+ *
20
+ * @example
21
+ * import { AppConfig } from "@gettersethya/mira"
22
+ *
23
+ * Effect.gen(function* () {
24
+ * const cfg = yield* AppConfig
25
+ * console.log(cfg.appName, cfg.port)
26
+ * const secret = cfg.jwtSecret // Redacted<string>
27
+ * })
28
+ *
29
+ * @see AppConfigLive — the live layer implementation
30
+ * @see AppConfigShape — the full config shape
31
+ */
32
+ export class AppConfig extends Context.Tag("AppConfig")() {
33
+ }
34
+ /**
35
+ * Live layer for `AppConfig`.
36
+ * Seeds the `_config` table on first boot with sensible defaults
37
+ * (including auto-generating `jwt_secret` via CryptoService).
38
+ *
39
+ * @example
40
+ * Layer.provideMerge(AppConfigLive)
41
+ *
42
+ * @see AppConfig — the service tag
43
+ */
44
+ export const AppConfigLive = Layer.effect(AppConfig, Effect.gen(function* () {
45
+ const sql = yield* SqlClient.SqlClient;
46
+ // DDL — sql.unsafe is fine for CREATE TABLE
47
+ yield* sql.unsafe(`CREATE TABLE IF NOT EXISTS _config (key TEXT PRIMARY KEY, value TEXT NOT NULL)`);
48
+ const rows = yield* SqlSchema.findAll({
49
+ Request: Schema.Void,
50
+ Result: ConfigRowSchema,
51
+ execute: () => sql `SELECT key, value FROM ${sql("_config")}`
52
+ })(undefined);
53
+ const stored = new Map(rows.map((r) => [r.key, r.value]));
54
+ const seed = (key, defaultValue) => Effect.gen(function* () {
55
+ const existing = stored.get(key);
56
+ if (existing !== undefined)
57
+ return existing;
58
+ yield* sql `INSERT INTO ${sql("_config")} ${sql.insert({ key, value: defaultValue })}`;
59
+ return defaultValue;
60
+ });
61
+ const require = (key) => Effect.fromNullable(stored.get(key)).pipe(Effect.mapError(() => new Error(`_config key "${key}" is required when use_s3=true`)), Effect.orDie);
62
+ const appName = yield* seed("app_name", "mira");
63
+ const port = Number(yield* seed("port", "8080"));
64
+ const applicationUrl = yield* seed("application_url", `http://localhost:${port}`);
65
+ // Generated once on first boot, persisted so tokens survive restarts
66
+ const existingSecret = stored.get("jwt_secret");
67
+ const jwtSecretStr = existingSecret !== undefined
68
+ ? existingSecret
69
+ : yield* Effect.gen(function* () {
70
+ const cryptoSvc = yield* CryptoService;
71
+ const generated = Buffer.from(yield* cryptoSvc.randomBytes(48)).toString("hex");
72
+ yield* sql `INSERT INTO ${sql("_config")} ${sql.insert({ key: "jwt_secret", value: generated })}`;
73
+ yield* Effect.logInfo("jwt_secret generated and persisted to _config table.");
74
+ return generated;
75
+ });
76
+ const jwtSecret = Redacted.make(jwtSecretStr);
77
+ const useS3 = (yield* seed("use_s3", "false")) === "true";
78
+ const s3Config = useS3
79
+ ? Option.some({
80
+ endpoint: Redacted.make(yield* require("s3_endpoint")),
81
+ bucketName: yield* require("s3_bucket_name"),
82
+ regionName: yield* require("s3_region_name"),
83
+ accessKey: Redacted.make(yield* require("s3_access_key")),
84
+ secret: Redacted.make(yield* require("s3_secret"))
85
+ })
86
+ : Option.none();
87
+ return { appName, port, applicationUrl, jwtSecret, useS3, s3Config };
88
+ }));
89
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/config/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { AppConfig, AppConfigLive } from "./config.js";
2
+ export type { AppConfigShape, S3Config } from "./types.js";
3
+ //# sourceMappingURL=index.d.ts.map