@teleporthq/teleport-plugin-next-workflows 0.43.65 → 0.43.67

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 (305) hide show
  1. package/__tests__/_helpers/bind-workflow-utils.ts +30 -0
  2. package/__tests__/_helpers/run-generated-middleware.ts +11 -2
  3. package/__tests__/admin-form-row-hydration.test.ts +55 -0
  4. package/__tests__/cart-clear-db-mirror.test.ts +12 -0
  5. package/__tests__/cart-get-total-regional-pricing.test.ts +166 -0
  6. package/__tests__/client-config-redaction.test.ts +53 -0
  7. package/__tests__/continue-on-error.test.ts +119 -0
  8. package/__tests__/email-locale-module.test.ts +323 -0
  9. package/__tests__/email-locale-senders.test.ts +268 -0
  10. package/__tests__/invoice-delivery-fee.test.ts +104 -0
  11. package/__tests__/invoice-regional-tax.test.ts +126 -0
  12. package/__tests__/locale-aware-redirects.test.ts +355 -0
  13. package/__tests__/navigation-go-to-page.test.ts +43 -0
  14. package/__tests__/node-handler-file-inline-map.test.ts +29 -3
  15. package/__tests__/payment-redirect-and-order-notification.test.ts +6 -0
  16. package/__tests__/paypal-webhook-order-notification.test.ts +41 -0
  17. package/__tests__/resolve-config-localized-templates.test.ts +262 -0
  18. package/__tests__/sent-email-log-module.test.ts +381 -0
  19. package/__tests__/sent-email-log-wiring.test.ts +267 -0
  20. package/dist/cjs/account-delete-route-generator.d.ts +20 -0
  21. package/dist/cjs/account-delete-route-generator.d.ts.map +1 -1
  22. package/dist/cjs/account-delete-route-generator.js +29 -26
  23. package/dist/cjs/account-delete-route-generator.js.map +1 -1
  24. package/dist/cjs/api-route-generator.d.ts.map +1 -1
  25. package/dist/cjs/api-route-generator.js +57 -11
  26. package/dist/cjs/api-route-generator.js.map +1 -1
  27. package/dist/cjs/auth-generator.d.ts +2 -1
  28. package/dist/cjs/auth-generator.d.ts.map +1 -1
  29. package/dist/cjs/auth-generator.js +55 -18
  30. package/dist/cjs/auth-generator.js.map +1 -1
  31. package/dist/cjs/data-api-route-generator.d.ts.map +1 -1
  32. package/dist/cjs/data-api-route-generator.js +19 -0
  33. package/dist/cjs/data-api-route-generator.js.map +1 -1
  34. package/dist/cjs/email-locale/email-locale-code.d.ts +25 -0
  35. package/dist/cjs/email-locale/email-locale-code.d.ts.map +1 -0
  36. package/dist/cjs/email-locale/email-locale-code.js +228 -0
  37. package/dist/cjs/email-locale/email-locale-code.js.map +1 -0
  38. package/dist/cjs/email-locale/email-locale-scope.d.ts +46 -0
  39. package/dist/cjs/email-locale/email-locale-scope.d.ts.map +1 -0
  40. package/dist/cjs/email-locale/email-locale-scope.js +51 -0
  41. package/dist/cjs/email-locale/email-locale-scope.js.map +1 -0
  42. package/dist/cjs/email-locale/index.d.ts +11 -0
  43. package/dist/cjs/email-locale/index.d.ts.map +1 -0
  44. package/dist/cjs/email-locale/index.js +40 -0
  45. package/dist/cjs/email-locale/index.js.map +1 -0
  46. package/dist/cjs/executor-generator.d.ts +11 -1
  47. package/dist/cjs/executor-generator.d.ts.map +1 -1
  48. package/dist/cjs/executor-generator.js +49 -7
  49. package/dist/cjs/executor-generator.js.map +1 -1
  50. package/dist/cjs/index.d.ts +2 -0
  51. package/dist/cjs/index.d.ts.map +1 -1
  52. package/dist/cjs/index.js +9 -1
  53. package/dist/cjs/index.js.map +1 -1
  54. package/dist/cjs/invoice/api-routes-code.d.ts.map +1 -1
  55. package/dist/cjs/invoice/api-routes-code.js +55 -6
  56. package/dist/cjs/invoice/api-routes-code.js.map +1 -1
  57. package/dist/cjs/invoice/email-sender-code.d.ts.map +1 -1
  58. package/dist/cjs/invoice/email-sender-code.js +72 -31
  59. package/dist/cjs/invoice/email-sender-code.js.map +1 -1
  60. package/dist/cjs/invoice/index.d.ts +1 -4
  61. package/dist/cjs/invoice/index.d.ts.map +1 -1
  62. package/dist/cjs/invoice/index.js +8 -19
  63. package/dist/cjs/invoice/index.js.map +1 -1
  64. package/dist/cjs/invoice/invoice-html-code.d.ts.map +1 -1
  65. package/dist/cjs/invoice/invoice-html-code.js +31 -8
  66. package/dist/cjs/invoice/invoice-html-code.js.map +1 -1
  67. package/dist/cjs/invoice/regional-invoice-tax-code.d.ts +25 -0
  68. package/dist/cjs/invoice/regional-invoice-tax-code.d.ts.map +1 -0
  69. package/dist/cjs/invoice/regional-invoice-tax-code.js +116 -0
  70. package/dist/cjs/invoice/regional-invoice-tax-code.js.map +1 -0
  71. package/dist/cjs/invoice/resolve-data-source.d.ts +6 -0
  72. package/dist/cjs/invoice/resolve-data-source.d.ts.map +1 -0
  73. package/dist/cjs/invoice/resolve-data-source.js +23 -0
  74. package/dist/cjs/invoice/resolve-data-source.js.map +1 -0
  75. package/dist/cjs/nodes/account/account-delete-current.d.ts.map +1 -1
  76. package/dist/cjs/nodes/account/account-delete-current.js +10 -3
  77. package/dist/cjs/nodes/account/account-delete-current.js.map +1 -1
  78. package/dist/cjs/nodes/account/account-login.d.ts.map +1 -1
  79. package/dist/cjs/nodes/account/account-login.js +3 -1
  80. package/dist/cjs/nodes/account/account-login.js.map +1 -1
  81. package/dist/cjs/nodes/account/account-logout.d.ts.map +1 -1
  82. package/dist/cjs/nodes/account/account-logout.js +4 -2
  83. package/dist/cjs/nodes/account/account-logout.js.map +1 -1
  84. package/dist/cjs/nodes/account/account-signup.d.ts.map +1 -1
  85. package/dist/cjs/nodes/account/account-signup.js +12 -2
  86. package/dist/cjs/nodes/account/account-signup.js.map +1 -1
  87. package/dist/cjs/nodes/account/account-social-login.d.ts.map +1 -1
  88. package/dist/cjs/nodes/account/account-social-login.js +4 -2
  89. package/dist/cjs/nodes/account/account-social-login.js.map +1 -1
  90. package/dist/cjs/nodes/cart/cart-clear.d.ts.map +1 -1
  91. package/dist/cjs/nodes/cart/cart-clear.js +6 -0
  92. package/dist/cjs/nodes/cart/cart-clear.js.map +1 -1
  93. package/dist/cjs/nodes/cart/cart-get-total.d.ts.map +1 -1
  94. package/dist/cjs/nodes/cart/cart-get-total.js +81 -5
  95. package/dist/cjs/nodes/cart/cart-get-total.js.map +1 -1
  96. package/dist/cjs/nodes/data/data-create-item.d.ts.map +1 -1
  97. package/dist/cjs/nodes/data/data-create-item.js +16 -0
  98. package/dist/cjs/nodes/data/data-create-item.js.map +1 -1
  99. package/dist/cjs/nodes/ecommerce/ecommerce-generate-invoice.d.ts.map +1 -1
  100. package/dist/cjs/nodes/ecommerce/ecommerce-generate-invoice.js +6 -0
  101. package/dist/cjs/nodes/ecommerce/ecommerce-generate-invoice.js.map +1 -1
  102. package/dist/cjs/nodes/navigation/navigation-go-to-page.d.ts.map +1 -1
  103. package/dist/cjs/nodes/navigation/navigation-go-to-page.js +4 -1
  104. package/dist/cjs/nodes/navigation/navigation-go-to-page.js.map +1 -1
  105. package/dist/cjs/nodes/navigation/navigation-navigate-to-url.d.ts.map +1 -1
  106. package/dist/cjs/nodes/navigation/navigation-navigate-to-url.js +5 -2
  107. package/dist/cjs/nodes/navigation/navigation-navigate-to-url.js.map +1 -1
  108. package/dist/cjs/nodes/payment/payment-charge-user.d.ts.map +1 -1
  109. package/dist/cjs/nodes/payment/payment-charge-user.js +7 -2
  110. package/dist/cjs/nodes/payment/payment-charge-user.js.map +1 -1
  111. package/dist/cjs/segment-splitter.d.ts +1 -1
  112. package/dist/cjs/segment-splitter.d.ts.map +1 -1
  113. package/dist/cjs/segment-splitter.js +29 -2
  114. package/dist/cjs/segment-splitter.js.map +1 -1
  115. package/dist/cjs/sent-email-log/index.d.ts +16 -0
  116. package/dist/cjs/sent-email-log/index.d.ts.map +1 -0
  117. package/dist/cjs/sent-email-log/index.js +53 -0
  118. package/dist/cjs/sent-email-log/index.js.map +1 -0
  119. package/dist/cjs/sent-email-log/sent-email-log-code.d.ts +4 -0
  120. package/dist/cjs/sent-email-log/sent-email-log-code.d.ts.map +1 -0
  121. package/dist/cjs/sent-email-log/sent-email-log-code.js +415 -0
  122. package/dist/cjs/sent-email-log/sent-email-log-code.js.map +1 -0
  123. package/dist/cjs/sent-email-log/sent-email-log-scope.d.ts +21 -0
  124. package/dist/cjs/sent-email-log/sent-email-log-scope.d.ts.map +1 -0
  125. package/dist/cjs/sent-email-log/sent-email-log-scope.js +36 -0
  126. package/dist/cjs/sent-email-log/sent-email-log-scope.js.map +1 -0
  127. package/dist/cjs/transactional-email-code.d.ts +39 -1
  128. package/dist/cjs/transactional-email-code.d.ts.map +1 -1
  129. package/dist/cjs/transactional-email-code.js +86 -12
  130. package/dist/cjs/transactional-email-code.js.map +1 -1
  131. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  132. package/dist/cjs/webhook-generator.d.ts.map +1 -1
  133. package/dist/cjs/webhook-generator.js +9 -2
  134. package/dist/cjs/webhook-generator.js.map +1 -1
  135. package/dist/cjs/workflow-component-plugin.js +4 -3
  136. package/dist/cjs/workflow-component-plugin.js.map +1 -1
  137. package/dist/cjs/workflow-project-plugin.d.ts.map +1 -1
  138. package/dist/cjs/workflow-project-plugin.js +31 -3
  139. package/dist/cjs/workflow-project-plugin.js.map +1 -1
  140. package/dist/cjs/workflow-utils-alias.d.ts +21 -0
  141. package/dist/cjs/workflow-utils-alias.d.ts.map +1 -0
  142. package/dist/cjs/workflow-utils-alias.js +27 -0
  143. package/dist/cjs/workflow-utils-alias.js.map +1 -0
  144. package/dist/esm/account-delete-route-generator.d.ts +20 -0
  145. package/dist/esm/account-delete-route-generator.d.ts.map +1 -1
  146. package/dist/esm/account-delete-route-generator.js +30 -27
  147. package/dist/esm/account-delete-route-generator.js.map +1 -1
  148. package/dist/esm/api-route-generator.d.ts.map +1 -1
  149. package/dist/esm/api-route-generator.js +57 -11
  150. package/dist/esm/api-route-generator.js.map +1 -1
  151. package/dist/esm/auth-generator.d.ts +2 -1
  152. package/dist/esm/auth-generator.d.ts.map +1 -1
  153. package/dist/esm/auth-generator.js +56 -19
  154. package/dist/esm/auth-generator.js.map +1 -1
  155. package/dist/esm/data-api-route-generator.d.ts.map +1 -1
  156. package/dist/esm/data-api-route-generator.js +19 -0
  157. package/dist/esm/data-api-route-generator.js.map +1 -1
  158. package/dist/esm/email-locale/email-locale-code.d.ts +25 -0
  159. package/dist/esm/email-locale/email-locale-code.d.ts.map +1 -0
  160. package/dist/esm/email-locale/email-locale-code.js +222 -0
  161. package/dist/esm/email-locale/email-locale-code.js.map +1 -0
  162. package/dist/esm/email-locale/email-locale-scope.d.ts +46 -0
  163. package/dist/esm/email-locale/email-locale-scope.d.ts.map +1 -0
  164. package/dist/esm/email-locale/email-locale-scope.js +47 -0
  165. package/dist/esm/email-locale/email-locale-scope.js.map +1 -0
  166. package/dist/esm/email-locale/index.d.ts +11 -0
  167. package/dist/esm/email-locale/index.d.ts.map +1 -0
  168. package/dist/esm/email-locale/index.js +28 -0
  169. package/dist/esm/email-locale/index.js.map +1 -0
  170. package/dist/esm/executor-generator.d.ts +11 -1
  171. package/dist/esm/executor-generator.d.ts.map +1 -1
  172. package/dist/esm/executor-generator.js +49 -7
  173. package/dist/esm/executor-generator.js.map +1 -1
  174. package/dist/esm/index.d.ts +2 -0
  175. package/dist/esm/index.d.ts.map +1 -1
  176. package/dist/esm/index.js +2 -0
  177. package/dist/esm/index.js.map +1 -1
  178. package/dist/esm/invoice/api-routes-code.d.ts.map +1 -1
  179. package/dist/esm/invoice/api-routes-code.js +55 -6
  180. package/dist/esm/invoice/api-routes-code.js.map +1 -1
  181. package/dist/esm/invoice/email-sender-code.d.ts.map +1 -1
  182. package/dist/esm/invoice/email-sender-code.js +72 -31
  183. package/dist/esm/invoice/email-sender-code.js.map +1 -1
  184. package/dist/esm/invoice/index.d.ts +1 -4
  185. package/dist/esm/invoice/index.d.ts.map +1 -1
  186. package/dist/esm/invoice/index.js +7 -18
  187. package/dist/esm/invoice/index.js.map +1 -1
  188. package/dist/esm/invoice/invoice-html-code.d.ts.map +1 -1
  189. package/dist/esm/invoice/invoice-html-code.js +31 -8
  190. package/dist/esm/invoice/invoice-html-code.js.map +1 -1
  191. package/dist/esm/invoice/regional-invoice-tax-code.d.ts +25 -0
  192. package/dist/esm/invoice/regional-invoice-tax-code.d.ts.map +1 -0
  193. package/dist/esm/invoice/regional-invoice-tax-code.js +113 -0
  194. package/dist/esm/invoice/regional-invoice-tax-code.js.map +1 -0
  195. package/dist/esm/invoice/resolve-data-source.d.ts +6 -0
  196. package/dist/esm/invoice/resolve-data-source.d.ts.map +1 -0
  197. package/dist/esm/invoice/resolve-data-source.js +19 -0
  198. package/dist/esm/invoice/resolve-data-source.js.map +1 -0
  199. package/dist/esm/nodes/account/account-delete-current.d.ts.map +1 -1
  200. package/dist/esm/nodes/account/account-delete-current.js +10 -3
  201. package/dist/esm/nodes/account/account-delete-current.js.map +1 -1
  202. package/dist/esm/nodes/account/account-login.d.ts.map +1 -1
  203. package/dist/esm/nodes/account/account-login.js +3 -1
  204. package/dist/esm/nodes/account/account-login.js.map +1 -1
  205. package/dist/esm/nodes/account/account-logout.d.ts.map +1 -1
  206. package/dist/esm/nodes/account/account-logout.js +4 -2
  207. package/dist/esm/nodes/account/account-logout.js.map +1 -1
  208. package/dist/esm/nodes/account/account-signup.d.ts.map +1 -1
  209. package/dist/esm/nodes/account/account-signup.js +12 -2
  210. package/dist/esm/nodes/account/account-signup.js.map +1 -1
  211. package/dist/esm/nodes/account/account-social-login.d.ts.map +1 -1
  212. package/dist/esm/nodes/account/account-social-login.js +4 -2
  213. package/dist/esm/nodes/account/account-social-login.js.map +1 -1
  214. package/dist/esm/nodes/cart/cart-clear.d.ts.map +1 -1
  215. package/dist/esm/nodes/cart/cart-clear.js +6 -0
  216. package/dist/esm/nodes/cart/cart-clear.js.map +1 -1
  217. package/dist/esm/nodes/cart/cart-get-total.d.ts.map +1 -1
  218. package/dist/esm/nodes/cart/cart-get-total.js +81 -5
  219. package/dist/esm/nodes/cart/cart-get-total.js.map +1 -1
  220. package/dist/esm/nodes/data/data-create-item.d.ts.map +1 -1
  221. package/dist/esm/nodes/data/data-create-item.js +16 -0
  222. package/dist/esm/nodes/data/data-create-item.js.map +1 -1
  223. package/dist/esm/nodes/ecommerce/ecommerce-generate-invoice.d.ts.map +1 -1
  224. package/dist/esm/nodes/ecommerce/ecommerce-generate-invoice.js +6 -0
  225. package/dist/esm/nodes/ecommerce/ecommerce-generate-invoice.js.map +1 -1
  226. package/dist/esm/nodes/navigation/navigation-go-to-page.d.ts.map +1 -1
  227. package/dist/esm/nodes/navigation/navigation-go-to-page.js +4 -1
  228. package/dist/esm/nodes/navigation/navigation-go-to-page.js.map +1 -1
  229. package/dist/esm/nodes/navigation/navigation-navigate-to-url.d.ts.map +1 -1
  230. package/dist/esm/nodes/navigation/navigation-navigate-to-url.js +5 -2
  231. package/dist/esm/nodes/navigation/navigation-navigate-to-url.js.map +1 -1
  232. package/dist/esm/nodes/payment/payment-charge-user.d.ts.map +1 -1
  233. package/dist/esm/nodes/payment/payment-charge-user.js +7 -2
  234. package/dist/esm/nodes/payment/payment-charge-user.js.map +1 -1
  235. package/dist/esm/segment-splitter.d.ts +1 -1
  236. package/dist/esm/segment-splitter.d.ts.map +1 -1
  237. package/dist/esm/segment-splitter.js +29 -2
  238. package/dist/esm/segment-splitter.js.map +1 -1
  239. package/dist/esm/sent-email-log/index.d.ts +16 -0
  240. package/dist/esm/sent-email-log/index.d.ts.map +1 -0
  241. package/dist/esm/sent-email-log/index.js +45 -0
  242. package/dist/esm/sent-email-log/index.js.map +1 -0
  243. package/dist/esm/sent-email-log/sent-email-log-code.d.ts +4 -0
  244. package/dist/esm/sent-email-log/sent-email-log-code.d.ts.map +1 -0
  245. package/dist/esm/sent-email-log/sent-email-log-code.js +411 -0
  246. package/dist/esm/sent-email-log/sent-email-log-code.js.map +1 -0
  247. package/dist/esm/sent-email-log/sent-email-log-scope.d.ts +21 -0
  248. package/dist/esm/sent-email-log/sent-email-log-scope.d.ts.map +1 -0
  249. package/dist/esm/sent-email-log/sent-email-log-scope.js +31 -0
  250. package/dist/esm/sent-email-log/sent-email-log-scope.js.map +1 -0
  251. package/dist/esm/transactional-email-code.d.ts +39 -1
  252. package/dist/esm/transactional-email-code.d.ts.map +1 -1
  253. package/dist/esm/transactional-email-code.js +81 -10
  254. package/dist/esm/transactional-email-code.js.map +1 -1
  255. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  256. package/dist/esm/webhook-generator.d.ts.map +1 -1
  257. package/dist/esm/webhook-generator.js +9 -2
  258. package/dist/esm/webhook-generator.js.map +1 -1
  259. package/dist/esm/workflow-component-plugin.js +4 -3
  260. package/dist/esm/workflow-component-plugin.js.map +1 -1
  261. package/dist/esm/workflow-project-plugin.d.ts.map +1 -1
  262. package/dist/esm/workflow-project-plugin.js +32 -4
  263. package/dist/esm/workflow-project-plugin.js.map +1 -1
  264. package/dist/esm/workflow-utils-alias.d.ts +21 -0
  265. package/dist/esm/workflow-utils-alias.d.ts.map +1 -0
  266. package/dist/esm/workflow-utils-alias.js +21 -0
  267. package/dist/esm/workflow-utils-alias.js.map +1 -0
  268. package/package.json +4 -4
  269. package/src/account-delete-route-generator.ts +36 -7
  270. package/src/api-route-generator.ts +64 -11
  271. package/src/auth-generator.ts +63 -18
  272. package/src/data-api-route-generator.ts +19 -0
  273. package/src/email-locale/email-locale-code.ts +239 -0
  274. package/src/email-locale/email-locale-scope.ts +65 -0
  275. package/src/email-locale/index.ts +46 -0
  276. package/src/executor-generator.ts +65 -7
  277. package/src/index.ts +8 -0
  278. package/src/invoice/api-routes-code.ts +65 -6
  279. package/src/invoice/email-sender-code.ts +72 -31
  280. package/src/invoice/index.ts +7 -23
  281. package/src/invoice/invoice-html-code.ts +31 -8
  282. package/src/invoice/regional-invoice-tax-code.ts +112 -0
  283. package/src/invoice/resolve-data-source.ts +25 -0
  284. package/src/nodes/account/account-delete-current.ts +10 -3
  285. package/src/nodes/account/account-login.ts +3 -1
  286. package/src/nodes/account/account-logout.ts +4 -2
  287. package/src/nodes/account/account-signup.ts +12 -2
  288. package/src/nodes/account/account-social-login.ts +7 -2
  289. package/src/nodes/cart/cart-clear.ts +6 -0
  290. package/src/nodes/cart/cart-get-total.ts +94 -5
  291. package/src/nodes/data/data-create-item.ts +16 -0
  292. package/src/nodes/ecommerce/ecommerce-generate-invoice.ts +6 -0
  293. package/src/nodes/navigation/navigation-go-to-page.ts +5 -1
  294. package/src/nodes/navigation/navigation-navigate-to-url.ts +6 -2
  295. package/src/nodes/payment/payment-charge-user.ts +13 -2
  296. package/src/nodes/workflow-utils-global.d.ts +12 -0
  297. package/src/segment-splitter.ts +33 -2
  298. package/src/sent-email-log/index.ts +57 -0
  299. package/src/sent-email-log/sent-email-log-code.ts +419 -0
  300. package/src/sent-email-log/sent-email-log-scope.ts +36 -0
  301. package/src/transactional-email-code.ts +112 -4
  302. package/src/webhook-generator.ts +11 -2
  303. package/src/workflow-component-plugin.ts +4 -3
  304. package/src/workflow-project-plugin.ts +36 -4
  305. package/src/workflow-utils-alias.ts +26 -0
@@ -3,6 +3,7 @@ import { WorkflowSegment, WorkflowExecutionEnv } from './types'
3
3
  import { getLoopBodyNodes, getNodeById, getTopologicalOrder } from './graph-utils'
4
4
  import { nodeRegistry } from './nodes'
5
5
  import { AWAIT_RESULT_CONFIG_KEY } from './await-result'
6
+ import { WELCOME_EMAIL_CONFIG_KEYS } from './transactional-email-code'
6
7
 
7
8
  const CLIENT_ONLY_NODE_TYPES = new Set([
8
9
  'account-login',
@@ -322,11 +323,17 @@ export const CLIENT_SAFE_SERVER_CONFIG_KEYS: ReadonlyArray<string> = [
322
323
  */
323
324
  export const redactServerNodeConfig = (
324
325
  config: Record<string, unknown>,
325
- env: WorkflowExecutionEnv
326
+ env: WorkflowExecutionEnv,
327
+ nodeType?: string
326
328
  ): Record<string, unknown> => {
327
- if (env !== 'server' || !config || typeof config !== 'object') {
329
+ if (!config || typeof config !== 'object') {
328
330
  return config
329
331
  }
332
+ if (env !== 'server') {
333
+ return nodeType && ROUTE_BACKED_ACCOUNT_NODE_TYPES.has(nodeType)
334
+ ? redactRouteOnlyAccountConfig(config)
335
+ : config
336
+ }
330
337
  const safe: Record<string, unknown> = {}
331
338
  for (const key of CLIENT_SAFE_SERVER_CONFIG_KEYS) {
332
339
  if (config[key] !== undefined) {
@@ -336,6 +343,30 @@ export const redactServerNodeConfig = (
336
343
  return safe
337
344
  }
338
345
 
346
+ // The two CLIENT account nodes carry the config of the transactional email
347
+ // their generated ROUTE sends (provider, credential reference, sender, the
348
+ // subject and body in every language). The route bakes all of it from the full
349
+ // UIDL config at generation time, and the client handlers never read a key of
350
+ // it (the signup handler even skips them so they are not forwarded as user
351
+ // columns) — so none of it belongs in a page bundle.
352
+ const ROUTE_ONLY_ACCOUNT_CONFIG_KEYS = new Set<string>([
353
+ ...WELCOME_EMAIL_CONFIG_KEYS,
354
+ 'domain',
355
+ 'deletedEmailPattern',
356
+ ])
357
+
358
+ const ROUTE_BACKED_ACCOUNT_NODE_TYPES = new Set(['account-signup', 'account-delete-current'])
359
+
360
+ const redactRouteOnlyAccountConfig = (config: Record<string, unknown>): Record<string, unknown> => {
361
+ const safe: Record<string, unknown> = {}
362
+ for (const key of Object.keys(config)) {
363
+ if (!ROUTE_ONLY_ACCOUNT_CONFIG_KEYS.has(key)) {
364
+ safe[key] = config[key]
365
+ }
366
+ }
367
+ return safe
368
+ }
369
+
339
370
  export const getServerSegments = (segments: WorkflowSegment[]): WorkflowSegment[] => {
340
371
  return segments.filter((s) => s.env === 'server')
341
372
  }
@@ -0,0 +1,57 @@
1
+ import { FileType, ProjectPluginStructure } from '@teleporthq/teleport-types'
2
+ import { getDatabaseDriverDependencies } from '../auth-generator'
3
+ import { resolveInvoiceDataSource } from '../invoice/resolve-data-source'
4
+ import { generateSentEmailLogCode } from './sent-email-log-code'
5
+ import {
6
+ SENT_EMAIL_LOG_FILE_KEY,
7
+ SENT_EMAIL_LOG_FILE_NAME,
8
+ SENT_EMAIL_LOG_PATH,
9
+ } from './sent-email-log-scope'
10
+
11
+ export {
12
+ EMAIL_CAPABLE_INTEGRATION_NODE_TYPES,
13
+ hasEmailSendingNodeType,
14
+ isEmailSendingNodeType,
15
+ } from './sent-email-log-scope'
16
+ export { generateSentEmailLogCode } from './sent-email-log-code'
17
+
18
+ /**
19
+ * Writes `utils/email/sent-email-log.js` into the project, once. Every
20
+ * emitter of a send path calls this right where it emits the code that
21
+ * `require`s the module (workflow routes, the invoice sender, the account
22
+ * routes, the e-commerce notification sender), so the file exists exactly
23
+ * when something needs it, whichever plugin ran first.
24
+ *
25
+ * The ledger is Postgres-only: on another data source the module is a no-op
26
+ * with the same exports. The `pg` dependency is added only when the project's
27
+ * database is Postgres, through the same driver map auth and invoices use.
28
+ */
29
+ export const ensureSentEmailLogModule = (structure: ProjectPluginStructure): void => {
30
+ const { files, dependencies } = structure
31
+ if (files.has(SENT_EMAIL_LOG_FILE_KEY)) {
32
+ return
33
+ }
34
+
35
+ const { dataSourceType } = resolveInvoiceDataSource(structure)
36
+ const driverDeps = getDatabaseDriverDependencies(dataSourceType)
37
+ const pgSupported = 'pg' in driverDeps
38
+
39
+ files.set(SENT_EMAIL_LOG_FILE_KEY, {
40
+ path: SENT_EMAIL_LOG_PATH,
41
+ files: [
42
+ {
43
+ name: SENT_EMAIL_LOG_FILE_NAME,
44
+ fileType: FileType.JS,
45
+ content: generateSentEmailLogCode({ pgSupported }),
46
+ },
47
+ ],
48
+ })
49
+
50
+ if (pgSupported) {
51
+ for (const [pkg, version] of Object.entries(driverDeps)) {
52
+ if (!dependencies[pkg]) {
53
+ dependencies[pkg] = version
54
+ }
55
+ }
56
+ }
57
+ }
@@ -0,0 +1,419 @@
1
+ import { generatePgClientCode } from '../pg-client-code'
2
+
3
+ /**
4
+ * Emits `utils/email/sent-email-log.js` — the ONE place every email the
5
+ * generated app sends is recorded into `teleport_sent_emails`.
6
+ *
7
+ * Callers (in this order of coverage):
8
+ * - workflow `email-*` / Gmail / Outlook nodes: wrapped per server route by
9
+ * `wrapEmailNodeHandler` (see `generateNodeHandlersForSegment`);
10
+ * - the invoice sender (`utils/invoices/email-sender.js`);
11
+ * - the welcome / farewell routes (`transactional-email-code.ts`);
12
+ * - the order-notification / low-stock routes (`utils/ecommerce/email-sender.js`).
13
+ *
14
+ * Contract: `recordSentEmail` never throws and never rejects, the send is
15
+ * never delayed by it, and a route drains it before replying (a serverless
16
+ * function may be frozen the instant it responds). Only an explicit allow-list
17
+ * of fields is stored — a node config carries credentials.
18
+ *
19
+ * `pgSupported=false` (a MySQL / Mongo / Firestore project) emits a module with
20
+ * the same exports that records nothing, so consumers need no branching.
21
+ */
22
+ const PG_REQUIRE_LINE = "const { Client } = require('pg');"
23
+
24
+ /**
25
+ * The shared `getClient()` boilerplate with its eager `require('pg')` swapped
26
+ * for the lazy loader above: a project can carry an email node and no
27
+ * Postgres driver, and a top-level require would fail the build of every
28
+ * workflow route ("Collecting page data"). `new Client(opts)` keeps working —
29
+ * a constructor that returns an object yields that object.
30
+ */
31
+ const lazyPgClientCode = (): string => {
32
+ const code = generatePgClientCode()
33
+ if (!code.startsWith(PG_REQUIRE_LINE)) {
34
+ throw new Error(
35
+ 'sent-email-log: generatePgClientCode() no longer starts with the pg require line'
36
+ )
37
+ }
38
+ return code.replace(
39
+ PG_REQUIRE_LINE,
40
+ 'function Client(opts) { var pg = __loadPg(); return new pg.Client(opts); }'
41
+ )
42
+ }
43
+
44
+ export const generateSentEmailLogCode = (options: { pgSupported: boolean }): string => {
45
+ if (!options.pgSupported) {
46
+ return `/**
47
+ * Sent-email ledger — disabled: the project's data source is not Postgres.
48
+ */
49
+ function recordSentEmail() { return Promise.resolve(false); }
50
+ function settleSentEmailLog() { return Promise.resolve(); }
51
+ function wrapEmailNodeHandler(_nodeType, handler) { return handler; }
52
+
53
+ module.exports = { recordSentEmail, settleSentEmailLog, wrapEmailNodeHandler };
54
+ `
55
+ }
56
+
57
+ return `/**
58
+ * Sent-email ledger.
59
+ *
60
+ * Every email the app sends — workflow email nodes, the invoice sender, the
61
+ * welcome/farewell routes, order and stock alerts — lands here as one row of
62
+ * \`teleport_sent_emails\`: who it went to, what it said, the values the
63
+ * template was filled with, and whether the provider accepted it.
64
+ *
65
+ * Never awaited by the send itself; never throws; drained before a route
66
+ * replies (see settleSentEmailLog).
67
+ */
68
+ var __pg = null;
69
+ var __pgLoadFailed = false;
70
+ function __loadPg() {
71
+ if (__pg || __pgLoadFailed) return __pg;
72
+ try { __pg = require('pg'); } catch (_e) { __pgLoadFailed = true; __pg = null; }
73
+ return __pg;
74
+ }
75
+
76
+ ${lazyPgClientCode()}
77
+
78
+ var TABLE_NAME = 'teleport_sent_emails';
79
+ var BODY_MAX_CHARS = 1000000;
80
+ var PAYLOAD_MAX_CHARS = 200000;
81
+ var SUBJECT_MAX_CHARS = 2000;
82
+ var ADDRESS_MAX_CHARS = 320;
83
+ var TRUNCATION_MARKER = '\\n<!-- truncated by sent-email-log -->';
84
+ var INSERT_TIMEOUT_MS = 15000;
85
+ var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
86
+ // Template parameters whose VALUE must not be persisted: a reset link carries
87
+ // a live token, and the ledger is readable from the admin panel.
88
+ var SENSITIVE_PARAM_KEY_RE = /token|password|secret|otp|reset|verif|magic|passcode/i;
89
+ var REDACTED = '[redacted]';
90
+
91
+ var __pending = [];
92
+ var __disabledReason = '';
93
+ var __consecutiveFailures = 0;
94
+ var MAX_CONSECUTIVE_FAILURES = 3;
95
+
96
+ function __disable(reason) {
97
+ if (__disabledReason) return;
98
+ __disabledReason = reason;
99
+ console.warn('[sent-email-log] disabled for this process: ' + reason);
100
+ }
101
+
102
+ function __hasDatabaseEnv() {
103
+ return !!(process.env.TELEPORT_DB_CONNECTION_STRING || process.env.TELEPORT_DB_HOST);
104
+ }
105
+
106
+ function __toArray(value) {
107
+ if (value == null || value === '') return [];
108
+ if (Array.isArray(value)) {
109
+ var out = [];
110
+ for (var i = 0; i < value.length; i++) { out = out.concat(__toArray(value[i])); }
111
+ return out;
112
+ }
113
+ if (typeof value === 'object') {
114
+ // Provider SDK shapes: { email, name } / { address }.
115
+ var addr = value.email || value.address || value.emailAddress;
116
+ return addr ? [String(addr)] : [];
117
+ }
118
+ return String(value).split(',').map(function (s) { return s.trim(); }).filter(Boolean);
119
+ }
120
+
121
+ function __truncate(text, max) {
122
+ if (text == null) return null;
123
+ var str = String(text);
124
+ if (str.length <= max) return str;
125
+ return str.slice(0, max) + TRUNCATION_MARKER;
126
+ }
127
+
128
+ function __safeStringify(value, max) {
129
+ if (value == null) return null;
130
+ var json;
131
+ try {
132
+ json = JSON.stringify(value, function (_k, v) {
133
+ if (typeof v === 'bigint') return String(v);
134
+ if (v && typeof v === 'object' && v.type === 'Buffer' && Array.isArray(v.data)) return '[buffer ' + v.data.length + ' bytes]';
135
+ return v;
136
+ });
137
+ } catch (_e) {
138
+ return '"[unserializable]"';
139
+ }
140
+ if (json == null) return null;
141
+ return __truncate(json, max);
142
+ }
143
+
144
+ // "Acme Billing <billing@acme.com>" → { name, email }; "billing@acme.com" → { name: '', email }.
145
+ function __parseAddress(from) {
146
+ var str = String(from || '').trim();
147
+ if (!str) return { name: '', email: '' };
148
+ var m = /^(.*)<([^<>]+)>\\s*$/.exec(str);
149
+ if (m) return { name: m[1].trim().replace(/^"|"$/g, ''), email: m[2].trim() };
150
+ return { name: '', email: str };
151
+ }
152
+
153
+ function __uuidOrNull(value) {
154
+ if (typeof value !== 'string' || !UUID_RE.test(value)) return null;
155
+ return value;
156
+ }
157
+
158
+ // templateParams arrive as [{ key, value }] (workflow nodes) or as a plain
159
+ // object (routes). Returns { payload, redactedValues } where redactedValues
160
+ // are the string values of sensitive keys, to be scrubbed from the body too.
161
+ function __normalizePayload(params) {
162
+ var payload = {};
163
+ var redactedValues = [];
164
+ var entries = [];
165
+ if (Array.isArray(params)) {
166
+ for (var i = 0; i < params.length; i++) {
167
+ var p = params[i];
168
+ if (p && typeof p === 'object' && typeof p.key === 'string') entries.push([p.key, p.value]);
169
+ }
170
+ } else if (params && typeof params === 'object') {
171
+ var keys = Object.keys(params);
172
+ for (var k = 0; k < keys.length; k++) entries.push([keys[k], params[keys[k]]]);
173
+ }
174
+ for (var e = 0; e < entries.length; e++) {
175
+ var key = entries[e][0];
176
+ var value = entries[e][1];
177
+ if (SENSITIVE_PARAM_KEY_RE.test(key)) {
178
+ if (typeof value === 'string' && value.length >= 8) redactedValues.push(value);
179
+ payload[key] = REDACTED;
180
+ } else {
181
+ payload[key] = value;
182
+ }
183
+ }
184
+ return { payload: entries.length ? payload : null, redactedValues: redactedValues };
185
+ }
186
+
187
+ function __scrub(text, redactedValues) {
188
+ if (!text) return text;
189
+ var out = String(text);
190
+ for (var i = 0; i < redactedValues.length; i++) {
191
+ out = out.split(redactedValues[i]).join(REDACTED);
192
+ }
193
+ return out;
194
+ }
195
+
196
+ function __normalizeAttachments(attachments) {
197
+ if (!Array.isArray(attachments) || attachments.length === 0) return null;
198
+ var out = [];
199
+ for (var i = 0; i < attachments.length; i++) {
200
+ var a = attachments[i] || {};
201
+ out.push({
202
+ filename: a.filename || a.name || a.Name || 'attachment',
203
+ contentType: a.contentType || a.type || a.ContentType || null,
204
+ sizeBytes: typeof a.sizeBytes === 'number' ? a.sizeBytes : null,
205
+ url: a.url || null,
206
+ });
207
+ }
208
+ return __safeStringify(out, PAYLOAD_MAX_CHARS);
209
+ }
210
+
211
+ /**
212
+ * Maps a loose entry onto the table's columns. Returns null when there is
213
+ * nothing to record (no recipient at all).
214
+ *
215
+ * entry: { emailType, audience, to, cc, bcc, from, fromName, replyTo, subject,
216
+ * html, payload, attachments, provider, providerMessageId, status,
217
+ * error, source, sourceRef, orderId, userId, referenceType, referenceId }
218
+ */
219
+ function buildSentEmailRow(entry) {
220
+ var e = entry || {};
221
+ var recipients = __toArray(e.to);
222
+ if (recipients.length === 0) return null;
223
+ var from = __parseAddress(e.from);
224
+ var fromName = e.fromName ? String(e.fromName) : from.name;
225
+ var normalized = __normalizePayload(e.payload);
226
+ var cc = __toArray(e.cc);
227
+ var bcc = __toArray(e.bcc);
228
+ var status = e.status === 'failed' ? 'failed' : 'sent';
229
+ return {
230
+ email_type: __truncate(e.emailType || 'custom', 100),
231
+ audience: __truncate(e.audience || 'other', 20),
232
+ recipient_email: __truncate(recipients[0], ADDRESS_MAX_CHARS),
233
+ recipients: JSON.stringify(recipients),
234
+ cc: cc.length ? JSON.stringify(cc) : null,
235
+ bcc: bcc.length ? JSON.stringify(bcc) : null,
236
+ reply_to: e.replyTo ? __truncate(__toArray(e.replyTo)[0] || '', ADDRESS_MAX_CHARS) : null,
237
+ from_email: from.email ? __truncate(from.email, ADDRESS_MAX_CHARS) : null,
238
+ from_name: fromName ? __truncate(fromName, 255) : null,
239
+ subject: __truncate(__scrub(e.subject, normalized.redactedValues), SUBJECT_MAX_CHARS),
240
+ body_html: __truncate(__scrub(e.html, normalized.redactedValues), BODY_MAX_CHARS) || '',
241
+ payload: __safeStringify(normalized.payload, PAYLOAD_MAX_CHARS),
242
+ attachments: __normalizeAttachments(e.attachments),
243
+ provider: e.provider ? __truncate(e.provider, 50) : null,
244
+ provider_message_id: e.providerMessageId ? __truncate(String(e.providerMessageId), 255) : null,
245
+ status: status,
246
+ error_message: e.error ? __truncate(String(e.error), 4000) : null,
247
+ source: __truncate(e.source || 'app', 50),
248
+ source_ref: e.sourceRef ? __truncate(String(e.sourceRef), 255) : null,
249
+ order_id: __uuidOrNull(e.orderId),
250
+ user_id: __uuidOrNull(e.userId),
251
+ reference_type: e.referenceType ? __truncate(String(e.referenceType), 50) : null,
252
+ reference_id: e.referenceId ? __truncate(String(e.referenceId), 255) : null,
253
+ };
254
+ }
255
+
256
+ function __newId() {
257
+ try {
258
+ var crypto = require('crypto');
259
+ if (typeof crypto.randomUUID === 'function') return crypto.randomUUID();
260
+ var b = crypto.randomBytes(16);
261
+ b[6] = (b[6] & 0x0f) | 0x40;
262
+ b[8] = (b[8] & 0x3f) | 0x80;
263
+ var h = b.toString('hex');
264
+ return h.slice(0, 8) + '-' + h.slice(8, 12) + '-' + h.slice(12, 16) + '-' + h.slice(16, 20) + '-' + h.slice(20);
265
+ } catch (_e) {
266
+ return null;
267
+ }
268
+ }
269
+
270
+ function __withTimeout(promise, ms) {
271
+ var timer;
272
+ var timeout = new Promise(function (_resolve, reject) {
273
+ timer = setTimeout(function () { reject(new Error('sent-email-log insert timed out after ' + ms + 'ms')); }, ms);
274
+ });
275
+ return Promise.race([promise, timeout]).then(function (v) { clearTimeout(timer); return v; }, function (err) { clearTimeout(timer); throw err; });
276
+ }
277
+
278
+ async function __insert(row) {
279
+ var columns = Object.keys(row);
280
+ var values = columns.map(function (c) { return row[c]; });
281
+ var id = __newId();
282
+ if (id) { columns.unshift('id'); values.unshift(id); }
283
+ var placeholders = values.map(function (_v, i) { return '$' + (i + 1); });
284
+ var sql = 'INSERT INTO "' + TABLE_NAME + '" (' + columns.map(function (c) { return '"' + c + '"'; }).join(', ') + ') VALUES (' + placeholders.join(', ') + ')';
285
+ var client = getClient();
286
+ await client.connect();
287
+ try {
288
+ await __withTimeout(client.query(sql, values), INSERT_TIMEOUT_MS);
289
+ } finally {
290
+ try { await client.end(); } catch (_e) {}
291
+ }
292
+ }
293
+
294
+ /**
295
+ * Records one send attempt. Resolves to true when the row landed, false
296
+ * otherwise. NEVER rejects.
297
+ */
298
+ function recordSentEmail(entry) {
299
+ var task = (async function () {
300
+ if (__disabledReason) return false;
301
+ if (!__hasDatabaseEnv()) { __disable('no database connection configured'); return false; }
302
+ if (!__loadPg()) { __disable('the pg driver is not installed'); return false; }
303
+ var row;
304
+ try { row = buildSentEmailRow(entry); } catch (buildErr) {
305
+ console.error('[sent-email-log] could not build the row:', buildErr && buildErr.message ? buildErr.message : buildErr);
306
+ return false;
307
+ }
308
+ if (!row) return false;
309
+ try {
310
+ await __insert(row);
311
+ __consecutiveFailures = 0;
312
+ return true;
313
+ } catch (err) {
314
+ var code = err && err.code;
315
+ if (code === '42P01') { __disable('table ' + TABLE_NAME + ' does not exist — re-run the feature activation in the editor'); return false; }
316
+ if (code === '42703') { __disable('table ' + TABLE_NAME + ' is missing a column — re-run the feature activation in the editor'); return false; }
317
+ __consecutiveFailures += 1;
318
+ console.error('[sent-email-log] insert failed: ' + (err && err.message ? err.message : String(err)));
319
+ if (__consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) __disable('repeated insert failures');
320
+ return false;
321
+ }
322
+ })();
323
+ __pending.push(task);
324
+ task.then(function () { __forget(task); }, function () { __forget(task); });
325
+ return task;
326
+ }
327
+
328
+ function __forget(task) {
329
+ var idx = __pending.indexOf(task);
330
+ if (idx >= 0) __pending.splice(idx, 1);
331
+ }
332
+
333
+ /** Awaits every in-flight record. Never rejects. */
334
+ async function settleSentEmailLog() {
335
+ for (var pass = 0; pass < 5 && __pending.length > 0; pass++) {
336
+ await Promise.all(__pending.slice());
337
+ }
338
+ }
339
+
340
+ // Provider name from a node type: 'email-resend' → 'resend', 'integration-gmail' → 'gmail'.
341
+ function __providerOf(nodeType) {
342
+ var t = String(nodeType || '');
343
+ if (t.indexOf('email-') === 0) return t.slice(6);
344
+ if (t.indexOf('integration-') === 0) return t.slice(12);
345
+ return t || null;
346
+ }
347
+
348
+ function __shouldRecordNode(nodeType, config) {
349
+ if (String(nodeType).indexOf('email-') === 0) return true;
350
+ return !!config && config.action === 'send-email';
351
+ }
352
+
353
+ function __entryFromNode(nodeType, config, result, error) {
354
+ var c = config || {};
355
+ var r = result || {};
356
+ var failed = !!error || r.success === false || (typeof r.error === 'string' && r.error) || r.error === true;
357
+ var message = r.message && typeof r.message === 'object' ? r.message : null;
358
+ var providerMessageId = r.messageId || r.id || (message && message.id) || null;
359
+ var errorText = error ? (error.message || String(error)) : (typeof r.error === 'string' ? r.error : (r.error === true && typeof r.message === 'string' ? r.message : null));
360
+ return {
361
+ emailType: c.emailPurpose || 'custom',
362
+ audience: c.emailAudience || 'other',
363
+ to: c.to,
364
+ cc: c.cc,
365
+ bcc: c.bcc,
366
+ from: c.from,
367
+ fromName: c.fromName,
368
+ replyTo: c.replyTo,
369
+ subject: c.subject,
370
+ html: c.body != null ? c.body : (c.html != null ? c.html : c.text),
371
+ payload: c.templateParams,
372
+ provider: __providerOf(nodeType),
373
+ providerMessageId: providerMessageId,
374
+ status: failed ? 'failed' : 'sent',
375
+ error: errorText,
376
+ source: 'workflow',
377
+ sourceRef: nodeType,
378
+ };
379
+ }
380
+
381
+ /**
382
+ * Wraps a server node handler so every send is recorded. The record is
383
+ * registered on the workflow context's fire-and-forget queue — the same one
384
+ * \`settlePendingNodePromises\` drains before the route replies — and pushed
385
+ * BEFORE the handler's result is returned, so the drain always sees it.
386
+ * Extra arguments (a streaming callback) are forwarded untouched.
387
+ */
388
+ function wrapEmailNodeHandler(nodeType, handler) {
389
+ if (typeof handler !== 'function') return handler;
390
+ return async function (config, context) {
391
+ if (!__shouldRecordNode(nodeType, config)) {
392
+ return handler.apply(this, arguments);
393
+ }
394
+ var result;
395
+ try {
396
+ result = await handler.apply(this, arguments);
397
+ } catch (err) {
398
+ __register(context, recordSentEmail(__entryFromNode(nodeType, config, null, err)));
399
+ throw err;
400
+ }
401
+ __register(context, recordSentEmail(__entryFromNode(nodeType, config, result, null)));
402
+ return result;
403
+ };
404
+ }
405
+
406
+ function __register(context, promise) {
407
+ if (!context || typeof context !== 'object') return;
408
+ if (!Array.isArray(context.__pendingNodePromises)) context.__pendingNodePromises = [];
409
+ context.__pendingNodePromises.push(promise);
410
+ }
411
+
412
+ module.exports = {
413
+ recordSentEmail: recordSentEmail,
414
+ settleSentEmailLog: settleSentEmailLog,
415
+ wrapEmailNodeHandler: wrapEmailNodeHandler,
416
+ buildSentEmailRow: buildSentEmailRow,
417
+ };
418
+ `
419
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Which generated code sends email, and therefore which projects get the
3
+ * sent-email ledger module (`utils/email/sent-email-log.js`).
4
+ *
5
+ * Every emitter of a send path calls `ensureSentEmailLogModule` itself, so the
6
+ * module exists exactly when something `require`s it. This file only holds the
7
+ * node-type vocabulary the route generators share.
8
+ */
9
+
10
+ export const SENT_EMAIL_LOG_FILE_KEY = 'sent-email-log'
11
+ export const SENT_EMAIL_LOG_PATH = ['utils', 'email']
12
+ export const SENT_EMAIL_LOG_FILE_NAME = 'sent-email-log'
13
+
14
+ /** Provider send-email nodes: `email-resend`, `email-sendgrid`, … */
15
+ export const EMAIL_NODE_TYPE_PREFIX = 'email-'
16
+
17
+ /**
18
+ * Integration nodes that can send mail among other actions. Only their
19
+ * `send-email` action is recorded; the wrapper checks the resolved config.
20
+ */
21
+ export const EMAIL_CAPABLE_INTEGRATION_NODE_TYPES = new Set([
22
+ 'integration-gmail',
23
+ 'integration-outlook',
24
+ ])
25
+
26
+ export const isEmailSendingNodeType = (nodeType: string): boolean =>
27
+ nodeType.startsWith(EMAIL_NODE_TYPE_PREFIX) || EMAIL_CAPABLE_INTEGRATION_NODE_TYPES.has(nodeType)
28
+
29
+ export const hasEmailSendingNodeType = (nodeTypes: Iterable<string>): boolean => {
30
+ for (const nodeType of nodeTypes) {
31
+ if (isEmailSendingNodeType(nodeType)) {
32
+ return true
33
+ }
34
+ }
35
+ return false
36
+ }