@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,777 @@
1
+ # `libraries/email/` — Resend-backed transactional email
2
+
3
+ A type-safe email service built around [Resend](https://resend.com/), with a built-in template system (variable substitution, conditionals, loops), batch sending, scheduling, and tagging.
4
+
5
+ > **Install via**: `ship-api add -l email`. Pulls in the `resend` SDK; configure `RESEND_API_KEY` + `RESEND_DEFAULT_FROM` in your `.env`.
6
+
7
+ ## What's exported
8
+
9
+ - `EmailService` — the main service class
10
+ - `TemplateRegistry` — manages registered templates
11
+ - `TemplateRenderer` — renders a template with variables
12
+ - The full type set for `SendEmailOptions`, `EmailTemplate<TVars>`, batch payloads, etc.
13
+
14
+ ```ts
15
+ import {
16
+ EmailService,
17
+ TemplateRegistry,
18
+ TemplateRenderer,
19
+ type EmailTemplate,
20
+ type SendEmailOptions,
21
+ } from "@sixthsummit/ship-api/libraries/email";
22
+ ```
23
+
24
+ ## Installation
25
+
26
+ ## Configuration
27
+
28
+ ### Environment Variables
29
+
30
+ Add the following environment variables to your `.env` file:
31
+
32
+ ```bash
33
+ # Required: Resend API key
34
+ RESEND_API_KEY=re_your_api_key_here
35
+
36
+ # Optional: Default "from" email address
37
+ RESEND_DEFAULT_FROM=noreply@yourdomain.com
38
+ ```
39
+
40
+ ### Domain Setup
41
+
42
+ Before sending emails, you need to:
43
+
44
+ 1. Add and verify your domain in the [Resend dashboard](https://resend.com/domains)
45
+ 2. Configure DNS records (SPF, DKIM, DMARC)
46
+ 3. Use an email address from your verified domain as the sender
47
+
48
+ ## Quick Start
49
+
50
+ Construct the service once in your app's composition root (`src/index.ts`) and inject it into the modules and jobs that send mail:
51
+
52
+ ```typescript
53
+ // src/index.ts
54
+ import { EmailService } from "@sixthsummit/ship-api/libraries/email";
55
+ import { welcomeTemplate, passwordResetTemplate } from "./templates/index.js";
56
+ import { env } from "./environment.js";
57
+
58
+ const emailService = new EmailService(env.RESEND_API_KEY, env.RESEND_DEFAULT_FROM);
59
+ emailService.registerTemplates([welcomeTemplate, passwordResetTemplate]);
60
+
61
+ // Pass `emailService` into modules / jobs / route deps that need it.
62
+ ```
63
+
64
+ ### Sending via a registered template
65
+
66
+ ```typescript
67
+ await emailService.sendEmailWithTemplate({
68
+ templateId: "welcome",
69
+ to: "user@example.com",
70
+ variables: {
71
+ firstName: "John",
72
+ lastName: "Doe",
73
+ email: "john@example.com",
74
+ },
75
+ });
76
+ ```
77
+
78
+ ### Direct send (no template)
79
+
80
+ ```typescript
81
+ await emailService.sendEmail({
82
+ from: "noreply@yourdomain.com",
83
+ to: "user@example.com",
84
+ subject: "Welcome!",
85
+ text: "Welcome to our platform",
86
+ });
87
+ ```
88
+
89
+ ### HTML Email
90
+
91
+ ```typescript
92
+ await emailService.sendEmail({
93
+ from: "noreply@yourdomain.com",
94
+ to: "user@example.com",
95
+ subject: "Welcome!",
96
+ html: `
97
+ <h1>Welcome to our platform!</h1>
98
+ <p>We're excited to have you on board.</p>
99
+ `,
100
+ });
101
+ ```
102
+
103
+ ### Multiple Recipients
104
+
105
+ ```typescript
106
+ await emailService.sendEmail({
107
+ from: "noreply@yourdomain.com",
108
+ to: ["user1@example.com", "user2@example.com"],
109
+ subject: "Team Update",
110
+ html: "<p>Important team announcement</p>",
111
+ });
112
+ ```
113
+
114
+ ### Named Recipients
115
+
116
+ ```typescript
117
+ await emailService.sendEmail({
118
+ from: { name: "ShipAPI App", email: "noreply@yourdomain.com" },
119
+ to: [
120
+ { name: "John Doe", email: "john@example.com" },
121
+ { name: "Jane Smith", email: "jane@example.com" },
122
+ ],
123
+ subject: "Welcome Team!",
124
+ html: "<p>Welcome to the team!</p>",
125
+ });
126
+ ```
127
+
128
+ ### CC and BCC
129
+
130
+ ```typescript
131
+ await emailService.sendEmail({
132
+ from: "noreply@yourdomain.com",
133
+ to: "user@example.com",
134
+ cc: "manager@example.com",
135
+ bcc: ["audit@example.com", "compliance@example.com"],
136
+ subject: "Project Update",
137
+ html: "<p>Project status update</p>",
138
+ });
139
+ ```
140
+
141
+ ### Reply-To
142
+
143
+ ```typescript
144
+ await emailService.sendEmail({
145
+ from: "noreply@yourdomain.com",
146
+ to: "user@example.com",
147
+ replyTo: "support@yourdomain.com",
148
+ subject: "Need Help?",
149
+ html: "<p>Click reply if you need assistance</p>",
150
+ });
151
+ ```
152
+
153
+ ### Attachments
154
+
155
+ ```typescript
156
+ await emailService.sendEmail({
157
+ from: "noreply@yourdomain.com",
158
+ to: "user@example.com",
159
+ subject: "Invoice Attached",
160
+ html: "<p>Please find your invoice attached.</p>",
161
+ attachments: [
162
+ {
163
+ filename: "invoice.pdf",
164
+ content: pdfBuffer, // Buffer
165
+ contentType: "application/pdf",
166
+ },
167
+ {
168
+ filename: "logo.png",
169
+ content: "base64EncodedString", // Base64 string
170
+ contentType: "image/png",
171
+ },
172
+ ],
173
+ });
174
+ ```
175
+
176
+ ### Tags for Tracking
177
+
178
+ ```typescript
179
+ await emailService.sendEmail({
180
+ from: "noreply@yourdomain.com",
181
+ to: "user@example.com",
182
+ subject: "Welcome!",
183
+ html: "<p>Welcome email</p>",
184
+ tags: [
185
+ { name: "category", value: "onboarding" },
186
+ { name: "user_id", value: "12345" },
187
+ ],
188
+ });
189
+ ```
190
+
191
+ ### Custom Headers
192
+
193
+ ```typescript
194
+ await emailService.sendEmail({
195
+ from: "noreply@yourdomain.com",
196
+ to: "user@example.com",
197
+ subject: "Custom Headers",
198
+ html: "<p>Email with custom headers</p>",
199
+ headers: {
200
+ "X-Custom-Header": "custom-value",
201
+ "X-Priority": "1",
202
+ },
203
+ });
204
+ ```
205
+
206
+ ### Scheduled Emails
207
+
208
+ ```typescript
209
+ await emailService.sendEmail({
210
+ from: "noreply@yourdomain.com",
211
+ to: "user@example.com",
212
+ subject: "Scheduled Email",
213
+ html: "<p>This email was scheduled</p>",
214
+ scheduledAt: "2025-12-31T23:59:59Z", // ISO 8601 format
215
+ });
216
+ ```
217
+
218
+ ### Batch Emails
219
+
220
+ Send up to 100 emails in a single batch for better performance:
221
+
222
+ ```typescript
223
+ const results = await emailService.sendBatchEmails({
224
+ emails: [
225
+ {
226
+ from: "noreply@yourdomain.com",
227
+ to: "user1@example.com",
228
+ subject: "Welcome User 1",
229
+ html: "<p>Personalized welcome message</p>",
230
+ },
231
+ {
232
+ from: "noreply@yourdomain.com",
233
+ to: "user2@example.com",
234
+ subject: "Welcome User 2",
235
+ html: "<p>Personalized welcome message</p>",
236
+ },
237
+ // ... up to 100 emails
238
+ ],
239
+ });
240
+
241
+ // Check results
242
+ results.data?.forEach((result, index) => {
243
+ console.log(`Email ${index} sent with ID: ${result.id}`);
244
+ });
245
+ ```
246
+
247
+ ### Using Default From Address
248
+
249
+ ```typescript
250
+ // Set default from address in constructor
251
+ const emailService = new EmailService(undefined, "noreply@yourdomain.com");
252
+
253
+ // Now you can omit "from" in sendEmail
254
+ await emailService.sendEmail({
255
+ to: "user@example.com",
256
+ subject: "Welcome!",
257
+ text: "Welcome to our platform",
258
+ });
259
+
260
+ // Or set it later
261
+ emailService.setDefaultFrom("support@yourdomain.com");
262
+ ```
263
+
264
+ ## Email Templates
265
+
266
+ The email service includes a powerful template system that allows you to create reusable email templates with variable substitution, conditionals, and loops.
267
+
268
+ ### Using Templates
269
+
270
+ Register templates once at app startup (in `src/index.ts`), then use the configured `emailService` instance:
271
+
272
+ ```typescript
273
+ await emailService.sendEmailWithTemplate({
274
+ templateId: "welcome",
275
+ to: "user@example.com",
276
+ variables: {
277
+ firstName: "John",
278
+ lastName: "Doe",
279
+ email: "john@example.com",
280
+ activationUrl: "https://yourdomain.com/activate/token123",
281
+ },
282
+ });
283
+
284
+ // Send import completion email
285
+ await emailService.sendEmailWithTemplate({
286
+ templateId: "import-completion",
287
+ to: "user@example.com",
288
+ variables: {
289
+ firstName: "John",
290
+ importSource: "Twitter Followers",
291
+ processedCount: 100,
292
+ matchedAccountCount: 50,
293
+ createdAccountCount: 30,
294
+ matchedPersonCount: 40,
295
+ createdPersonCount: 20,
296
+ edgeCreatedCount: 80,
297
+ rejectedCount: 5,
298
+ viewImportUrl: "https://yourdomain.com/imports/123",
299
+ },
300
+ });
301
+ ```
302
+
303
+ ### Available Templates
304
+
305
+ The library ships with no pre-built templates — define your own per-module.
306
+
307
+ ### Creating Custom Templates
308
+
309
+ Templates live alongside the module that owns them, e.g. `modules/orders/templates/`:
310
+
311
+ **Step 1: Create the template file** (`modules/orders/templates/OrderConfirmationTemplate.ts`):
312
+
313
+ ```typescript
314
+ import type { EmailTemplate } from "@sixthsummit/ship-api/libraries/email";
315
+ import type { OrderConfirmationVariables } from "./types.js";
316
+
317
+ export const orderConfirmationTemplate: EmailTemplate<OrderConfirmationVariables> = {
318
+ id: "order-confirmation",
319
+ name: "Order Confirmation",
320
+ description: "Sent when a customer places an order",
321
+ subject: "Order Confirmation #{{orderNumber}}",
322
+ html: `
323
+ <h1>Thank you for your order, {{customerName}}!</h1>
324
+ <p>Order Number: {{orderNumber}}</p>
325
+ <p>Total: ${{total}}</p>
326
+
327
+ {{#if hasDiscount}}
328
+ <p>Discount Applied: {{discount}}%</p>
329
+ {{/if}}
330
+
331
+ <h2>Items:</h2>
332
+ <ul>
333
+ {{#each items}}
334
+ <li>{{this.name}} - ${{this.price}} x {{this.quantity}}</li>
335
+ {{/each}}
336
+ </ul>
337
+ `,
338
+ text: `...`,
339
+ tags: ["order", "confirmation"],
340
+ };
341
+ ```
342
+
343
+ **Step 2: Define type-safe variables** (`modules/orders/templates/types.ts`):
344
+
345
+ ```typescript
346
+ export interface OrderConfirmationVariables {
347
+ customerName: string;
348
+ orderNumber: string;
349
+ total: number;
350
+ hasDiscount?: boolean;
351
+ discount?: number;
352
+ items: Array<{
353
+ name: string;
354
+ price: number;
355
+ quantity: number;
356
+ }>;
357
+ }
358
+ ```
359
+
360
+ **Step 3: Export from module** (`modules/orders/templates/index.ts`):
361
+
362
+ ```typescript
363
+ import type { EmailTemplate } from "@sixthsummit/ship-api/libraries/email";
364
+ import { orderConfirmationTemplate } from "./OrderConfirmationTemplate.js";
365
+
366
+ export { orderConfirmationTemplate } from "./OrderConfirmationTemplate.js";
367
+ export * from "./types.js";
368
+
369
+ export const orderTemplates: EmailTemplate[] = [orderConfirmationTemplate];
370
+ ```
371
+
372
+ **Step 4: Register at app startup** (`src/index.ts`):
373
+
374
+ ```typescript
375
+ import { EmailService } from "@sixthsummit/ship-api/libraries/email";
376
+ import { orderTemplates } from "./modules/orders/templates/index.js";
377
+ import { userTemplates } from "./modules/users/templates/index.js";
378
+ import { env } from "./environment.js";
379
+
380
+ const emailService = new EmailService(env.RESEND_API_KEY, env.RESEND_DEFAULT_FROM);
381
+ emailService.registerTemplates([...userTemplates, ...orderTemplates]);
382
+ ```
383
+
384
+ **Step 5: Use the template**:
385
+
386
+ ```typescript
387
+ await emailService.sendEmailWithTemplate({
388
+ templateId: "order-confirmation",
389
+ to: "customer@example.com",
390
+ variables: {
391
+ customerName: "Jane Smith",
392
+ orderNumber: "ORD-12345",
393
+ total: 99.99,
394
+ hasDiscount: true,
395
+ discount: 10,
396
+ items: [
397
+ { name: "Product A", price: 49.99, quantity: 1 },
398
+ { name: "Product B", price: 49.99, quantity: 1 },
399
+ ],
400
+ },
401
+ });
402
+ ```
403
+
404
+ ### Template Syntax
405
+
406
+ #### Variable Substitution
407
+
408
+ ```typescript
409
+ // Simple variables
410
+ "Hello {{firstName}}!";
411
+
412
+ // Nested objects
413
+ "Email: {{user.email}}";
414
+
415
+ // Array indexing
416
+ "First item: {{items.0.name}}";
417
+ ```
418
+
419
+ #### Conditionals
420
+
421
+ ```typescript
422
+ // Show content if variable is truthy
423
+ `{{#if showWelcome}}
424
+ <p>Welcome!</p>
425
+ {{/if}}`
426
+ // Nested conditionals
427
+ `{{#if user.isActive}}
428
+ <p>Active user</p>
429
+ {{/if}}`;
430
+ ```
431
+
432
+ #### Loops
433
+
434
+ ```typescript
435
+ // Iterate over array
436
+ `{{#each items}}
437
+ <li>{{this.name}}</li>
438
+ {{/each}}`
439
+ // Access loop variables
440
+ `{{#each items}}
441
+ <li>{{@index}}: {{this.name}}</li>
442
+ {{#if @first}}(First){{/if}}
443
+ {{#if @last}}(Last){{/if}}
444
+ {{/each}}`;
445
+ ```
446
+
447
+ #### Helper Functions
448
+
449
+ ```typescript
450
+ // Format numbers with commas
451
+ "Total: {{formatNumber count}}";
452
+ // Output: "Total: 1,000,000"
453
+
454
+ // Format dates
455
+ "Date: {{formatDate date}}";
456
+ // Output: "Date: January 15, 2025"
457
+
458
+ // Pluralize based on count
459
+ "{{count}} {{pluralize count 'item' 'items'}}";
460
+ // Output: "1 item" or "5 items"
461
+ ```
462
+
463
+ ### Batch Sending with Templates
464
+
465
+ ```typescript
466
+ // Send multiple emails using templates
467
+ const results = await emailService.sendBatchEmailsWithTemplates([
468
+ {
469
+ templateId: "welcome",
470
+ to: "user1@example.com",
471
+ variables: { firstName: "John", lastName: "Doe", email: "user1@example.com" },
472
+ },
473
+ {
474
+ templateId: "welcome",
475
+ to: "user2@example.com",
476
+ variables: { firstName: "Jane", lastName: "Smith", email: "user2@example.com" },
477
+ },
478
+ ]);
479
+ ```
480
+
481
+ ### Template Management
482
+
483
+ ```typescript
484
+ // Register a single template
485
+ emailService.registerTemplate(template);
486
+
487
+ // Register multiple templates
488
+ emailService.registerTemplates([template1, template2, template3]);
489
+
490
+ // Check if template exists
491
+ if (emailService.hasTemplate("welcome")) {
492
+ // Template is available
493
+ }
494
+
495
+ // Get a template
496
+ const template = emailService.getTemplate("welcome");
497
+
498
+ // List all templates
499
+ const allTemplates = emailService.listTemplates();
500
+
501
+ // Render template without sending (for preview)
502
+ const rendered = emailService.renderTemplate({
503
+ templateId: "welcome",
504
+ variables: { firstName: "John", lastName: "Doe", email: "john@example.com" },
505
+ });
506
+ console.log(rendered.subject); // "Welcome to ShipAPI App, John!"
507
+ console.log(rendered.html); // Rendered HTML
508
+ console.log(rendered.text); // Rendered text
509
+ ```
510
+
511
+ ### Template Organization Best Practices
512
+
513
+ 1. **Module Ownership** - Each module owns its email templates
514
+ - User/auth templates: `modules/users/templates/`
515
+ - Import templates: `modules/imports/templates/`
516
+ - Order templates: `modules/orders/templates/`
517
+
518
+ 2. **Type Safety** - Define interfaces for template variables in `types.ts`
519
+
520
+ 3. **Centralized Registration** - Construct `EmailService` once in `src/index.ts` and register every module's templates against the same instance.
521
+
522
+ 4. **Consistent Structure** - Each module's templates directory should have:
523
+ - Individual template files (`WelcomeTemplate.ts`)
524
+ - Type definitions (`types.ts`)
525
+ - Barrel export (`index.ts`)
526
+
527
+ ### Why This Structure?
528
+
529
+ - **Cohesion**: Templates live with the domain logic they support
530
+ - **Modularity**: Removing a module removes its templates
531
+ - **Discoverability**: Easy to find templates related to a feature
532
+ - **Separation of Concerns**: Email library stays generic and reusable
533
+ - **Type Safety**: TypeScript ensures correct variable usage
534
+
535
+ ### Error Handling
536
+
537
+ ```typescript
538
+ const result = await emailService.sendEmail({
539
+ from: "noreply@yourdomain.com",
540
+ to: "user@example.com",
541
+ subject: "Welcome!",
542
+ text: "Welcome!",
543
+ });
544
+
545
+ if (result.error) {
546
+ console.error("Failed to send email:", result.error.message);
547
+ // Handle error (retry, log, notify, etc.)
548
+ } else {
549
+ console.log("Email sent successfully:", result.id);
550
+ // Store email ID for tracking
551
+ }
552
+ ```
553
+
554
+ ### Batch Error Handling
555
+
556
+ ```typescript
557
+ const results = await emailService.sendBatchEmails({
558
+ emails: [...],
559
+ });
560
+
561
+ if (results.error) {
562
+ console.error("Batch send failed:", results.error.message);
563
+ } else {
564
+ results.data?.forEach((result, index) => {
565
+ console.log(`Email ${index} sent with ID: ${result.id}`);
566
+ });
567
+ }
568
+ ```
569
+
570
+ ## Common Use Cases
571
+
572
+ ### Welcome Email
573
+
574
+ ```typescript
575
+ async function sendWelcomeEmail(user: { email: string; name: string }) {
576
+ const emailService = new EmailService();
577
+
578
+ return await emailService.sendEmail({
579
+ from: "noreply@yourdomain.com",
580
+ to: { name: user.name, email: user.email },
581
+ subject: "Welcome to ShipAPI App!",
582
+ html: `
583
+ <h1>Welcome, ${user.name}!</h1>
584
+ <p>We're excited to have you on board.</p>
585
+ <p>Get started by logging in to your account.</p>
586
+ `,
587
+ tags: [
588
+ { name: "type", value: "welcome" },
589
+ { name: "user_id", value: user.id },
590
+ ],
591
+ });
592
+ }
593
+ ```
594
+
595
+ ### Password Reset
596
+
597
+ ```typescript
598
+ async function sendPasswordResetEmail(user: { email: string }, resetToken: string) {
599
+ const emailService = new EmailService();
600
+ const resetUrl = `https://yourdomain.com/reset-password?token=${resetToken}`;
601
+
602
+ return await emailService.sendEmail({
603
+ from: "noreply@yourdomain.com",
604
+ to: user.email,
605
+ replyTo: "support@yourdomain.com",
606
+ subject: "Password Reset Request",
607
+ html: `
608
+ <h1>Password Reset</h1>
609
+ <p>Click the link below to reset your password:</p>
610
+ <a href="${resetUrl}">Reset Password</a>
611
+ <p>This link will expire in 1 hour.</p>
612
+ <p>If you didn't request this, please ignore this email.</p>
613
+ `,
614
+ tags: [{ name: "type", value: "password_reset" }],
615
+ });
616
+ }
617
+ ```
618
+
619
+ ### Bulk User Notifications
620
+
621
+ ```typescript
622
+ async function sendBulkNotifications(
623
+ users: Array<{ email: string; name: string }>,
624
+ message: string,
625
+ ) {
626
+ const emailService = new EmailService();
627
+
628
+ // Split into batches of 100
629
+ const batches = [];
630
+ for (let i = 0; i < users.length; i += 100) {
631
+ batches.push(users.slice(i, i + 100));
632
+ }
633
+
634
+ // Send each batch
635
+ for (const batch of batches) {
636
+ await emailService.sendBatchEmails({
637
+ emails: batch.map((user) => ({
638
+ from: "notifications@yourdomain.com",
639
+ to: { name: user.name, email: user.email },
640
+ subject: "Important Update",
641
+ html: `<p>Hi ${user.name},</p><p>${message}</p>`,
642
+ tags: [{ name: "type", value: "bulk_notification" }],
643
+ })),
644
+ });
645
+ }
646
+ }
647
+ ```
648
+
649
+ ## API Reference
650
+
651
+ ### `EmailService`
652
+
653
+ #### Constructor
654
+
655
+ ```typescript
656
+ new EmailService(
657
+ apiKey?: string,
658
+ defaultFrom?: string
659
+ )
660
+ ```
661
+
662
+ - `apiKey` - Optional Resend API key (defaults to `RESEND_API_KEY` environment variable)
663
+ - `defaultFrom` - Optional default "from" email address
664
+
665
+ **Note**: Templates are not auto-registered. Construct `EmailService` once at app startup (in `src/index.ts`) and call `registerTemplates([...])` with each module's template list.
666
+
667
+ #### Methods
668
+
669
+ ##### `sendEmail(options: SendEmailOptions): Promise<SendEmailResult>`
670
+
671
+ Send a single email.
672
+
673
+ ##### `sendBatchEmails(options: SendBatchEmailsOptions): Promise<SendBatchEmailsResult>`
674
+
675
+ Send multiple emails in a batch (max 100).
676
+
677
+ ##### `sendEmailWithTemplate<T>(options: RenderTemplateOptions<T> & EmailOptions): Promise<SendEmailResult>`
678
+
679
+ Send an email using a template.
680
+
681
+ ##### `sendBatchEmailsWithTemplates<T>(emails: Array<...>): Promise<SendBatchEmailsResult>`
682
+
683
+ Send multiple emails using templates.
684
+
685
+ ##### `registerTemplate<T>(template: EmailTemplate<T>): void`
686
+
687
+ Register an email template.
688
+
689
+ ##### `registerTemplates(templates: EmailTemplate[]): void`
690
+
691
+ Register multiple email templates.
692
+
693
+ ##### `getTemplate(id: string): EmailTemplate | undefined`
694
+
695
+ Get a registered template by ID.
696
+
697
+ ##### `listTemplates(): EmailTemplate[]`
698
+
699
+ List all registered templates.
700
+
701
+ ##### `hasTemplate(id: string): boolean`
702
+
703
+ Check if a template exists.
704
+
705
+ ##### `renderTemplate<T>(options: RenderTemplateOptions<T>): RenderedTemplate`
706
+
707
+ Render a template with variables (without sending).
708
+
709
+ ##### `getDefaultFrom(): string`
710
+
711
+ Get the default from address.
712
+
713
+ ##### `setDefaultFrom(defaultFrom: string): void`
714
+
715
+ Set the default from address.
716
+
717
+ ### Types
718
+
719
+ See [types/index.ts](./types/index.ts) for detailed type definitions.
720
+
721
+ ## Best Practices
722
+
723
+ ### Email Sending
724
+
725
+ 1. **Use Verified Domains** - Always send from verified domains to ensure deliverability
726
+ 2. **Handle Errors** - Always check for errors in the response and handle them appropriately
727
+ 3. **Use Tags** - Add tags to track email types and measure performance
728
+ 4. **Batch When Possible** - Use batch sending for better performance when sending multiple emails
729
+ 5. **Set Reply-To** - Always provide a reply-to address for customer support
730
+ 6. **Test Thoroughly** - Test emails in development before sending to production
731
+ 7. **Monitor Delivery** - Use Resend's dashboard to monitor email delivery and engagement
732
+
733
+ ### Template Usage
734
+
735
+ 8. **Use Templates** - Leverage templates for consistent branding and easier maintenance
736
+ 9. **Single Instance** - Construct `EmailService` once at app startup and inject it into the modules / jobs that need it; don't reconstruct per request
737
+ 10. **Type-Safe Variables** - Define interfaces for template variables to catch errors at compile time
738
+ 11. **Preview Templates** - Use `renderTemplate()` to preview emails before sending
739
+ 12. **Organize Templates** - Keep templates in their respective module directories
740
+ 13. **Version Control** - Keep templates in version control for tracking changes
741
+ 14. **Module Ownership** - Each module should own and maintain its email templates
742
+
743
+ ## Testing
744
+
745
+ When testing in development:
746
+
747
+ 1. Use Resend's test mode or a test domain
748
+ 2. Send to your own email addresses
749
+ 3. Check Resend dashboard for delivery status
750
+ 4. Verify email content in your inbox
751
+
752
+ ## Troubleshooting
753
+
754
+ ### "From address is required"
755
+
756
+ Make sure you either:
757
+
758
+ - Provide a `from` address in `sendEmail()` options
759
+ - Set a default from address in the constructor
760
+ - Set `RESEND_DEFAULT_FROM` environment variable
761
+
762
+ ### "Resend API key is required"
763
+
764
+ Make sure you have set the `RESEND_API_KEY` environment variable.
765
+
766
+ ### Email not delivered
767
+
768
+ 1. Check Resend dashboard for delivery status
769
+ 2. Verify your domain is properly configured
770
+ 3. Check spam folders
771
+ 4. Ensure recipient email addresses are valid
772
+
773
+ ## Resources
774
+
775
+ - [Resend Documentation](https://resend.com/docs)
776
+ - [Resend API Reference](https://resend.com/docs/api-reference)
777
+ - [Resend Node.js SDK](https://github.com/resendlabs/resend-node)