@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,70 @@
1
+ /**
2
+ * Framework-wide `Cache` interface.
3
+ *
4
+ * Two reference implementations ship in v4.0:
5
+ * - `RedisCache` — production default, msgpackr-serialized, with
6
+ * tag-based invalidation via Redis Sets.
7
+ * - `InMemoryCache` — `lru-cache`-backed; intended for tests + dev
8
+ * fallback when Redis is unavailable.
9
+ *
10
+ * Consumers usually don't construct caches directly — `cached(key, ttl, fn)`
11
+ * is the high-level helper that hides the lookup / miss / store dance.
12
+ *
13
+ * The interface is intentionally narrow: any backend that can do `get`,
14
+ * `set` (with TTL), `del`, and tag-tracking can plug in. Future v4.x
15
+ * adapters (Memcached, Cloudflare KV, Upstash) implement the same contract.
16
+ */
17
+ export interface CacheSetOptions {
18
+ /** TTL in seconds. `undefined` means no expiry (use sparingly). */
19
+ ttlSec?: number;
20
+ /**
21
+ * Tag this key under each label. `invalidateTag(tag)` later wipes all keys
22
+ * sharing the tag — useful for "everything related to user X" or
23
+ * "everything in module Y".
24
+ */
25
+ tags?: readonly string[];
26
+ }
27
+ export interface Cache {
28
+ /** Returns `null` on miss. */
29
+ get<T = unknown>(key: string): Promise<T | null>;
30
+ /** Store with optional TTL + tags. Idempotent. */
31
+ set<T = unknown>(key: string, value: T, opts?: CacheSetOptions): Promise<void>;
32
+ /**
33
+ * Atomic SET-IF-ABSENT. Stores `value` if no entry already exists at `key`,
34
+ * returning `true`; returns `false` when an entry is present (no-op).
35
+ *
36
+ * Used as a low-level claim / lock primitive — the idempotency middleware
37
+ * uses it to deduplicate concurrent requests sharing an `Idempotency-Key`.
38
+ * Tags are NOT supported here (locks should not survive `invalidateTag`).
39
+ *
40
+ * Redis: implemented via `SET NX EX` (atomic at the Redis server).
41
+ * In-memory: the `has` / `set` body runs synchronously inside the async
42
+ * function — within a single event-loop tick the check + write is a true
43
+ * CAS.
44
+ *
45
+ * **F19 — Atomicity invariant.** Implementations MUST run the check + write
46
+ * in one continuation (no `await` between them). A future refactor that
47
+ * inserts an `await` silently breaks idempotency under concurrent load on
48
+ * a public app — multiple callers would see an empty slot, all "claim" the
49
+ * key, and the cache ends up holding the last writer's value with every
50
+ * caller observing `true`. The regression test in
51
+ * `InMemoryCache.test.ts` (100 concurrent `setIfAbsent("same-key")` →
52
+ * exactly one `true`) is the canary that catches the regression.
53
+ */
54
+ setIfAbsent<T = unknown>(key: string, value: T, opts?: {
55
+ ttlSec?: number;
56
+ }): Promise<boolean>;
57
+ /** Delete one or many keys. Missing keys are silently ignored. */
58
+ del(key: string | readonly string[]): Promise<void>;
59
+ /**
60
+ * Wipe every key recorded under `tag`, plus the tag-tracking record itself.
61
+ * Use for "user updated → invalidate everything tagged `user:<id>`".
62
+ */
63
+ invalidateTag(tag: string): Promise<void>;
64
+ /**
65
+ * Optional admin / test hook. Implementations that can't cheaply enumerate
66
+ * may throw. Avoid in production paths.
67
+ */
68
+ clear?(): Promise<void>;
69
+ }
70
+ //# sourceMappingURL=Cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Cache.d.ts","sourceRoot":"","sources":["../../../../src/app/services/cache/Cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,eAAe;IAC9B,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,KAAK;IACpB,8BAA8B;IAC9B,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAEjD,kDAAkD;IAClD,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/E;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,WAAW,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE9F,kEAAkE;IAClE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpD;;;OAGG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1C;;;OAGG;IACH,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Framework-wide `Cache` interface.
3
+ *
4
+ * Two reference implementations ship in v4.0:
5
+ * - `RedisCache` — production default, msgpackr-serialized, with
6
+ * tag-based invalidation via Redis Sets.
7
+ * - `InMemoryCache` — `lru-cache`-backed; intended for tests + dev
8
+ * fallback when Redis is unavailable.
9
+ *
10
+ * Consumers usually don't construct caches directly — `cached(key, ttl, fn)`
11
+ * is the high-level helper that hides the lookup / miss / store dance.
12
+ *
13
+ * The interface is intentionally narrow: any backend that can do `get`,
14
+ * `set` (with TTL), `del`, and tag-tracking can plug in. Future v4.x
15
+ * adapters (Memcached, Cloudflare KV, Upstash) implement the same contract.
16
+ */
17
+ export {};
18
+ //# sourceMappingURL=Cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Cache.js","sourceRoot":"","sources":["../../../../src/app/services/cache/Cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}
@@ -0,0 +1,35 @@
1
+ import type { Cache, CacheSetOptions } from "./Cache.js";
2
+ /**
3
+ * `lru-cache`-backed cache used in tests and as a graceful fallback when
4
+ * Redis is unavailable.
5
+ *
6
+ * Tag tracking is in-process only — the `tagIndex` Map mirrors the Redis
7
+ * Sets that `RedisCache` uses. `invalidateTag(tag)` walks the index +
8
+ * deletes the keys + drops the tag set, mirroring Redis behavior.
9
+ *
10
+ * Designed for *single-process* use only. In a multi-instance deployment
11
+ * each instance has its own cache, so tag invalidation in one instance
12
+ * does NOT propagate. This is acceptable for the test-fixture and
13
+ * dev-fallback use cases. Production must use `RedisCache`.
14
+ */
15
+ export interface InMemoryCacheOptions {
16
+ /** Max number of entries before LRU eviction. Default 10_000. */
17
+ max?: number;
18
+ /** Default TTL (ms) for entries created without a TTL. */
19
+ defaultTtlMs?: number;
20
+ }
21
+ export declare class InMemoryCache implements Cache {
22
+ private store;
23
+ /** tag → set of cache keys tagged with it. */
24
+ private tagIndex;
25
+ constructor(opts?: InMemoryCacheOptions);
26
+ get<T = unknown>(key: string): Promise<T | null>;
27
+ setIfAbsent<T = unknown>(key: string, value: T, opts?: {
28
+ ttlSec?: number;
29
+ }): Promise<boolean>;
30
+ set<T = unknown>(key: string, value: T, opts?: CacheSetOptions): Promise<void>;
31
+ del(key: string | readonly string[]): Promise<void>;
32
+ invalidateTag(tag: string): Promise<void>;
33
+ clear(): Promise<void>;
34
+ }
35
+ //# sourceMappingURL=InMemoryCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InMemoryCache.d.ts","sourceRoot":"","sources":["../../../../src/app/services/cache/InMemoryCache.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEzD;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,oBAAoB;IACnC,iEAAiE;IACjE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AASD,qBAAa,aAAc,YAAW,KAAK;IACzC,OAAO,CAAC,KAAK,CAAwB;IACrC,8CAA8C;IAC9C,OAAO,CAAC,QAAQ,CAAkC;gBAEtC,IAAI,GAAE,oBAAyB;IAQrC,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAMhD,WAAW,CAAC,CAAC,GAAG,OAAO,EAC3B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,CAAC,EACR,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GAC7B,OAAO,CAAC,OAAO,CAAC;IAYb,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBlF,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAYnD,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOzC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B"}
@@ -0,0 +1,76 @@
1
+ import { LRUCache } from "lru-cache";
2
+ export class InMemoryCache {
3
+ store;
4
+ /** tag → set of cache keys tagged with it. */
5
+ tagIndex = new Map();
6
+ constructor(opts = {}) {
7
+ this.store = new LRUCache({
8
+ max: opts.max ?? 10_000,
9
+ ttl: opts.defaultTtlMs,
10
+ ttlAutopurge: opts.defaultTtlMs !== undefined,
11
+ });
12
+ }
13
+ async get(key) {
14
+ const box = this.store.get(key);
15
+ if (box === undefined)
16
+ return null;
17
+ return box.v;
18
+ }
19
+ async setIfAbsent(key, value, opts = {}) {
20
+ if (this.store.has(key))
21
+ return false;
22
+ const ttlMs = opts.ttlSec !== undefined ? opts.ttlSec * 1000 : undefined;
23
+ const box = { v: value };
24
+ if (ttlMs !== undefined && ttlMs > 0) {
25
+ this.store.set(key, box, { ttl: ttlMs });
26
+ }
27
+ else {
28
+ this.store.set(key, box);
29
+ }
30
+ return true;
31
+ }
32
+ async set(key, value, opts = {}) {
33
+ const ttlMs = opts.ttlSec !== undefined ? opts.ttlSec * 1000 : undefined;
34
+ const box = { v: value };
35
+ if (ttlMs !== undefined && ttlMs > 0) {
36
+ this.store.set(key, box, { ttl: ttlMs });
37
+ }
38
+ else {
39
+ this.store.set(key, box);
40
+ }
41
+ if (opts.tags) {
42
+ for (const tag of opts.tags) {
43
+ let bucket = this.tagIndex.get(tag);
44
+ if (!bucket) {
45
+ bucket = new Set();
46
+ this.tagIndex.set(tag, bucket);
47
+ }
48
+ bucket.add(key);
49
+ }
50
+ }
51
+ }
52
+ async del(key) {
53
+ const keys = Array.isArray(key) ? key : [key];
54
+ for (const k of keys) {
55
+ this.store.delete(k);
56
+ // Also drop from any tag buckets so invalidateTag doesn't try to
57
+ // delete already-evicted keys.
58
+ for (const bucket of this.tagIndex.values()) {
59
+ bucket.delete(k);
60
+ }
61
+ }
62
+ }
63
+ async invalidateTag(tag) {
64
+ const bucket = this.tagIndex.get(tag);
65
+ if (!bucket)
66
+ return;
67
+ for (const k of bucket)
68
+ this.store.delete(k);
69
+ this.tagIndex.delete(tag);
70
+ }
71
+ async clear() {
72
+ this.store.clear();
73
+ this.tagIndex.clear();
74
+ }
75
+ }
76
+ //# sourceMappingURL=InMemoryCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InMemoryCache.js","sourceRoot":"","sources":["../../../../src/app/services/cache/InMemoryCache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ import type { Cache, CacheSetOptions } from "./Cache.js";
2
+ /**
3
+ * Redis-backed cache with msgpackr serialization.
4
+ *
5
+ * Production default. Designed to be Redis-client-agnostic: any object that
6
+ * implements the methods in `RedisLike` works (production: ioredis client;
7
+ * tests: hand-rolled fake).
8
+ *
9
+ * Serialization: msgpackr encodes/decodes via Buffer — faster than JSON,
10
+ * preserves Date / Map / Set / undefined / bigint that JSON loses.
11
+ *
12
+ * Tag tracking: each `set(key, value, { tags })` SADDs the key into a
13
+ * sibling Redis Set named `<tagPrefix><tag>`. `invalidateTag(tag)` SMEMBERs,
14
+ * deletes them all, and drops the tag set. Atomic for typical use because
15
+ * tag-set membership and value-key live in the same Redis instance — for
16
+ * cluster mode, hash-tag the keys to keep them on one shard.
17
+ *
18
+ * Key namespacing: every key is prefixed with `keyPrefix` so cache content
19
+ * can't bleed across services or framework versions.
20
+ */
21
+ export interface RedisLike {
22
+ set(key: string, value: Buffer | string, ...args: unknown[]): Promise<unknown>;
23
+ get(key: string): Promise<string | null>;
24
+ getBuffer(key: string): Promise<Buffer | null>;
25
+ del(...keys: string[]): Promise<number>;
26
+ sadd(key: string, ...members: string[]): Promise<number>;
27
+ smembers(key: string): Promise<string[]>;
28
+ expire(key: string, seconds: number): Promise<number>;
29
+ }
30
+ export interface RedisCacheOptions {
31
+ /** Redis client. */
32
+ client: RedisLike;
33
+ /**
34
+ * String prepended to every key (and tag set name) to namespace the
35
+ * cache. Recommended `${SERVICE_NAME}:${pkg.version}:` so a deploy of
36
+ * a new version can't read stale entries.
37
+ */
38
+ keyPrefix?: string;
39
+ /** Tag-set namespace prefix. Default `"tag:"`. */
40
+ tagPrefix?: string;
41
+ /**
42
+ * **Opt-in (F14) HMAC integrity key.** When set, every `set` /
43
+ * `setIfAbsent` writes `[0x01][HMAC-SHA256(key||msgpackrBytes)][msgpackrBytes]`
44
+ * into Redis; every `get` checks the MAC and returns `null`
45
+ * (deleting the poisoned entry in the background) on mismatch.
46
+ * Disabled by default — adopters running a dedicated Redis don't
47
+ * need it. Enable when the Redis tier is shared with untrusted
48
+ * clustermates (multi-tenant Redis, leaked password, co-located
49
+ * service with the Redis password).
50
+ *
51
+ * `defineEnv` is the recommended boundary: source from an env
52
+ * `CACHE_SIGNING_KEY` of ≥32 random bytes, rotate independently
53
+ * of JWT keys. The framework reads this once at construction;
54
+ * rotating means restarting the process with a new value.
55
+ *
56
+ * Documented in `.cursor/rules/security.mdc` (Cache section).
57
+ */
58
+ signingKey?: string;
59
+ }
60
+ export declare class RedisCache implements Cache {
61
+ private client;
62
+ private keyPrefix;
63
+ private tagPrefix;
64
+ private packr;
65
+ private signingKey?;
66
+ constructor(opts: RedisCacheOptions);
67
+ private k;
68
+ private t;
69
+ /**
70
+ * Wrap raw msgpackr bytes with the F14 signed frame when signing is
71
+ * enabled. The MAC binds the value to the namespaced key — an
72
+ * attacker who steals one key's signed payload cannot replay it
73
+ * under a different key.
74
+ */
75
+ private frame;
76
+ /**
77
+ * Unwrap a signed frame, verifying the MAC. Returns `null` (and
78
+ * fires a fire-and-forget delete of the offending key) on any
79
+ * mismatch — frame byte unrecognized, MAC truncated, MAC fails to
80
+ * verify, or signing was enabled but the value is unsigned (a
81
+ * pre-signing entry or a tampering attempt). When signing is
82
+ * disabled, returns the buffer as-is.
83
+ */
84
+ private unframe;
85
+ /**
86
+ * Best-effort delete of a poisoned entry. Run in the background so
87
+ * a failure (or a Redis hiccup) doesn't shadow the caller's
88
+ * read-returns-null semantics.
89
+ */
90
+ private dropPoisoned;
91
+ get<T = unknown>(key: string): Promise<T | null>;
92
+ setIfAbsent<T = unknown>(key: string, value: T, opts?: {
93
+ ttlSec?: number;
94
+ }): Promise<boolean>;
95
+ set<T = unknown>(key: string, value: T, opts?: CacheSetOptions): Promise<void>;
96
+ del(key: string | readonly string[]): Promise<void>;
97
+ invalidateTag(tag: string): Promise<void>;
98
+ }
99
+ //# sourceMappingURL=RedisCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RedisCache.d.ts","sourceRoot":"","sources":["../../../../src/app/services/cache/RedisCache.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAiBzD;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/E,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/C,GAAG,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACzD,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACvD;AAED,MAAM,WAAW,iBAAiB;IAChC,oBAAoB;IACpB,MAAM,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;;;;;;OAgBG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,UAAW,YAAW,KAAK;IACtC,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,KAAK,CAAkC;IAC/C,OAAO,CAAC,UAAU,CAAC,CAAS;gBAEhB,IAAI,EAAE,iBAAiB;IAYnC,OAAO,CAAC,CAAC;IAIT,OAAO,CAAC,CAAC;IAIT;;;;;OAKG;IACH,OAAO,CAAC,KAAK;IASb;;;;;;;OAOG;IACH,OAAO,CAAC,OAAO;IAuBf;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAId,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAShD,WAAW,CAAC,CAAC,GAAG,OAAO,EAC3B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,CAAC,EACR,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GAC7B,OAAO,CAAC,OAAO,CAAC;IAYb,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBlF,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnD,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAQhD"}
@@ -0,0 +1,150 @@
1
+ import { createHmac, timingSafeEqual } from "node:crypto";
2
+ import { Packr } from "msgpackr";
3
+ /**
4
+ * Frame version byte for HMAC-signed RedisCache values (F14). The
5
+ * first byte of a signed payload is one of these magic markers so
6
+ * `get()` can:
7
+ * - tell signed values from legacy unsigned ones (signing was
8
+ * introduced post-shipping; consumers may have old entries),
9
+ * - rotate the MAC scheme in a future release without breaking
10
+ * verifying caches.
11
+ *
12
+ * Layout (when signing enabled): `[FRAME_BYTE][32-byte MAC][msgpackr bytes]`
13
+ * Layout (when signing disabled): raw msgpackr bytes (unchanged).
14
+ */
15
+ const FRAME_SIGNED_V1 = 0x01;
16
+ const MAC_LENGTH = 32; // SHA-256 output
17
+ export class RedisCache {
18
+ client;
19
+ keyPrefix;
20
+ tagPrefix;
21
+ packr = new Packr({ moreTypes: true });
22
+ signingKey;
23
+ constructor(opts) {
24
+ this.client = opts.client;
25
+ this.keyPrefix = opts.keyPrefix ?? "";
26
+ this.tagPrefix = opts.tagPrefix ?? "tag:";
27
+ if (opts.signingKey) {
28
+ if (opts.signingKey.length < 32) {
29
+ throw new Error("RedisCache: signingKey must be at least 32 characters");
30
+ }
31
+ this.signingKey = Buffer.from(opts.signingKey, "utf8");
32
+ }
33
+ }
34
+ k(key) {
35
+ return this.keyPrefix + key;
36
+ }
37
+ t(tag) {
38
+ return this.keyPrefix + this.tagPrefix + tag;
39
+ }
40
+ /**
41
+ * Wrap raw msgpackr bytes with the F14 signed frame when signing is
42
+ * enabled. The MAC binds the value to the namespaced key — an
43
+ * attacker who steals one key's signed payload cannot replay it
44
+ * under a different key.
45
+ */
46
+ frame(namespacedKey, payload) {
47
+ if (!this.signingKey)
48
+ return payload;
49
+ const mac = createHmac("sha256", this.signingKey)
50
+ .update(namespacedKey)
51
+ .update(payload)
52
+ .digest();
53
+ return Buffer.concat([Buffer.from([FRAME_SIGNED_V1]), mac, payload]);
54
+ }
55
+ /**
56
+ * Unwrap a signed frame, verifying the MAC. Returns `null` (and
57
+ * fires a fire-and-forget delete of the offending key) on any
58
+ * mismatch — frame byte unrecognized, MAC truncated, MAC fails to
59
+ * verify, or signing was enabled but the value is unsigned (a
60
+ * pre-signing entry or a tampering attempt). When signing is
61
+ * disabled, returns the buffer as-is.
62
+ */
63
+ unframe(namespacedKey, buf) {
64
+ if (!this.signingKey)
65
+ return buf;
66
+ if (buf.length < 1 + MAC_LENGTH) {
67
+ this.dropPoisoned(namespacedKey);
68
+ return null;
69
+ }
70
+ if (buf[0] !== FRAME_SIGNED_V1) {
71
+ this.dropPoisoned(namespacedKey);
72
+ return null;
73
+ }
74
+ const mac = buf.subarray(1, 1 + MAC_LENGTH);
75
+ const payload = buf.subarray(1 + MAC_LENGTH);
76
+ const expected = createHmac("sha256", this.signingKey)
77
+ .update(namespacedKey)
78
+ .update(payload)
79
+ .digest();
80
+ if (mac.length !== expected.length || !timingSafeEqual(mac, expected)) {
81
+ this.dropPoisoned(namespacedKey);
82
+ return null;
83
+ }
84
+ return payload;
85
+ }
86
+ /**
87
+ * Best-effort delete of a poisoned entry. Run in the background so
88
+ * a failure (or a Redis hiccup) doesn't shadow the caller's
89
+ * read-returns-null semantics.
90
+ */
91
+ dropPoisoned(namespacedKey) {
92
+ void this.client.del(namespacedKey).catch(() => undefined);
93
+ }
94
+ async get(key) {
95
+ const namespacedKey = this.k(key);
96
+ const buf = await this.client.getBuffer(namespacedKey);
97
+ if (buf === null)
98
+ return null;
99
+ const unframed = this.unframe(namespacedKey, buf);
100
+ if (unframed === null)
101
+ return null;
102
+ return this.packr.unpack(unframed);
103
+ }
104
+ async setIfAbsent(key, value, opts = {}) {
105
+ const namespacedKey = this.k(key);
106
+ const payload = this.frame(namespacedKey, this.packr.pack(value));
107
+ const args = ["NX"];
108
+ if (opts.ttlSec !== undefined && opts.ttlSec > 0) {
109
+ args.push("EX", opts.ttlSec);
110
+ }
111
+ const result = await this.client.set(namespacedKey, payload, ...args);
112
+ // Real ioredis returns "OK" on success or null when the NX guard rejected.
113
+ return result === "OK";
114
+ }
115
+ async set(key, value, opts = {}) {
116
+ const namespacedKey = this.k(key);
117
+ const payload = this.frame(namespacedKey, this.packr.pack(value));
118
+ if (opts.ttlSec !== undefined && opts.ttlSec > 0) {
119
+ await this.client.set(namespacedKey, payload, "EX", opts.ttlSec);
120
+ }
121
+ else {
122
+ await this.client.set(namespacedKey, payload);
123
+ }
124
+ if (opts.tags && opts.tags.length > 0) {
125
+ for (const tag of opts.tags) {
126
+ const tagKey = this.t(tag);
127
+ await this.client.sadd(tagKey, namespacedKey);
128
+ // Match the value's TTL so tag bookkeeping doesn't outlive the data.
129
+ if (opts.ttlSec !== undefined && opts.ttlSec > 0) {
130
+ await this.client.expire(tagKey, opts.ttlSec);
131
+ }
132
+ }
133
+ }
134
+ }
135
+ async del(key) {
136
+ const keys = (Array.isArray(key) ? key : [key]).map((k) => this.k(k));
137
+ if (keys.length === 0)
138
+ return;
139
+ await this.client.del(...keys);
140
+ }
141
+ async invalidateTag(tag) {
142
+ const tagKey = this.t(tag);
143
+ const members = await this.client.smembers(tagKey);
144
+ if (members.length > 0) {
145
+ await this.client.del(...members);
146
+ }
147
+ await this.client.del(tagKey);
148
+ }
149
+ }
150
+ //# sourceMappingURL=RedisCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RedisCache.js","sourceRoot":"","sources":["../../../../src/app/services/cache/RedisCache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { Cache, CacheSetOptions } from "./Cache.js";
2
+ /**
3
+ * `cached(cache, key, ttlSec, fn, opts?)` — read-through cache helper.
4
+ *
5
+ * On cache hit, returns the stored value. On miss, runs `fn()`, stores the
6
+ * result with the supplied TTL + tags, and returns it.
7
+ *
8
+ * No promise coalescing — if N concurrent callers miss for the same key
9
+ * they all run `fn()` and the last write wins. Acceptable for idempotent
10
+ * read-through caching of expensive lookups; not safe for non-idempotent
11
+ * `fn()` (use a queue or distributed lock for those).
12
+ *
13
+ * `fn()` returning `undefined` skips the store step (treated as "do not
14
+ * cache"). `null` IS cached — it represents a known absence.
15
+ *
16
+ * @example
17
+ * const account = await cached(cache, `accounts:${id}`, 60, () =>
18
+ * accountService.getById(id),
19
+ * );
20
+ *
21
+ * @example
22
+ * const profile = await cached(
23
+ * cache, `profiles:${userId}`, 300,
24
+ * () => profileService.fetch(userId),
25
+ * { tags: [`user:${userId}`] },
26
+ * );
27
+ * // Later: cache.invalidateTag(`user:${userId}`) wipes everything tagged.
28
+ */
29
+ export declare function cached<T>(cache: Cache, key: string, ttlSec: number, fn: () => Promise<T> | T, opts?: Omit<CacheSetOptions, "ttlSec">): Promise<T>;
30
+ //# sourceMappingURL=cached.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cached.d.ts","sourceRoot":"","sources":["../../../../src/app/services/cache/cached.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,MAAM,CAAC,CAAC,EAC5B,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EACxB,IAAI,GAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAM,GACzC,OAAO,CAAC,CAAC,CAAC,CASZ"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * `cached(cache, key, ttlSec, fn, opts?)` — read-through cache helper.
3
+ *
4
+ * On cache hit, returns the stored value. On miss, runs `fn()`, stores the
5
+ * result with the supplied TTL + tags, and returns it.
6
+ *
7
+ * No promise coalescing — if N concurrent callers miss for the same key
8
+ * they all run `fn()` and the last write wins. Acceptable for idempotent
9
+ * read-through caching of expensive lookups; not safe for non-idempotent
10
+ * `fn()` (use a queue or distributed lock for those).
11
+ *
12
+ * `fn()` returning `undefined` skips the store step (treated as "do not
13
+ * cache"). `null` IS cached — it represents a known absence.
14
+ *
15
+ * @example
16
+ * const account = await cached(cache, `accounts:${id}`, 60, () =>
17
+ * accountService.getById(id),
18
+ * );
19
+ *
20
+ * @example
21
+ * const profile = await cached(
22
+ * cache, `profiles:${userId}`, 300,
23
+ * () => profileService.fetch(userId),
24
+ * { tags: [`user:${userId}`] },
25
+ * );
26
+ * // Later: cache.invalidateTag(`user:${userId}`) wipes everything tagged.
27
+ */
28
+ export async function cached(cache, key, ttlSec, fn, opts = {}) {
29
+ const hit = await cache.get(key);
30
+ if (hit !== null)
31
+ return hit;
32
+ const value = await fn();
33
+ if (value !== undefined) {
34
+ await cache.set(key, value, { ttlSec, tags: opts.tags });
35
+ }
36
+ return value;
37
+ }
38
+ //# sourceMappingURL=cached.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cached.js","sourceRoot":"","sources":["../../../../src/app/services/cache/cached.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,KAAY,EACZ,GAAW,EACX,MAAc,EACd,EAAwB,EACxB,OAAwC,EAAE;IAE1C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAI,GAAG,CAAC,CAAC;IACpC,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,GAAG,CAAC;IAE7B,MAAM,KAAK,GAAG,MAAM,EAAE,EAAE,CAAC;IACzB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,5 @@
1
+ export type { Cache, CacheSetOptions } from "./Cache.js";
2
+ export { cached } from "./cached.js";
3
+ export { InMemoryCache, type InMemoryCacheOptions } from "./InMemoryCache.js";
4
+ export { RedisCache, type RedisCacheOptions, type RedisLike } from "./RedisCache.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/app/services/cache/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { cached } from "./cached.js";
2
+ export { InMemoryCache } from "./InMemoryCache.js";
3
+ export { RedisCache } from "./RedisCache.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/app/services/cache/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,aAAa,EAA6B,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,UAAU,EAA0C,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,57 @@
1
+ import { type JobDefinition, type JobHandler } from "../jobs/defineJob.js";
2
+ /**
3
+ * `defineCron({ name, schedule, handler, options? })` — schema-driven
4
+ * cron registration via BullMQ repeatable jobs.
5
+ *
6
+ * Cron jobs ARE jobs — they live in the same `jobRegistry` and run on the
7
+ * same Worker as queued jobs. The differences are ergonomic:
8
+ *
9
+ * - One queue per process by default (`"cron"`), so the framework's
10
+ * worker picks them up automatically without having to declare a
11
+ * queue per cron task.
12
+ * - The handler doesn't receive a meaningful payload — just the
13
+ * run-context (job id, request context). Payload type is `void`.
14
+ * - The schedule is expressed at the top level, not nested under
15
+ * `options.schedule`.
16
+ *
17
+ * Files at `modules/<name>/cron/<cronName>.cron.ts` default-export a
18
+ * `defineCron(...)` call (convention enforced by `ship-api g cron`).
19
+ *
20
+ * @example
21
+ * import { defineCron } from "@sixthsummit/ship-api/app/services/cron";
22
+ *
23
+ * export default defineCron({
24
+ * name: "purge-stale-tokens",
25
+ * schedule: "0 2 * * *", // daily at 02:00 UTC
26
+ * handler: async (_payload, { job }) => {
27
+ * await refreshTokenService.purgeRevoked();
28
+ * job.log("done");
29
+ * },
30
+ * });
31
+ */
32
+ export interface DefineCronArgs {
33
+ /** Unique name within the cron queue. */
34
+ name: string;
35
+ /** Cron expression (BullMQ `repeat.pattern`). */
36
+ schedule: string;
37
+ /** Job handler — payload arg is `void` because cron jobs don't carry one. */
38
+ handler: JobHandler<void, unknown>;
39
+ /**
40
+ * Override the queue name. Default `"cron"` so a single Worker handles
41
+ * every cron task in the process. Set when you want a dedicated queue
42
+ * (e.g., low-priority cleanup vs high-priority billing).
43
+ */
44
+ queue?: string;
45
+ /** Optional timezone for the cron pattern (defaults to UTC). */
46
+ tz?: string;
47
+ /** BullMQ JobsOptions applied to each scheduled run. */
48
+ defaultJobOptions?: JobDefinition["options"] extends infer O ? O extends {
49
+ defaultJobOptions?: infer J;
50
+ } ? J : undefined : undefined;
51
+ }
52
+ /** Default queue name for cron tasks. */
53
+ export declare const CRON_QUEUE = "cron";
54
+ export declare function defineCron(args: DefineCronArgs, register?: {
55
+ add: (def: JobDefinition) => void;
56
+ } | false): JobDefinition<void, unknown>;
57
+ //# sourceMappingURL=defineCron.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defineCron.d.ts","sourceRoot":"","sources":["../../../../src/app/services/cron/defineCron.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,UAAU,EAGhB,MAAM,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,MAAM,WAAW,cAAc;IAC7B,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,OAAO,EAAE,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACnC;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,wDAAwD;IACxD,iBAAiB,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,SAAS,MAAM,CAAC,GACxD,CAAC,SAAS;QAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC,CAAA;KAAE,GACvC,CAAC,GACD,SAAS,GACX,SAAS,CAAC;CACf;AAED,yCAAyC;AACzC,eAAO,MAAM,UAAU,SAAS,CAAC;AAEjC,wBAAgB,UAAU,CACxB,IAAI,EAAE,cAAc,EACpB,QAAQ,GAAE;IAAE,GAAG,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,IAAI,CAAA;CAAE,GAAG,KAAmB,GACpE,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAa9B"}