@hed-hog/core 0.0.398 → 0.0.400

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 (664) hide show
  1. package/dist/ai/ai-agent.sort.d.ts +6 -0
  2. package/dist/ai/ai-agent.sort.d.ts.map +1 -0
  3. package/dist/ai/ai-agent.sort.js +21 -0
  4. package/dist/ai/ai-agent.sort.js.map +1 -0
  5. package/dist/ai/ai.controller.d.ts +4 -4
  6. package/dist/ai/ai.service.d.ts +35 -4
  7. package/dist/ai/ai.service.d.ts.map +1 -1
  8. package/dist/ai/ai.service.js +51 -137
  9. package/dist/ai/ai.service.js.map +1 -1
  10. package/dist/ai-instruction/ai-instruction.service.d.ts.map +1 -1
  11. package/dist/ai-instruction/ai-instruction.service.js +26 -23
  12. package/dist/ai-instruction/ai-instruction.service.js.map +1 -1
  13. package/dist/ai-instruction/ai-instruction.sort.d.ts +16 -0
  14. package/dist/ai-instruction/ai-instruction.sort.d.ts.map +1 -0
  15. package/dist/ai-instruction/ai-instruction.sort.js +32 -0
  16. package/dist/ai-instruction/ai-instruction.sort.js.map +1 -0
  17. package/dist/auth/auth.controller.d.ts +24 -8
  18. package/dist/auth/auth.controller.d.ts.map +1 -1
  19. package/dist/auth/auth.module.d.ts.map +1 -1
  20. package/dist/auth/auth.module.js +8 -1
  21. package/dist/auth/auth.module.js.map +1 -1
  22. package/dist/auth/auth.service.d.ts +72 -25
  23. package/dist/auth/auth.service.d.ts.map +1 -1
  24. package/dist/auth/auth.service.js +41 -4
  25. package/dist/auth/auth.service.js.map +1 -1
  26. package/dist/auth/guards/auth.guard.d.ts +3 -1
  27. package/dist/auth/guards/auth.guard.d.ts.map +1 -1
  28. package/dist/auth/guards/auth.guard.js +12 -3
  29. package/dist/auth/guards/auth.guard.js.map +1 -1
  30. package/dist/authorize/authorize.controller.d.ts +30 -6
  31. package/dist/authorize/authorize.controller.d.ts.map +1 -1
  32. package/dist/authorize/authorize.controller.js +120 -13
  33. package/dist/authorize/authorize.controller.js.map +1 -1
  34. package/dist/authorize/authorize.errors.d.ts +34 -0
  35. package/dist/authorize/authorize.errors.d.ts.map +1 -0
  36. package/dist/authorize/authorize.errors.js +37 -0
  37. package/dist/authorize/authorize.errors.js.map +1 -0
  38. package/dist/authorize/authorize.module.d.ts.map +1 -1
  39. package/dist/authorize/authorize.module.js +6 -1
  40. package/dist/authorize/authorize.module.js.map +1 -1
  41. package/dist/authorize/authorize.service.d.ts +78 -4
  42. package/dist/authorize/authorize.service.d.ts.map +1 -1
  43. package/dist/authorize/authorize.service.js +212 -21
  44. package/dist/authorize/authorize.service.js.map +1 -1
  45. package/dist/authorize/dto/authorize-info.dto.d.ts +10 -1
  46. package/dist/authorize/dto/authorize-info.dto.d.ts.map +1 -1
  47. package/dist/authorize/dto/authorize-info.dto.js +16 -1
  48. package/dist/authorize/dto/authorize-info.dto.js.map +1 -1
  49. package/dist/authorize/dto/consent.dto.d.ts +10 -1
  50. package/dist/authorize/dto/consent.dto.d.ts.map +1 -1
  51. package/dist/authorize/dto/consent.dto.js +16 -1
  52. package/dist/authorize/dto/consent.dto.js.map +1 -1
  53. package/dist/authorize/dto/token.dto.d.ts +12 -0
  54. package/dist/authorize/dto/token.dto.d.ts.map +1 -1
  55. package/dist/authorize/dto/token.dto.js +21 -1
  56. package/dist/authorize/dto/token.dto.js.map +1 -1
  57. package/dist/authorize/oauth-exception.filter.d.ts +17 -0
  58. package/dist/authorize/oauth-exception.filter.d.ts.map +1 -0
  59. package/dist/authorize/oauth-exception.filter.js +54 -0
  60. package/dist/authorize/oauth-exception.filter.js.map +1 -0
  61. package/dist/authorize/oauth-metadata.service.d.ts +39 -0
  62. package/dist/authorize/oauth-metadata.service.d.ts.map +1 -0
  63. package/dist/authorize/oauth-metadata.service.js +81 -0
  64. package/dist/authorize/oauth-metadata.service.js.map +1 -0
  65. package/dist/authorize/well-known.controller.d.ts +67 -0
  66. package/dist/authorize/well-known.controller.d.ts.map +1 -0
  67. package/dist/authorize/well-known.controller.js +126 -0
  68. package/dist/authorize/well-known.controller.js.map +1 -0
  69. package/dist/captcha/captcha.service.d.ts +32 -2
  70. package/dist/captcha/captcha.service.d.ts.map +1 -1
  71. package/dist/captcha/captcha.service.js +85 -12
  72. package/dist/captcha/captcha.service.js.map +1 -1
  73. package/dist/challenge/challenge.service.d.ts +2 -2
  74. package/dist/core.module.d.ts.map +1 -1
  75. package/dist/core.module.js +6 -0
  76. package/dist/core.module.js.map +1 -1
  77. package/dist/dashboard/dashboard/dashboard.controller.d.ts +9 -9
  78. package/dist/dashboard/dashboard/dashboard.service.d.ts +9 -9
  79. package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +3 -3
  80. package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +3 -3
  81. package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts +3 -3
  82. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts +3 -3
  83. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts.map +1 -1
  84. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.js +2 -4
  85. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.js.map +1 -1
  86. package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.d.ts +8 -0
  87. package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.d.ts.map +1 -0
  88. package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.js +18 -0
  89. package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.js.map +1 -0
  90. package/dist/dashboard/dashboard-item/dashboard-item.service.d.ts.map +1 -1
  91. package/dist/dashboard/dashboard-item/dashboard-item.service.js +2 -4
  92. package/dist/dashboard/dashboard-item/dashboard-item.service.js.map +1 -1
  93. package/dist/dashboard/dashboard-item/dashboard-item.sort.d.ts +9 -0
  94. package/dist/dashboard/dashboard-item/dashboard-item.sort.d.ts.map +1 -0
  95. package/dist/dashboard/dashboard-item/dashboard-item.sort.js +19 -0
  96. package/dist/dashboard/dashboard-item/dashboard-item.sort.js.map +1 -0
  97. package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts +3 -3
  98. package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts +3 -3
  99. package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts.map +1 -1
  100. package/dist/dashboard/dashboard-role/dashboard-role.service.js +2 -4
  101. package/dist/dashboard/dashboard-role/dashboard-role.service.js.map +1 -1
  102. package/dist/dashboard/dashboard-role/dashboard-role.sort.d.ts +8 -0
  103. package/dist/dashboard/dashboard-role/dashboard-role.sort.d.ts.map +1 -0
  104. package/dist/dashboard/dashboard-role/dashboard-role.sort.js +16 -0
  105. package/dist/dashboard/dashboard-role/dashboard-role.sort.js.map +1 -0
  106. package/dist/file/file-upload-ticket.service.d.ts +160 -0
  107. package/dist/file/file-upload-ticket.service.d.ts.map +1 -0
  108. package/dist/file/file-upload-ticket.service.js +382 -0
  109. package/dist/file/file-upload-ticket.service.js.map +1 -0
  110. package/dist/file/file.controller.d.ts +24 -1
  111. package/dist/file/file.controller.d.ts.map +1 -1
  112. package/dist/file/file.controller.js +63 -2
  113. package/dist/file/file.controller.js.map +1 -1
  114. package/dist/file/file.module.d.ts.map +1 -1
  115. package/dist/file/file.module.js +14 -2
  116. package/dist/file/file.module.js.map +1 -1
  117. package/dist/file/file.service.d.ts +182 -6
  118. package/dist/file/file.service.d.ts.map +1 -1
  119. package/dist/file/file.service.js +385 -36
  120. package/dist/file/file.service.js.map +1 -1
  121. package/dist/file/filename-encoding.util.d.ts +24 -0
  122. package/dist/file/filename-encoding.util.d.ts.map +1 -0
  123. package/dist/file/filename-encoding.util.js +63 -0
  124. package/dist/file/filename-encoding.util.js.map +1 -0
  125. package/dist/file/image-optimization.service.d.ts +27 -0
  126. package/dist/file/image-optimization.service.d.ts.map +1 -1
  127. package/dist/file/image-optimization.service.js +63 -14
  128. package/dist/file/image-optimization.service.js.map +1 -1
  129. package/dist/file/mcp-file-source.schema.d.ts +33 -0
  130. package/dist/file/mcp-file-source.schema.d.ts.map +1 -0
  131. package/dist/file/mcp-file-source.schema.js +75 -0
  132. package/dist/file/mcp-file-source.schema.js.map +1 -0
  133. package/dist/file/mcp-file-source.service.d.ts +124 -0
  134. package/dist/file/mcp-file-source.service.d.ts.map +1 -0
  135. package/dist/file/mcp-file-source.service.js +262 -0
  136. package/dist/file/mcp-file-source.service.js.map +1 -0
  137. package/dist/file/mimetype-sniff.util.d.ts +62 -0
  138. package/dist/file/mimetype-sniff.util.d.ts.map +1 -0
  139. package/dist/file/mimetype-sniff.util.js +226 -0
  140. package/dist/file/mimetype-sniff.util.js.map +1 -0
  141. package/dist/file/remote-fetch.util.d.ts +35 -0
  142. package/dist/file/remote-fetch.util.d.ts.map +1 -0
  143. package/dist/file/remote-fetch.util.js +236 -0
  144. package/dist/file/remote-fetch.util.js.map +1 -0
  145. package/dist/impersonation/dto/start-impersonation.dto.d.ts +4 -1
  146. package/dist/impersonation/dto/start-impersonation.dto.d.ts.map +1 -1
  147. package/dist/impersonation/dto/start-impersonation.dto.js +1 -1
  148. package/dist/impersonation/dto/start-impersonation.dto.js.map +1 -1
  149. package/dist/impersonation/impersonation.service.d.ts +8 -3
  150. package/dist/impersonation/impersonation.service.d.ts.map +1 -1
  151. package/dist/impersonation/impersonation.service.js +14 -4
  152. package/dist/impersonation/impersonation.service.js.map +1 -1
  153. package/dist/incident/incident.controller.d.ts +2 -1
  154. package/dist/incident/incident.controller.d.ts.map +1 -1
  155. package/dist/incident/incident.controller.js +10 -6
  156. package/dist/incident/incident.controller.js.map +1 -1
  157. package/dist/incident/incident.service.d.ts +2 -0
  158. package/dist/incident/incident.service.d.ts.map +1 -1
  159. package/dist/incident/incident.service.js +4 -0
  160. package/dist/incident/incident.service.js.map +1 -1
  161. package/dist/index.d.ts +17 -0
  162. package/dist/index.d.ts.map +1 -1
  163. package/dist/index.js +17 -0
  164. package/dist/index.js.map +1 -1
  165. package/dist/integration-profile/integration-profile.secrets.d.ts.map +1 -1
  166. package/dist/integration-profile/integration-profile.secrets.js +7 -0
  167. package/dist/integration-profile/integration-profile.secrets.js.map +1 -1
  168. package/dist/integration-profile/integration-profile.service.d.ts +0 -13
  169. package/dist/integration-profile/integration-profile.service.d.ts.map +1 -1
  170. package/dist/integration-profile/integration-profile.service.js +5 -40
  171. package/dist/integration-profile/integration-profile.service.js.map +1 -1
  172. package/dist/integration-profile/integration-profile.utils.js +5 -5
  173. package/dist/integration-profile/integration-profile.utils.js.map +1 -1
  174. package/dist/integration-profile/testers/index.d.ts.map +1 -1
  175. package/dist/integration-profile/testers/index.js +2 -0
  176. package/dist/integration-profile/testers/index.js.map +1 -1
  177. package/dist/integration-profile/testers/shipping.testers.d.ts +3 -0
  178. package/dist/integration-profile/testers/shipping.testers.d.ts.map +1 -0
  179. package/dist/integration-profile/testers/shipping.testers.js +71 -0
  180. package/dist/integration-profile/testers/shipping.testers.js.map +1 -0
  181. package/dist/locale/locale.controller.d.ts +1 -1
  182. package/dist/locale/locale.service.d.ts +1 -1
  183. package/dist/mail/dto/send.dto.d.ts +6 -1
  184. package/dist/mail/dto/send.dto.d.ts.map +1 -1
  185. package/dist/mail/dto/send.dto.js.map +1 -1
  186. package/dist/mail/mail.service.d.ts +9 -0
  187. package/dist/mail/mail.service.d.ts.map +1 -1
  188. package/dist/mail/mail.service.js +34 -14
  189. package/dist/mail/mail.service.js.map +1 -1
  190. package/dist/mail-sent/mail-sent.controller.d.ts +1 -1
  191. package/dist/mail-sent/mail-sent.service.d.ts +1 -1
  192. package/dist/mail-sent/mail-sent.service.d.ts.map +1 -1
  193. package/dist/mail-sent/mail-sent.service.js +2 -1
  194. package/dist/mail-sent/mail-sent.service.js.map +1 -1
  195. package/dist/mail-sent/mail-sent.sort.d.ts +9 -0
  196. package/dist/mail-sent/mail-sent.sort.d.ts.map +1 -0
  197. package/dist/mail-sent/mail-sent.sort.js +19 -0
  198. package/dist/mail-sent/mail-sent.sort.js.map +1 -0
  199. package/dist/mcp/filters/mcp-challenge.filter.d.ts +20 -0
  200. package/dist/mcp/filters/mcp-challenge.filter.d.ts.map +1 -0
  201. package/dist/mcp/filters/mcp-challenge.filter.js +69 -0
  202. package/dist/mcp/filters/mcp-challenge.filter.js.map +1 -0
  203. package/dist/mcp/guards/mcp-auth.guard.d.ts +4 -1
  204. package/dist/mcp/guards/mcp-auth.guard.d.ts.map +1 -1
  205. package/dist/mcp/guards/mcp-auth.guard.js +19 -5
  206. package/dist/mcp/guards/mcp-auth.guard.js.map +1 -1
  207. package/dist/mcp/guards/mcp-permission.guard.d.ts +25 -3
  208. package/dist/mcp/guards/mcp-permission.guard.d.ts.map +1 -1
  209. package/dist/mcp/guards/mcp-permission.guard.js +46 -26
  210. package/dist/mcp/guards/mcp-permission.guard.js.map +1 -1
  211. package/dist/mcp/mcp-audit.service.d.ts +17 -0
  212. package/dist/mcp/mcp-audit.service.d.ts.map +1 -1
  213. package/dist/mcp/mcp-audit.service.js +32 -3
  214. package/dist/mcp/mcp-audit.service.js.map +1 -1
  215. package/dist/mcp/mcp-permission.service.d.ts +64 -0
  216. package/dist/mcp/mcp-permission.service.d.ts.map +1 -0
  217. package/dist/mcp/mcp-permission.service.js +178 -0
  218. package/dist/mcp/mcp-permission.service.js.map +1 -0
  219. package/dist/mcp/mcp-server.service.d.ts +3 -1
  220. package/dist/mcp/mcp-server.service.d.ts.map +1 -1
  221. package/dist/mcp/mcp-server.service.js +36 -15
  222. package/dist/mcp/mcp-server.service.js.map +1 -1
  223. package/dist/mcp/mcp.controller.d.ts.map +1 -1
  224. package/dist/mcp/mcp.controller.js +10 -2
  225. package/dist/mcp/mcp.controller.js.map +1 -1
  226. package/dist/mcp/mcp.module.d.ts.map +1 -1
  227. package/dist/mcp/mcp.module.js +5 -1
  228. package/dist/mcp/mcp.module.js.map +1 -1
  229. package/dist/mcp/tools/core-ai.mcp-tools.js +2 -9
  230. package/dist/mcp/tools/core-ai.mcp-tools.js.map +1 -1
  231. package/dist/mcp/tools/core-dashboard-items.mcp-tools.js +1 -1
  232. package/dist/mcp/tools/core-dashboard-items.mcp-tools.js.map +1 -1
  233. package/dist/mcp/tools/core-dashboard.mcp-tools.js +2 -9
  234. package/dist/mcp/tools/core-dashboard.mcp-tools.js.map +1 -1
  235. package/dist/mcp/tools/core-event-webhooks.mcp-tools.d.ts.map +1 -1
  236. package/dist/mcp/tools/core-event-webhooks.mcp-tools.js +2 -10
  237. package/dist/mcp/tools/core-event-webhooks.mcp-tools.js.map +1 -1
  238. package/dist/mcp/tools/core-files.mcp-tools.d.ts +17 -5
  239. package/dist/mcp/tools/core-files.mcp-tools.d.ts.map +1 -1
  240. package/dist/mcp/tools/core-files.mcp-tools.js +186 -24
  241. package/dist/mcp/tools/core-files.mcp-tools.js.map +1 -1
  242. package/dist/mcp/tools/core-integration-events.mcp-tools.js +2 -9
  243. package/dist/mcp/tools/core-integration-events.mcp-tools.js.map +1 -1
  244. package/dist/mcp/tools/core-mail-sent.mcp-tools.js +2 -14
  245. package/dist/mcp/tools/core-mail-sent.mcp-tools.js.map +1 -1
  246. package/dist/mcp/tools/core-mail.mcp-tools.js +2 -9
  247. package/dist/mcp/tools/core-mail.mcp-tools.js.map +1 -1
  248. package/dist/mcp/tools/core-menus.mcp-tools.d.ts.map +1 -1
  249. package/dist/mcp/tools/core-menus.mcp-tools.js +2 -10
  250. package/dist/mcp/tools/core-menus.mcp-tools.js.map +1 -1
  251. package/dist/mcp/tools/core-notifications.mcp-tools.d.ts.map +1 -1
  252. package/dist/mcp/tools/core-notifications.mcp-tools.js +0 -1
  253. package/dist/mcp/tools/core-notifications.mcp-tools.js.map +1 -1
  254. package/dist/mcp/tools/core-roles.mcp-tools.d.ts.map +1 -1
  255. package/dist/mcp/tools/core-roles.mcp-tools.js +2 -13
  256. package/dist/mcp/tools/core-roles.mcp-tools.js.map +1 -1
  257. package/dist/mcp/tools/core-routes.mcp-tools.d.ts.map +1 -1
  258. package/dist/mcp/tools/core-routes.mcp-tools.js +2 -11
  259. package/dist/mcp/tools/core-routes.mcp-tools.js.map +1 -1
  260. package/dist/mcp/tools/core-screens.mcp-tools.d.ts.map +1 -1
  261. package/dist/mcp/tools/core-screens.mcp-tools.js +2 -11
  262. package/dist/mcp/tools/core-screens.mcp-tools.js.map +1 -1
  263. package/dist/mcp/tools/core-sessions.mcp-tools.d.ts.map +1 -1
  264. package/dist/mcp/tools/core-sessions.mcp-tools.js +0 -2
  265. package/dist/mcp/tools/core-sessions.mcp-tools.js.map +1 -1
  266. package/dist/mcp/tools/core-settings.mcp-tools.d.ts.map +1 -1
  267. package/dist/mcp/tools/core-settings.mcp-tools.js +2 -10
  268. package/dist/mcp/tools/core-settings.mcp-tools.js.map +1 -1
  269. package/dist/mcp/tools/core-users.mcp-tools.js +2 -9
  270. package/dist/mcp/tools/core-users.mcp-tools.js.map +1 -1
  271. package/dist/mcp/tools/core-webhooks.mcp-tools.d.ts.map +1 -1
  272. package/dist/mcp/tools/core-webhooks.mcp-tools.js +2 -10
  273. package/dist/mcp/tools/core-webhooks.mcp-tools.js.map +1 -1
  274. package/dist/mcp/types/mcp-context.type.d.ts +9 -0
  275. package/dist/mcp/types/mcp-context.type.d.ts.map +1 -1
  276. package/dist/mcp-chat/mcp-chat.service.d.ts.map +1 -1
  277. package/dist/mcp-chat/mcp-chat.service.js +8 -0
  278. package/dist/mcp-chat/mcp-chat.service.js.map +1 -1
  279. package/dist/meeting/meeting-provider.registry.d.ts +115 -0
  280. package/dist/meeting/meeting-provider.registry.d.ts.map +1 -1
  281. package/dist/meeting/meeting-provider.registry.js.map +1 -1
  282. package/dist/meeting/meeting.constants.d.ts +70 -0
  283. package/dist/meeting/meeting.constants.d.ts.map +1 -1
  284. package/dist/meeting/meeting.constants.js +9 -1
  285. package/dist/meeting/meeting.constants.js.map +1 -1
  286. package/dist/menu/menu.service.d.ts.map +1 -1
  287. package/dist/menu/menu.service.js +29 -9
  288. package/dist/menu/menu.service.js.map +1 -1
  289. package/dist/message-template/dto/update-message-template.dto.d.ts +18 -0
  290. package/dist/message-template/dto/update-message-template.dto.d.ts.map +1 -0
  291. package/dist/message-template/dto/update-message-template.dto.js +38 -0
  292. package/dist/message-template/dto/update-message-template.dto.js.map +1 -0
  293. package/dist/message-template/message-template-admin.service.d.ts +70 -0
  294. package/dist/message-template/message-template-admin.service.d.ts.map +1 -0
  295. package/dist/message-template/message-template-admin.service.js +226 -0
  296. package/dist/message-template/message-template-admin.service.js.map +1 -0
  297. package/dist/message-template/message-template.controller.d.ts +29 -0
  298. package/dist/message-template/message-template.controller.d.ts.map +1 -0
  299. package/dist/message-template/message-template.controller.js +101 -0
  300. package/dist/message-template/message-template.controller.js.map +1 -0
  301. package/dist/message-template/message-template.module.d.ts +10 -0
  302. package/dist/message-template/message-template.module.d.ts.map +1 -0
  303. package/dist/message-template/message-template.module.js +33 -0
  304. package/dist/message-template/message-template.module.js.map +1 -0
  305. package/dist/message-template/message-template.registry.d.ts +55 -0
  306. package/dist/message-template/message-template.registry.d.ts.map +1 -0
  307. package/dist/message-template/message-template.registry.js +64 -0
  308. package/dist/message-template/message-template.registry.js.map +1 -0
  309. package/dist/message-template/message-template.service.d.ts +59 -0
  310. package/dist/message-template/message-template.service.d.ts.map +1 -0
  311. package/dist/message-template/message-template.service.js +166 -0
  312. package/dist/message-template/message-template.service.js.map +1 -0
  313. package/dist/notification/notification.constants.d.ts +11 -0
  314. package/dist/notification/notification.constants.d.ts.map +1 -0
  315. package/dist/notification/notification.constants.js +14 -0
  316. package/dist/notification/notification.constants.js.map +1 -0
  317. package/dist/notification/notification.controller.d.ts +20 -20
  318. package/dist/notification/notification.module.d.ts.map +1 -1
  319. package/dist/notification/notification.module.js +3 -0
  320. package/dist/notification/notification.module.js.map +1 -1
  321. package/dist/notification/notification.service.d.ts +33 -21
  322. package/dist/notification/notification.service.d.ts.map +1 -1
  323. package/dist/notification/notification.service.js +36 -2
  324. package/dist/notification/notification.service.js.map +1 -1
  325. package/dist/oauth/oauth.controller.d.ts +4 -6
  326. package/dist/oauth/oauth.controller.d.ts.map +1 -1
  327. package/dist/oauth/oauth.controller.js +0 -1
  328. package/dist/oauth/oauth.controller.js.map +1 -1
  329. package/dist/oauth/oauth.errors.d.ts +15 -1
  330. package/dist/oauth/oauth.errors.d.ts.map +1 -1
  331. package/dist/oauth/oauth.errors.js +9 -1
  332. package/dist/oauth/oauth.errors.js.map +1 -1
  333. package/dist/oauth/oauth.module.d.ts.map +1 -1
  334. package/dist/oauth/oauth.module.js +6 -1
  335. package/dist/oauth/oauth.module.js.map +1 -1
  336. package/dist/oauth/oauth.service.d.ts +25 -5
  337. package/dist/oauth/oauth.service.d.ts.map +1 -1
  338. package/dist/oauth/oauth.service.js +63 -27
  339. package/dist/oauth/oauth.service.js.map +1 -1
  340. package/dist/oauth/providers/abstract.provider.d.ts +10 -0
  341. package/dist/oauth/providers/abstract.provider.d.ts.map +1 -1
  342. package/dist/oauth/providers/abstract.provider.js +39 -12
  343. package/dist/oauth/providers/abstract.provider.js.map +1 -1
  344. package/dist/oauth/providers/github.provider.d.ts +1 -1
  345. package/dist/oauth/providers/github.provider.d.ts.map +1 -1
  346. package/dist/oauth/providers/github.provider.js +48 -22
  347. package/dist/oauth/providers/github.provider.js.map +1 -1
  348. package/dist/oauth/providers/microsoft-entra-id.provider.d.ts.map +1 -1
  349. package/dist/oauth/providers/microsoft-entra-id.provider.js +6 -0
  350. package/dist/oauth/providers/microsoft-entra-id.provider.js.map +1 -1
  351. package/dist/observability/monitored-cron.d.ts +29 -12
  352. package/dist/observability/monitored-cron.d.ts.map +1 -1
  353. package/dist/observability/monitored-cron.js +131 -46
  354. package/dist/observability/monitored-cron.js.map +1 -1
  355. package/dist/pairing/pairing.controller.d.ts +9 -9
  356. package/dist/pairing/pairing.service.d.ts +15 -11
  357. package/dist/pairing/pairing.service.d.ts.map +1 -1
  358. package/dist/profile/dto/change-password.dto.d.ts.map +1 -1
  359. package/dist/profile/dto/change-password.dto.js +4 -6
  360. package/dist/profile/dto/change-password.dto.js.map +1 -1
  361. package/dist/profile/profile.controller.d.ts +1 -1
  362. package/dist/profile/profile.service.d.ts +1 -1
  363. package/dist/profile/profile.service.d.ts.map +1 -1
  364. package/dist/profile/profile.service.js +9 -3
  365. package/dist/profile/profile.service.js.map +1 -1
  366. package/dist/realtime/realtime-tick.coalescer.d.ts +34 -0
  367. package/dist/realtime/realtime-tick.coalescer.d.ts.map +1 -0
  368. package/dist/realtime/realtime-tick.coalescer.js +60 -0
  369. package/dist/realtime/realtime-tick.coalescer.js.map +1 -0
  370. package/dist/realtime/realtime.service.d.ts +2 -0
  371. package/dist/realtime/realtime.service.d.ts.map +1 -1
  372. package/dist/realtime/realtime.service.js +22 -2
  373. package/dist/realtime/realtime.service.js.map +1 -1
  374. package/dist/redis/redis-kv.service.d.ts +90 -0
  375. package/dist/redis/redis-kv.service.d.ts.map +1 -0
  376. package/dist/redis/redis-kv.service.js +247 -0
  377. package/dist/redis/redis-kv.service.js.map +1 -0
  378. package/dist/redis/redis-master.d.ts +29 -0
  379. package/dist/redis/redis-master.d.ts.map +1 -0
  380. package/dist/redis/redis-master.js +81 -0
  381. package/dist/redis/redis-master.js.map +1 -0
  382. package/dist/redis/redis-pubsub.d.ts +12 -0
  383. package/dist/redis/redis-pubsub.d.ts.map +1 -1
  384. package/dist/redis/redis-pubsub.js +25 -2
  385. package/dist/redis/redis-pubsub.js.map +1 -1
  386. package/dist/redis/redis.module.d.ts +11 -0
  387. package/dist/redis/redis.module.d.ts.map +1 -0
  388. package/dist/redis/redis.module.js +30 -0
  389. package/dist/redis/redis.module.js.map +1 -0
  390. package/dist/session/session.controller.d.ts +6 -2
  391. package/dist/session/session.controller.d.ts.map +1 -1
  392. package/dist/session/session.service.d.ts +118 -15
  393. package/dist/session/session.service.d.ts.map +1 -1
  394. package/dist/session/session.service.js +251 -77
  395. package/dist/session/session.service.js.map +1 -1
  396. package/dist/setting/setting.controller.d.ts +5 -0
  397. package/dist/setting/setting.controller.d.ts.map +1 -1
  398. package/dist/setting/setting.service.d.ts +7 -0
  399. package/dist/setting/setting.service.d.ts.map +1 -1
  400. package/dist/setting/setting.service.js +38 -3
  401. package/dist/setting/setting.service.js.map +1 -1
  402. package/dist/task/task.service.d.ts +17 -0
  403. package/dist/task/task.service.d.ts.map +1 -1
  404. package/dist/task/task.service.js +48 -13
  405. package/dist/task/task.service.js.map +1 -1
  406. package/dist/token/token.service.d.ts +19 -1
  407. package/dist/token/token.service.d.ts.map +1 -1
  408. package/dist/token/token.service.js +39 -2
  409. package/dist/token/token.service.js.map +1 -1
  410. package/dist/user/user-credential.util.d.ts +10 -0
  411. package/dist/user/user-credential.util.d.ts.map +1 -1
  412. package/dist/user/user-credential.util.js +14 -1
  413. package/dist/user/user-credential.util.js.map +1 -1
  414. package/dist/user/user.service.d.ts +12 -4
  415. package/dist/user/user.service.d.ts.map +1 -1
  416. package/dist/user/user.service.js +2 -11
  417. package/dist/user/user.service.js.map +1 -1
  418. package/dist/user/user.sort.d.ts +16 -0
  419. package/dist/user/user.sort.d.ts.map +1 -0
  420. package/dist/user/user.sort.js +25 -0
  421. package/dist/user/user.sort.js.map +1 -0
  422. package/dist/utils/abbreviate-name.d.ts +13 -0
  423. package/dist/utils/abbreviate-name.d.ts.map +1 -0
  424. package/dist/utils/abbreviate-name.js +42 -0
  425. package/dist/utils/abbreviate-name.js.map +1 -0
  426. package/dist/utils/date-range-query.dto.d.ts +11 -0
  427. package/dist/utils/date-range-query.dto.d.ts.map +1 -0
  428. package/dist/utils/date-range-query.dto.js +63 -0
  429. package/dist/utils/date-range-query.dto.js.map +1 -0
  430. package/dist/utils/date-range.d.ts +96 -0
  431. package/dist/utils/date-range.d.ts.map +1 -0
  432. package/dist/utils/date-range.js +172 -0
  433. package/dist/utils/date-range.js.map +1 -0
  434. package/dist/webhook-integration/webhook-utils.d.ts.map +1 -1
  435. package/dist/webhook-integration/webhook-utils.js +24 -0
  436. package/dist/webhook-integration/webhook-utils.js.map +1 -1
  437. package/dist/whatsapp-sender/whatsapp-recipients.d.ts +49 -0
  438. package/dist/whatsapp-sender/whatsapp-recipients.d.ts.map +1 -0
  439. package/dist/whatsapp-sender/whatsapp-recipients.js +66 -0
  440. package/dist/whatsapp-sender/whatsapp-recipients.js.map +1 -0
  441. package/dist/whatsapp-sender/whatsapp-sender.service.d.ts +25 -0
  442. package/dist/whatsapp-sender/whatsapp-sender.service.d.ts.map +1 -1
  443. package/dist/whatsapp-sender/whatsapp-sender.service.js +46 -5
  444. package/dist/whatsapp-sender/whatsapp-sender.service.js.map +1 -1
  445. package/hedhog/data/integration_provider.yaml +9 -0
  446. package/hedhog/data/integration_type.yaml +6 -0
  447. package/hedhog/data/locale.yaml +0 -1
  448. package/hedhog/data/mail.yaml +2 -2
  449. package/hedhog/data/mail_layout.yaml +6 -3
  450. package/hedhog/data/menu.yaml +25 -5
  451. package/hedhog/data/route.yaml +140 -0
  452. package/hedhog/data/setting_group.yaml +137 -3
  453. package/hedhog/frontend/app/access-log/page.tsx.ejs +47 -53
  454. package/hedhog/frontend/app/account/components/active-sessions.tsx.ejs +33 -8
  455. package/hedhog/frontend/app/account/components/mcp-tokens.tsx.ejs +54 -13
  456. package/hedhog/frontend/app/account/components/mfa-method-card.tsx.ejs +7 -1
  457. package/hedhog/frontend/app/account/components/recovery-codes-dialog.tsx.ejs +1 -0
  458. package/hedhog/frontend/app/account/components/tokens.tsx.ejs +47 -17
  459. package/hedhog/frontend/app/ai_agent/page.tsx.ejs +46 -5
  460. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-form.tsx.ejs +101 -30
  461. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-versions.tsx.ejs +24 -8
  462. package/hedhog/frontend/app/ai_instruction/page.tsx.ejs +80 -15
  463. package/hedhog/frontend/app/configurations/[slug]/components/image-optimization-action.tsx.ejs +166 -0
  464. package/hedhog/frontend/app/configurations/[slug]/components/setting-field.test.tsx.ejs +145 -45
  465. package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +99 -219
  466. package/hedhog/frontend/app/configurations/[slug]/page.tsx.ejs +19 -1
  467. package/hedhog/frontend/app/configurations/layout.tsx.ejs +19 -5
  468. package/hedhog/frontend/app/dashboard/[slug]/widget-renderer.tsx.ejs +2 -8
  469. package/hedhog/frontend/app/dashboard/components/dynamic-widget.tsx.ejs +3 -0
  470. package/hedhog/frontend/app/dashboard/components/widget-wrapper.tsx.ejs +4 -0
  471. package/hedhog/frontend/app/dashboard/dashboard-home-tabs.tsx.ejs +43 -44
  472. package/hedhog/frontend/app/dashboard/management/tabs/component-roles-tab.tsx.ejs +41 -3
  473. package/hedhog/frontend/app/dashboard/management/tabs/components-tab.tsx.ejs +42 -2
  474. package/hedhog/frontend/app/dashboard/management/tabs/dashboard-roles-tab.tsx.ejs +41 -3
  475. package/hedhog/frontend/app/dashboard/management/tabs/dashboards-tab.tsx.ejs +39 -4
  476. package/hedhog/frontend/app/dashboard/management/tabs/items-tab.tsx.ejs +42 -3
  477. package/hedhog/frontend/app/incidents/page.tsx.ejs +60 -31
  478. package/hedhog/frontend/app/integration/profiles/page.tsx.ejs +45 -5
  479. package/hedhog/frontend/app/integrations-webhooks/page.tsx.ejs +92 -15
  480. package/hedhog/frontend/app/mail/log/page.tsx.ejs +109 -61
  481. package/hedhog/frontend/app/mail/template/page.tsx.ejs +125 -23
  482. package/hedhog/frontend/app/mcp_chat/chat-components.tsx.ejs +13 -15
  483. package/hedhog/frontend/app/mcp_chat/page.tsx.ejs +116 -110
  484. package/hedhog/frontend/app/message-templates/_components/message-template-sheet.tsx.ejs +245 -0
  485. package/hedhog/frontend/app/message-templates/_lib/types.ts.ejs +24 -0
  486. package/hedhog/frontend/app/message-templates/page.tsx.ejs +182 -0
  487. package/hedhog/frontend/app/pages/_components/page-wizard-sheet.tsx.ejs +1 -0
  488. package/hedhog/frontend/app/pages/page.tsx.ejs +94 -9
  489. package/hedhog/frontend/app/roles/menus.tsx.ejs +4 -4
  490. package/hedhog/frontend/app/roles/routes.tsx.ejs +4 -4
  491. package/hedhog/frontend/app/roles/users.tsx.ejs +4 -4
  492. package/hedhog/frontend/app/setting-list/page.tsx.ejs +71 -9
  493. package/hedhog/frontend/app/users/page.tsx.ejs +77 -67
  494. package/hedhog/frontend/messages/en.json +183 -36
  495. package/hedhog/frontend/messages/pt.json +183 -36
  496. package/hedhog/table/cron_lock.yaml +17 -0
  497. package/hedhog/table/file.yaml +13 -1
  498. package/hedhog/table/file_upload_chunk.yaml +23 -0
  499. package/hedhog/table/file_upload_ticket.yaml +67 -0
  500. package/hedhog/table/mcp_tool_call_log.yaml +30 -22
  501. package/hedhog/table/message_template.yaml +33 -0
  502. package/hedhog/table/setting.yaml +8 -0
  503. package/hedhog/table/user_session.yaml +36 -1
  504. package/package.json +8 -6
  505. package/src/ai/ai-agent.sort.ts +21 -0
  506. package/src/ai/ai.service.spec.ts +173 -1
  507. package/src/ai/ai.service.ts +64 -193
  508. package/src/ai-instruction/ai-instruction.service.ts +32 -28
  509. package/src/ai-instruction/ai-instruction.sort.ts +32 -0
  510. package/src/auth/auth.module.ts +8 -1
  511. package/src/auth/auth.service.spec.ts +108 -1
  512. package/src/auth/auth.service.ts +59 -5
  513. package/src/auth/guards/auth.guard.ts +9 -1
  514. package/src/authorize/authorize.controller.ts +126 -11
  515. package/src/authorize/authorize.errors.ts +55 -0
  516. package/src/authorize/authorize.module.ts +6 -1
  517. package/src/authorize/authorize.service.spec.ts +379 -7
  518. package/src/authorize/authorize.service.ts +309 -23
  519. package/src/authorize/dto/authorize-info.dto.ts +21 -3
  520. package/src/authorize/dto/consent.dto.ts +21 -3
  521. package/src/authorize/dto/token.dto.ts +24 -2
  522. package/src/authorize/oauth-exception.filter.ts +58 -0
  523. package/src/authorize/oauth-metadata.service.ts +67 -0
  524. package/src/authorize/well-known.controller.spec.ts +84 -0
  525. package/src/authorize/well-known.controller.ts +96 -0
  526. package/src/captcha/captcha.service.spec.ts +211 -4
  527. package/src/captcha/captcha.service.ts +127 -10
  528. package/src/core.module.ts +6 -0
  529. package/src/dashboard/dashboard-component-role/dashboard-component-role.service.ts +2 -3
  530. package/src/dashboard/dashboard-component-role/dashboard-component-role.sort.ts +18 -0
  531. package/src/dashboard/dashboard-item/dashboard-item.service.ts +2 -3
  532. package/src/dashboard/dashboard-item/dashboard-item.sort.ts +19 -0
  533. package/src/dashboard/dashboard-role/dashboard-role.service.ts +2 -3
  534. package/src/dashboard/dashboard-role/dashboard-role.sort.ts +16 -0
  535. package/src/file/file-upload-ticket.service.spec.ts +422 -0
  536. package/src/file/file-upload-ticket.service.ts +513 -0
  537. package/src/file/file.controller.ts +65 -0
  538. package/src/file/file.module.ts +14 -2
  539. package/src/file/file.service.spec.ts +94 -0
  540. package/src/file/file.service.ts +432 -30
  541. package/src/file/filename-encoding.util.spec.ts +54 -0
  542. package/src/file/filename-encoding.util.ts +67 -0
  543. package/src/file/image-optimization.service.spec.ts +156 -19
  544. package/src/file/image-optimization.service.ts +106 -21
  545. package/src/file/mcp-file-source.schema.ts +83 -0
  546. package/src/file/mcp-file-source.service.spec.ts +473 -0
  547. package/src/file/mcp-file-source.service.ts +445 -0
  548. package/src/file/mimetype-sniff.util.spec.ts +126 -0
  549. package/src/file/mimetype-sniff.util.ts +265 -0
  550. package/src/file/remote-fetch.util.spec.ts +117 -0
  551. package/src/file/remote-fetch.util.ts +330 -0
  552. package/src/impersonation/dto/start-impersonation.dto.ts +5 -2
  553. package/src/impersonation/impersonation.service.spec.ts +24 -1
  554. package/src/impersonation/impersonation.service.ts +14 -4
  555. package/src/incident/incident.controller.ts +9 -1
  556. package/src/incident/incident.service.ts +7 -0
  557. package/src/index.ts +17 -0
  558. package/src/integration-profile/integration-profile.secrets.ts +7 -0
  559. package/src/integration-profile/integration-profile.service.ts +7 -64
  560. package/src/integration-profile/integration-profile.utils.spec.ts +9 -0
  561. package/src/integration-profile/integration-profile.utils.ts +5 -5
  562. package/src/integration-profile/testers/index.ts +2 -0
  563. package/src/integration-profile/testers/remaining.testers.spec.ts +79 -0
  564. package/src/integration-profile/testers/shipping.testers.ts +94 -0
  565. package/src/mail/dto/send.dto.ts +6 -1
  566. package/src/mail/mail-template.spec.ts +58 -1
  567. package/src/mail/mail.service.spec.ts +112 -0
  568. package/src/mail/mail.service.ts +42 -4
  569. package/src/mail-sent/mail-sent.service.ts +3 -0
  570. package/src/mail-sent/mail-sent.sort.ts +19 -0
  571. package/src/mcp/filters/mcp-challenge.filter.spec.ts +76 -0
  572. package/src/mcp/filters/mcp-challenge.filter.ts +70 -0
  573. package/src/mcp/guards/mcp-auth.guard.spec.ts +51 -2
  574. package/src/mcp/guards/mcp-auth.guard.ts +24 -1
  575. package/src/mcp/guards/mcp-permission.guard.spec.ts +109 -15
  576. package/src/mcp/guards/mcp-permission.guard.ts +76 -51
  577. package/src/mcp/mcp-audit.service.spec.ts +107 -0
  578. package/src/mcp/mcp-audit.service.ts +37 -1
  579. package/src/mcp/mcp-permission.service.spec.ts +197 -0
  580. package/src/mcp/mcp-permission.service.ts +184 -0
  581. package/src/mcp/mcp-server.service.spec.ts +84 -2
  582. package/src/mcp/mcp-server.service.ts +111 -87
  583. package/src/mcp/mcp.controller.ts +8 -1
  584. package/src/mcp/mcp.module.ts +5 -1
  585. package/src/mcp/tools/core-ai.mcp-tools.ts +1 -1
  586. package/src/mcp/tools/core-dashboard-items.mcp-tools.ts +1 -1
  587. package/src/mcp/tools/core-dashboard.mcp-tools.ts +1 -1
  588. package/src/mcp/tools/core-event-webhooks.mcp-tools.ts +1 -2
  589. package/src/mcp/tools/core-files.mcp-tools.ts +202 -22
  590. package/src/mcp/tools/core-integration-events.mcp-tools.ts +1 -1
  591. package/src/mcp/tools/core-mail-sent.mcp-tools.ts +1 -1
  592. package/src/mcp/tools/core-mail.mcp-tools.ts +1 -1
  593. package/src/mcp/tools/core-menus.mcp-tools.ts +1 -2
  594. package/src/mcp/tools/core-notifications.mcp-tools.ts +0 -1
  595. package/src/mcp/tools/core-roles.mcp-tools.ts +1 -5
  596. package/src/mcp/tools/core-routes.mcp-tools.ts +1 -3
  597. package/src/mcp/tools/core-screens.mcp-tools.ts +1 -3
  598. package/src/mcp/tools/core-sessions.mcp-tools.ts +0 -2
  599. package/src/mcp/tools/core-settings.mcp-tools.ts +1 -2
  600. package/src/mcp/tools/core-users.mcp-tools.ts +1 -1
  601. package/src/mcp/tools/core-webhooks.mcp-tools.ts +1 -2
  602. package/src/mcp/types/mcp-context.type.ts +15 -6
  603. package/src/mcp-chat/mcp-chat.service.ts +8 -0
  604. package/src/meeting/meeting-provider.registry.ts +121 -0
  605. package/src/meeting/meeting.constants.ts +74 -0
  606. package/src/menu/menu.service.spec.ts +89 -0
  607. package/src/menu/menu.service.ts +29 -11
  608. package/src/message-template/dto/update-message-template.dto.ts +22 -0
  609. package/src/message-template/message-template-admin.service.spec.ts +163 -0
  610. package/src/message-template/message-template-admin.service.ts +239 -0
  611. package/src/message-template/message-template.controller.ts +52 -0
  612. package/src/message-template/message-template.module.ts +21 -0
  613. package/src/message-template/message-template.registry.spec.ts +62 -0
  614. package/src/message-template/message-template.registry.ts +125 -0
  615. package/src/message-template/message-template.service.spec.ts +149 -0
  616. package/src/message-template/message-template.service.ts +149 -0
  617. package/src/notification/notification.constants.ts +10 -0
  618. package/src/notification/notification.module.ts +3 -0
  619. package/src/notification/notification.service.spec.ts +75 -1
  620. package/src/notification/notification.service.ts +39 -1
  621. package/src/oauth/oauth.controller.ts +0 -1
  622. package/src/oauth/oauth.errors.ts +7 -0
  623. package/src/oauth/oauth.module.ts +6 -1
  624. package/src/oauth/oauth.service.spec.ts +58 -7
  625. package/src/oauth/oauth.service.ts +71 -32
  626. package/src/oauth/providers/abstract.provider.spec.ts +192 -0
  627. package/src/oauth/providers/abstract.provider.ts +46 -14
  628. package/src/oauth/providers/github.provider.ts +57 -34
  629. package/src/oauth/providers/microsoft-entra-id.provider.ts +8 -1
  630. package/src/observability/monitored-cron.spec.ts +164 -31
  631. package/src/observability/monitored-cron.ts +154 -62
  632. package/src/profile/dto/change-password.dto.ts +25 -7
  633. package/src/profile/profile.service.spec.ts +97 -0
  634. package/src/profile/profile.service.ts +9 -3
  635. package/src/realtime/realtime-tick.coalescer.spec.ts +92 -0
  636. package/src/realtime/realtime-tick.coalescer.ts +60 -0
  637. package/src/realtime/realtime.service.spec.ts +33 -0
  638. package/src/realtime/realtime.service.ts +28 -2
  639. package/src/redis/redis-kv.service.ts +261 -0
  640. package/src/redis/redis-master.spec.ts +111 -0
  641. package/src/redis/redis-master.ts +86 -0
  642. package/src/redis/redis-pubsub.ts +27 -3
  643. package/src/redis/redis.module.ts +17 -0
  644. package/src/session/session.service.spec.ts +121 -42
  645. package/src/session/session.service.ts +279 -82
  646. package/src/setting/setting.service.ts +44 -3
  647. package/src/task/task.service.spec.ts +41 -0
  648. package/src/task/task.service.ts +53 -13
  649. package/src/token/token.service.spec.ts +90 -0
  650. package/src/token/token.service.ts +48 -2
  651. package/src/user/user-credential.util.ts +14 -5
  652. package/src/user/user.service.ts +2 -12
  653. package/src/user/user.sort.ts +25 -0
  654. package/src/utils/abbreviate-name.spec.ts +50 -0
  655. package/src/utils/abbreviate-name.ts +44 -0
  656. package/src/utils/date-range-query.dto.ts +56 -0
  657. package/src/utils/date-range.spec.ts +175 -0
  658. package/src/utils/date-range.ts +246 -0
  659. package/src/webhook-integration/webhook-utils.spec.ts +67 -0
  660. package/src/webhook-integration/webhook-utils.ts +26 -0
  661. package/src/whatsapp-sender/whatsapp-recipients.spec.ts +89 -0
  662. package/src/whatsapp-sender/whatsapp-recipients.ts +83 -0
  663. package/src/whatsapp-sender/whatsapp-sender.service.spec.ts +112 -0
  664. package/src/whatsapp-sender/whatsapp-sender.service.ts +58 -5
@@ -27,7 +27,7 @@ export function buildMailConfigFromIntegration(
27
27
  clientId: String(cfg.client_id ?? ''),
28
28
  clientSecret: String(cfg.client_secret ?? ''),
29
29
  refreshToken: String(cfg.refresh_token ?? ''),
30
- from: String(cfg.from_email ?? ''),
30
+ from: String(cfg.from_email ?? '').trim(),
31
31
  };
32
32
  case 'ses':
33
33
  return {
@@ -36,7 +36,7 @@ export function buildMailConfigFromIntegration(
36
36
  region: String(cfg.region ?? ''),
37
37
  accessKeyId: String(cfg.access_key_id ?? ''),
38
38
  secretAccessKey: String(cfg.secret_access_key ?? ''),
39
- from: String(cfg.from_email ?? ''),
39
+ from: String(cfg.from_email ?? '').trim(),
40
40
  };
41
41
  case 'resend':
42
42
  // Resend usa a API HTTP própria (não nodemailer). Retornamos um marcador
@@ -48,7 +48,7 @@ export function buildMailConfigFromIntegration(
48
48
  apiToken: String(cfg.api_token ?? ''),
49
49
  domain: String(cfg.domain ?? ''),
50
50
  region: String(cfg.region ?? ''),
51
- from: String(cfg.from_email ?? ''),
51
+ from: String(cfg.from_email ?? '').trim(),
52
52
  };
53
53
  case 'imap':
54
54
  // Sem este caso o operador que apontasse o perfil de envio para uma caixa
@@ -123,8 +123,8 @@ export function buildResendConfigFromIntegration(
123
123
 
124
124
  export function getFromAddress(config: unknown): string {
125
125
  const cfg = (config as Cfg) ?? {};
126
- const fromEmail = String(cfg.from_email ?? '');
127
- const fromName = String(cfg.from_name ?? '');
126
+ const fromEmail = String(cfg.from_email ?? '').trim();
127
+ const fromName = String(cfg.from_name ?? '').trim();
128
128
  return fromName ? `${fromName} <${fromEmail}>` : fromEmail;
129
129
  }
130
130
 
@@ -6,6 +6,7 @@ import { IntegrationTester } from './integration-tester.types';
6
6
  import { MESSAGING_TESTERS } from './messaging.testers';
7
7
  import { OAUTH_TESTERS } from './oauth.testers';
8
8
  import { PAYMENT_TESTERS } from './payment.testers';
9
+ import { SHIPPING_TESTERS } from './shipping.testers';
9
10
  import { STORAGE_TESTERS } from './storage.testers';
10
11
 
11
12
  /**
@@ -23,6 +24,7 @@ export const BUILTIN_INTEGRATION_TESTERS: IntegrationTester[] = [
23
24
  ...PAYMENT_TESTERS,
24
25
  ...CAPTCHA_TESTERS,
25
26
  ...INFRASTRUCTURE_TESTERS,
27
+ ...SHIPPING_TESTERS,
26
28
  ];
27
29
 
28
30
  export * from './http-probe';
@@ -5,6 +5,7 @@ import { EMAIL_TESTERS } from './email.testers';
5
5
  import { INFRASTRUCTURE_TESTERS } from './infrastructure.testers';
6
6
  import { MESSAGING_TESTERS } from './messaging.testers';
7
7
  import { PAYMENT_TESTERS } from './payment.testers';
8
+ import { SHIPPING_TESTERS } from './shipping.testers';
8
9
  import { IntegrationTestContext, IntegrationTester } from './integration-tester.types';
9
10
 
10
11
  /**
@@ -19,6 +20,7 @@ const all = [
19
20
  ...AI_TESTERS,
20
21
  ...PAYMENT_TESTERS,
21
22
  ...INFRASTRUCTURE_TESTERS,
23
+ ...SHIPPING_TESTERS,
22
24
  ];
23
25
 
24
26
  const bySlug = (slug: string): IntegrationTester =>
@@ -444,3 +446,80 @@ describe('digitalocean tester', () => {
444
446
  });
445
447
  });
446
448
  });
449
+
450
+ describe('melhor-envio tester', () => {
451
+ const tester = bySlug('melhor-envio');
452
+ const account = { firstname: 'Ana', lastname: 'Souza', email: 'ana@acme.com' };
453
+
454
+ it('identifica a conta e o ambiente de produção', async () => {
455
+ fetchMock.mockResolvedValue(jsonResponse(account));
456
+
457
+ await expect(tester.test({ access_token: 'tok' }, ctx())).resolves.toEqual({
458
+ ok: true,
459
+ info: 'Ana Souza — ana@acme.com (production)',
460
+ });
461
+
462
+ const [url, init] = fetchMock.mock.calls[0] as [string, RequestInit];
463
+ expect(url).toBe('https://melhorenvio.com.br/api/v2/me');
464
+ const headers = init.headers as Record<string, string>;
465
+ expect(headers.Authorization).toBe('Bearer tok');
466
+ // Sem User-Agent identificável o Melhor Envio recusa a requisição.
467
+ expect(headers['User-Agent']).toBe('HedHog Commerce');
468
+ });
469
+
470
+ it('usa a base de sandbox e avisa que o preço não é real', async () => {
471
+ fetchMock.mockResolvedValue(jsonResponse(account));
472
+
473
+ const outcome = await tester.test(
474
+ { access_token: 'tok', sandbox: true, user_agent: 'Loja (contato@acme.com)' },
475
+ ctx(),
476
+ );
477
+
478
+ expect(outcome.ok).toBe(true);
479
+ expect(outcome.info).toContain('(sandbox)');
480
+ expect(outcome.warning).toContain('not real prices');
481
+
482
+ const [url, init] = fetchMock.mock.calls[0] as [string, RequestInit];
483
+ expect(url).toBe('https://sandbox.melhorenvio.com.br/api/v2/me');
484
+ expect((init.headers as Record<string, string>)['User-Agent']).toBe(
485
+ 'Loja (contato@acme.com)',
486
+ );
487
+ });
488
+
489
+ it('aceita a string "true" que o formulário do admin grava', async () => {
490
+ fetchMock.mockResolvedValue(jsonResponse(account));
491
+
492
+ await tester.test({ access_token: 'tok', sandbox: 'true' }, ctx());
493
+
494
+ const [url] = fetchMock.mock.calls[0] as [string];
495
+ expect(url).toBe('https://sandbox.melhorenvio.com.br/api/v2/me');
496
+ });
497
+
498
+ it('aponta o switch de sandbox no 401, que é o erro mais comum', async () => {
499
+ fetchMock.mockResolvedValue(jsonResponse({}, 401));
500
+
501
+ const outcome = await tester.test({ access_token: 'tok' }, ctx());
502
+
503
+ expect(outcome.ok).toBe(false);
504
+ expect(outcome.error).toContain('in production');
505
+ expect(outcome.error).toContain('sandbox switch');
506
+ });
507
+
508
+ it('distingue falta de escopo (403) de token inválido', async () => {
509
+ fetchMock.mockResolvedValue(jsonResponse({}, 403));
510
+
511
+ await expect(tester.test({ access_token: 'tok' }, ctx())).resolves.toEqual({
512
+ ok: false,
513
+ error:
514
+ 'The Melhor Envio token has no permission to read the account. Reissue it including the shipping scopes.',
515
+ });
516
+ });
517
+
518
+ it('exige o token antes de ir à rede', async () => {
519
+ await expect(tester.test({}, ctx())).resolves.toEqual({
520
+ ok: false,
521
+ error: 'Access token is required.',
522
+ });
523
+ expect(fetchMock).not.toHaveBeenCalled();
524
+ });
525
+ });
@@ -0,0 +1,94 @@
1
+ import {
2
+ describeHttpError,
3
+ fail,
4
+ pass,
5
+ probeJson,
6
+ requireFields,
7
+ str,
8
+ } from './http-probe';
9
+ import { IntegrationTester } from './integration-tester.types';
10
+
11
+ /**
12
+ * Testadores das transportadoras / intermediadores de frete.
13
+ *
14
+ * Só leitura da conta: nada aqui gera etiqueta, compra postagem ou mexe no saldo
15
+ * da carteira — mesmo princípio dos testers de pagamento.
16
+ */
17
+
18
+ /**
19
+ * Sandbox e produção são contas SEPARADAS no Melhor Envio, cada uma com o seu
20
+ * token. Trocar o switch sem trocar o token devolve 401, então a resolução da
21
+ * base tem que ser idêntica à do consumidor
22
+ * (libraries/commerce/src/commerce-shipping/melhor-envio.provider.ts) — senão o
23
+ * teste valida um ambiente e a loja cota no outro.
24
+ */
25
+ function resolveBaseUrl(config: Record<string, unknown>): {
26
+ baseUrl: string;
27
+ sandbox: boolean;
28
+ } {
29
+ // Aceita boolean do JSON e a string do formulário do admin.
30
+ const sandbox = config.sandbox === true || String(config.sandbox ?? '') === 'true';
31
+ return {
32
+ sandbox,
33
+ baseUrl: sandbox
34
+ ? 'https://sandbox.melhorenvio.com.br'
35
+ : 'https://melhorenvio.com.br',
36
+ };
37
+ }
38
+
39
+ const melhorEnvioTester: IntegrationTester = {
40
+ providerSlug: 'melhor-envio',
41
+ test: async (config, ctx) => {
42
+ const missing = requireFields(config, [['access_token', 'Access token']]);
43
+ if (missing) return missing;
44
+
45
+ const { baseUrl, sandbox } = resolveBaseUrl(config);
46
+ const environment = sandbox ? 'sandbox' : 'production';
47
+
48
+ const result = await probeJson(
49
+ `${baseUrl}/api/v2/me`,
50
+ {
51
+ headers: {
52
+ Authorization: `Bearer ${str(config, 'access_token')}`,
53
+ Accept: 'application/json',
54
+ // Sem User-Agent identificável o Melhor Envio recusa a requisição, e o
55
+ // teste falharia por etiqueta faltando em vez de credencial errada.
56
+ 'User-Agent': str(config, 'user_agent') || 'HedHog Commerce',
57
+ },
58
+ },
59
+ ctx.signal,
60
+ );
61
+
62
+ if (result.status === 401) {
63
+ // O erro mais comum não é token digitado errado: é token de sandbox num
64
+ // perfil de produção (ou o contrário), porque são contas diferentes.
65
+ return fail(
66
+ `Melhor Envio rejected the access token in ${environment}. Check the token and the sandbox switch — sandbox and production are separate accounts.`,
67
+ );
68
+ }
69
+ if (result.status === 403) {
70
+ return fail(
71
+ 'The Melhor Envio token has no permission to read the account. Reissue it including the shipping scopes.',
72
+ );
73
+ }
74
+ if (!result.ok) {
75
+ return fail(describeHttpError(result, 'Melhor Envio rejected the credentials.'));
76
+ }
77
+
78
+ const name = [result.body?.firstname, result.body?.lastname]
79
+ .map((part) => String(part ?? '').trim())
80
+ .filter(Boolean)
81
+ .join(' ');
82
+ const email = String(result.body?.email ?? '').trim();
83
+ const account = [name, email].filter(Boolean).join(' — ') || 'Melhor Envio account';
84
+
85
+ return pass(
86
+ `${account} (${environment})`,
87
+ // Cotação de sandbox tem preço fictício: passar despercebido significa loja
88
+ // no ar vendendo frete que não existe.
89
+ sandbox ? 'This profile points to the sandbox, so quotes are not real prices.' : undefined,
90
+ );
91
+ },
92
+ };
93
+
94
+ export const SHIPPING_TESTERS: IntegrationTester[] = [melhorEnvioTester];
@@ -10,8 +10,13 @@ export class SendTemplatedMailDTO {
10
10
  @IsNotEmpty({ message: (args) => getLocaleText('validation.fieldRequired', args.value) })
11
11
  slug: string;
12
12
 
13
+ /**
14
+ * Contexto do Handlebars. Nao e so string: o corpo do e-mail e compilado com
15
+ * Handlebars de verdade, entao um array aqui alimenta `{{#each}}` no template
16
+ * (e o resumo do aluno usa isso para a grade de sequencia da semana).
17
+ */
13
18
  @IsObject({ message: (args) => getLocaleText('validation.objectRequired', args.value) })
14
- variables: Record<string, string>;
19
+ variables: Record<string, unknown>;
15
20
 
16
21
  /**
17
22
  * Slug do perfil de integração de e-mail a usar neste envio.
@@ -1,5 +1,10 @@
1
1
  import { describe, it, expect } from '@jest/globals';
2
- import { DEFAULT_MAIL_LAYOUT, renderMailTemplate, resolveMailAssetUrl } from '@hed-hog/api-mail';
2
+ import {
3
+ DEFAULT_MAIL_LAYOUT,
4
+ renderMailTemplate,
5
+ resolveMailAssetUrl,
6
+ sanitizeAccentColor,
7
+ } from '@hed-hog/api-mail';
3
8
 
4
9
  // Testes do renderizador de e-mail moram aqui (e nao em packages/api-mail)
5
10
  // porque o api-mail nao tem jest configurado; o jest do core resolve o pacote.
@@ -249,6 +254,58 @@ describe('renderMailTemplate', () => {
249
254
  });
250
255
  });
251
256
 
257
+ describe('cor da etapa (accentColor)', () => {
258
+ // O commerce manda uma cor por etapa da compra; as demais libraries nao
259
+ // mandam nada e precisam continuar exatamente como estavam.
260
+ it('pinta a barra de destaque com a cor da etapa', () => {
261
+ const html = renderMailTemplate({
262
+ subject: 'Pagamento confirmado',
263
+ body: '<p>Ola</p>',
264
+ primaryColor: '#111827',
265
+ accentColor: '#16a34a',
266
+ });
267
+
268
+ expect(html).toContain('background:#16a34a;');
269
+ expect(html).toContain('background: #16a34a;');
270
+ });
271
+
272
+ it('cai na cor da marca quando nenhuma etapa e informada', () => {
273
+ const html = renderMailTemplate({
274
+ subject: 'Recuperar senha',
275
+ body: '<p>Ola</p>',
276
+ primaryColor: '#1465b8',
277
+ });
278
+
279
+ expect(html).toContain('background:#1465b8;');
280
+ expect(html).not.toContain('{{accentColor}}');
281
+ });
282
+
283
+ // O valor e interpolado dentro do bloco <style> do wrapper: string livre ali
284
+ // fecharia a regra e reescreveria o layout inteiro.
285
+ it('ignora cor fora do formato #rrggbb', () => {
286
+ const html = renderMailTemplate({
287
+ subject: 'Oi',
288
+ body: '<p>Ola</p>',
289
+ primaryColor: '#1465b8',
290
+ accentColor: 'red;} body { display:none } .x {',
291
+ });
292
+
293
+ expect(html).not.toContain('display:none');
294
+ expect(html).toContain('background:#1465b8;');
295
+ });
296
+
297
+ it('sanitizeAccentColor aceita so hexadecimal de 6 digitos', () => {
298
+ expect(sanitizeAccentColor('#16a34a')).toBe('#16a34a');
299
+ expect(sanitizeAccentColor(' #ABCDEF ')).toBe('#ABCDEF');
300
+ expect(sanitizeAccentColor('#abc')).toBeUndefined();
301
+ expect(sanitizeAccentColor('green')).toBeUndefined();
302
+ expect(sanitizeAccentColor('#16a34a;')).toBeUndefined();
303
+ expect(sanitizeAccentColor('')).toBeUndefined();
304
+ expect(sanitizeAccentColor(undefined)).toBeUndefined();
305
+ expect(sanitizeAccentColor(null)).toBeUndefined();
306
+ });
307
+ });
308
+
252
309
  describe('resolveMailAssetUrl', () => {
253
310
  it('mantem URLs ja absolutas ou data: intactas', () => {
254
311
  expect(resolveMailAssetUrl('https://cdn.example.com/logo.svg', 'http://localhost:3100')).toBe(
@@ -82,11 +82,45 @@ describe('MailService', () => {
82
82
  expect(call('A\r\nB', {})).toBe('A<br/>B');
83
83
  });
84
84
 
85
+ it('preserva as quebras de linha de um documento HTML completo (não injeta <br/> dentro de <style>/<head>)', () => {
86
+ // Bug real: um HTML completo colado em Templates de e-mail (que
87
+ // funciona no preview cru de Campanhas) aparecia quebrado aqui porque
88
+ // toda quebra de linha virava "<br/>" literal mesmo dentro de <style>,
89
+ // invalidando o CSS antes de chegar em renderMailTemplate.
90
+ const fullHtml =
91
+ '<!DOCTYPE html>\n<html>\n<head>\n<style>\n.foo {\n color: red;\n}\n</style>\n</head>\n<body>{{name}}</body>\n</html>';
92
+ const result = call(fullHtml, { name: 'Bob' });
93
+ expect(result).not.toContain('<br/>');
94
+ expect(result).toContain('.foo {\n color: red;\n}');
95
+ expect(result).toContain('Bob');
96
+ });
97
+
85
98
  it('lança BadRequestException em sintaxe inválida', () => {
86
99
  expect(() => call('{{#if foo}}sem fechar', {})).toThrow(
87
100
  BadRequestException,
88
101
  );
89
102
  });
103
+
104
+ // Bug real: o assunto e texto puro (vira o header `subject:` do e-mail),
105
+ // mas o Handlebars padrao escapa `& < > " ' `` `` como se fosse HTML —
106
+ // uma crase no titulo da tarefa saia como `&#x60;` cru na caixa de
107
+ // entrada, e escapava DE NOVO no `<h1>` do corpo (renderMailTemplate),
108
+ // virando `&amp;#x60;`. `escapeHtml: false` e o que os call sites do
109
+ // assunto passam pra evitar isso.
110
+ it('com escapeHtml:false, nao escapa nada — usado no assunto (texto puro)', () => {
111
+ const src = 'Tarefa `{{title}}` & <urgente> "importante"';
112
+ const result = (makeService().service as any).interpolateTemplate(
113
+ src,
114
+ { title: 'status' },
115
+ { escapeHtml: false },
116
+ );
117
+ expect(result).toBe('Tarefa `status` & <urgente> "importante"');
118
+ });
119
+
120
+ it('por padrao (sem a opcao) continua escapando — usado no corpo, que e HTML de verdade', () => {
121
+ const result = call('Nome: {{name}}', { name: 'A & B <b>' });
122
+ expect(result).toBe('Nome: A &amp; B &lt;b&gt;');
123
+ });
90
124
  });
91
125
 
92
126
  describe('isSettingEnabled', () => {
@@ -331,6 +365,54 @@ describe('MailService', () => {
331
365
  ).resolves.toEqual({ sent: true, providerMessageId: 'ses-abc' });
332
366
  });
333
367
 
368
+ it('assunto com crase, & e aspas chega cru no e-mail — sem &#x60;/&amp; vazando (corpo continua escapando)', async () => {
369
+ const { service, deps } = makeService();
370
+ deps.setting.getSettingValues.mockResolvedValue({
371
+ 'configured-mail': 'true',
372
+ } as any);
373
+ // `resolveUserLocale` diferente de 'en' evita o fallback que chama
374
+ // `normalizeLocaleCode(callerLocale)` — sem relação com o bug desta
375
+ // task, só contorna o pacote @hed-hog/api-locale com dist desatualizado
376
+ // neste ambiente (falta o export, dist nao republicado).
377
+ deps.setting.resolveUserLocale.mockResolvedValue('pt');
378
+ jest
379
+ .spyOn(service, 'reloadConfig')
380
+ .mockResolvedValue({ success: true, provider: 'ses', from: 'a@b.com', config: {} });
381
+ deps.prismaService.locale.findUnique.mockResolvedValue({ id: 1, code: 'en' });
382
+ deps.prismaService.mail.findUnique.mockResolvedValue({
383
+ id: 7,
384
+ mail_locale: [
385
+ {
386
+ // A crase literal no template (fora de {{}}) nunca foi escapada
387
+ // pelo Handlebars — quem escapava era o VALOR interpolado da
388
+ // variavel. O bug real tinha a crase dentro do dado (nome da
389
+ // tarefa), entao o teste reproduz isso: a crase mora em `title`,
390
+ // nao no texto fixo do template.
391
+ subject: 'Você foi atribuído à tarefa {{title}} & "urgente"',
392
+ body: 'Título: {{title}}',
393
+ locale: { code: 'en' },
394
+ },
395
+ ],
396
+ mail_var: [],
397
+ });
398
+ deps.mailMainService.send.mockResolvedValue({ result: { MessageId: 'ses-abc' } });
399
+
400
+ await service.sendTemplatedMail('en', {
401
+ email: 'a@b.com',
402
+ slug: 's',
403
+ variables: { title: '`status`' },
404
+ } as any);
405
+
406
+ const sentArgs = deps.mailMainService.send.mock.calls[0][0] as { subject: string; body: string };
407
+ expect(sentArgs.subject).toBe('Você foi atribuído à tarefa `status` & "urgente"');
408
+ expect(sentArgs.subject).not.toContain('&#x60;');
409
+ expect(sentArgs.subject).not.toContain('&amp;');
410
+ // O corpo e HTML de verdade — a mesma crase, vinda do mesmo dado,
411
+ // continua escapando normalmente ali (nao é dupla checagem à toa: prova
412
+ // que `escapeHtml:false` ficou restrito ao assunto).
413
+ expect(sentArgs.body).toContain('&#x60;status&#x60;');
414
+ });
415
+
334
416
  // O bug que originou esta mudanca: o e-mail saia no idioma do header (ou no
335
417
  // `en` de quem nao manda header), ignorando a preferencia do destinatario.
336
418
  describe('idioma do destinatario', () => {
@@ -579,6 +661,36 @@ describe('MailService', () => {
579
661
  expect(html).toContain('lang="pt"');
580
662
  });
581
663
 
664
+ // Regressao do bug real: assunto com crase saia como `&#x60;` cru no
665
+ // assunto do e-mail e `&amp;#x60;` (escape duplo) no <h1> do corpo. O
666
+ // fluxo completo (interpolateTemplate -> renderMailTemplate) precisa
667
+ // produzir cada caractere especial escapado NO MAXIMO uma vez, e so pelo
668
+ // renderMailTemplate — sem o <script> escapando pra HTML executavel.
669
+ it('assunto com crase, &, aspas e <script> nao vaza entidade e nao escapa duas vezes no <h1>', async () => {
670
+ const { service } = makePreviewService();
671
+
672
+ const { html } = await service.preview('pt', {
673
+ subject: 'Tarefa `{{title}}` & "urgente" <script>alert(1)</script>',
674
+ body: '<p>Corpo</p>',
675
+ variables: { title: 'status' },
676
+ });
677
+
678
+ // Crase nunca vira entidade (renderMailTemplate/escapeHtml nem trata
679
+ // crase como caractere especial) — nem &#x60; nem, pior, &amp;#x60;.
680
+ expect(html).not.toContain('#x60;');
681
+ // & e " escapados exatamente uma vez (não &amp;amp; / &amp;quot;).
682
+ expect(html).toContain('&amp;');
683
+ expect(html).not.toContain('&amp;amp;');
684
+ expect(html).not.toContain('&amp;quot;');
685
+ // <script> chega escapado, nunca como tag executável.
686
+ expect(html).not.toContain('<script>alert(1)</script>');
687
+ expect(html).toContain('&lt;script&gt;');
688
+
689
+ expect(html).toContain(
690
+ '<h1>Tarefa `status` &amp; &quot;urgente&quot; &lt;script&gt;alert(1)&lt;/script&gt;</h1>',
691
+ );
692
+ });
693
+
582
694
  it('produz exatamente o mesmo corpo que o envio real', async () => {
583
695
  // Esta é a asserção que justifica o endpoint: o preview do admin não pode
584
696
  // divergir do e-mail que sai. Os dois caminhos passam pelo mesmo
@@ -8,9 +8,11 @@ import {
8
8
  import {
9
9
  DEFAULT_PRIMARY_COLOR,
10
10
  DEFAULT_PRIMARY_FOREGROUND,
11
+ isFullHtmlDocument,
11
12
  MailLayout,
12
13
  MailService as MailMainService,
13
14
  renderMailTemplate,
15
+ sanitizeAccentColor,
14
16
  } from '@hed-hog/api-mail';
15
17
  import { PaginationDTO } from '@hed-hog/api-pagination';
16
18
  import { PrismaService } from '@hed-hog/api-prisma';
@@ -508,8 +510,14 @@ export class MailService implements OnModuleInit {
508
510
  const brandName = await this.mailMainService.getBrandName(app, templateLocale);
509
511
  const { primaryColor, primaryForeground } = await this.getThemeVariables();
510
512
  const mergedVariables = { brandName, primaryColor, primaryForeground, ...variables };
511
- const parsedSubject = this.interpolateTemplate(subject, mergedVariables);
513
+ const parsedSubject = this.interpolateTemplate(subject, mergedVariables, { escapeHtml: false });
512
514
  const parsedBody = this.interpolateTemplate(body, mergedVariables);
515
+ // A cor da etapa vem do remetente (o commerce manda uma por slug) e chega
516
+ // ate o wrapper, que pinta a barra de destaque. `sanitizeAccentColor`
517
+ // descarta o que nao for `#rrggbb` porque o valor entra num bloco <style>.
518
+ const accentColor = sanitizeAccentColor(
519
+ typeof variables?.accentColor === 'string' ? variables.accentColor : undefined,
520
+ );
513
521
 
514
522
  const sendResult: any = await this.mailMainService.send({
515
523
  to: email,
@@ -517,6 +525,7 @@ export class MailService implements OnModuleInit {
517
525
  ...(resolvedReplyTo ? { replyTo: resolvedReplyTo } : {}),
518
526
  subject: parsedSubject,
519
527
  body: parsedBody,
528
+ ...(accentColor ? { accentColor } : {}),
520
529
  mail_id: mail.id,
521
530
  // O layout (header/footer) e escolhido por este locale la no api-mail,
522
531
  // entao tem que ser o do template escolhido, nao o cru do request.
@@ -662,12 +671,31 @@ export class MailService implements OnModuleInit {
662
671
  return mail;
663
672
  }
664
673
 
674
+ /**
675
+ * `escapeHtml` (default true) controla o escape padrao do Handlebars pra
676
+ * `&`, `<`, `>`, `"`, `'` e crase. O corpo e HTML de verdade e precisa dele;
677
+ * o assunto e texto puro (vira o header `subject:` do e-mail e, no corpo,
678
+ * passa de novo por `renderMailTemplate`/`escapeHtml` do `@hed-hog/api-mail`
679
+ * pra virar o `<h1>`) — escapar aqui tambem faria uma crase no assunto virar
680
+ * `&#x60;` cru na caixa de entrada, e depois `&amp;#x60;` no `<h1>` (escape
681
+ * duplo). Quem chama pro assunto passa `{ escapeHtml: false }`.
682
+ */
665
683
  private interpolateTemplate(
666
684
  source: string,
667
685
  data: any,
686
+ { escapeHtml = true }: { escapeHtml?: boolean } = {},
668
687
  ): string {
669
688
  try {
670
- const template = Handlebars.compile(source.replace(/(\r\n|\n|\r)/g, '<br/>'));
689
+ // Um documento HTML completo (<style>/<head>/<script>) tem quebra de
690
+ // linha significativa dentro dessas tags — trocar por <br/> às cegas
691
+ // quebra o CSS/HTML (renderMailTemplate já pula o wrapper pra esse
692
+ // caso; aqui só espelhamos a mesma detecção pra não mutilar antes
693
+ // disso). Emails simples (sem <html>) continuam ganhando <br/> pra
694
+ // preservar quebras de linha digitadas pelo usuário.
695
+ const normalized = isFullHtmlDocument(source)
696
+ ? source
697
+ : source.replace(/(\r\n|\n|\r)/g, '<br/>');
698
+ const template = Handlebars.compile(normalized, { noEscape: !escapeHtml });
671
699
  return template(data);
672
700
  } catch (error: any) {
673
701
  this.logger.error('Handlebars template compilation error:', error);
@@ -741,7 +769,7 @@ export class MailService implements OnModuleInit {
741
769
  ? (await this.brandAsset.resolveAssetUrl(rawLogoUrl)) || undefined
742
770
  : undefined;
743
771
  const data = { brandName, primaryColor, primaryForeground, ...(variables || {}) };
744
- const parsedSubject = subject ? this.interpolateTemplate(subject, data) : '';
772
+ const parsedSubject = subject ? this.interpolateTemplate(subject, data, { escapeHtml: false }) : '';
745
773
  const parsedBody = body ? this.interpolateTemplate(body, data) : '';
746
774
 
747
775
  let resolvedLayout: MailLayout | null = null;
@@ -765,6 +793,11 @@ export class MailService implements OnModuleInit {
765
793
  brandName,
766
794
  primaryColor,
767
795
  primaryForeground,
796
+ // Mesma leitura do envio: sem isto a pre-visualizacao do admin mostraria a
797
+ // barra na cor da marca e o e-mail sairia na cor da etapa.
798
+ accentColor: sanitizeAccentColor(
799
+ typeof variables?.accentColor === 'string' ? variables.accentColor : undefined,
800
+ ),
768
801
  logoUrl,
769
802
  lang: locale,
770
803
  });
@@ -792,13 +825,18 @@ export class MailService implements OnModuleInit {
792
825
  const brandName = await this.mailMainService.getBrandName(undefined, locale);
793
826
  const { primaryColor, primaryForeground } = await this.getThemeVariables();
794
827
  const mergedVariables = { brandName, primaryColor, primaryForeground, ...(variables || {}) };
795
- const parsedSubject = this.interpolateTemplate(subject, mergedVariables);
828
+ const parsedSubject = this.interpolateTemplate(subject, mergedVariables, { escapeHtml: false });
796
829
  const parsedBody = this.interpolateTemplate(body, mergedVariables);
797
830
 
831
+ const accentColor = sanitizeAccentColor(
832
+ typeof variables?.accentColor === 'string' ? variables.accentColor : undefined,
833
+ );
834
+
798
835
  return this.mailMainService.send({
799
836
  to: email,
800
837
  subject: parsedSubject,
801
838
  body: parsedBody,
839
+ ...(accentColor ? { accentColor } : {}),
802
840
  mail_id: mail.id,
803
841
  from,
804
842
  locale,
@@ -12,6 +12,7 @@ import {
12
12
  import { CreateDTO } from './dto/create.dto';
13
13
  import { QueryMailSentListDTO } from './dto/query-mail-sent-list.dto';
14
14
  import { UpdateDTO } from './dto/update.dto';
15
+ import { MAIL_SENT_SORT } from './mail-sent.sort';
15
16
 
16
17
  type MailSentUserStatus = 'received' | 'read' | 'error';
17
18
 
@@ -186,6 +187,8 @@ export class MailSentService {
186
187
  },
187
188
  },
188
189
  },
190
+ undefined,
191
+ { sort: MAIL_SENT_SORT },
189
192
  );
190
193
 
191
194
  const data = (result.data as MailSentWithUsers[]).map((item) => {
@@ -0,0 +1,19 @@
1
+ import { defineSortable } from '@hed-hog/api-pagination';
2
+
3
+ /**
4
+ * Campos ordenáveis de `mail_sent`.
5
+ *
6
+ * "Delivery" (o badge exibido na listagem) fica de fora: é um resumo agregado
7
+ * calculado no service a partir de `mail_sent_user` (to-many), não uma coluna
8
+ * — o Prisma não tem como ordenar por ele.
9
+ */
10
+ export const MAIL_SENT_SORT = defineSortable(
11
+ {
12
+ subject: true,
13
+ from: true,
14
+ to: true,
15
+ created_at: { initialOrder: 'desc' },
16
+ id: { initialOrder: 'desc' },
17
+ },
18
+ { default: 'created_at', defaultOrder: 'desc' },
19
+ );