@gettersethya/mira 0.1.0-alpha.2 → 0.1.0-alpha.21

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 (371) hide show
  1. package/README.md +174 -0
  2. package/dist/src/app/app.d.ts +45 -26
  3. package/dist/src/app/app.d.ts.map +1 -1
  4. package/dist/src/app/app.js +138 -41
  5. package/dist/src/app/app.js.map +1 -1
  6. package/dist/src/app/builder.d.ts +56 -15
  7. package/dist/src/app/builder.d.ts.map +1 -1
  8. package/dist/src/app/builder.js +56 -4
  9. package/dist/src/app/builder.js.map +1 -1
  10. package/dist/src/app/define-rule.d.ts +70 -0
  11. package/dist/src/app/define-rule.d.ts.map +1 -0
  12. package/dist/src/app/define-rule.js +42 -0
  13. package/dist/src/app/define-rule.js.map +1 -0
  14. package/dist/src/app/index.d.ts +8 -3
  15. package/dist/src/app/index.d.ts.map +1 -1
  16. package/dist/src/app/index.js +3 -0
  17. package/dist/src/app/index.js.map +1 -1
  18. package/dist/src/app/plugin.d.ts +83 -0
  19. package/dist/src/app/plugin.d.ts.map +1 -0
  20. package/dist/src/app/plugin.js +20 -0
  21. package/dist/src/app/plugin.js.map +1 -0
  22. package/dist/src/app/types.d.ts +4 -4
  23. package/dist/src/app/types.d.ts.map +1 -1
  24. package/dist/src/cache/cached-collection.d.ts +7 -5
  25. package/dist/src/cache/cached-collection.d.ts.map +1 -1
  26. package/dist/src/cache/cached-collection.js +8 -5
  27. package/dist/src/cache/cached-collection.js.map +1 -1
  28. package/dist/src/cache/collection-cache.d.ts +1 -1
  29. package/dist/src/cache/collection-cache.d.ts.map +1 -1
  30. package/dist/src/cache/collection-cache.js +1 -1
  31. package/dist/src/cache/collection-cache.js.map +1 -1
  32. package/dist/src/cache/ctx-key.d.ts +15 -0
  33. package/dist/src/cache/ctx-key.d.ts.map +1 -0
  34. package/dist/src/cache/ctx-key.js +37 -0
  35. package/dist/src/cache/ctx-key.js.map +1 -0
  36. package/dist/src/cache/index.d.ts +2 -1
  37. package/dist/src/cache/index.d.ts.map +1 -1
  38. package/dist/src/cache/index.js +2 -1
  39. package/dist/src/cache/index.js.map +1 -1
  40. package/dist/src/collection-service/collection-service.d.ts +7 -5
  41. package/dist/src/collection-service/collection-service.d.ts.map +1 -1
  42. package/dist/src/collection-service/collection-service.js +201 -51
  43. package/dist/src/collection-service/collection-service.js.map +1 -1
  44. package/dist/src/collection-service/context.d.ts +2 -0
  45. package/dist/src/collection-service/context.d.ts.map +1 -1
  46. package/dist/src/collection-service/decode.d.ts +4 -2
  47. package/dist/src/collection-service/decode.d.ts.map +1 -1
  48. package/dist/src/collection-service/decode.js +32 -16
  49. package/dist/src/collection-service/decode.js.map +1 -1
  50. package/dist/src/collection-service/errors.d.ts +1 -1
  51. package/dist/src/collection-service/errors.d.ts.map +1 -1
  52. package/dist/src/collection-service/errors.js +1 -1
  53. package/dist/src/collection-service/errors.js.map +1 -1
  54. package/dist/src/collection-service/index.d.ts +1 -1
  55. package/dist/src/collection-service/index.d.ts.map +1 -1
  56. package/dist/src/collection-service/index.js.map +1 -1
  57. package/dist/src/collection-service/input-schema.d.ts +5 -4
  58. package/dist/src/collection-service/input-schema.d.ts.map +1 -1
  59. package/dist/src/collection-service/input-schema.js +31 -18
  60. package/dist/src/collection-service/input-schema.js.map +1 -1
  61. package/dist/src/collection-service/where.d.ts +14 -2
  62. package/dist/src/collection-service/where.d.ts.map +1 -1
  63. package/dist/src/collection-service/where.js +35 -1
  64. package/dist/src/collection-service/where.js.map +1 -1
  65. package/dist/src/config/config.d.ts +4 -4
  66. package/dist/src/config/config.d.ts.map +1 -1
  67. package/dist/src/config/config.js +34 -5
  68. package/dist/src/config/config.js.map +1 -1
  69. package/dist/src/config/types.d.ts +9 -0
  70. package/dist/src/config/types.d.ts.map +1 -1
  71. package/dist/src/cron/cron-service.d.ts +14 -0
  72. package/dist/src/cron/cron-service.d.ts.map +1 -0
  73. package/dist/src/cron/cron-service.js +135 -0
  74. package/dist/src/cron/cron-service.js.map +1 -0
  75. package/dist/src/cron/index.d.ts +4 -0
  76. package/dist/src/cron/index.d.ts.map +1 -0
  77. package/dist/src/cron/index.js +3 -0
  78. package/dist/src/cron/index.js.map +1 -0
  79. package/dist/src/cron/persistence.d.ts +22 -0
  80. package/dist/src/cron/persistence.d.ts.map +1 -0
  81. package/dist/src/cron/persistence.js +48 -0
  82. package/dist/src/cron/persistence.js.map +1 -0
  83. package/dist/src/cron/types.d.ts +51 -0
  84. package/dist/src/cron/types.d.ts.map +1 -0
  85. package/dist/src/cron/types.js +4 -0
  86. package/dist/src/cron/types.js.map +1 -0
  87. package/dist/src/crypto/crypto.d.ts +3 -2
  88. package/dist/src/crypto/crypto.d.ts.map +1 -1
  89. package/dist/src/crypto/crypto.js +1 -1
  90. package/dist/src/crypto/crypto.js.map +1 -1
  91. package/dist/src/crypto/node.d.ts.map +1 -1
  92. package/dist/src/crypto/node.js.map +1 -1
  93. package/dist/src/databases/sqlite.d.ts.map +1 -1
  94. package/dist/src/databases/sqlite.js +2 -2
  95. package/dist/src/databases/sqlite.js.map +1 -1
  96. package/dist/src/dialect/dialect-sqlite.d.ts +9 -0
  97. package/dist/src/dialect/dialect-sqlite.d.ts.map +1 -0
  98. package/dist/src/dialect/dialect-sqlite.js +109 -0
  99. package/dist/src/dialect/dialect-sqlite.js.map +1 -0
  100. package/dist/src/dialect/dialect.d.ts +26 -0
  101. package/dist/src/dialect/dialect.d.ts.map +1 -0
  102. package/dist/src/dialect/dialect.js +5 -0
  103. package/dist/src/dialect/dialect.js.map +1 -0
  104. package/dist/src/hooks/hook-collection.d.ts +5 -0
  105. package/dist/src/hooks/hook-collection.d.ts.map +1 -0
  106. package/dist/src/hooks/hook-collection.js +77 -0
  107. package/dist/src/hooks/hook-collection.js.map +1 -0
  108. package/dist/src/hooks/hook-service.d.ts +38 -0
  109. package/dist/src/hooks/hook-service.d.ts.map +1 -0
  110. package/dist/src/hooks/hook-service.js +150 -0
  111. package/dist/src/hooks/hook-service.js.map +1 -0
  112. package/dist/src/hooks/index.d.ts +4 -0
  113. package/dist/src/hooks/index.d.ts.map +1 -0
  114. package/dist/src/hooks/index.js +3 -0
  115. package/dist/src/hooks/index.js.map +1 -0
  116. package/dist/src/hooks/types.d.ts +74 -0
  117. package/dist/src/hooks/types.d.ts.map +1 -0
  118. package/dist/src/hooks/types.js +2 -0
  119. package/dist/src/hooks/types.js.map +1 -0
  120. package/dist/src/http/auth-node.d.ts.map +1 -1
  121. package/dist/src/http/auth-node.js +1 -1
  122. package/dist/src/http/auth-node.js.map +1 -1
  123. package/dist/src/http/auth.d.ts +3 -1
  124. package/dist/src/http/auth.d.ts.map +1 -1
  125. package/dist/src/http/auth.js +12 -2
  126. package/dist/src/http/auth.js.map +1 -1
  127. package/dist/src/http/cors.d.ts +94 -0
  128. package/dist/src/http/cors.d.ts.map +1 -0
  129. package/dist/src/http/cors.js +57 -0
  130. package/dist/src/http/cors.js.map +1 -0
  131. package/dist/src/http/errors.d.ts +1 -1
  132. package/dist/src/http/errors.d.ts.map +1 -1
  133. package/dist/src/http/errors.js +7 -7
  134. package/dist/src/http/errors.js.map +1 -1
  135. package/dist/src/http/file-serve.d.ts +4 -4
  136. package/dist/src/http/file-serve.d.ts.map +1 -1
  137. package/dist/src/http/file-serve.js +39 -34
  138. package/dist/src/http/file-serve.js.map +1 -1
  139. package/dist/src/http/file-token.d.ts +4 -3
  140. package/dist/src/http/file-token.d.ts.map +1 -1
  141. package/dist/src/http/file-token.js +19 -17
  142. package/dist/src/http/file-token.js.map +1 -1
  143. package/dist/src/http/files.d.ts +3 -3
  144. package/dist/src/http/files.d.ts.map +1 -1
  145. package/dist/src/http/files.js +5 -5
  146. package/dist/src/http/files.js.map +1 -1
  147. package/dist/src/http/index.d.ts +8 -5
  148. package/dist/src/http/index.d.ts.map +1 -1
  149. package/dist/src/http/index.js +5 -3
  150. package/dist/src/http/index.js.map +1 -1
  151. package/dist/src/http/ip-middleware.d.ts +3 -2
  152. package/dist/src/http/ip-middleware.d.ts.map +1 -1
  153. package/dist/src/http/ip-middleware.js +7 -4
  154. package/dist/src/http/ip-middleware.js.map +1 -1
  155. package/dist/src/http/params.d.ts +3 -3
  156. package/dist/src/http/params.d.ts.map +1 -1
  157. package/dist/src/http/params.js +2 -2
  158. package/dist/src/http/params.js.map +1 -1
  159. package/dist/src/http/port-retry.d.ts +18 -0
  160. package/dist/src/http/port-retry.d.ts.map +1 -0
  161. package/dist/src/http/port-retry.js +43 -0
  162. package/dist/src/http/port-retry.js.map +1 -0
  163. package/dist/src/http/router.d.ts +10 -7
  164. package/dist/src/http/router.d.ts.map +1 -1
  165. package/dist/src/http/router.js +184 -63
  166. package/dist/src/http/router.js.map +1 -1
  167. package/dist/src/http/schema.d.ts +5 -0
  168. package/dist/src/http/schema.d.ts.map +1 -0
  169. package/dist/src/http/schema.js +18 -0
  170. package/dist/src/http/schema.js.map +1 -0
  171. package/dist/src/http/server-factory-node.d.ts.map +1 -1
  172. package/dist/src/http/server-factory-node.js +1 -1
  173. package/dist/src/http/server-factory-node.js.map +1 -1
  174. package/dist/src/http/server-factory.d.ts +3 -3
  175. package/dist/src/http/server-factory.d.ts.map +1 -1
  176. package/dist/src/http/server-factory.js +1 -1
  177. package/dist/src/http/server-factory.js.map +1 -1
  178. package/dist/src/http/telemetry-routes.d.ts +5 -0
  179. package/dist/src/http/telemetry-routes.d.ts.map +1 -0
  180. package/dist/src/http/telemetry-routes.js +220 -0
  181. package/dist/src/http/telemetry-routes.js.map +1 -0
  182. package/dist/src/index.d.ts +18 -1
  183. package/dist/src/index.d.ts.map +1 -1
  184. package/dist/src/index.js +14 -1
  185. package/dist/src/index.js.map +1 -1
  186. package/dist/src/migrator/dialect-sqlite.d.ts.map +1 -1
  187. package/dist/src/migrator/dialect-sqlite.js +7 -1
  188. package/dist/src/migrator/dialect-sqlite.js.map +1 -1
  189. package/dist/src/migrator/index.d.ts +4 -4
  190. package/dist/src/migrator/index.d.ts.map +1 -1
  191. package/dist/src/migrator/index.js +2 -2
  192. package/dist/src/migrator/index.js.map +1 -1
  193. package/dist/src/migrator/migrator.d.ts +8 -8
  194. package/dist/src/migrator/migrator.d.ts.map +1 -1
  195. package/dist/src/migrator/migrator.js +16 -13
  196. package/dist/src/migrator/migrator.js.map +1 -1
  197. package/dist/src/migrator/schema-diff.d.ts +2 -2
  198. package/dist/src/migrator/schema-diff.d.ts.map +1 -1
  199. package/dist/src/migrator/schema-diff.js.map +1 -1
  200. package/dist/src/migrator/types.d.ts +5 -5
  201. package/dist/src/migrator/types.d.ts.map +1 -1
  202. package/dist/src/migrator/types.js +6 -7
  203. package/dist/src/migrator/types.js.map +1 -1
  204. package/dist/src/platforms/node.d.ts +1 -1
  205. package/dist/src/platforms/node.d.ts.map +1 -1
  206. package/dist/src/platforms/node.js +1 -1
  207. package/dist/src/platforms/node.js.map +1 -1
  208. package/dist/src/repository/id.d.ts +1 -1
  209. package/dist/src/repository/id.d.ts.map +1 -1
  210. package/dist/src/repository/id.js +15 -3
  211. package/dist/src/repository/id.js.map +1 -1
  212. package/dist/src/repository/repository.d.ts +3 -2
  213. package/dist/src/repository/repository.d.ts.map +1 -1
  214. package/dist/src/repository/repository.js +11 -7
  215. package/dist/src/repository/repository.js.map +1 -1
  216. package/dist/src/rule/compiler.d.ts.map +1 -1
  217. package/dist/src/rule/compiler.js +2 -0
  218. package/dist/src/rule/compiler.js.map +1 -1
  219. package/dist/src/rule/enforcer.d.ts.map +1 -1
  220. package/dist/src/rule/enforcer.js.map +1 -1
  221. package/dist/src/storage/index.d.ts +1 -1
  222. package/dist/src/storage/index.d.ts.map +1 -1
  223. package/dist/src/storage/index.js +1 -1
  224. package/dist/src/storage/index.js.map +1 -1
  225. package/dist/src/storage/local-preset.d.ts.map +1 -1
  226. package/dist/src/storage/local-preset.js.map +1 -1
  227. package/dist/src/storage/storage.d.ts +2 -2
  228. package/dist/src/storage/storage.d.ts.map +1 -1
  229. package/dist/src/storage/storage.js +8 -26
  230. package/dist/src/storage/storage.js.map +1 -1
  231. package/dist/src/telemetry/collections.d.ts +4 -0
  232. package/dist/src/telemetry/collections.d.ts.map +1 -0
  233. package/dist/src/telemetry/collections.js +19 -0
  234. package/dist/src/telemetry/collections.js.map +1 -0
  235. package/dist/src/telemetry/index.d.ts +17 -3
  236. package/dist/src/telemetry/index.d.ts.map +1 -1
  237. package/dist/src/telemetry/index.js +15 -5
  238. package/dist/src/telemetry/index.js.map +1 -1
  239. package/dist/src/telemetry/logger.d.ts +29 -2
  240. package/dist/src/telemetry/logger.d.ts.map +1 -1
  241. package/dist/src/telemetry/logger.js +52 -15
  242. package/dist/src/telemetry/logger.js.map +1 -1
  243. package/dist/src/telemetry/sqlite-logger.d.ts +36 -0
  244. package/dist/src/telemetry/sqlite-logger.d.ts.map +1 -0
  245. package/dist/src/telemetry/sqlite-logger.js +193 -0
  246. package/dist/src/telemetry/sqlite-logger.js.map +1 -0
  247. package/dist/src/telemetry/telemetry-sql-client.d.ts +11 -0
  248. package/dist/src/telemetry/telemetry-sql-client.d.ts.map +1 -0
  249. package/dist/src/telemetry/telemetry-sql-client.js +8 -0
  250. package/dist/src/telemetry/telemetry-sql-client.js.map +1 -0
  251. package/dist/src/telemetry/tracer.d.ts +16 -1
  252. package/dist/src/telemetry/tracer.d.ts.map +1 -1
  253. package/dist/src/telemetry/tracer.js +87 -70
  254. package/dist/src/telemetry/tracer.js.map +1 -1
  255. package/dist/src/telemetry/types.d.ts +11 -0
  256. package/dist/src/telemetry/types.d.ts.map +1 -0
  257. package/dist/src/telemetry/types.js +2 -0
  258. package/dist/src/telemetry/types.js.map +1 -0
  259. package/dist/src/thumbnail/index.d.ts +2 -2
  260. package/dist/src/thumbnail/index.d.ts.map +1 -1
  261. package/dist/src/thumbnail/index.js +1 -1
  262. package/dist/src/thumbnail/index.js.map +1 -1
  263. package/dist/src/thumbnail/photon.d.ts.map +1 -1
  264. package/dist/src/thumbnail/photon.js +1 -1
  265. package/dist/src/thumbnail/photon.js.map +1 -1
  266. package/dist/src/thumbnail/types.d.ts +1 -1
  267. package/dist/src/thumbnail/types.d.ts.map +1 -1
  268. package/dist/src/thumbnail/types.js +2 -2
  269. package/dist/src/thumbnail/types.js.map +1 -1
  270. package/dist/tests/app/app.test.js +101 -26
  271. package/dist/tests/app/app.test.js.map +1 -1
  272. package/dist/tests/app/builder.test.js +77 -9
  273. package/dist/tests/app/builder.test.js.map +1 -1
  274. package/dist/tests/app/define-rule.test.d.ts +2 -0
  275. package/dist/tests/app/define-rule.test.d.ts.map +1 -0
  276. package/dist/tests/app/define-rule.test.js +147 -0
  277. package/dist/tests/app/define-rule.test.js.map +1 -0
  278. package/dist/tests/cache/cached-collection.test.js +200 -40
  279. package/dist/tests/cache/cached-collection.test.js.map +1 -1
  280. package/dist/tests/cache/collection-cache.test.js +1 -1
  281. package/dist/tests/cache/collection-cache.test.js.map +1 -1
  282. package/dist/tests/collection-service/auth-credentials.test.d.ts +2 -0
  283. package/dist/tests/collection-service/auth-credentials.test.d.ts.map +1 -0
  284. package/dist/tests/collection-service/auth-credentials.test.js +172 -0
  285. package/dist/tests/collection-service/auth-credentials.test.js.map +1 -0
  286. package/dist/tests/collection-service/collection-service.test.js +374 -174
  287. package/dist/tests/collection-service/collection-service.test.js.map +1 -1
  288. package/dist/tests/collection-service/decode.test.d.ts +2 -0
  289. package/dist/tests/collection-service/decode.test.d.ts.map +1 -0
  290. package/dist/tests/collection-service/decode.test.js +37 -0
  291. package/dist/tests/collection-service/decode.test.js.map +1 -0
  292. package/dist/tests/collection-service/input-schema.test.js +162 -95
  293. package/dist/tests/collection-service/input-schema.test.js.map +1 -1
  294. package/dist/tests/config/config.test.js +15 -4
  295. package/dist/tests/config/config.test.js.map +1 -1
  296. package/dist/tests/cron/cron-integration.test.d.ts +2 -0
  297. package/dist/tests/cron/cron-integration.test.d.ts.map +1 -0
  298. package/dist/tests/cron/cron-integration.test.js +109 -0
  299. package/dist/tests/cron/cron-integration.test.js.map +1 -0
  300. package/dist/tests/cron/cron-persistence.test.d.ts +2 -0
  301. package/dist/tests/cron/cron-persistence.test.d.ts.map +1 -0
  302. package/dist/tests/cron/cron-persistence.test.js +123 -0
  303. package/dist/tests/cron/cron-persistence.test.js.map +1 -0
  304. package/dist/tests/cron/cron-service.test.d.ts +2 -0
  305. package/dist/tests/cron/cron-service.test.d.ts.map +1 -0
  306. package/dist/tests/cron/cron-service.test.js +124 -0
  307. package/dist/tests/cron/cron-service.test.js.map +1 -0
  308. package/dist/tests/crypto/crypto.test.js +2 -2
  309. package/dist/tests/crypto/crypto.test.js.map +1 -1
  310. package/dist/tests/hooks/hook-collection.test.d.ts +2 -0
  311. package/dist/tests/hooks/hook-collection.test.d.ts.map +1 -0
  312. package/dist/tests/hooks/hook-collection.test.js +110 -0
  313. package/dist/tests/hooks/hook-collection.test.js.map +1 -0
  314. package/dist/tests/hooks/hook-service.test.d.ts +2 -0
  315. package/dist/tests/hooks/hook-service.test.d.ts.map +1 -0
  316. package/dist/tests/hooks/hook-service.test.js +220 -0
  317. package/dist/tests/hooks/hook-service.test.js.map +1 -0
  318. package/dist/tests/http/cors.test.d.ts +2 -0
  319. package/dist/tests/http/cors.test.d.ts.map +1 -0
  320. package/dist/tests/http/cors.test.js +211 -0
  321. package/dist/tests/http/cors.test.js.map +1 -0
  322. package/dist/tests/http/file-serve.test.js +63 -54
  323. package/dist/tests/http/file-serve.test.js.map +1 -1
  324. package/dist/tests/http/file-token.test.js +69 -51
  325. package/dist/tests/http/file-token.test.js.map +1 -1
  326. package/dist/tests/http/ip-middleware.test.js +13 -13
  327. package/dist/tests/http/ip-middleware.test.js.map +1 -1
  328. package/dist/tests/http/port-retry.test.d.ts +2 -0
  329. package/dist/tests/http/port-retry.test.d.ts.map +1 -0
  330. package/dist/tests/http/port-retry.test.js +52 -0
  331. package/dist/tests/http/port-retry.test.js.map +1 -0
  332. package/dist/tests/http/router.test.js +260 -85
  333. package/dist/tests/http/router.test.js.map +1 -1
  334. package/dist/tests/migrator/dialect-sqlite.test.js +1 -1
  335. package/dist/tests/migrator/dialect-sqlite.test.js.map +1 -1
  336. package/dist/tests/migrator/integration.test.js +6 -6
  337. package/dist/tests/migrator/integration.test.js.map +1 -1
  338. package/dist/tests/migrator/migrator.test.js +5 -5
  339. package/dist/tests/migrator/migrator.test.js.map +1 -1
  340. package/dist/tests/migrator/schema-diff.test.js.map +1 -1
  341. package/dist/tests/repository/repository.test.js +71 -8
  342. package/dist/tests/repository/repository.test.js.map +1 -1
  343. package/dist/tests/rule/compiler.test.js +1 -1
  344. package/dist/tests/rule/compiler.test.js.map +1 -1
  345. package/dist/tests/rule/enforcer.test.js +9 -9
  346. package/dist/tests/rule/enforcer.test.js.map +1 -1
  347. package/dist/tests/storage/storage.test.js +15 -15
  348. package/dist/tests/storage/storage.test.js.map +1 -1
  349. package/dist/tests/telemetry/collections.test.d.ts +2 -0
  350. package/dist/tests/telemetry/collections.test.d.ts.map +1 -0
  351. package/dist/tests/telemetry/collections.test.js +67 -0
  352. package/dist/tests/telemetry/collections.test.js.map +1 -0
  353. package/dist/tests/telemetry/instrumentation.test.js +27 -20
  354. package/dist/tests/telemetry/instrumentation.test.js.map +1 -1
  355. package/dist/tests/telemetry/logger.test.js +38 -6
  356. package/dist/tests/telemetry/logger.test.js.map +1 -1
  357. package/dist/tests/telemetry/sqlite-logger.test.d.ts +2 -0
  358. package/dist/tests/telemetry/sqlite-logger.test.d.ts.map +1 -0
  359. package/dist/tests/telemetry/sqlite-logger.test.js +272 -0
  360. package/dist/tests/telemetry/sqlite-logger.test.js.map +1 -0
  361. package/dist/tests/telemetry/telemetry-routes.test.d.ts +2 -0
  362. package/dist/tests/telemetry/telemetry-routes.test.d.ts.map +1 -0
  363. package/dist/tests/telemetry/telemetry-routes.test.js +154 -0
  364. package/dist/tests/telemetry/telemetry-routes.test.js.map +1 -0
  365. package/dist/tests/telemetry/tracer.test.js +41 -4
  366. package/dist/tests/telemetry/tracer.test.js.map +1 -1
  367. package/dist/tests/thumbnail/photon.test.js +35 -35
  368. package/dist/tests/thumbnail/photon.test.js.map +1 -1
  369. package/dist/tests/thumbnail/thumbnail.test.js +7 -7
  370. package/dist/tests/thumbnail/thumbnail.test.js.map +1 -1
  371. package/package.json +9 -9
package/README.md ADDED
@@ -0,0 +1,174 @@
1
+ # @gettersethya/mira
2
+
3
+ [![npm](https://img.shields.io/npm/v/@gettersethya/mira)](https://www.npmjs.com/package/@gettersethya/mira)
4
+
5
+ > **Early pre-alpha.** Breaking changes may occur without notice.
6
+
7
+ Self-hosted backend in TypeScript using [Effect v4](https://effect.website). Define collections, get a full REST API with auth, file storage, access rules, and schema migrations — all with zero config.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install @gettersethya/mira @gettersethya/mira-collection effect
13
+ # or
14
+ pnpm add @gettersethya/mira @gettersethya/mira-collection effect
15
+ ```
16
+
17
+ ## Quick start
18
+
19
+ ```typescript
20
+ import { defineRule, LocalFileStorage, Mira, NodePlatform, Rule, SqliteDatabase } from "@gettersethya/mira"
21
+ import { Posts, Users } from "./collections.js"
22
+
23
+ const userRules = defineRule(Users, (R) => ({
24
+ list: Rule.public(),
25
+ view: Rule.public(),
26
+ create: Rule.public(),
27
+ update: R.selfId().eq(R.authId(Users)),
28
+ }))
29
+
30
+ const postRules = defineRule(Posts, (R) => ({
31
+ list: R.field("published").eq(R.literal(true)),
32
+ view: R.or(
33
+ R.field("published").eq(R.literal(true)),
34
+ R.field("authorId").eq(R.authId(Users))
35
+ ),
36
+ create: R.authId(Users).neq(R.literal("")),
37
+ update: R.field("authorId").eq(R.authId(Users)),
38
+ delete: R.field("authorId").eq(R.authId(Users)),
39
+ }))
40
+
41
+ const app = Mira.builder()
42
+ .platform(NodePlatform)
43
+ .database(SqliteDatabase({ filename: "mira.db" }))
44
+ .storage(LocalFileStorage({ directory: "./uploads" }))
45
+ .collections([Users, Posts])
46
+ .rules([userRules, postRules])
47
+ .build()
48
+
49
+ app.serve({ port: 3000 })
50
+ ```
51
+
52
+ The builder uses phantom types to enforce step ordering — TypeScript will not let you call `.build()` until all four required steps are complete.
53
+
54
+ On first boot, Mira auto-generates a `jwt_secret`, runs schema migrations, and creates SQL views for view collections. Everything is persisted in the database.
55
+
56
+ ## Builder steps
57
+
58
+ | Step | Required | Description |
59
+ |---|---|---|
60
+ | `.platform(p)` | Yes | Runtime environment (Node.js, etc.) |
61
+ | `.database(d)` | Yes | Database backend |
62
+ | `.storage(s)` | Yes | File storage backend |
63
+ | `.collections(c)` | Yes | Collection definitions |
64
+ | `.rules(r)` | No | Array of `RuleBinding` from `defineRule(collection, cb)` |
65
+ | `.crons(c)` | No | Array of `CronDef` — scheduled tasks using Effect `Schedule` |
66
+ | `.telemetry(layer)` | No | Custom Effect telemetry layer |
67
+ | `.cors(c)` | No | CORS config. Defaults to permissive (`*`), so a separately-hosted frontend works with zero config |
68
+ | `.extend(plugin)` | No | Register a `MiraPlugin` (lifecycle hooks, routes, crons, layers) |
69
+
70
+ ## Platforms
71
+
72
+ ```typescript
73
+ import { NodePlatform } from "@gettersethya/mira"
74
+
75
+ // Provides: CryptoService, FileSystem, HttpServerFactory, AuthService
76
+ ```
77
+
78
+ ## Databases
79
+
80
+ ```typescript
81
+ import { SqliteDatabase } from "@gettersethya/mira"
82
+
83
+ SqliteDatabase({ filename: "mira.db" })
84
+ SqliteDatabase({ filename: ":memory:" }) // in-memory for tests
85
+ ```
86
+
87
+ ## Storage
88
+
89
+ ```typescript
90
+ import { LocalFileStorage } from "@gettersethya/mira"
91
+
92
+ LocalFileStorage({ directory: "./uploads" })
93
+ ```
94
+
95
+ ## CORS
96
+
97
+ By default the server is fully permissive (`Access-Control-Allow-Origin: *`), so a frontend hosted on another origin works with zero configuration. `OPTIONS` preflights are answered automatically, and error responses carry CORS headers too.
98
+
99
+ ```typescript
100
+ Mira.builder()
101
+ // ... required steps
102
+ .cors({
103
+ allowedOrigins: ["https://app.example.com"], // list, or (origin) => boolean predicate
104
+ credentials: true, // requires explicit origins — never combines with "*"
105
+ // allowedMethods, allowedHeaders, exposedHeaders, maxAge are optional
106
+ })
107
+ .build()
108
+ ```
109
+
110
+ `credentials: true` combined with a wildcard origin throws at build time.
111
+
112
+ ## Auto-generated endpoints
113
+
114
+ Each collection gets a full set of REST endpoints:
115
+
116
+ | Method | Path | Description |
117
+ |---|---|---|
118
+ | `GET` | `/api/collections/:collection` | List (filter, sort, cursor, expand, select) |
119
+ | `GET` | `/api/collections/:collection/:id` | Get one |
120
+ | `POST` | `/api/collections/:collection` | Create |
121
+ | `PATCH` | `/api/collections/:collection/:id` | Update |
122
+ | `DELETE` | `/api/collections/:collection/:id` | Delete |
123
+ | `POST` | `/api/collections/:collection/auth-with-password` | Login (auth collections only) |
124
+ | `GET` | `/api/auth/me` | Current authenticated record |
125
+ | `POST` | `/api/auth/logout` | Logout |
126
+ | `POST` | `/api/files/token` | Request protected file token |
127
+ | `GET` | `/api/files/:collection/:id/:filename` | Serve file |
128
+ | `GET` | `/api/_schema` | Schema introspection |
129
+
130
+ ## Cron jobs
131
+
132
+ Register scheduled tasks via the `.crons()` builder step. Each cron uses an Effect `Schedule` to define its recurrence.
133
+
134
+ ```typescript
135
+ import { Schedule } from "effect"
136
+ import { CronService } from "@gettersethya/mira"
137
+
138
+ const app = Mira.builder()
139
+ .platform(NodePlatform)
140
+ .database(SqliteDatabase({ filename: "mira.db" }))
141
+ .storage(LocalFileStorage({ directory: "./uploads" }))
142
+ .collections([Users, Posts])
143
+ .crons([
144
+ {
145
+ name: "cleanup",
146
+ schedule: Schedule.fixed("1 hour"),
147
+ handler: () => Effect.log("[cron] cleaning up..."),
148
+ },
149
+ ])
150
+ .build()
151
+ .serve()
152
+ ```
153
+
154
+ Cron names must be globally unique. Use `CronService.getAll()` to inspect state and `CronService.runNow(name)` to trigger immediate execution. Plugins can declare crons via `crons` and hook into `onCronStart`/`onCronExecute`/`onCronSuccess`/`onCronError`/`onCronFinished`.
155
+
156
+ See the [Mira root README](https://github.com/gettersethya/mira#cron-jobs) for full cron documentation.
157
+
158
+ ## Testing with the service layer
159
+
160
+ Use `.buildServiceLayer()` to get an Effect `Layer` for all services without starting an HTTP server:
161
+
162
+ ```typescript
163
+ import { Effect, Layer } from "effect"
164
+
165
+ const serviceLayer = app.buildServiceLayer()
166
+
167
+ const test = Effect.gen(function* () {
168
+ // inject and use services directly
169
+ }).pipe(Effect.provide(serviceLayer))
170
+ ```
171
+
172
+ ## More
173
+
174
+ See the [Mira root README](https://github.com/gettersethya/mira) for collection definitions, field types, rules, filter DSL, and client usage.
@@ -1,8 +1,24 @@
1
- import { HttpServer } from "@effect/platform";
1
+ import type { AnyCollectionDef } from "@gettersethya/mira-client";
2
2
  import { Layer } from "effect";
3
- import { Migrator } from "../migrator/migrator.js";
4
3
  import { AppConfig } from "../config/index.js";
4
+ import { Migrator } from "../migrator/migrator.js";
5
5
  import type { MiraAppConfig } from "./builder.js";
6
+ import type { RuleBinding } from "./define-rule.js";
7
+ import type { MiraPlugin } from "./plugin.js";
8
+ export declare function applyRulesToCollections<C extends AnyCollectionDef>(collections: ReadonlyArray<C>, rules: ReadonlyArray<RuleBinding>): Array<C>;
9
+ /**
10
+ * Options for `MiraApp.serve()` and `MiraApp.buildLayer()`.
11
+ */
12
+ export interface ServeOptions {
13
+ /** Port to listen on. Defaults to the port from `AppConfig`. */
14
+ port?: number;
15
+ /**
16
+ * Total number of ports to try when the requested port is already in use.
17
+ * The server increments the port and retries until a free one is found.
18
+ * Defaults to 10. Pass `1` to disable retrying.
19
+ */
20
+ maxPortAttempts?: number;
21
+ }
6
22
  /**
7
23
  * The assembled Mira application, ready to serve.
8
24
  *
@@ -11,7 +27,7 @@ import type { MiraAppConfig } from "./builder.js";
11
27
  *
12
28
  * `MiraApp` wires all layers (database, storage, collection service, HTTP server,
13
29
  * telemetry, auto-migration) and provides `serve()` to start the server.
14
- * Use `extend()` to add custom layers before serving.
30
+ * Use `extend()` to add plugins before serving.
15
31
  *
16
32
  * @example
17
33
  * const app = Mira.builder()
@@ -24,38 +40,40 @@ import type { MiraAppConfig } from "./builder.js";
24
40
  * app.serve()
25
41
  *
26
42
  * @example
27
- * // With custom layer
28
- * app.extend(MyCustomLayer).serve({ port: 8080 })
43
+ * // With plugin
44
+ * app.extend(MiraDashboard).serve({ port: 8080 })
29
45
  *
30
46
  * @see MiraBuilder — builds MiraApp
31
47
  * @see Mira — entry point: Mira.builder()
32
48
  */
33
- export declare class MiraApp {
49
+ export declare class MiraApp<R = never> {
34
50
  #private;
35
51
  constructor(config: MiraAppConfig);
36
52
  /** @internal for tests only */
37
53
  _getConfig(): MiraAppConfig;
38
54
  /** @internal for tests only */
39
- _getExtras(): ReadonlyArray<Layer.Layer<never, never, never>>;
55
+ _getExtras(): ReadonlyArray<MiraPlugin<any>>;
56
+ /** @internal for tests only */
57
+ _resolveAdminCollections(): ReadonlyArray<AnyCollectionDef>;
40
58
  /**
41
- * Add an arbitrary Effect Layer to the application's layer composition.
42
- * Useful for providing custom services (e.g., custom telemetry, custom auth).
43
- * Layers are merged in order of calls to `extend()`.
59
+ * Add a plugin to the application. Plugins can register lifecycle hooks,
60
+ * record-lifecycle hooks, custom routes, service layers, and additional
61
+ * collection definitions.
44
62
  *
45
- * @param layer - Any Layer<never, never, never>
63
+ * @param plugin - A MiraPlugin (use `fromLayer()` to wrap a plain Layer)
46
64
  * @returns this (for chaining)
47
65
  *
48
66
  * @example
49
- * app.extend(Layer.succeed(MyTag, myImpl))
67
+ * app.extend(MiraDashboard).serve()
50
68
  */
51
- extend(layer: Layer.Layer<never, never, never>): this;
69
+ extend(plugin: MiraPlugin<any>): MiraApp<R>;
52
70
  /**
53
71
  * Build the full service layer without the HTTP server.
54
72
  * Useful for testing — you can run Effects against the service layer without
55
73
  * starting a network server.
56
74
  *
57
75
  * Includes: database, storage, telemetry, repository, migrator, app config,
58
- * collection service (with cache), and auto-migration.
76
+ * collection service (with cache + hooks), and auto-migration.
59
77
  *
60
78
  * @returns A Layer providing all services
61
79
  *
@@ -65,32 +83,33 @@ export declare class MiraApp {
65
83
  * Effect.gen(function* () { ... }).pipe(Effect.provide(serviceLayer))
66
84
  * )
67
85
  */
68
- buildServiceLayer(): Layer.Layer<import("../index.js").FileStorage | import("./types.js").PlatformServices | import("./types.js").DatabaseServices | import("../repository/repository.js").Repository | Migrator | import("../collection-service/collection-service.js").CollectionService | import("../thumbnail/index.js").ThumbnailService | AppConfig, import("effect/ParseResult").ParseError | import("@effect/sql/SqlError").SqlError, never>;
86
+ buildServiceLayer(): Layer.Layer<import("../index.js").FileStorage | import("./types.js").PlatformServices | import("./types.js").DatabaseServices | import("../repository/repository.js").Repository | import("../index.js").CollectionService | AppConfig | Migrator | import("../cron/cron-service.js").CronService | import("../thumbnail/index.js").ThumbnailService, import("effect/sql/SqlError").SqlError | import("effect/Schema").SchemaError, any>;
69
87
  /**
70
88
  * Build the complete server layer including the HTTP router and server.
71
89
  * Accepts an optional port override (otherwise uses the port from AppConfig).
72
90
  *
73
- * @param options.port - Optional port number override
91
+ * @param options - Optional serve options (`port`, `maxPortAttempts`)
74
92
  * @returns A Layer ready to be launched
75
93
  *
76
94
  * @internal Called by serve() — most users should use serve() directly.
77
95
  */
78
- buildLayer(options?: {
79
- port?: number;
80
- }): Layer.Layer<HttpServer.HttpServer | import("@effect/platform/HttpPlatform").HttpPlatform | import("@effect/platform/Etag").Generator | import("../index.js").FileStorage | import("./types.js").PlatformServices | import("./types.js").DatabaseServices | import("../repository/repository.js").Repository | Migrator | import("../collection-service/collection-service.js").CollectionService | import("../thumbnail/index.js").ThumbnailService | AppConfig, import("effect/ParseResult").ParseError | import("@effect/platform/HttpServerError").ServeError | import("@effect/sql/SqlError").SqlError, never>;
96
+ buildLayer(options?: ServeOptions): Layer.Layer<import("../index.js").FileStorage | import("./types.js").PlatformServices | import("./types.js").DatabaseServices | import("../repository/repository.js").Repository | import("../index.js").CollectionService | AppConfig | Migrator | import("../cron/cron-service.js").CronService | import("../thumbnail/index.js").ThumbnailService, import("effect/http/HttpServerError").ServeError | import("effect/sql/SqlError").SqlError | import("effect/Schema").SchemaError, any>;
81
97
  /**
82
98
  * Start the Mira HTTP server.
83
- * Sets up all services, runs auto-migration, and listens for incoming requests.
99
+ * Sets up all services, runs auto-migration, runs plugin lifecycle hooks,
100
+ * and listens for incoming requests.
84
101
  * Blocks the main thread until the server is shut down.
85
102
  *
86
- * @param options.port - Optional port override (default: from AppConfig, typically 8080)
103
+ * If the requested port is already in use, the server automatically retries
104
+ * on the next available port (up to `maxPortAttempts`, default 10).
105
+ *
106
+ * @param options - Optional serve options (`port`, `maxPortAttempts`)
87
107
  *
88
108
  * @example
89
- * app.serve() // default port
90
- * app.serve({ port: 8080 }) // port override
109
+ * app.serve() // default port, auto-increment if busy
110
+ * app.serve({ port: 8080 }) // explicit port, auto-increment if busy
111
+ * app.serve({ port: 8080, maxPortAttempts: 1 }) // fail instead of incrementing
91
112
  */
92
- serve(options?: {
93
- port?: number;
94
- }): void;
113
+ serve(options?: ServeOptions): void;
95
114
  }
96
115
  //# sourceMappingURL=app.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../../src/app/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAU,KAAK,EAAE,MAAM,QAAQ,CAAA;AAEtC,OAAO,EAAE,QAAQ,EAAgB,MAAM,wBAAwB,CAAA;AAM/D,OAAO,EAAE,SAAS,EAAiB,MAAM,mBAAmB,CAAA;AAG5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,OAAO;;gBAIN,MAAM,EAAE,aAAa;IAKjC,+BAA+B;IAC/B,UAAU,IAAI,aAAa;IAI3B,+BAA+B;IAC/B,UAAU,IAAI,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAI7D;;;;;;;;;;OAUG;IACH,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,IAAI;IAKrD;;;;;;;;;;;;;;;OAeG;IACH,iBAAiB;IAsCjB;;;;;;;;OAQG;IACH,UAAU,CAAC,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE;IAoBtC;;;;;;;;;;OAUG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;CAKzC"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../../src/app/app.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAEjE,OAAO,EAAU,KAAK,EAAE,MAAM,QAAQ,CAAA;AAItC,OAAO,EAAE,SAAS,EAAiB,MAAM,mBAAmB,CAAA;AAW5D,OAAO,EAAE,QAAQ,EAAgB,MAAM,wBAAwB,CAAA;AAK/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAY7C,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,gBAAgB,EAChE,WAAW,EAAE,aAAa,CAAC,CAAC,CAAC,EAC7B,KAAK,EAAE,aAAa,CAAC,WAAW,CAAC,GAChC,KAAK,CAAC,CAAC,CAAC,CAkBV;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,OAAO,CAAC,CAAC,GAAG,KAAK;;gBAGhB,MAAM,EAAE,aAAa;IAKjC,+BAA+B;IAC/B,UAAU,IAAI,aAAa;IAI3B,+BAA+B;IAC/B,UAAU,IAAI,aAAa,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAI5C,+BAA+B;IAC/B,wBAAwB,IAAI,aAAa,CAAC,gBAAgB,CAAC;IAI3D;;;;;;;;;;OAUG;IACH,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAiC3C;;;;;;;;;;;;;;;OAeG;IACH,iBAAiB;IAsDjB;;;;;;;;OAQG;IACH,UAAU,CAAC,OAAO,CAAC,EAAE,YAAY;IAyBjC;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;CAqBpC"}
@@ -1,13 +1,45 @@
1
- import { HttpServer } from "@effect/platform";
2
1
  import { Effect, Layer } from "effect";
3
- import { RepositoryLive } from "../repository/repository.js";
4
- import { Migrator, MigratorLive } from "../migrator/migrator.js";
2
+ import { HttpRouter } from "effect/http";
5
3
  import { makeCachedCollectionServiceLayer } from "../cache/index.js";
6
- import { makeCollectionRouter } from "../http/router.js";
7
- import { ThumbnailServicePhotonLive } from "../thumbnail/index.js";
8
- import { ipAnnotationMiddleware } from "../http/ip-middleware.js";
9
4
  import { AppConfig, AppConfigLive } from "../config/index.js";
5
+ import { makeCronServiceLayer } from "../cron/cron-service.js";
6
+ import { makeHookCollectionServiceLayer } from "../hooks/hook-collection.js";
7
+ import { makeHookServiceLayer } from "../hooks/hook-service.js";
8
+ import { HookService } from "../hooks/hook-service.js";
9
+ import { defaultCorsConfig, makeCorsMiddleware } from "../http/cors.js";
10
+ import { ipAnnotationMiddleware } from "../http/ip-middleware.js";
11
+ import { makePortRetryServerLayer } from "../http/port-retry.js";
12
+ import { makeCollectionRouter } from "../http/router.js";
10
13
  import { HttpServerFactory } from "../http/server-factory.js";
14
+ import { Migrator, MigratorLive } from "../migrator/migrator.js";
15
+ import { RepositoryLive } from "../repository/repository.js";
16
+ import { ThumbnailServicePhotonLive } from "../thumbnail/index.js";
17
+ function assertUniqueCronNames(defs) {
18
+ const seen = new Set();
19
+ for (const def of defs) {
20
+ if (seen.has(def.name)) {
21
+ throw new Error(`Duplicate cron name: "${def.name}". Cron names must be globally unique.`);
22
+ }
23
+ seen.add(def.name);
24
+ }
25
+ }
26
+ export function applyRulesToCollections(collections, rules) {
27
+ const collectionNames = new Set(collections.map((c) => c.name));
28
+ for (const rb of rules) {
29
+ if (!collectionNames.has(rb.collectionName)) {
30
+ throw new Error(`RuleBinding references unknown collection "${rb.collectionName}". ` +
31
+ `Available collections: ${[...collectionNames].join(", ")}.`);
32
+ }
33
+ }
34
+ const ruleMap = new Map(rules.map((r) => [r.collectionName, r.ruleMap]));
35
+ return collections.map((c) => {
36
+ const rm = ruleMap.get(c.name);
37
+ if (rm) {
38
+ return { ...c, schema: { ...c.schema, "x-rules": rm } };
39
+ }
40
+ return c;
41
+ });
42
+ }
11
43
  /**
12
44
  * The assembled Mira application, ready to serve.
13
45
  *
@@ -16,7 +48,7 @@ import { HttpServerFactory } from "../http/server-factory.js";
16
48
  *
17
49
  * `MiraApp` wires all layers (database, storage, collection service, HTTP server,
18
50
  * telemetry, auto-migration) and provides `serve()` to start the server.
19
- * Use `extend()` to add custom layers before serving.
51
+ * Use `extend()` to add plugins before serving.
20
52
  *
21
53
  * @example
22
54
  * const app = Mira.builder()
@@ -29,8 +61,8 @@ import { HttpServerFactory } from "../http/server-factory.js";
29
61
  * app.serve()
30
62
  *
31
63
  * @example
32
- * // With custom layer
33
- * app.extend(MyCustomLayer).serve({ port: 8080 })
64
+ * // With plugin
65
+ * app.extend(MiraDashboard).serve({ port: 8080 })
34
66
  *
35
67
  * @see MiraBuilder — builds MiraApp
36
68
  * @see Mira — entry point: Mira.builder()
@@ -50,28 +82,56 @@ export class MiraApp {
50
82
  _getExtras() {
51
83
  return this.#extras;
52
84
  }
85
+ /** @internal for tests only */
86
+ _resolveAdminCollections() {
87
+ return this.#getAdminCollections();
88
+ }
53
89
  /**
54
- * Add an arbitrary Effect Layer to the application's layer composition.
55
- * Useful for providing custom services (e.g., custom telemetry, custom auth).
56
- * Layers are merged in order of calls to `extend()`.
90
+ * Add a plugin to the application. Plugins can register lifecycle hooks,
91
+ * record-lifecycle hooks, custom routes, service layers, and additional
92
+ * collection definitions.
57
93
  *
58
- * @param layer - Any Layer<never, never, never>
94
+ * @param plugin - A MiraPlugin (use `fromLayer()` to wrap a plain Layer)
59
95
  * @returns this (for chaining)
60
96
  *
61
97
  * @example
62
- * app.extend(Layer.succeed(MyTag, myImpl))
98
+ * app.extend(MiraDashboard).serve()
63
99
  */
64
- extend(layer) {
65
- this.#extras.push(layer);
100
+ extend(plugin) {
101
+ this.#extras.push(plugin);
66
102
  return this;
67
103
  }
104
+ #getAllCollections() {
105
+ const configCollections = applyRulesToCollections(this.#config.collections, this.#config.rules ?? []);
106
+ const all = [
107
+ ...configCollections,
108
+ ...this.#extras.flatMap((p) => p.collections ?? []),
109
+ ...this.#getAdminCollections()
110
+ ];
111
+ const byName = new Map();
112
+ for (const c of all) {
113
+ if (!byName.has(c.name)) {
114
+ byName.set(c.name, c);
115
+ }
116
+ }
117
+ return [...byName.values()];
118
+ }
119
+ #getAllPlugins() {
120
+ return this.#extras;
121
+ }
122
+ #getAllCrons() {
123
+ return [...this.#config.crons, ...this.#extras.flatMap((p) => p.crons ?? [])];
124
+ }
125
+ #getAdminCollections() {
126
+ return this.#extras.flatMap((p) => p.adminCollections ?? []);
127
+ }
68
128
  /**
69
129
  * Build the full service layer without the HTTP server.
70
130
  * Useful for testing — you can run Effects against the service layer without
71
131
  * starting a network server.
72
132
  *
73
133
  * Includes: database, storage, telemetry, repository, migrator, app config,
74
- * collection service (with cache), and auto-migration.
134
+ * collection service (with cache + hooks), and auto-migration.
75
135
  *
76
136
  * @returns A Layer providing all services
77
137
  *
@@ -82,58 +142,95 @@ export class MiraApp {
82
142
  * )
83
143
  */
84
144
  buildServiceLayer() {
85
- const { platform, database, storage, collections, telemetry } = this.#config;
86
- const collectionList = collections;
87
- const extrasLayer = this.#extras.length > 0
88
- ? this.#extras.reduce((acc, l) => Layer.merge(acc, l))
89
- : Layer.empty;
90
- // Foundation: database + storage + thumbnail + telemetry + extras, wired on platform
91
- const foundation = Layer.mergeAll(database.layer, storage.layer, ThumbnailServicePhotonLive, telemetry, extrasLayer).pipe(Layer.provideMerge(platform.layer));
145
+ const { database, platform, storage, telemetry } = this.#config;
146
+ const allCollections = this.#getAllCollections();
147
+ const allPlugins = this.#getAllPlugins();
148
+ const allCronDefs = this.#getAllCrons();
149
+ assertUniqueCronNames(allCronDefs);
150
+ const pluginLayers = allPlugins.filter((p) => p.layer !== undefined).map((p) => p.layer);
151
+ const extrasLayer = pluginLayers.length > 0 ? pluginLayers.reduce((acc, l) => Layer.merge(acc, l)) : Layer.empty;
152
+ // Foundation: database + storage + thumbnail + telemetry, wired on platform
153
+ const foundation = Layer.mergeAll(database.layer, storage.layer, ThumbnailServicePhotonLive, telemetry).pipe(Layer.provideMerge(platform.layer));
92
154
  // Mid: Repository + Migrator + AppConfig, wired on foundation
93
155
  const mid = Layer.mergeAll(RepositoryLive, MigratorLive, AppConfigLive).pipe(Layer.provideMerge(foundation));
156
+ // Extras: plugin layers run after mid so they can depend on AppConfig + platform services
157
+ const extrasProvided = extrasLayer.pipe(Layer.provide(mid));
158
+ const fullMid = Layer.merge(mid, extrasProvided);
94
159
  // Auto-migrate on boot: runs during layer initialization before requests are served
95
- const schemas = collectionList.map((c) => ({ name: c.name, schema: c.schema }));
160
+ const schemas = allCollections.map((c) => ({ name: c.name, schema: c.schema }));
96
161
  const autoMigrateLayer = Layer.effectDiscard(Effect.gen(function* () {
97
162
  const migrator = yield* Migrator;
98
163
  yield* migrator.migrate(schemas);
99
- }).pipe(Effect.orDie)).pipe(Layer.provide(mid));
100
- // Top: CollectionService + all mid services + auto-migration side effect
101
- return makeCachedCollectionServiceLayer(collectionList).pipe(Layer.provideMerge(Layer.merge(mid, autoMigrateLayer)));
164
+ }).pipe(Effect.orDie)).pipe(Layer.provide(fullMid));
165
+ // Core collection service (cached)
166
+ const cachedCollectionLayer = makeCachedCollectionServiceLayer(allCollections);
167
+ // Hook service layer (collects all plugin hooks)
168
+ const hookServiceLayer = makeHookServiceLayer(allPlugins);
169
+ // Hook collection service decorator: wraps cached collection service with hooks
170
+ const hookCollectionLayer = makeHookCollectionServiceLayer().pipe(Layer.provide(Layer.mergeAll(cachedCollectionLayer, hookServiceLayer)));
171
+ // Full top layer: hook-wrapped collection service + all mid services + auto-migration side effect
172
+ const topLayer = hookCollectionLayer.pipe(Layer.provideMerge(Layer.merge(fullMid, autoMigrateLayer)));
173
+ // Cron service: scoped fibers die when server stops; provided with full service stack + hook service
174
+ const cronServiceLayer = makeCronServiceLayer(allCronDefs).pipe(Layer.provide(Layer.mergeAll(topLayer, hookServiceLayer)));
175
+ return Layer.merge(topLayer, cronServiceLayer);
102
176
  }
103
177
  /**
104
178
  * Build the complete server layer including the HTTP router and server.
105
179
  * Accepts an optional port override (otherwise uses the port from AppConfig).
106
180
  *
107
- * @param options.port - Optional port number override
181
+ * @param options - Optional serve options (`port`, `maxPortAttempts`)
108
182
  * @returns A Layer ready to be launched
109
183
  *
110
184
  * @internal Called by serve() — most users should use serve() directly.
111
185
  */
112
186
  buildLayer(options) {
113
- const { collections } = this.#config;
114
- const collectionList = collections;
115
- const router = makeCollectionRouter(collectionList);
187
+ const allCollections = this.#getAllCollections();
188
+ const adminCollections = this.#getAdminCollections().map((c) => c.name);
189
+ const collectionRoutes = makeCollectionRouter(allCollections, adminCollections);
190
+ const pluginRoutes = this.#extras.flatMap((p) => p.routes ?? []);
191
+ const routes = [...collectionRoutes, ...pluginRoutes];
116
192
  const serviceLayer = this.buildServiceLayer();
117
- const serverLayer = Layer.unwrapEffect(Effect.gen(function* () {
193
+ const serverLayer = Layer.unwrap(Effect.gen(function* () {
118
194
  const cfg = yield* AppConfig;
119
195
  const factory = yield* HttpServerFactory;
120
- return factory.makeLayer(options?.port ?? cfg.port);
121
- }));
122
- return HttpServer.serve(ipAnnotationMiddleware(router)).pipe(Layer.provideMerge(serverLayer), Layer.provideMerge(serviceLayer));
196
+ const effectivePort = options?.port ?? cfg.port;
197
+ return makePortRetryServerLayer(factory, effectivePort, options?.maxPortAttempts, (boundPort) => cfg.updateBoundPort?.(boundPort));
198
+ })).pipe(Layer.provide(serviceLayer));
199
+ return HttpRouter.serve(HttpRouter.addAll(routes), {
200
+ middleware: (effect) => ipAnnotationMiddleware(makeCorsMiddleware(this.#config.cors)(effect))
201
+ }).pipe(Layer.provide(serverLayer), Layer.provideMerge(serviceLayer));
123
202
  }
124
203
  /**
125
204
  * Start the Mira HTTP server.
126
- * Sets up all services, runs auto-migration, and listens for incoming requests.
205
+ * Sets up all services, runs auto-migration, runs plugin lifecycle hooks,
206
+ * and listens for incoming requests.
127
207
  * Blocks the main thread until the server is shut down.
128
208
  *
129
- * @param options.port - Optional port override (default: from AppConfig, typically 8080)
209
+ * If the requested port is already in use, the server automatically retries
210
+ * on the next available port (up to `maxPortAttempts`, default 10).
211
+ *
212
+ * @param options - Optional serve options (`port`, `maxPortAttempts`)
130
213
  *
131
214
  * @example
132
- * app.serve() // default port
133
- * app.serve({ port: 8080 }) // port override
215
+ * app.serve() // default port, auto-increment if busy
216
+ * app.serve({ port: 8080 }) // explicit port, auto-increment if busy
217
+ * app.serve({ port: 8080, maxPortAttempts: 1 }) // fail instead of incrementing
134
218
  */
135
219
  serve(options) {
136
- this.#config.platform.runMain(Layer.launch(this.buildLayer(options)).pipe(Effect.orDie));
220
+ const allPlugins = this.#getAllPlugins();
221
+ const hookServiceLayer = makeHookServiceLayer(allPlugins);
222
+ const fullLayer = this.buildLayer(options);
223
+ const usingDefaultCors = this.#config.cors === defaultCorsConfig;
224
+ this.#config.platform.runMain(Effect.gen(function* () {
225
+ if (usingDefaultCors) {
226
+ yield* Effect.logWarning("CORS: using the permissive default — every Origin is reflected and credentials are allowed. " +
227
+ "Configure Mira.builder().cors({ allowedOrigins, credentials }) for production.");
228
+ }
229
+ const hookService = yield* HookService.pipe(Effect.provide(hookServiceLayer));
230
+ const bootstrapLayer = Layer.effectDiscard(hookService.runBootstrap());
231
+ yield* Layer.launch(bootstrapLayer.pipe(Layer.provideMerge(fullLayer)));
232
+ yield* hookService.runServe();
233
+ }));
137
234
  }
138
235
  }
139
236
  //# sourceMappingURL=app.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../../../src/app/app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../../src/app/app.ts"],"names":[],"mappings":"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"}