@sixthsummit/ship-api 0.0.0-stage → 4.1.1

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 (556) hide show
  1. package/CHANGELOG.md +605 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +4 -0
  4. package/README.md +58 -2
  5. package/cli/commands/add.js +537 -0
  6. package/cli/commands/contract.js +2 -0
  7. package/cli/commands/create.js +250 -0
  8. package/cli/commands/dev.js +227 -0
  9. package/cli/commands/doctor.js +286 -0
  10. package/cli/commands/generate.js +937 -0
  11. package/cli/commands/graph.js +2 -0
  12. package/cli/commands/migrate-orm.js +1171 -0
  13. package/cli/commands/update.js +37 -0
  14. package/cli/ship-api.js +285 -0
  15. package/lib/app/auth/AuthProvider.d.ts +91 -0
  16. package/lib/app/auth/AuthProvider.d.ts.map +1 -0
  17. package/lib/app/auth/AuthProvider.js +13 -0
  18. package/lib/app/auth/AuthProvider.js.map +1 -0
  19. package/lib/app/auth/adapters/firebase.d.ts +79 -0
  20. package/lib/app/auth/adapters/firebase.d.ts.map +1 -0
  21. package/lib/app/auth/adapters/firebase.js +122 -0
  22. package/lib/app/auth/adapters/firebase.js.map +1 -0
  23. package/lib/app/auth/adapters/jwtCookie.d.ts +55 -0
  24. package/lib/app/auth/adapters/jwtCookie.d.ts.map +1 -0
  25. package/lib/app/auth/adapters/jwtCookie.js +120 -0
  26. package/lib/app/auth/adapters/jwtCookie.js.map +1 -0
  27. package/lib/app/auth/index.d.ts +8 -0
  28. package/lib/app/auth/index.d.ts.map +1 -0
  29. package/lib/app/auth/index.js +7 -0
  30. package/lib/app/auth/index.js.map +1 -0
  31. package/lib/app/auth/jwt/AuthFlow.d.ts +94 -0
  32. package/lib/app/auth/jwt/AuthFlow.d.ts.map +1 -0
  33. package/lib/app/auth/jwt/AuthFlow.js +127 -0
  34. package/lib/app/auth/jwt/AuthFlow.js.map +1 -0
  35. package/lib/app/auth/jwt/DrizzleRefreshTokenStore.d.ts +80 -0
  36. package/lib/app/auth/jwt/DrizzleRefreshTokenStore.d.ts.map +1 -0
  37. package/lib/app/auth/jwt/DrizzleRefreshTokenStore.js +134 -0
  38. package/lib/app/auth/jwt/DrizzleRefreshTokenStore.js.map +1 -0
  39. package/lib/app/auth/jwt/JwtSigner.d.ts +123 -0
  40. package/lib/app/auth/jwt/JwtSigner.d.ts.map +1 -0
  41. package/lib/app/auth/jwt/JwtSigner.js +118 -0
  42. package/lib/app/auth/jwt/JwtSigner.js.map +1 -0
  43. package/lib/app/auth/jwt/RefreshTokenStore.d.ts +97 -0
  44. package/lib/app/auth/jwt/RefreshTokenStore.d.ts.map +1 -0
  45. package/lib/app/auth/jwt/RefreshTokenStore.js +122 -0
  46. package/lib/app/auth/jwt/RefreshTokenStore.js.map +1 -0
  47. package/lib/app/auth/permissionDefinition.d.ts +20 -0
  48. package/lib/app/auth/permissionDefinition.d.ts.map +1 -0
  49. package/lib/app/auth/permissionDefinition.js +2 -0
  50. package/lib/app/auth/permissionDefinition.js.map +1 -0
  51. package/lib/app/context/RequestContext.d.ts +59 -0
  52. package/lib/app/context/RequestContext.d.ts.map +1 -0
  53. package/lib/app/context/RequestContext.js +25 -0
  54. package/lib/app/context/RequestContext.js.map +1 -0
  55. package/lib/app/db/QueryOptions.d.ts +82 -0
  56. package/lib/app/db/QueryOptions.d.ts.map +1 -0
  57. package/lib/app/db/QueryOptions.js +37 -0
  58. package/lib/app/db/QueryOptions.js.map +1 -0
  59. package/lib/app/db/baseFields.d.ts +60 -0
  60. package/lib/app/db/baseFields.d.ts.map +1 -0
  61. package/lib/app/db/baseFields.js +54 -0
  62. package/lib/app/db/baseFields.js.map +1 -0
  63. package/lib/app/db/buildWhere.d.ts +22 -0
  64. package/lib/app/db/buildWhere.d.ts.map +1 -0
  65. package/lib/app/db/buildWhere.js +75 -0
  66. package/lib/app/db/buildWhere.js.map +1 -0
  67. package/lib/app/db/client.d.ts +111 -0
  68. package/lib/app/db/client.d.ts.map +1 -0
  69. package/lib/app/db/client.js +99 -0
  70. package/lib/app/db/client.js.map +1 -0
  71. package/lib/app/db/tenantScoped.d.ts +59 -0
  72. package/lib/app/db/tenantScoped.d.ts.map +1 -0
  73. package/lib/app/db/tenantScoped.js +54 -0
  74. package/lib/app/db/tenantScoped.js.map +1 -0
  75. package/lib/app/db/transaction.d.ts +58 -0
  76. package/lib/app/db/transaction.d.ts.map +1 -0
  77. package/lib/app/db/transaction.js +106 -0
  78. package/lib/app/db/transaction.js.map +1 -0
  79. package/lib/app/health/HealthCheck.d.ts +121 -0
  80. package/lib/app/health/HealthCheck.d.ts.map +1 -0
  81. package/lib/app/health/HealthCheck.js +151 -0
  82. package/lib/app/health/HealthCheck.js.map +1 -0
  83. package/lib/app/health/redisHealthCheck.d.ts +14 -0
  84. package/lib/app/health/redisHealthCheck.d.ts.map +1 -0
  85. package/lib/app/health/redisHealthCheck.js +21 -0
  86. package/lib/app/health/redisHealthCheck.js.map +1 -0
  87. package/lib/app/lifecycle/Bootstrapper.d.ts +92 -0
  88. package/lib/app/lifecycle/Bootstrapper.d.ts.map +1 -0
  89. package/lib/app/lifecycle/Bootstrapper.js +99 -0
  90. package/lib/app/lifecycle/Bootstrapper.js.map +1 -0
  91. package/lib/app/registry/routes.d.ts +89 -0
  92. package/lib/app/registry/routes.d.ts.map +1 -0
  93. package/lib/app/registry/routes.js +72 -0
  94. package/lib/app/registry/routes.js.map +1 -0
  95. package/lib/app/services/DrizzleEntityService.d.ts +123 -0
  96. package/lib/app/services/DrizzleEntityService.d.ts.map +1 -0
  97. package/lib/app/services/DrizzleEntityService.js +342 -0
  98. package/lib/app/services/DrizzleEntityService.js.map +1 -0
  99. package/lib/app/services/RedisProvider.d.ts +52 -0
  100. package/lib/app/services/RedisProvider.d.ts.map +1 -0
  101. package/lib/app/services/RedisProvider.js +75 -0
  102. package/lib/app/services/RedisProvider.js.map +1 -0
  103. package/lib/app/services/cache/Cache.d.ts +70 -0
  104. package/lib/app/services/cache/Cache.d.ts.map +1 -0
  105. package/lib/app/services/cache/Cache.js +18 -0
  106. package/lib/app/services/cache/Cache.js.map +1 -0
  107. package/lib/app/services/cache/InMemoryCache.d.ts +35 -0
  108. package/lib/app/services/cache/InMemoryCache.d.ts.map +1 -0
  109. package/lib/app/services/cache/InMemoryCache.js +76 -0
  110. package/lib/app/services/cache/InMemoryCache.js.map +1 -0
  111. package/lib/app/services/cache/RedisCache.d.ts +99 -0
  112. package/lib/app/services/cache/RedisCache.d.ts.map +1 -0
  113. package/lib/app/services/cache/RedisCache.js +150 -0
  114. package/lib/app/services/cache/RedisCache.js.map +1 -0
  115. package/lib/app/services/cache/cached.d.ts +30 -0
  116. package/lib/app/services/cache/cached.d.ts.map +1 -0
  117. package/lib/app/services/cache/cached.js +38 -0
  118. package/lib/app/services/cache/cached.js.map +1 -0
  119. package/lib/app/services/cache/index.d.ts +5 -0
  120. package/lib/app/services/cache/index.d.ts.map +1 -0
  121. package/lib/app/services/cache/index.js +4 -0
  122. package/lib/app/services/cache/index.js.map +1 -0
  123. package/lib/app/services/cron/defineCron.d.ts +57 -0
  124. package/lib/app/services/cron/defineCron.d.ts.map +1 -0
  125. package/lib/app/services/cron/defineCron.js +15 -0
  126. package/lib/app/services/cron/defineCron.js.map +1 -0
  127. package/lib/app/services/cron/index.d.ts +2 -0
  128. package/lib/app/services/cron/index.d.ts.map +1 -0
  129. package/lib/app/services/cron/index.js +2 -0
  130. package/lib/app/services/cron/index.js.map +1 -0
  131. package/lib/app/services/hooks/LifecycleHooks.d.ts +61 -0
  132. package/lib/app/services/hooks/LifecycleHooks.d.ts.map +1 -0
  133. package/lib/app/services/hooks/LifecycleHooks.js +85 -0
  134. package/lib/app/services/hooks/LifecycleHooks.js.map +1 -0
  135. package/lib/app/services/jobs/JobsManager.d.ts +67 -0
  136. package/lib/app/services/jobs/JobsManager.d.ts.map +1 -0
  137. package/lib/app/services/jobs/JobsManager.js +121 -0
  138. package/lib/app/services/jobs/JobsManager.js.map +1 -0
  139. package/lib/app/services/jobs/bullBoard.d.ts +72 -0
  140. package/lib/app/services/jobs/bullBoard.d.ts.map +1 -0
  141. package/lib/app/services/jobs/bullBoard.js +96 -0
  142. package/lib/app/services/jobs/bullBoard.js.map +1 -0
  143. package/lib/app/services/jobs/defineJob.d.ts +81 -0
  144. package/lib/app/services/jobs/defineJob.d.ts.map +1 -0
  145. package/lib/app/services/jobs/defineJob.js +49 -0
  146. package/lib/app/services/jobs/defineJob.js.map +1 -0
  147. package/lib/app/services/jobs/index.d.ts +4 -0
  148. package/lib/app/services/jobs/index.d.ts.map +1 -0
  149. package/lib/app/services/jobs/index.js +4 -0
  150. package/lib/app/services/jobs/index.js.map +1 -0
  151. package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.d.ts +23 -0
  152. package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.d.ts.map +1 -0
  153. package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.js +51 -0
  154. package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.js.map +1 -0
  155. package/lib/app/services/rateLimit/RateLimitBackend.d.ts +41 -0
  156. package/lib/app/services/rateLimit/RateLimitBackend.d.ts.map +1 -0
  157. package/lib/app/services/rateLimit/RateLimitBackend.js +19 -0
  158. package/lib/app/services/rateLimit/RateLimitBackend.js.map +1 -0
  159. package/lib/app/services/rateLimit/RedisSlidingWindowBackend.d.ts +16 -0
  160. package/lib/app/services/rateLimit/RedisSlidingWindowBackend.d.ts.map +1 -0
  161. package/lib/app/services/rateLimit/RedisSlidingWindowBackend.js +80 -0
  162. package/lib/app/services/rateLimit/RedisSlidingWindowBackend.js.map +1 -0
  163. package/lib/app/services/rateLimit/index.d.ts +4 -0
  164. package/lib/app/services/rateLimit/index.d.ts.map +1 -0
  165. package/lib/app/services/rateLimit/index.js +3 -0
  166. package/lib/app/services/rateLimit/index.js.map +1 -0
  167. package/lib/app/services/storage/DiskStorageAdapter.d.ts +62 -0
  168. package/lib/app/services/storage/DiskStorageAdapter.d.ts.map +1 -0
  169. package/lib/app/services/storage/DiskStorageAdapter.js +295 -0
  170. package/lib/app/services/storage/DiskStorageAdapter.js.map +1 -0
  171. package/lib/app/services/storage/GCSStorageAdapter.d.ts +44 -0
  172. package/lib/app/services/storage/GCSStorageAdapter.d.ts.map +1 -0
  173. package/lib/app/services/storage/GCSStorageAdapter.js +133 -0
  174. package/lib/app/services/storage/GCSStorageAdapter.js.map +1 -0
  175. package/lib/app/services/storage/S3StorageAdapter.d.ts +57 -0
  176. package/lib/app/services/storage/S3StorageAdapter.d.ts.map +1 -0
  177. package/lib/app/services/storage/S3StorageAdapter.js +162 -0
  178. package/lib/app/services/storage/S3StorageAdapter.js.map +1 -0
  179. package/lib/app/services/storage/StorageService.d.ts +88 -0
  180. package/lib/app/services/storage/StorageService.d.ts.map +1 -0
  181. package/lib/app/services/storage/StorageService.js +18 -0
  182. package/lib/app/services/storage/StorageService.js.map +1 -0
  183. package/lib/app/services/storage/index.d.ts +5 -0
  184. package/lib/app/services/storage/index.d.ts.map +1 -0
  185. package/lib/app/services/storage/index.js +4 -0
  186. package/lib/app/services/storage/index.js.map +1 -0
  187. package/lib/app/utils/ContextValidators.d.ts +46 -0
  188. package/lib/app/utils/ContextValidators.d.ts.map +1 -0
  189. package/lib/app/utils/ContextValidators.js +81 -0
  190. package/lib/app/utils/ContextValidators.js.map +1 -0
  191. package/lib/app/utils/defineEnv.d.ts +80 -0
  192. package/lib/app/utils/defineEnv.d.ts.map +1 -0
  193. package/lib/app/utils/defineEnv.js +95 -0
  194. package/lib/app/utils/defineEnv.js.map +1 -0
  195. package/lib/client.d.ts +139 -0
  196. package/lib/client.d.ts.map +1 -0
  197. package/lib/client.js +98 -0
  198. package/lib/client.js.map +1 -0
  199. package/lib/contract/application.d.ts +3 -0
  200. package/lib/contract/application.d.ts.map +1 -0
  201. package/lib/contract/application.js +2 -0
  202. package/lib/contract/application.js.map +1 -0
  203. package/lib/contract/client.d.ts +3 -0
  204. package/lib/contract/client.d.ts.map +1 -0
  205. package/lib/contract/client.js +3 -0
  206. package/lib/contract/client.js.map +1 -0
  207. package/lib/contract/index.d.ts +3 -0
  208. package/lib/contract/index.d.ts.map +1 -0
  209. package/lib/contract/index.js +3 -0
  210. package/lib/contract/index.js.map +1 -0
  211. package/lib/contract/manifest.d.ts +3 -0
  212. package/lib/contract/manifest.d.ts.map +1 -0
  213. package/lib/contract/manifest.js +2 -0
  214. package/lib/contract/manifest.js.map +1 -0
  215. package/lib/contract/openapi.d.ts +3 -0
  216. package/lib/contract/openapi.d.ts.map +1 -0
  217. package/lib/contract/openapi.js +3 -0
  218. package/lib/contract/openapi.js.map +1 -0
  219. package/lib/contract/project.d.ts +3 -0
  220. package/lib/contract/project.d.ts.map +1 -0
  221. package/lib/contract/project.js +3 -0
  222. package/lib/contract/project.js.map +1 -0
  223. package/lib/contract/schema.d.ts +3 -0
  224. package/lib/contract/schema.d.ts.map +1 -0
  225. package/lib/contract/schema.js +3 -0
  226. package/lib/contract/schema.js.map +1 -0
  227. package/lib/drizzle/index.d.ts +3 -0
  228. package/lib/drizzle/index.d.ts.map +1 -0
  229. package/lib/drizzle/index.js +3 -0
  230. package/lib/drizzle/index.js.map +1 -0
  231. package/lib/hono/auth.d.ts +6 -0
  232. package/lib/hono/auth.d.ts.map +1 -0
  233. package/lib/hono/auth.js +54 -0
  234. package/lib/hono/auth.js.map +1 -0
  235. package/lib/hono/index.d.ts +4 -0
  236. package/lib/hono/index.d.ts.map +1 -0
  237. package/lib/hono/index.js +4 -0
  238. package/lib/hono/index.js.map +1 -0
  239. package/lib/http/app/createApp.d.ts +132 -0
  240. package/lib/http/app/createApp.d.ts.map +1 -0
  241. package/lib/http/app/createApp.js +215 -0
  242. package/lib/http/app/createApp.js.map +1 -0
  243. package/lib/http/app/devRoutes.d.ts +31 -0
  244. package/lib/http/app/devRoutes.d.ts.map +1 -0
  245. package/lib/http/app/devRoutes.js +145 -0
  246. package/lib/http/app/devRoutes.js.map +1 -0
  247. package/lib/http/app/errors.d.ts +45 -0
  248. package/lib/http/app/errors.d.ts.map +1 -0
  249. package/lib/http/app/errors.js +93 -0
  250. package/lib/http/app/errors.js.map +1 -0
  251. package/lib/http/app/health.d.ts +66 -0
  252. package/lib/http/app/health.d.ts.map +1 -0
  253. package/lib/http/app/health.js +104 -0
  254. package/lib/http/app/health.js.map +1 -0
  255. package/lib/http/errors/AppError.d.ts +10 -0
  256. package/lib/http/errors/AppError.d.ts.map +1 -0
  257. package/lib/http/errors/AppError.js +19 -0
  258. package/lib/http/errors/AppError.js.map +1 -0
  259. package/lib/http/errors/AuthenticationError.d.ts +8 -0
  260. package/lib/http/errors/AuthenticationError.d.ts.map +1 -0
  261. package/lib/http/errors/AuthenticationError.js +10 -0
  262. package/lib/http/errors/AuthenticationError.js.map +1 -0
  263. package/lib/http/errors/AuthorizationError.d.ts +8 -0
  264. package/lib/http/errors/AuthorizationError.d.ts.map +1 -0
  265. package/lib/http/errors/AuthorizationError.js +10 -0
  266. package/lib/http/errors/AuthorizationError.js.map +1 -0
  267. package/lib/http/errors/BadRequestError.d.ts +8 -0
  268. package/lib/http/errors/BadRequestError.d.ts.map +1 -0
  269. package/lib/http/errors/BadRequestError.js +10 -0
  270. package/lib/http/errors/BadRequestError.js.map +1 -0
  271. package/lib/http/errors/ConflictError.d.ts +8 -0
  272. package/lib/http/errors/ConflictError.d.ts.map +1 -0
  273. package/lib/http/errors/ConflictError.js +10 -0
  274. package/lib/http/errors/ConflictError.js.map +1 -0
  275. package/lib/http/errors/InternalServerError.d.ts +8 -0
  276. package/lib/http/errors/InternalServerError.d.ts.map +1 -0
  277. package/lib/http/errors/InternalServerError.js +10 -0
  278. package/lib/http/errors/InternalServerError.js.map +1 -0
  279. package/lib/http/errors/NotFoundError.d.ts +8 -0
  280. package/lib/http/errors/NotFoundError.d.ts.map +1 -0
  281. package/lib/http/errors/NotFoundError.js +10 -0
  282. package/lib/http/errors/NotFoundError.js.map +1 -0
  283. package/lib/http/errors/RateLimitError.d.ts +13 -0
  284. package/lib/http/errors/RateLimitError.d.ts.map +1 -0
  285. package/lib/http/errors/RateLimitError.js +16 -0
  286. package/lib/http/errors/RateLimitError.js.map +1 -0
  287. package/lib/http/errors/ServiceUnavailableError.d.ts +8 -0
  288. package/lib/http/errors/ServiceUnavailableError.d.ts.map +1 -0
  289. package/lib/http/errors/ServiceUnavailableError.js +10 -0
  290. package/lib/http/errors/ServiceUnavailableError.js.map +1 -0
  291. package/lib/http/errors/ValidationError.d.ts +9 -0
  292. package/lib/http/errors/ValidationError.d.ts.map +1 -0
  293. package/lib/http/errors/ValidationError.js +12 -0
  294. package/lib/http/errors/ValidationError.js.map +1 -0
  295. package/lib/http/errors/index.d.ts +11 -0
  296. package/lib/http/errors/index.d.ts.map +1 -0
  297. package/lib/http/errors/index.js +12 -0
  298. package/lib/http/errors/index.js.map +1 -0
  299. package/lib/http/middleware/apiKey.d.ts +9 -0
  300. package/lib/http/middleware/apiKey.d.ts.map +1 -0
  301. package/lib/http/middleware/apiKey.js +71 -0
  302. package/lib/http/middleware/apiKey.js.map +1 -0
  303. package/lib/http/middleware/csrf.d.ts +63 -0
  304. package/lib/http/middleware/csrf.d.ts.map +1 -0
  305. package/lib/http/middleware/csrf.js +169 -0
  306. package/lib/http/middleware/csrf.js.map +1 -0
  307. package/lib/http/middleware/httpLogger.d.ts +39 -0
  308. package/lib/http/middleware/httpLogger.d.ts.map +1 -0
  309. package/lib/http/middleware/httpLogger.js +118 -0
  310. package/lib/http/middleware/httpLogger.js.map +1 -0
  311. package/lib/http/middleware/idempotency.d.ts +48 -0
  312. package/lib/http/middleware/idempotency.d.ts.map +1 -0
  313. package/lib/http/middleware/idempotency.js +180 -0
  314. package/lib/http/middleware/idempotency.js.map +1 -0
  315. package/lib/http/middleware/rateLimit.d.ts +105 -0
  316. package/lib/http/middleware/rateLimit.d.ts.map +1 -0
  317. package/lib/http/middleware/rateLimit.js +84 -0
  318. package/lib/http/middleware/rateLimit.js.map +1 -0
  319. package/lib/http/middleware/requireAuth.d.ts +58 -0
  320. package/lib/http/middleware/requireAuth.d.ts.map +1 -0
  321. package/lib/http/middleware/requireAuth.js +63 -0
  322. package/lib/http/middleware/requireAuth.js.map +1 -0
  323. package/lib/http/middleware/requirePermission.d.ts +23 -0
  324. package/lib/http/middleware/requirePermission.d.ts.map +1 -0
  325. package/lib/http/middleware/requirePermission.js +50 -0
  326. package/lib/http/middleware/requirePermission.js.map +1 -0
  327. package/lib/http/middleware/resolveTenant.d.ts +41 -0
  328. package/lib/http/middleware/resolveTenant.d.ts.map +1 -0
  329. package/lib/http/middleware/resolveTenant.js +17 -0
  330. package/lib/http/middleware/resolveTenant.js.map +1 -0
  331. package/lib/http/streaming/sse.d.ts +31 -0
  332. package/lib/http/streaming/sse.d.ts.map +1 -0
  333. package/lib/http/streaming/sse.js +11 -0
  334. package/lib/http/streaming/sse.js.map +1 -0
  335. package/lib/http/streaming/streamLLM.d.ts +94 -0
  336. package/lib/http/streaming/streamLLM.d.ts.map +1 -0
  337. package/lib/http/streaming/streamLLM.js +94 -0
  338. package/lib/http/streaming/streamLLM.js.map +1 -0
  339. package/lib/http/utils/authCookies.d.ts +74 -0
  340. package/lib/http/utils/authCookies.d.ts.map +1 -0
  341. package/lib/http/utils/authCookies.js +102 -0
  342. package/lib/http/utils/authCookies.js.map +1 -0
  343. package/lib/http/utils/clientIp.d.ts +85 -0
  344. package/lib/http/utils/clientIp.d.ts.map +1 -0
  345. package/lib/http/utils/clientIp.js +249 -0
  346. package/lib/http/utils/clientIp.js.map +1 -0
  347. package/lib/http/utils/index.d.ts +4 -0
  348. package/lib/http/utils/index.d.ts.map +1 -0
  349. package/lib/http/utils/index.js +5 -0
  350. package/lib/http/utils/index.js.map +1 -0
  351. package/lib/http/utils/metaTags.d.ts +49 -0
  352. package/lib/http/utils/metaTags.d.ts.map +1 -0
  353. package/lib/http/utils/metaTags.js +32 -0
  354. package/lib/http/utils/metaTags.js.map +1 -0
  355. package/lib/http/utils/publicSuffix.d.ts +34 -0
  356. package/lib/http/utils/publicSuffix.d.ts.map +1 -0
  357. package/lib/http/utils/publicSuffix.js +276 -0
  358. package/lib/http/utils/publicSuffix.js.map +1 -0
  359. package/lib/http/utils/uploads.d.ts +92 -0
  360. package/lib/http/utils/uploads.d.ts.map +1 -0
  361. package/lib/http/utils/uploads.js +126 -0
  362. package/lib/http/utils/uploads.js.map +1 -0
  363. package/lib/http/utils/validate.d.ts +41 -0
  364. package/lib/http/utils/validate.d.ts.map +1 -0
  365. package/lib/http/utils/validate.js +55 -0
  366. package/lib/http/utils/validate.js.map +1 -0
  367. package/lib/http/utils/webhooks.d.ts +63 -0
  368. package/lib/http/utils/webhooks.d.ts.map +1 -0
  369. package/lib/http/utils/webhooks.js +133 -0
  370. package/lib/http/utils/webhooks.js.map +1 -0
  371. package/lib/http/ws/auth.d.ts +46 -0
  372. package/lib/http/ws/auth.d.ts.map +1 -0
  373. package/lib/http/ws/auth.js +123 -0
  374. package/lib/http/ws/auth.js.map +1 -0
  375. package/lib/index.d.ts +80 -0
  376. package/lib/index.d.ts.map +1 -0
  377. package/lib/index.js +61 -0
  378. package/lib/index.js.map +1 -0
  379. package/lib/kernel/index.d.ts +3 -0
  380. package/lib/kernel/index.d.ts.map +1 -0
  381. package/lib/kernel/index.js +3 -0
  382. package/lib/kernel/index.js.map +1 -0
  383. package/lib/libraries/.gitkeep +0 -0
  384. package/lib/libraries/ai/CHANGELOG.md +17 -0
  385. package/lib/libraries/ai/README.md +164 -0
  386. package/lib/libraries/ai/adapters/AnthropicAdapter.ts +382 -0
  387. package/lib/libraries/ai/adapters/LLMProvider.ts +76 -0
  388. package/lib/libraries/ai/adapters/OpenAIAdapter.ts +466 -0
  389. package/lib/libraries/ai/experimental/index.ts +20 -0
  390. package/lib/libraries/ai/index.ts +128 -0
  391. package/lib/libraries/ai/library.json +19 -0
  392. package/lib/libraries/ai/loop/agentLoop.ts +377 -0
  393. package/lib/libraries/ai/prompts/definePrompt.ts +0 -0
  394. package/lib/libraries/ai/rag/retrieveAndAnswer.ts +177 -0
  395. package/lib/libraries/ai/streaming/streamLLM.ts +94 -0
  396. package/lib/libraries/ai/structured/completeStructured.ts +143 -0
  397. package/lib/libraries/ai/tokens/Tokenizer.ts +216 -0
  398. package/lib/libraries/ai/tools/defineTool.ts +208 -0
  399. package/lib/libraries/ai/types.ts +260 -0
  400. package/lib/libraries/chunking/ChunkingService.ts +103 -0
  401. package/lib/libraries/chunking/README.md +104 -0
  402. package/lib/libraries/chunking/docs/api-reference.md +549 -0
  403. package/lib/libraries/chunking/docs/best-practices.md +321 -0
  404. package/lib/libraries/chunking/docs/code-organization.md +538 -0
  405. package/lib/libraries/chunking/docs/configuration.md +418 -0
  406. package/lib/libraries/chunking/docs/index.md +236 -0
  407. package/lib/libraries/chunking/docs/quick-start.md +298 -0
  408. package/lib/libraries/chunking/docs/strategies.md +407 -0
  409. package/lib/libraries/chunking/docs/summary.md +258 -0
  410. package/lib/libraries/chunking/docs/troubleshooting.md +527 -0
  411. package/lib/libraries/chunking/index.ts +17 -0
  412. package/lib/libraries/chunking/library.json +16 -0
  413. package/lib/libraries/chunking/strategies/ChunkingStrategy.ts +13 -0
  414. package/lib/libraries/chunking/strategies/FixedLengthChunkingStrategy.ts +88 -0
  415. package/lib/libraries/chunking/strategies/SemanticChunkingStrategy.ts +389 -0
  416. package/lib/libraries/chunking/strategies/SlidingWindowChunkingStrategy.ts +258 -0
  417. package/lib/libraries/chunking/types/index.ts +63 -0
  418. package/lib/libraries/email/EmailService.ts +591 -0
  419. package/lib/libraries/email/README.md +777 -0
  420. package/lib/libraries/email/TemplateRegistry.ts +148 -0
  421. package/lib/libraries/email/TemplateRenderer.ts +273 -0
  422. package/lib/libraries/email/index.ts +4 -0
  423. package/lib/libraries/email/initializeEmailService.ts +60 -0
  424. package/lib/libraries/email/library.json +12 -0
  425. package/lib/libraries/email/types/EmailAddress.ts +4 -0
  426. package/lib/libraries/email/types/EmailAttachment.ts +11 -0
  427. package/lib/libraries/email/types/EmailTag.ts +9 -0
  428. package/lib/libraries/email/types/EmailTemplate.ts +124 -0
  429. package/lib/libraries/email/types/SendBatchEmailsOptions.ts +9 -0
  430. package/lib/libraries/email/types/SendBatchEmailsResult.ts +9 -0
  431. package/lib/libraries/email/types/SendEmailOptions.ts +33 -0
  432. package/lib/libraries/email/types/SendEmailResult.ts +9 -0
  433. package/lib/libraries/email/types/index.ts +8 -0
  434. package/lib/libraries/weaviate/QueryBuilder.ts +292 -0
  435. package/lib/libraries/weaviate/README.md +284 -0
  436. package/lib/libraries/weaviate/Weaviate.ts +1419 -0
  437. package/lib/libraries/weaviate/WeaviateConfig.ts +268 -0
  438. package/lib/libraries/weaviate/docs/.gitkeep +1 -0
  439. package/lib/libraries/weaviate/docs/API_REFERENCE.md +1067 -0
  440. package/lib/libraries/weaviate/docs/CONFIGURATION.md +320 -0
  441. package/lib/libraries/weaviate/docs/ERROR_HANDLING.md +271 -0
  442. package/lib/libraries/weaviate/docs/MULTI_TENANCY.md +348 -0
  443. package/lib/libraries/weaviate/docs/PERFORMANCE.md +602 -0
  444. package/lib/libraries/weaviate/docs/PLUGIN_DEVELOPMENT.md +547 -0
  445. package/lib/libraries/weaviate/docs/QUICK_START.md +443 -0
  446. package/lib/libraries/weaviate/docs/README.md +269 -0
  447. package/lib/libraries/weaviate/docs/SCHEMA_GUIDE.md +630 -0
  448. package/lib/libraries/weaviate/docs/WEAVIATE_README.md +520 -0
  449. package/lib/libraries/weaviate/errors/WeaviateError.ts +92 -0
  450. package/lib/libraries/weaviate/errors/index.ts +1 -0
  451. package/lib/libraries/weaviate/index.ts +35 -0
  452. package/lib/libraries/weaviate/library.json +26 -0
  453. package/lib/libraries/weaviate/plugins/index.ts +2 -0
  454. package/lib/libraries/weaviate/schemas/SchemaRegistry.ts +284 -0
  455. package/lib/libraries/weaviate/schemas/index.ts +2 -0
  456. package/lib/libraries/weaviate/types/BM25SearchOptions.ts +9 -0
  457. package/lib/libraries/weaviate/types/ExtendedWeaviateClient.ts +7 -0
  458. package/lib/libraries/weaviate/types/HybridSearchOptions.ts +11 -0
  459. package/lib/libraries/weaviate/types/MultiTenancy.ts +81 -0
  460. package/lib/libraries/weaviate/types/Plugin.ts +17 -0
  461. package/lib/libraries/weaviate/types/SchemaConfig.ts +25 -0
  462. package/lib/libraries/weaviate/types/SearchMethod.ts +8 -0
  463. package/lib/libraries/weaviate/types/SearchOptions.ts +16 -0
  464. package/lib/libraries/weaviate/types/SearchRequest.ts +19 -0
  465. package/lib/libraries/weaviate/types/SearchResult.ts +16 -0
  466. package/lib/libraries/weaviate/types/SearchableField.ts +87 -0
  467. package/lib/libraries/weaviate/types/VectorIndexConfig.ts +19 -0
  468. package/lib/libraries/weaviate/types/VectorSearchOptions.ts +18 -0
  469. package/lib/libraries/weaviate/types/VectorizerConfig.ts +8 -0
  470. package/lib/libraries/weaviate/types/index.ts +29 -0
  471. package/lib/libraries/weaviate/utils/TenantContextManager.ts +94 -0
  472. package/lib/modules/accounts/index.ts +47 -0
  473. package/lib/modules/accounts/module.json +15 -0
  474. package/lib/modules/accounts/permissions.ts +33 -0
  475. package/lib/modules/accounts/routes.ts +200 -0
  476. package/lib/modules/accounts/schema.ts +219 -0
  477. package/lib/modules/accounts/services/AccountService.ts +44 -0
  478. package/lib/modules/accounts/validation/schemas.ts +70 -0
  479. package/lib/modules/oauth/adapters/GmailOAuthAdapter.ts +35 -0
  480. package/lib/modules/oauth/adapters/GoogleOAuthAdapter.ts +278 -0
  481. package/lib/modules/oauth/adapters/MicrosoftOAuthAdapter.ts +269 -0
  482. package/lib/modules/oauth/adapters/MockOAuthAdapter.ts +138 -0
  483. package/lib/modules/oauth/adapters/OAuthAdapter.ts +211 -0
  484. package/lib/modules/oauth/adapters/OAuthAdapterRegistry.ts +77 -0
  485. package/lib/modules/oauth/adapters/OutlookOAuthAdapter.ts +38 -0
  486. package/lib/modules/oauth/index.ts +79 -0
  487. package/lib/modules/oauth/module.json +23 -0
  488. package/lib/modules/oauth/permissions.ts +39 -0
  489. package/lib/modules/oauth/routes.ts +497 -0
  490. package/lib/modules/oauth/schema.ts +127 -0
  491. package/lib/modules/oauth/services/OAuthConnectionService.ts +147 -0
  492. package/lib/modules/oauth/state.ts +234 -0
  493. package/lib/modules/oauth/stateJtiCache.ts +85 -0
  494. package/lib/modules/oauth/verifyIdToken.ts +178 -0
  495. package/lib/modules/outbox/EventEmitter.ts +106 -0
  496. package/lib/modules/outbox/OutboxDrainer.ts +163 -0
  497. package/lib/modules/outbox/handlers/EventHandler.ts +115 -0
  498. package/lib/modules/outbox/index.ts +43 -0
  499. package/lib/modules/outbox/module.json +15 -0
  500. package/lib/modules/outbox/permissions.ts +36 -0
  501. package/lib/modules/outbox/routes.ts +219 -0
  502. package/lib/modules/outbox/schema.ts +207 -0
  503. package/lib/modules/outbox/services/OutboxEventService.ts +223 -0
  504. package/lib/observability/logger.d.ts +30 -0
  505. package/lib/observability/logger.d.ts.map +1 -0
  506. package/lib/observability/logger.js +110 -0
  507. package/lib/observability/logger.js.map +1 -0
  508. package/lib/observability/metrics.d.ts +3 -0
  509. package/lib/observability/metrics.d.ts.map +1 -0
  510. package/lib/observability/metrics.js +3 -0
  511. package/lib/observability/metrics.js.map +1 -0
  512. package/lib/observability/otel.d.ts +3 -0
  513. package/lib/observability/otel.d.ts.map +1 -0
  514. package/lib/observability/otel.js +3 -0
  515. package/lib/observability/otel.js.map +1 -0
  516. package/lib/observability/safeErrorFields.d.ts +14 -0
  517. package/lib/observability/safeErrorFields.d.ts.map +1 -0
  518. package/lib/observability/safeErrorFields.js +14 -0
  519. package/lib/observability/safeErrorFields.js.map +1 -0
  520. package/lib/observability/tracing.d.ts +3 -0
  521. package/lib/observability/tracing.d.ts.map +1 -0
  522. package/lib/observability/tracing.js +3 -0
  523. package/lib/observability/tracing.js.map +1 -0
  524. package/lib/package.json +4 -0
  525. package/lib/testing.d.ts +3 -0
  526. package/lib/testing.d.ts.map +1 -0
  527. package/lib/testing.js +3 -0
  528. package/lib/testing.js.map +1 -0
  529. package/package.json +193 -3
  530. package/templates/default/.claude/agents/qa-brief.md +106 -0
  531. package/templates/default/.claude/commands/sherpa-brief.md +23 -0
  532. package/templates/default/.cursor/rules/api.mdc +80 -0
  533. package/templates/default/.cursor/rules/commits.mdc +88 -0
  534. package/templates/default/.cursor/rules/security.mdc +92 -0
  535. package/templates/default/.cursor/rules/testing.mdc +123 -0
  536. package/templates/default/.cursor/rules/typescript.mdc +86 -0
  537. package/templates/default/.env.example +79 -0
  538. package/templates/default/.github/workflows/sherpa-brief.yml +180 -0
  539. package/templates/default/AGENTS.md +166 -0
  540. package/templates/default/CLAUDE.md +17 -0
  541. package/templates/default/README.md +97 -0
  542. package/templates/default/_gitignore +27 -0
  543. package/templates/default/docker-compose.yml +83 -0
  544. package/templates/default/drizzle.config.ts +34 -0
  545. package/templates/default/eslint.config.mjs +106 -0
  546. package/templates/default/package.json +57 -0
  547. package/templates/default/ship-api.config.ts +21 -0
  548. package/templates/default/src/client.ts +34 -0
  549. package/templates/default/src/config/modules.ts +23 -0
  550. package/templates/default/src/db/schema.ts +26 -0
  551. package/templates/default/src/environment.ts +81 -0
  552. package/templates/default/src/index.test.ts +53 -0
  553. package/templates/default/src/index.ts +11 -0
  554. package/templates/default/src/instrumentation.ts +13 -0
  555. package/templates/default/src/server.ts +90 -0
  556. package/templates/default/tsconfig.json +24 -0
@@ -0,0 +1,106 @@
1
+ import type { ShipDb } from "@sixthsummit/ship-api/app/db/client";
2
+ import { type NewOutboxEvent, type OutboxEvent, outboxEvents } from "./schema.js";
3
+
4
+ /**
5
+ * Producer-side helper for the transactional outbox pattern.
6
+ *
7
+ * Domain operations call `emitter.emit(...)` *inside the same
8
+ * transaction* as the business write. Postgres atomicity guarantees
9
+ * either both commit or neither — the outbox row is never orphaned
10
+ * from the domain change, and the domain change is never published
11
+ * without an outbox row to drain.
12
+ *
13
+ * Usage:
14
+ *
15
+ * ```ts
16
+ * await db.transaction(async (tx) => {
17
+ * const account = await accountService.create({...}, { tx });
18
+ * await emitter.emit({
19
+ * eventType: "account.created",
20
+ * aggregateType: "account",
21
+ * aggregateId: account.id,
22
+ * payload: { id: account.id, email: account.email },
23
+ * }, { tx });
24
+ * });
25
+ * ```
26
+ *
27
+ * The drain worker (`OutboxDrainer`) picks up the row asynchronously
28
+ * and dispatches it to the registered `EventHandler`s. Producers
29
+ * never see the dispatch chain — they just write the event.
30
+ *
31
+ * Why a class instead of a free function: the emitter is constructed
32
+ * once per app with the framework's `db` client; consumers inject it
33
+ * into services / route handlers via the `deps` parameter.
34
+ */
35
+ export class OutboxEventEmitter<
36
+ TSchema extends Record<string, unknown> = { outboxEvents: typeof outboxEvents },
37
+ > {
38
+ constructor(private readonly db: ShipDb<TSchema>) {}
39
+
40
+ /**
41
+ * Append an event to the outbox. Pass a transaction client (`tx`)
42
+ * via `opts.tx` to atomically pair the event with a domain write —
43
+ * **strongly recommended**. Without `tx`, the event is appended in
44
+ * its own implicit transaction and could decouple from the domain
45
+ * write (defeats the purpose of the outbox pattern).
46
+ */
47
+ async emit(input: EmitEventInput, opts: EmitEventOptions = {}): Promise<OutboxEvent> {
48
+ const dbClient = (opts.tx ?? this.db) as unknown as ShipDb<TSchema>;
49
+ const values: NewOutboxEvent = {
50
+ eventType: input.eventType,
51
+ eventVersion: input.eventVersion ?? 1,
52
+ occurredAt: input.occurredAt ?? new Date(),
53
+ aggregateType: input.aggregateType ?? null,
54
+ aggregateId: input.aggregateId ?? null,
55
+ ownerUserId: input.ownerUserId ?? null,
56
+ tenantId: input.tenantId ?? null,
57
+ dedupeKey: input.dedupeKey ?? null,
58
+ correlationId: input.correlationId ?? null,
59
+ payload: input.payload,
60
+ maxRetries: input.maxRetries ?? 10,
61
+ };
62
+ const inserter = dbClient as unknown as {
63
+ insert: (table: typeof outboxEvents) => {
64
+ values: (v: unknown) => { returning: () => Promise<OutboxEvent[]> };
65
+ };
66
+ };
67
+ const [row] = await inserter.insert(outboxEvents).values(values).returning();
68
+ return row;
69
+ }
70
+ }
71
+
72
+ export interface EmitEventInput {
73
+ /** Domain event type — matches a registered handler's `type`. */
74
+ eventType: string;
75
+ /** Schema version for the payload. Bump when payload shape changes. */
76
+ eventVersion?: number;
77
+ /** When the domain operation occurred. Defaults to `now()`. */
78
+ occurredAt?: Date;
79
+ /** Aggregate type ("account", "post", ...). */
80
+ aggregateType?: string | null;
81
+ /** Aggregate id within `aggregateType`. */
82
+ aggregateId?: string | null;
83
+ /** Owner user id (typically `accounts.id`). */
84
+ ownerUserId?: string | null;
85
+ /** Multi-tenant scope. */
86
+ tenantId?: string | null;
87
+ /** Stable dedup key for upstream-deduplication. */
88
+ dedupeKey?: string | null;
89
+ /** Trace correlation id. */
90
+ correlationId?: string | null;
91
+ /** Event payload. Consumer-shaped JSON. */
92
+ payload: Record<string, unknown>;
93
+ /** Override the default 10-attempt retry budget. */
94
+ maxRetries?: number;
95
+ }
96
+
97
+ export interface EmitEventOptions {
98
+ /**
99
+ * Transaction client to participate in. Pass the same `tx` you're
100
+ * using for the domain write so the outbox row commits atomically
101
+ * with the business data. Without `tx`, the event is appended in
102
+ * its own transaction — usable for fire-and-forget signals where
103
+ * the outbox semantics don't matter.
104
+ */
105
+ tx?: unknown;
106
+ }
@@ -0,0 +1,163 @@
1
+ import type { EventHandlerRegistry } from "./handlers/EventHandler.js";
2
+ import { hasExhaustedRetries, type OutboxEvent } from "./schema.js";
3
+ import type { OutboxEventService } from "./services/OutboxEventService.js";
4
+
5
+ /**
6
+ * Consumer-side drain orchestrator. One pass:
7
+ *
8
+ * 1. `findReadyToPublish(batchSize)` — pull pending rows
9
+ * 2. `claimForProcessing(ids)` — atomic pending→processing
10
+ * transition (concurrent-safe — competing workers see different
11
+ * claimed subsets)
12
+ * 3. For each claimed row:
13
+ * - Resolve the handler via the registry
14
+ * - Invoke `handler.handle(event, ctx)`
15
+ * - On success → `markPublished(id)`
16
+ * - On throw → check the retry budget:
17
+ * - If exhausted → `markFailed(id, error)` (terminal)
18
+ * - Otherwise → `markForRetry(id, error, attempts)` (revert to pending,
19
+ * schedule via exponential backoff)
20
+ * - If no handler matches → mark for retry with a "no handler"
21
+ * message; ops backfills the handler and the next drain
22
+ * retries automatically.
23
+ * 4. Returns a summary — published / failed / retried counts.
24
+ *
25
+ * `runOnce()` does one pass. `runUntilEmpty()` keeps passing until
26
+ * the database returns 0 ready rows (polling-friendly worker entry
27
+ * point — wraps with `setInterval` outside this class).
28
+ *
29
+ * Honors `signal` end-to-end: handler invocations receive the same
30
+ * AbortSignal, the loop exits between batches, and the loop also
31
+ * exits *between* per-event handler calls so a SIGTERM mid-batch
32
+ * doesn't have to wait for the entire batch to finish.
33
+ */
34
+
35
+ export interface OutboxDrainerOptions {
36
+ /**
37
+ * Rows to claim per drain pass. Larger = fewer round trips but
38
+ * longer per-pass latency. Default 50.
39
+ */
40
+ batchSize?: number;
41
+ /** AbortSignal to short-circuit between handler invocations. */
42
+ signal?: AbortSignal;
43
+ /**
44
+ * Per-handler context the registry forwards to each handler.
45
+ * Typical contents: `{ requestId, traceId }`.
46
+ */
47
+ metadata?: Record<string, unknown>;
48
+ }
49
+
50
+ export interface OutboxDrainerResult {
51
+ /** Total events processed in this pass. */
52
+ processed: number;
53
+ /** Successfully published — terminal success. */
54
+ published: number;
55
+ /** Permanently failed — exhausted retry budget. */
56
+ failed: number;
57
+ /** Scheduled for retry — non-terminal failure. */
58
+ retried: number;
59
+ /** Skipped because no handler is registered for the event type. */
60
+ skippedNoHandler: number;
61
+ }
62
+
63
+ const ZERO_RESULT: OutboxDrainerResult = {
64
+ processed: 0,
65
+ published: 0,
66
+ failed: 0,
67
+ retried: 0,
68
+ skippedNoHandler: 0,
69
+ };
70
+
71
+ export class OutboxDrainer {
72
+ constructor(
73
+ private readonly service: OutboxEventService,
74
+ private readonly handlers: EventHandlerRegistry,
75
+ ) {}
76
+
77
+ async runOnce(opts: OutboxDrainerOptions = {}): Promise<OutboxDrainerResult> {
78
+ const batchSize = opts.batchSize ?? 50;
79
+ if (opts.signal?.aborted) return { ...ZERO_RESULT };
80
+
81
+ const candidates = await this.service.findReadyToPublish(batchSize);
82
+ if (candidates.length === 0) return { ...ZERO_RESULT };
83
+
84
+ const claimedIds = await this.service.claimForProcessing(candidates.map((c) => c.id));
85
+ const claimed = candidates.filter((c) => claimedIds.includes(c.id));
86
+
87
+ const result: OutboxDrainerResult = { ...ZERO_RESULT };
88
+ result.processed = claimed.length;
89
+
90
+ for (const event of claimed) {
91
+ if (opts.signal?.aborted) break;
92
+ await this.processOne(event, opts, result);
93
+ }
94
+
95
+ return result;
96
+ }
97
+
98
+ /**
99
+ * Loop `runOnce` until a pass returns `processed: 0` (queue
100
+ * drained) or the signal aborts. Useful for cron-driven flushes
101
+ * and for catch-up runs after an outage.
102
+ */
103
+ async runUntilEmpty(opts: OutboxDrainerOptions = {}): Promise<OutboxDrainerResult> {
104
+ const total: OutboxDrainerResult = { ...ZERO_RESULT };
105
+ while (!opts.signal?.aborted) {
106
+ const pass = await this.runOnce(opts);
107
+ total.processed += pass.processed;
108
+ total.published += pass.published;
109
+ total.failed += pass.failed;
110
+ total.retried += pass.retried;
111
+ total.skippedNoHandler += pass.skippedNoHandler;
112
+ if (pass.processed === 0) break;
113
+ }
114
+ return total;
115
+ }
116
+
117
+ private async processOne(
118
+ event: OutboxEvent,
119
+ opts: OutboxDrainerOptions,
120
+ result: OutboxDrainerResult,
121
+ ): Promise<void> {
122
+ const handler = this.handlers.findHandler({
123
+ eventType: event.eventType,
124
+ eventVersion: event.eventVersion,
125
+ });
126
+
127
+ if (!handler) {
128
+ // No handler registered. Don't fail-permanent — ops may add
129
+ // the handler later and the next drain should retry. Mark
130
+ // for retry with a clear marker, but don't increment the
131
+ // attempt charge against the row (claimForProcessing already
132
+ // bumped it).
133
+ const message = `no handler registered for ${event.eventType} (v${event.eventVersion})`;
134
+ if (hasExhaustedRetries(event)) {
135
+ await this.service.markFailed(event.id, message);
136
+ result.failed += 1;
137
+ } else {
138
+ await this.service.markForRetry(event.id, message, event.publishAttempts);
139
+ result.retried += 1;
140
+ }
141
+ result.skippedNoHandler += 1;
142
+ return;
143
+ }
144
+
145
+ try {
146
+ await handler.handle(event as never, {
147
+ signal: opts.signal,
148
+ metadata: opts.metadata,
149
+ });
150
+ await this.service.markPublished(event.id);
151
+ result.published += 1;
152
+ } catch (err) {
153
+ const message = err instanceof Error ? err.message : String(err);
154
+ if (hasExhaustedRetries(event)) {
155
+ await this.service.markFailed(event.id, message);
156
+ result.failed += 1;
157
+ } else {
158
+ await this.service.markForRetry(event.id, message, event.publishAttempts);
159
+ result.retried += 1;
160
+ }
161
+ }
162
+ }
163
+ }
@@ -0,0 +1,115 @@
1
+ import type { OutboxEvent } from "../schema.js";
2
+
3
+ /**
4
+ * Consumer-side event handler contract.
5
+ *
6
+ * One handler maps to one event type. The drain worker dispatches each
7
+ * pending row to the matching handler; the handler does the actual
8
+ * publish (queue enqueue, webhook POST, log emit, …) and returns
9
+ * normally on success or throws on failure. Handler throws are
10
+ * captured by the drainer and translated to retry / mark-failed
11
+ * decisions based on the row's retry budget.
12
+ *
13
+ * Handlers MUST be idempotent. The outbox guarantees at-least-once
14
+ * delivery — a handler may be re-invoked for the same event after a
15
+ * crash, after stale-processing recovery, or after an exhausted
16
+ * retry budget gets re-enabled by an admin. Use `dedupeKey` /
17
+ * `eventId` for downstream deduplication where the consumer system
18
+ * supports it.
19
+ *
20
+ * Handlers SHOULD honor `ctx.signal` for graceful shutdown — when
21
+ * the worker is asked to stop mid-publish, the signal aborts and
22
+ * the handler should clean up rather than push past.
23
+ */
24
+ export interface EventHandler<TPayload = Record<string, unknown>> {
25
+ /** Stable event type matching `OutboxEvent.eventType`. */
26
+ readonly eventType: string;
27
+ /**
28
+ * Schema version this handler supports. When omitted, the handler
29
+ * accepts any version (caller-side responsibility to keep handlers
30
+ * forward-compatible). When set, the drainer skips events with a
31
+ * different version (or routes to a versioned alternative if
32
+ * registered).
33
+ */
34
+ readonly eventVersion?: number;
35
+ /** Run the handler. Throw to signal failure (drainer decides retry vs final-fail). */
36
+ handle(event: OutboxEvent & { payload: TPayload }, ctx: HandlerContext): Promise<void>;
37
+ }
38
+
39
+ export interface HandlerContext {
40
+ /** Aborts when the drain worker is stopping. Handlers honor this. */
41
+ signal?: AbortSignal;
42
+ /** Per-attempt scoped logger / metadata. Caller decides shape. */
43
+ metadata?: Record<string, unknown>;
44
+ }
45
+
46
+ /**
47
+ * Registry of `EventHandler`s keyed by `eventType` (+ optional
48
+ * `eventVersion` discriminator). The drainer does
49
+ * `registry.findHandler(event)` to dispatch each row.
50
+ *
51
+ * Replaces v3's `EventHandlerRegistry` static-class pattern with an
52
+ * instance-based registry. Same justification as `OAuthAdapterRegistry`:
53
+ * lets consumers compose handler sets per app / per tenant without
54
+ * touching framework globals.
55
+ */
56
+ export class EventHandlerRegistry {
57
+ // Two-level map: eventType → (versionKey → handler). versionKey is
58
+ // either the literal version number or the sentinel "*" for
59
+ // version-agnostic handlers.
60
+ private readonly handlers = new Map<string, Map<string, EventHandler>>();
61
+
62
+ register(handler: EventHandler): this {
63
+ const versionKey = handler.eventVersion === undefined ? "*" : String(handler.eventVersion);
64
+ let versions = this.handlers.get(handler.eventType);
65
+ if (!versions) {
66
+ versions = new Map();
67
+ this.handlers.set(handler.eventType, versions);
68
+ }
69
+ if (versions.has(versionKey)) {
70
+ throw new Error(
71
+ `EventHandlerRegistry: duplicate handler for ${handler.eventType} v${versionKey}`,
72
+ );
73
+ }
74
+ versions.set(versionKey, handler);
75
+ return this;
76
+ }
77
+
78
+ /**
79
+ * Find the handler for an event. Resolution order:
80
+ * 1. Exact `(eventType, eventVersion)` match
81
+ * 2. Version-agnostic `(eventType, *)` fallback
82
+ * Returns `undefined` when nothing is registered for the event type.
83
+ */
84
+ findHandler(
85
+ event: Pick<{ eventType: string; eventVersion: number }, "eventType" | "eventVersion">,
86
+ ): EventHandler | undefined {
87
+ const versions = this.handlers.get(event.eventType);
88
+ if (!versions) return undefined;
89
+ const exact = versions.get(String(event.eventVersion));
90
+ if (exact) return exact;
91
+ return versions.get("*");
92
+ }
93
+
94
+ /** Adapter-equivalent of `has` — true when *any* handler matches. */
95
+ hasHandler(eventType: string): boolean {
96
+ return this.handlers.has(eventType);
97
+ }
98
+
99
+ /** All event types with at least one registered handler. */
100
+ eventTypes(): string[] {
101
+ return [...this.handlers.keys()];
102
+ }
103
+
104
+ size(): number {
105
+ let total = 0;
106
+ for (const versions of this.handlers.values()) total += versions.size;
107
+ return total;
108
+ }
109
+ }
110
+
111
+ export function eventHandlerRegistry(...handlers: EventHandler[]): EventHandlerRegistry {
112
+ const registry = new EventHandlerRegistry();
113
+ for (const h of handlers) registry.register(h);
114
+ return registry;
115
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Outbox module — public barrel.
3
+ *
4
+ * Postgres-backed transactional event outbox: emit events inside the
5
+ * same DB transaction as the domain write, then drain to handlers
6
+ * (which typically enqueue BullMQ jobs) outside the transaction.
7
+ * Atomicity with the domain write requires Postgres; Redis-backed
8
+ * BullMQ can't participate.
9
+ *
10
+ * Surface: outbox events table + service + status / lifecycle
11
+ * transition methods + retry/recover helpers + EventEmitter +
12
+ * EventHandlerRegistry + OutboxDrainer + HTTP routes.
13
+ */
14
+
15
+ export { type EmitEventInput, type EmitEventOptions, OutboxEventEmitter } from "./EventEmitter.js";
16
+ export {
17
+ type EventHandler,
18
+ EventHandlerRegistry,
19
+ eventHandlerRegistry,
20
+ type HandlerContext,
21
+ } from "./handlers/EventHandler.js";
22
+ export {
23
+ OutboxDrainer,
24
+ type OutboxDrainerOptions,
25
+ type OutboxDrainerResult,
26
+ } from "./OutboxDrainer.js";
27
+ export {
28
+ OUTBOX_PERMISSION_DEFINITIONS,
29
+ OUTBOX_PERMISSIONS,
30
+ type OutboxPermission,
31
+ } from "./permissions.js";
32
+ export { buildOutboxApp, defineOutboxRoutes, type OutboxRoutesDeps } from "./routes.js";
33
+ export {
34
+ computeNextAttempt,
35
+ hasExhaustedRetries,
36
+ isReadyForPublish,
37
+ type NewOutboxEvent,
38
+ type OutboxEvent,
39
+ type OutboxEventStatus,
40
+ outboxEventStatus,
41
+ outboxEvents,
42
+ } from "./schema.js";
43
+ export { OutboxEventService } from "./services/OutboxEventService.js";
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "outbox",
3
+ "description": "Transactional outbox on the v4 substrate. The v3 `operations` module bundled outbox events + a job queue; v4 splits them — the job runtime moves entirely into BullMQ (`defineJob` / `JobsManager`) and this module owns the Postgres-backed outbox (event row commits in the same tx as the domain write).",
4
+ "version": "2.0.0-alpha.1",
5
+ "dependencies": ["accounts"],
6
+ "npmDependencies": {},
7
+ "requiredEnvVars": [],
8
+ "optionalEnvVars": [],
9
+ "postInstall": [
10
+ "Add the schema to your composed schema: `createApp({ schema: { ...accountsSchema, outboxEvents } })`",
11
+ "Wire the routes: `defineOutboxRoutes(app, { service, drainer, provider })`",
12
+ "Generate the migration: `npm run db:generate`",
13
+ "If you're migrating from v3 operations: the `Job` entity + JobController are NOT ported. Move job processing to `defineJob` from @sixthsummit/ship-api (BullMQ-backed)."
14
+ ]
15
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Permission slugs for the outbox module.
3
+ *
4
+ * v3 had no permissions for the JobController routes (operational
5
+ * tooling assumed admin-only). v4 makes the permission boundary
6
+ * explicit so the same module can ship to consumers who route admin
7
+ * traffic through different RBAC layers.
8
+ */
9
+
10
+ import type { PermissionDefinition } from "@sixthsummit/ship-api";
11
+
12
+ export const OUTBOX_PERMISSIONS = {
13
+ /** View outbox events (for one's own scope or all, depending on RBAC). */
14
+ outboxRead: "outbox:read",
15
+ /** Trigger drain manually (admin operation). */
16
+ outboxDrain: "outbox:drain",
17
+ /** Recover stale processing events (admin operation). */
18
+ outboxRecover: "outbox:recover",
19
+ } as const;
20
+
21
+ export type OutboxPermission = (typeof OUTBOX_PERMISSIONS)[keyof typeof OUTBOX_PERMISSIONS];
22
+
23
+ export const OUTBOX_PERMISSION_DEFINITIONS = [
24
+ {
25
+ slug: OUTBOX_PERMISSIONS.outboxRead,
26
+ label: "View Outbox Events",
27
+ },
28
+ {
29
+ slug: OUTBOX_PERMISSIONS.outboxDrain,
30
+ label: "Drain Outbox (Admin)",
31
+ },
32
+ {
33
+ slug: OUTBOX_PERMISSIONS.outboxRecover,
34
+ label: "Recover Stale Outbox Events (Admin)",
35
+ },
36
+ ] as const satisfies readonly PermissionDefinition[];