ghost 6.37.1 → 6.38.0
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.
- package/components/tryghost-i18n-0.0.0.tgz +0 -0
- package/core/boot.js +13 -9
- package/core/bridge.js +10 -6
- package/core/built/admin/assets/{PolarAngleAxis-Cavik65s.js → PolarAngleAxis-CB-FJBDa.js} +1 -1
- package/core/built/admin/assets/{_baseAssignValue-CnqN6ZMT.js → _baseAssignValue-BEAjPAfy.js} +1 -1
- package/core/built/admin/assets/{a-large-small-Wi4LtZX-.js → a-large-small-L1BJa6mG.js} +1 -1
- package/core/built/admin/assets/admin-x-settings/admin-x-settings.js +1 -1
- package/core/built/admin/assets/admin-x-settings/{code-editor-view-Cf8T5Jfd.mjs → code-editor-view-bOZzJ3a1.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{index-BMWEh-vR.mjs → index-BRuMxaCz.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{index-Aj-hFSnY.mjs → index-CTAQj489.mjs} +5 -5
- package/core/built/admin/assets/admin-x-settings/{index-DjBJrXYn.mjs → index-WoKKBOe4.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{modals-8WpWZZdI.mjs → modals-BQ5M-RTA.mjs} +3 -3
- package/core/built/admin/assets/{arrow-right-BiAOKOto.js → arrow-right-B2j-ecEK.js} +1 -1
- package/core/built/admin/assets/{at-sign-z5gBMxDW.js → at-sign-CtAw8_lw.js} +1 -1
- package/core/built/admin/assets/{audience-DxNilLIv.js → audience-CvSOqHuo.js} +1 -1
- package/core/built/admin/assets/automations-BVUNuVOh.js +1 -0
- package/core/built/admin/assets/automations-Bi9RJq5E.js +1 -0
- package/core/built/admin/assets/{avatar-flipboard-5OzseZFV.js → avatar-flipboard-DocLTXLh.js} +1 -1
- package/core/built/admin/assets/{bluesky-sharing-D9YcSpW8.js → bluesky-sharing-DafX2lE1.js} +1 -1
- package/core/built/admin/assets/chart-BRQeD9eh.js +67 -0
- package/core/built/admin/assets/{chevron-up-DVt6fhV3.js → chevron-up-v4_QwmnL.js} +1 -1
- package/core/built/admin/assets/{chunk.524.fcd26ef812d73e2b0620.js → chunk.524.c3d844070c24d7984fd7.js} +4 -4
- package/core/built/admin/assets/{chunk.582.b61ffaad1c2fa4aba820.js → chunk.582.0e0ede1eac12926acceb.js} +6 -6
- package/core/built/admin/assets/{chunk.383.adb5a3fe32b6b98c43ff.js → chunk.995.4b32363ab39da3e7f5d7.js} +3 -3
- package/core/built/admin/assets/circle-alert-Dbz54fYb.js +1 -0
- package/core/built/admin/assets/{code-editor-view-CbQIqTrK.js → code-editor-view-D-pYCcdu.js} +1 -1
- package/core/built/admin/assets/comments-DSv09jRn.js +1 -0
- package/core/built/admin/assets/{content-helpers-jANWGIfA.js → content-helpers-DQdPPDGb.js} +1 -1
- package/core/built/admin/assets/{copy-BBLeLEnG.js → copy-BULQsPZ4.js} +1 -1
- package/core/built/admin/assets/{data-list-BveeOSGI.js → data-list-WxXC0iKE.js} +1 -1
- package/core/built/admin/assets/{deleted-feed-item-DupAEk4P.js → deleted-feed-item-ZBLfgRkK.js} +1 -1
- package/core/built/admin/assets/{dropzone-D3PSdAHN.js → dropzone-B8mAoWrn.js} +1 -1
- package/core/built/admin/assets/{edit-profile-NrCR9_bi.js → edit-profile-Bj3th8H0.js} +1 -1
- package/core/built/admin/assets/editor-BZV40eAE.css +1 -0
- package/core/built/admin/assets/editor-u20VuPzn.js +7 -0
- package/core/built/admin/assets/{empty-indicator-Dhi_KeYX.js → empty-indicator-P3IsUguf.js} +1 -1
- package/core/built/admin/assets/{en-BontI3SP.js → en-C9bUnuy7.js} +1 -1
- package/core/built/admin/assets/{feed-B3Kfiz5R.js → feed-B94mO944.js} +1 -1
- package/core/built/admin/assets/{filter-query-core-Dwh4Qulu.js → filter-query-core-CM0KKIr2.js} +1 -1
- package/core/built/admin/assets/filters-D52FTE0z.js +1 -0
- package/core/built/admin/assets/gh-chart-Xa6Nvzwz.js +1 -0
- package/core/built/admin/assets/{ghost-c25434d5bbf5a5429883d4c3590f1946.js → ghost-82f1c4ffe0e1cd058ce4b66b5253b620.js} +159 -201
- package/core/built/admin/assets/{ghost-dark-52df27573e5f2a75e6cf4b1d06eea9e4.css → ghost-dark-9897cf5102772faedf566e5e54d4fbee.css} +1 -1
- package/core/built/admin/assets/{ghost-fcf460028e04192f392f16e173f2e3a8.css → ghost-e11f1814be0f38e98bb77b49eba11178.css} +1 -1
- package/core/built/admin/assets/{growth-DRH8zUIJ.js → growth-D3TW3JIB.js} +1 -1
- package/core/built/admin/assets/{hash-UvX5iOa9.js → hash-CstXS-iB.js} +1 -1
- package/core/built/admin/assets/{header-G1a38jnf.js → header-StkTITw-.js} +1 -1
- package/core/built/admin/assets/{inbox-By7HZskI.js → inbox-D1RM3kVF.js} +1 -1
- package/core/built/admin/assets/index-BEkJ9xtY.css +1 -0
- package/core/built/admin/assets/{index-CS_ZmI8F.js → index-BJx5Uas5.js} +1 -1
- package/core/built/admin/assets/index-BKzg6OE7.js +1 -0
- package/core/built/admin/assets/{index-D7JyKf1m.js → index-BM-MBdD0.js} +1 -1
- package/core/built/admin/assets/index-BRzvVuXt.js +2 -0
- package/core/built/admin/assets/index-B_3xqeM9.js +1 -0
- package/core/built/admin/assets/{index-ydyrczVl.js → index-C-OdR2wJ.js} +1 -1
- package/core/built/admin/assets/{index-X-MG1ikg.js → index-C59QlJqT.js} +1 -1
- package/core/built/admin/assets/{index-CJo0Qh4V.js → index-CCq_1tCo.js} +1 -1
- package/core/built/admin/assets/{index-qHUvPjQB.js → index-CYyEyBYw.js} +11 -11
- package/core/built/admin/assets/{index-CX4ztLSk.js → index-DHbiBjyq.js} +1 -1
- package/core/built/admin/assets/{index-BP6hBbPK.js → index-DTVgSMyL.js} +2 -2
- package/core/built/admin/assets/{index-vZMbI8e8.js → index-DiUjEgRw.js} +1 -1
- package/core/built/admin/assets/{index-YM4ZplGj.js → index-DugxKzA6.js} +1 -1
- package/core/built/admin/assets/{index-D8InZCr2.js → index-DzVHlhO1.js} +1 -1
- package/core/built/admin/assets/{index-D4b7U6K-.js → index-LsaD9Cq7.js} +1 -1
- package/core/built/admin/assets/{index-DRUPF8nN.js → index-x0hNfyqU.js} +1 -1
- package/core/built/admin/assets/{inline-Bc9zHR7e.js → inline-B4cWemrJ.js} +1 -1
- package/core/built/admin/assets/{koenig-lexical-B-ZnqRE1.js → koenig-lexical-BOdeH3QJ.js} +1 -1
- package/core/built/admin/assets/{kpi-card-zyi5Onb0.js → kpi-card-P7zSpcx0.js} +1 -1
- package/core/built/admin/assets/{kpi-card-CzlPIEPE.js → kpi-card-plhYOEtA.js} +1 -1
- package/core/built/admin/assets/{kpi-tabs-Dsa5ldXK.js → kpi-tabs-DZw2Qktb.js} +1 -1
- package/core/built/admin/assets/{kpis-Cw5ZRQhk.js → kpis-CDHM0xhW.js} +1 -1
- package/core/built/admin/assets/{label-BvxmsD1M.js → label-Ckacdx14.js} +1 -1
- package/core/built/admin/assets/{links-CiS5BPKS.js → links-BtXE5d0Y.js} +1 -1
- package/core/built/admin/assets/{list-filter-zmkB7rg4.js → list-filter-DLjjiktn.js} +1 -1
- package/core/built/admin/assets/{list-header-Cp779e3H.js → list-header-Cc7Ia3nr.js} +1 -1
- package/core/built/admin/assets/loader-circle-DLJd-dNm.js +1 -0
- package/core/built/admin/assets/{mail-i2qs8CIG.js → mail-B97w28e2.js} +1 -1
- package/core/built/admin/assets/{main-layout-KCvKOX8F.js → main-layout-bwWvzc9B.js} +1 -1
- package/core/built/admin/assets/{members-w601v5JJ.js → members-CokS8MI2.js} +5 -5
- package/core/built/admin/assets/{message-square-text-bG9IoWIt.js → message-square-text-D3rsjDFR.js} +1 -1
- package/core/built/admin/assets/minus-BzXQVmMw.js +1 -0
- package/core/built/admin/assets/{modals-lNzhiL0o.js → modals-D0lip-iy.js} +2 -2
- package/core/built/admin/assets/{moderation-CyfNRSWj.js → moderation-Dv7AadCV.js} +1 -1
- package/core/built/admin/assets/newsletter-BazC5rIj.js +1 -0
- package/core/built/admin/assets/{newsletters-B8xSXSr_.js → newsletters-m6HQgU5J.js} +1 -1
- package/core/built/admin/assets/{note-dNfKEpxw.js → note-CCGiEKz-.js} +1 -1
- package/core/built/admin/assets/{onboarding-route-Drbw0QtT.js → onboarding-route-Cbt7qWNE.js} +1 -1
- package/core/built/admin/assets/overview-TN50tzUh.js +1 -0
- package/core/built/admin/assets/{pagemenu-VJXMoMB4.js → pagemenu-BXrHWtsU.js} +1 -1
- package/core/built/admin/assets/{pencil-DHNmlLjO.js → pencil-BL1r8KVy.js} +1 -1
- package/core/built/admin/assets/{post-analytics-PsqLsS2e.js → post-analytics-BqEXi6Ps.js} +1 -1
- package/core/built/admin/assets/{post-analytics-context-QLZsZCFg.js → post-analytics-context-DekYNlb3.js} +1 -1
- package/core/built/admin/assets/{post-analytics-header-PecXsIT-.js → post-analytics-header-AkNbn6uc.js} +1 -1
- package/core/built/admin/assets/{post-share-modal-B4Rvo7W1.js → post-share-modal-CXDGVKoQ.js} +1 -1
- package/core/built/admin/assets/posts/{app-utils-DIc5TmxO.mjs → app-utils-DxA7edI_.mjs} +2 -2
- package/core/built/admin/assets/posts/{automations-BZpT35kJ.mjs → automations-Cwu_gHl4.mjs} +64 -67
- package/core/built/admin/assets/posts/automations-D81hV_2c.mjs +13 -0
- package/core/built/admin/assets/posts/{avatar-K63cvqSS.mjs → avatar-IkjEzEjI.mjs} +19 -19
- package/core/built/admin/assets/posts/{button-ufGBCcsV.mjs → button-KaJZKcou.mjs} +21 -21
- package/core/built/admin/assets/posts/{check-IcEnuTpD.mjs → check-Cf74RvZ1.mjs} +21 -21
- package/core/built/admin/assets/posts/{comments-CyJU9Ums.mjs → comments-pdKhYbYG.mjs} +54 -52
- package/core/built/admin/assets/posts/createLucideIcon-Cj7h3r9g.mjs +320 -0
- package/core/built/admin/assets/posts/{dialog-D6_lBvtT.mjs → dialog-Ci3W8fjx.mjs} +71 -76
- package/core/built/admin/assets/posts/{dropdown-menu-BSSmAory.mjs → dropdown-menu-DZ9XCHSw.mjs} +5 -5
- package/core/built/admin/assets/posts/editor-Bb-xle0o.mjs +6084 -0
- package/core/built/admin/assets/posts/ellipsis-ChhZo9aT.mjs +10 -0
- package/core/built/admin/assets/posts/{empty-indicator-DvGCvRAX.mjs → empty-indicator-DnFs7hDy.mjs} +2 -2
- package/core/built/admin/assets/posts/{filters-BLBaHhJz.mjs → filters-CO_FUPX-.mjs} +42 -40
- package/core/built/admin/assets/posts/get-site-timezone-C21yKZT_.mjs +87 -0
- package/core/built/admin/assets/posts/{growth-Bz1ChJNB.mjs → growth-CtX9Efm2.mjs} +12 -12
- package/core/built/admin/assets/posts/heading-DZ_KtDTL.mjs +138 -0
- package/core/built/admin/assets/posts/{hooks-BEngBys9.mjs → hooks-DVhBDVlA.mjs} +3 -2
- package/core/built/admin/assets/posts/{index-BAF0YXsp.mjs → index-B4db8w_H.mjs} +181 -172
- package/core/built/admin/assets/posts/{inline-C2YFQAdU.mjs → inline-BfB-SNk0.mjs} +2 -2
- package/core/built/admin/assets/posts/{input-surface-TqJlNSp_.mjs → input-surface-CNwZJloi.mjs} +2 -2
- package/core/built/admin/assets/posts/{kpis-DAX5_0-Q.mjs → kpis-BvY_5Y1u.mjs} +8792 -8803
- package/core/built/admin/assets/posts/{links-A1YTsBbF.mjs → links-Ck-h7SKg.mjs} +57 -57
- package/core/built/admin/assets/posts/{loading-indicator-BZsjmp8g.mjs → loading-indicator-B_rU9Lie.mjs} +3 -3
- package/core/built/admin/assets/posts/mail-DiZ3oKEW.mjs +9 -0
- package/core/built/admin/assets/posts/{main-layout-D_HHTP_n.mjs → main-layout-aYo6qOBZ.mjs} +2 -2
- package/core/built/admin/assets/posts/{newsletter-BRzgjOIa.mjs → newsletter-BQc53TF2.mjs} +31 -30
- package/core/built/admin/assets/posts/{overview-C41VFjn7.mjs → overview-blz9Ak9q.mjs} +42 -41
- package/core/built/admin/assets/posts/plus-YVjtYaK3.mjs +15 -0
- package/core/built/admin/assets/posts/{post-analytics-DGgMkFaf.mjs → post-analytics-BQbWGoeu.mjs} +6 -6
- package/core/built/admin/assets/posts/{post-analytics-context-B1r3HBrp.mjs → post-analytics-context-Be7THgnd.mjs} +7 -7
- package/core/built/admin/assets/posts/{post-analytics-header-DTWSO0Aq.mjs → post-analytics-header-iDFy7Bao.mjs} +2762 -2764
- package/core/built/admin/assets/posts/{post-share-modal-ohHwk0Yt.mjs → post-share-modal-akP16idN.mjs} +50 -48
- package/core/built/admin/assets/posts/posts.js +2 -1
- package/core/built/admin/assets/posts/{settings-CZYL6Jhr.mjs → settings-BdQhfHxY.mjs} +2 -2
- package/core/built/admin/assets/posts/{sheet-D7YesQJE.mjs → sheet-3dBlKeXf.mjs} +14 -13
- package/core/built/admin/assets/posts/{skeleton-S1k58YKa.mjs → skeleton-DMgSvYqr.mjs} +11 -11
- package/core/built/admin/assets/posts/{source-icon-DnpCy5N4.mjs → source-icon-Bp5Qxq1E.mjs} +4 -4
- package/core/built/admin/assets/posts/{stats-CbOpowXb.mjs → stats-DJx9qc_u.mjs} +4 -4
- package/core/built/admin/assets/posts/{table-Cw3Wxf1C.mjs → table-BpVwuzeH.mjs} +2 -2
- package/core/built/admin/assets/posts/{data-list-BnZARP88.mjs → tabs-CbZCpxfI.mjs} +4885 -5284
- package/core/built/admin/assets/posts/{tags-BoMt6Ce3.mjs → tags-CNtvDS6f.mjs} +33 -33
- package/core/built/admin/assets/posts/{tags-CNdsvTtZ.mjs → tags-DFOoFZ_3.mjs} +2 -2
- package/core/built/admin/assets/posts/{tooltip-CTcyINxz.mjs → tooltip-Cc_09RDU.mjs} +106 -117
- package/core/built/admin/assets/posts/value-CwGM7M-1.mjs +410 -0
- package/core/built/admin/assets/posts/{virtual-list-window-Bs88yrut.mjs → virtual-list-window-D6nRoL0y.mjs} +5 -5
- package/core/built/admin/assets/posts/{web-Bsd8eTP6.mjs → web-yfPssEt8.mjs} +1042 -1040
- package/core/built/admin/assets/posts/x-DrUGcpfp.mjs +9 -0
- package/core/built/admin/assets/posts/zap-DAN0ur-o.mjs +24 -0
- package/core/built/admin/assets/posts-D-jyPPE6.js +1 -0
- package/core/built/admin/assets/power-Cc5ncYVl.js +1 -0
- package/core/built/admin/assets/{referrers-kcBT5smx.js → referrers-qnXsKsuv.js} +1 -1
- package/core/built/admin/assets/{repeat-Cn2sKd-L.js → repeat-BGIBynZH.js} +1 -1
- package/core/built/admin/assets/{reply-D7E-ZMd5.js → reply-DOKdAsL_.js} +1 -1
- package/core/built/admin/assets/{rocket-DnH0XAGW.js → rocket-CAN2NB82.js} +1 -1
- package/core/built/admin/assets/{select-f0MMMQWu.js → select-8S9kYGSM.js} +1 -1
- package/core/built/admin/assets/{settings-BAQNP3gU.js → settings-DeD-bmZc.js} +4 -4
- package/core/built/admin/assets/{settings-ORttG1jT.js → settings-e4IB9sx6.js} +1 -1
- package/core/built/admin/assets/{share-modal-CXU4tGY8.js → share-modal-CBavk20I.js} +1 -1
- package/core/built/admin/assets/{sort-button-BXMrChFu.js → sort-button-DlSKBzUq.js} +1 -1
- package/core/built/admin/assets/{source-icon-cjy79jGT.js → source-icon-27VIJSXr.js} +1 -1
- package/core/built/admin/assets/{sprout-DZ4tZ78G.js → sprout-D66nqc79.js} +1 -1
- package/core/built/admin/assets/{square-vOzqJf7x.js → square-DccaXQWe.js} +1 -1
- package/core/built/admin/assets/stats/{audience-5NeJICtP.mjs → audience-B84ClTDM.mjs} +3 -3
- package/core/built/admin/assets/stats/{content-helpers-DFSTl3uB.mjs → content-helpers-CBAddUg7.mjs} +4 -4
- package/core/built/admin/assets/stats/{index-C4T7u699.mjs → index-Bz5oVpED.mjs} +5 -5
- package/core/built/admin/assets/stats/{index-B8bp6qe2.mjs → index-Cs8i1uR4.mjs} +74 -75
- package/core/built/admin/assets/stats/{index-wvi17m79.mjs → index-DEsP_Tbd.mjs} +8 -8
- package/core/built/admin/assets/stats/{index-CFfAYHdD.mjs → index-Ds-pM47x.mjs} +5 -5
- package/core/built/admin/assets/stats/{index-Chqk7VlR.mjs → index-Wzk1IcAz.mjs} +6 -6
- package/core/built/admin/assets/stats/{kpi-tabs-Df9yOI2P.mjs → kpi-tabs-Cs4l8B_M.mjs} +7 -7
- package/core/built/admin/assets/stats/{sort-button-Doi8OgMU.mjs → sort-button-rR-GA9Hu.mjs} +3 -3
- package/core/built/admin/assets/stats/{stats-FXeCefyd.mjs → stats-RFpEJpEq.mjs} +34 -34
- package/core/built/admin/assets/stats/stats.js +1 -1
- package/core/built/admin/assets/stats/{use-growth-stats-93C_3EZk.mjs → use-growth-stats-DwgFzbq9.mjs} +3 -3
- package/core/built/admin/assets/{stats-CIGz2Win.js → stats-B4OybenW.js} +1 -1
- package/core/built/admin/assets/{stats-view-BTKRxYTQ.js → stats-view-BuExwFXa.js} +1 -1
- package/core/built/admin/assets/{step-1-BSMHbT-q.js → step-1-D_5LOQrC.js} +1 -1
- package/core/built/admin/assets/{step-2-_YC0LCZv.js → step-2-BZLBj8cj.js} +1 -1
- package/core/built/admin/assets/{step-3-DWMqP2bO.js → step-3-s5uNbcOH.js} +1 -1
- package/core/built/admin/assets/{table-mHKjXQba.js → table-pGS7EeJe.js} +1 -1
- package/core/built/admin/assets/{tabs-B93IVRBz.js → tabs-CjdKssUe.js} +1 -1
- package/core/built/admin/assets/{tags-DCb-x2ZB.js → tags-B0vRk0A6.js} +1 -1
- package/core/built/admin/assets/{tags-kUHJ1MZo.js → tags-Dso4-FA_.js} +1 -1
- package/core/built/admin/assets/{textarea-DswCtM7_.js → textarea-DzFnun0_.js} +1 -1
- package/core/built/admin/assets/{tiers-DueraQKd.js → tiers-4Vkr_D-L.js} +1 -1
- package/core/built/admin/assets/{toggle-group-ChTo8MPD.js → toggle-group-hDsr47IB.js} +1 -1
- package/core/built/admin/assets/{topic-filter-DrW3fYWo.js → topic-filter-C7TpPe1G.js} +1 -1
- package/core/built/admin/assets/{trash-B2ESGftj.js → trash-DCVuk7ZX.js} +1 -1
- package/core/built/admin/assets/{underline-vo-bPRac.js → underline-CjK8la2G.js} +1 -1
- package/core/built/admin/assets/{upload-DXQRkBBq.js → upload-CPYhmtWZ.js} +1 -1
- package/core/built/admin/assets/{use-growth-stats-CoB8-lsd.js → use-growth-stats-CaFSgp_R.js} +1 -1
- package/core/built/admin/assets/{use-simple-pagination-Y_Wv2N6g.js → use-simple-pagination-D0vJBMvF.js} +1 -1
- package/core/built/admin/assets/{user-round-check-Dp9a2x-e.js → user-round-check-CzQQeFd8.js} +1 -1
- package/core/built/admin/assets/{user-round-x-DwCTGlxc.js → user-round-x-BDFm8yQj.js} +1 -1
- package/core/built/admin/assets/value-BGBiTkF3.js +1 -0
- package/core/built/admin/assets/{vendor-17f3b979ba6f3898d1a8c5249cc22ff1.js → vendor-ce3fc901ccbcf37f36eb791b4e454138.js} +29 -31
- package/core/built/admin/assets/{virtual-list-window-BF7IvGMC.js → virtual-list-window-EKtWZ5cP.js} +1 -1
- package/core/built/admin/assets/{wallet-cards-IEmcxJvG.js → wallet-cards-C1NOBbWE.js} +1 -1
- package/core/built/admin/assets/web-DCA7HR1S.js +1 -0
- package/core/built/admin/index.html +8 -8
- package/core/frontend/helpers/social_accounts.js +91 -0
- package/core/frontend/services/sitemap/handler.js +14 -2
- package/core/frontend/services/sitemap/site-map-manager.js +133 -9
- package/core/frontend/web/middleware/handle-image-sizes.js +4 -0
- package/core/server/api/endpoints/automations.js +38 -45
- package/core/server/models/member.js +30 -25
- package/core/server/services/automations/automations-api.js +58 -0
- package/core/server/services/automations/automations-api.ts +71 -0
- package/core/server/services/automations/automations-repository.js +2 -0
- package/core/server/services/automations/automations-repository.ts +63 -0
- package/core/server/services/automations/fake-database-automations-repository.js +210 -0
- package/core/server/services/automations/fake-database-automations-repository.ts +273 -0
- package/core/server/services/automations/temporary-fake-database.js +5 -4
- package/core/server/services/gifts/email-templates/gift-purchase-confirmation.hbs +10 -32
- package/core/server/services/gifts/email-templates/gift-purchase-confirmation.js +6 -8
- package/core/server/services/gifts/email-templates/gift-purchase-confirmation.ts +6 -8
- package/core/server/services/gifts/email-templates/gift-reminder.hbs +12 -37
- package/core/server/services/gifts/email-templates/gift-reminder.js +5 -9
- package/core/server/services/gifts/email-templates/gift-reminder.ts +5 -9
- package/core/server/services/gifts/gift-service.js +1 -1
- package/core/server/services/gifts/gift-service.ts +2 -2
- package/core/server/services/member-welcome-emails/service.js +0 -1
- package/core/server/services/members/members-api/controllers/router-controller.js +52 -7
- package/core/server/services/members/members-api/services/member-bread-service.js +0 -8
- package/core/server/services/route-settings/route-settings.js +18 -2
- package/core/server/services/staff/email-templates/gift.hbs +1 -1
- package/core/server/services/staff/email-templates/gift.txt.js +1 -1
- package/core/server/services/staff/email-templates/new-gift-subscription.hbs +1 -1
- package/core/server/services/staff/email-templates/new-gift-subscription.txt.js +1 -1
- package/core/server/services/staff/staff-service-emails.js +1 -1
- package/core/server/services/url/index.js +16 -1
- package/core/server/services/url/lazy-find-resource.js +49 -0
- package/core/server/services/url/lazy-find-resource.ts +62 -0
- package/core/server/services/url/lazy-url-service.js +220 -0
- package/core/server/services/url/lazy-url-service.ts +265 -0
- package/core/server/web/api/endpoints/admin/routes.js +1 -0
- package/core/server/web/gift-preview/Inter.ttf +0 -0
- package/core/server/web/gift-preview/controller.js +56 -6
- package/core/server/web/gift-preview/gift-card-noise.png +0 -0
- package/core/server/web/gift-preview/gift-card-orb.png +0 -0
- package/core/server/web/gift-preview/image.js +170 -43
- package/core/shared/config/defaults.json +1 -0
- package/core/shared/one-at-a-time.js +28 -33
- package/core/shared/one-at-a-time.ts +58 -0
- package/package.json +18 -16
- package/pnpm-lock.yaml +989 -356
- package/core/built/admin/assets/automations-D1uMjd06.js +0 -1
- package/core/built/admin/assets/chart-_EXssQtm.js +0 -67
- package/core/built/admin/assets/comments-E00h1SbR.js +0 -1
- package/core/built/admin/assets/filters-CC7XfjOS.js +0 -1
- package/core/built/admin/assets/gh-chart-B9_ywrJJ.js +0 -1
- package/core/built/admin/assets/index-AsV-aY0z.css +0 -1
- package/core/built/admin/assets/index-B0y_ynZw.js +0 -1
- package/core/built/admin/assets/index-Bs6wWbLA.js +0 -2
- package/core/built/admin/assets/index-Cb4641XW.js +0 -1
- package/core/built/admin/assets/loader-circle-B5UPqSok.js +0 -1
- package/core/built/admin/assets/minus-DWx9VUtr.js +0 -1
- package/core/built/admin/assets/newsletter-fkQye9OK.js +0 -1
- package/core/built/admin/assets/overview-CZ-VrnXy.js +0 -1
- package/core/built/admin/assets/posts/createLucideIcon-DcUfTBt_.mjs +0 -454
- package/core/built/admin/assets/posts/get-site-timezone-DlXmHA3y.mjs +0 -93
- package/core/built/admin/assets/posts-Bx1RWrub.js +0 -1
- package/core/built/admin/assets/web-DSME3e8c.js +0 -1
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export interface Pagination {
|
|
2
|
+
page: number;
|
|
3
|
+
pages: number;
|
|
4
|
+
limit: number | 'all';
|
|
5
|
+
total: number;
|
|
6
|
+
prev: number | null;
|
|
7
|
+
next: number | null;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface Page<T> {
|
|
11
|
+
data: T[];
|
|
12
|
+
meta: {
|
|
13
|
+
pagination: Pagination;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface WaitAction {
|
|
18
|
+
id: string;
|
|
19
|
+
type: 'wait';
|
|
20
|
+
data: {
|
|
21
|
+
wait_hours: number;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface SendEmailAction {
|
|
26
|
+
id: string;
|
|
27
|
+
type: 'send_email';
|
|
28
|
+
data: {
|
|
29
|
+
email_subject: string;
|
|
30
|
+
email_lexical: string;
|
|
31
|
+
email_sender_name: string | null;
|
|
32
|
+
email_sender_email: string | null;
|
|
33
|
+
email_sender_reply_to: string | null;
|
|
34
|
+
email_design_setting_id: string;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type AutomationAction = WaitAction | SendEmailAction;
|
|
39
|
+
|
|
40
|
+
export interface AutomationEdge {
|
|
41
|
+
source_action_id: string;
|
|
42
|
+
target_action_id: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface AutomationSummary {
|
|
46
|
+
id: string;
|
|
47
|
+
slug: string;
|
|
48
|
+
name: string;
|
|
49
|
+
status: string;
|
|
50
|
+
created_at: string;
|
|
51
|
+
updated_at: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface Automation extends AutomationSummary {
|
|
55
|
+
actions: AutomationAction[];
|
|
56
|
+
edges: AutomationEdge[];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface AutomationsRepository {
|
|
60
|
+
browse(): Promise<Page<AutomationSummary>>;
|
|
61
|
+
getById(id: string): Promise<Automation | null>;
|
|
62
|
+
edit(id: string, data: Pick<AutomationSummary, 'status'>): Promise<Automation | null>;
|
|
63
|
+
}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createFakeDatabaseAutomationsRepository = createFakeDatabaseAutomationsRepository;
|
|
7
|
+
const errors_1 = __importDefault(require("@tryghost/errors"));
|
|
8
|
+
const tpl_1 = __importDefault(require("@tryghost/tpl"));
|
|
9
|
+
const messages = {
|
|
10
|
+
invalidAutomationActionRevision: 'Automation action "{actionId}" of type "{actionType}" is missing required revision field "{field}".'
|
|
11
|
+
};
|
|
12
|
+
function createFakeDatabaseAutomationsRepository({ getDatabase }) {
|
|
13
|
+
return {
|
|
14
|
+
async browse() {
|
|
15
|
+
const database = getDatabase();
|
|
16
|
+
return withTransaction(database, () => {
|
|
17
|
+
const rows = loadAutomations(database).map(row => buildAutomationSummary(row));
|
|
18
|
+
return {
|
|
19
|
+
data: rows,
|
|
20
|
+
meta: {
|
|
21
|
+
pagination: buildPagination(rows.length)
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
},
|
|
26
|
+
async getById(id) {
|
|
27
|
+
const database = getDatabase();
|
|
28
|
+
return withTransaction(database, () => {
|
|
29
|
+
const automation = loadAutomation(database, id);
|
|
30
|
+
if (!automation) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
return buildAutomation(database, automation);
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
async edit(id, data) {
|
|
37
|
+
const database = getDatabase();
|
|
38
|
+
return withTransaction(database, () => {
|
|
39
|
+
const automation = loadAutomation(database, id);
|
|
40
|
+
if (!automation) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
// TODO (NY-1229): Allow updating other fields and actions/edges.
|
|
44
|
+
const updatedAutomation = updateAutomation(database, {
|
|
45
|
+
...automation,
|
|
46
|
+
status: data.status,
|
|
47
|
+
updated_at: new Date().toISOString()
|
|
48
|
+
});
|
|
49
|
+
return buildAutomation(database, updatedAutomation);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function withTransaction(database, operation) {
|
|
55
|
+
database.exec('BEGIN TRANSACTION');
|
|
56
|
+
try {
|
|
57
|
+
const result = operation();
|
|
58
|
+
database.exec('COMMIT');
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
database.exec('ROLLBACK');
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function loadAutomation(database, automationId) {
|
|
67
|
+
const automation = database.prepare(`
|
|
68
|
+
SELECT id, slug, name, status, created_at, updated_at
|
|
69
|
+
FROM automations
|
|
70
|
+
WHERE id = ?
|
|
71
|
+
`).get(automationId);
|
|
72
|
+
return automation ?? null;
|
|
73
|
+
}
|
|
74
|
+
function loadAutomations(database) {
|
|
75
|
+
return database.prepare(`
|
|
76
|
+
SELECT id, slug, name, status, created_at, updated_at
|
|
77
|
+
FROM automations
|
|
78
|
+
ORDER BY created_at, id
|
|
79
|
+
`).all();
|
|
80
|
+
}
|
|
81
|
+
function updateAutomation(database, automation) {
|
|
82
|
+
database.prepare(`
|
|
83
|
+
UPDATE automations
|
|
84
|
+
SET status = :status,
|
|
85
|
+
updated_at = :updated_at
|
|
86
|
+
WHERE id = :id
|
|
87
|
+
`).run({
|
|
88
|
+
id: automation.id,
|
|
89
|
+
status: automation.status,
|
|
90
|
+
updated_at: automation.updated_at
|
|
91
|
+
});
|
|
92
|
+
return requireAutomation(loadAutomation(database, automation.id), automation.id);
|
|
93
|
+
}
|
|
94
|
+
function requireAutomation(automation, id) {
|
|
95
|
+
if (!automation) {
|
|
96
|
+
throw new errors_1.default.InternalServerError({
|
|
97
|
+
message: `Updated automation "${id}" could not be loaded.`
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return automation;
|
|
101
|
+
}
|
|
102
|
+
function buildAutomation(database, automation) {
|
|
103
|
+
return {
|
|
104
|
+
...buildAutomationSummary(automation),
|
|
105
|
+
actions: loadActionRows(database, automation.id).map(row => buildActionPayload(row)),
|
|
106
|
+
edges: loadEdgeRows(database, automation.id).map(row => buildEdgePayload(row))
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function buildAutomationSummary(automation) {
|
|
110
|
+
return {
|
|
111
|
+
id: automation.id,
|
|
112
|
+
slug: automation.slug,
|
|
113
|
+
name: automation.name,
|
|
114
|
+
status: automation.status,
|
|
115
|
+
created_at: serializeDate(automation.created_at),
|
|
116
|
+
updated_at: serializeDate(automation.updated_at)
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function serializeDate(date) {
|
|
120
|
+
const normalizedDate = new Date(date);
|
|
121
|
+
normalizedDate.setMilliseconds(0);
|
|
122
|
+
return normalizedDate.toISOString();
|
|
123
|
+
}
|
|
124
|
+
function loadActionRows(database, automationId) {
|
|
125
|
+
return database.prepare(`
|
|
126
|
+
SELECT
|
|
127
|
+
a.id AS id,
|
|
128
|
+
a.type AS type,
|
|
129
|
+
r.wait_hours AS wait_hours,
|
|
130
|
+
r.email_subject AS email_subject,
|
|
131
|
+
r.email_lexical AS email_lexical,
|
|
132
|
+
r.email_sender_name AS email_sender_name,
|
|
133
|
+
r.email_sender_email AS email_sender_email,
|
|
134
|
+
r.email_sender_reply_to AS email_sender_reply_to,
|
|
135
|
+
r.email_design_setting_id AS email_design_setting_id
|
|
136
|
+
FROM automation_actions a
|
|
137
|
+
INNER JOIN automation_action_revisions r ON r.action_id = a.id
|
|
138
|
+
WHERE a.automation_id = ?
|
|
139
|
+
AND a.deleted_at IS NULL
|
|
140
|
+
AND r.created_at = (
|
|
141
|
+
SELECT MAX(created_at)
|
|
142
|
+
FROM automation_action_revisions
|
|
143
|
+
WHERE action_id = a.id
|
|
144
|
+
)
|
|
145
|
+
ORDER BY a.created_at, a.id
|
|
146
|
+
`).all(automationId);
|
|
147
|
+
}
|
|
148
|
+
function loadEdgeRows(database, automationId) {
|
|
149
|
+
return database.prepare(`
|
|
150
|
+
SELECT e.source_action_id, e.target_action_id
|
|
151
|
+
FROM automation_action_edges e
|
|
152
|
+
INNER JOIN automation_actions a ON a.id = e.source_action_id
|
|
153
|
+
AND a.deleted_at IS NULL
|
|
154
|
+
WHERE a.automation_id = ?
|
|
155
|
+
ORDER BY e.source_action_id, e.target_action_id
|
|
156
|
+
`).all(automationId);
|
|
157
|
+
}
|
|
158
|
+
function buildActionPayload(row) {
|
|
159
|
+
switch (row.type) {
|
|
160
|
+
case 'wait':
|
|
161
|
+
return {
|
|
162
|
+
id: row.id,
|
|
163
|
+
type: 'wait',
|
|
164
|
+
data: {
|
|
165
|
+
wait_hours: requireValue(row.wait_hours, 'wait_hours', row)
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
case 'send_email':
|
|
169
|
+
return {
|
|
170
|
+
id: row.id,
|
|
171
|
+
type: 'send_email',
|
|
172
|
+
data: {
|
|
173
|
+
email_subject: requireValue(row.email_subject, 'email_subject', row),
|
|
174
|
+
email_lexical: requireValue(row.email_lexical, 'email_lexical', row),
|
|
175
|
+
email_sender_name: row.email_sender_name,
|
|
176
|
+
email_sender_email: row.email_sender_email,
|
|
177
|
+
email_sender_reply_to: row.email_sender_reply_to,
|
|
178
|
+
email_design_setting_id: requireValue(row.email_design_setting_id, 'email_design_setting_id', row)
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function requireValue(value, field, row) {
|
|
184
|
+
if (value === null) {
|
|
185
|
+
throw new errors_1.default.InternalServerError({
|
|
186
|
+
message: (0, tpl_1.default)(messages.invalidAutomationActionRevision, {
|
|
187
|
+
actionId: row.id,
|
|
188
|
+
actionType: row.type,
|
|
189
|
+
field
|
|
190
|
+
})
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
return value;
|
|
194
|
+
}
|
|
195
|
+
function buildEdgePayload(edge) {
|
|
196
|
+
return {
|
|
197
|
+
source_action_id: edge.source_action_id,
|
|
198
|
+
target_action_id: edge.target_action_id
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function buildPagination(total) {
|
|
202
|
+
return {
|
|
203
|
+
page: 1,
|
|
204
|
+
pages: 1,
|
|
205
|
+
limit: 'all',
|
|
206
|
+
total,
|
|
207
|
+
prev: null,
|
|
208
|
+
next: null
|
|
209
|
+
};
|
|
210
|
+
}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import errors from '@tryghost/errors';
|
|
2
|
+
import tpl from '@tryghost/tpl';
|
|
3
|
+
import type {DatabaseSync} from 'node:sqlite';
|
|
4
|
+
import type {
|
|
5
|
+
Automation,
|
|
6
|
+
AutomationAction,
|
|
7
|
+
AutomationEdge,
|
|
8
|
+
AutomationSummary,
|
|
9
|
+
AutomationsRepository,
|
|
10
|
+
Page
|
|
11
|
+
} from './automations-repository';
|
|
12
|
+
|
|
13
|
+
const messages = {
|
|
14
|
+
invalidAutomationActionRevision: 'Automation action "{actionId}" of type "{actionType}" is missing required revision field "{field}".'
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
interface AutomationRow {
|
|
18
|
+
id: string;
|
|
19
|
+
slug: string;
|
|
20
|
+
name: string;
|
|
21
|
+
status: string;
|
|
22
|
+
created_at: string;
|
|
23
|
+
updated_at: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface ActionRow {
|
|
27
|
+
id: string;
|
|
28
|
+
type: 'wait' | 'send_email';
|
|
29
|
+
wait_hours: number | null;
|
|
30
|
+
email_subject: string | null;
|
|
31
|
+
email_lexical: string | null;
|
|
32
|
+
email_sender_name: string | null;
|
|
33
|
+
email_sender_email: string | null;
|
|
34
|
+
email_sender_reply_to: string | null;
|
|
35
|
+
email_design_setting_id: string | null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface EdgeRow {
|
|
39
|
+
source_action_id: string;
|
|
40
|
+
target_action_id: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function createFakeDatabaseAutomationsRepository({
|
|
44
|
+
getDatabase
|
|
45
|
+
}: {
|
|
46
|
+
getDatabase: () => DatabaseSync;
|
|
47
|
+
}): AutomationsRepository {
|
|
48
|
+
return {
|
|
49
|
+
async browse(): Promise<Page<AutomationSummary>> {
|
|
50
|
+
const database = getDatabase();
|
|
51
|
+
|
|
52
|
+
return withTransaction(database, () => {
|
|
53
|
+
const rows = loadAutomations(database).map(row => buildAutomationSummary(row));
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
data: rows,
|
|
57
|
+
meta: {
|
|
58
|
+
pagination: buildPagination(rows.length)
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
async getById(id: string): Promise<Automation | null> {
|
|
65
|
+
const database = getDatabase();
|
|
66
|
+
return withTransaction(database, () => {
|
|
67
|
+
const automation = loadAutomation(database, id);
|
|
68
|
+
|
|
69
|
+
if (!automation) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return buildAutomation(database, automation);
|
|
74
|
+
});
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
async edit(id: string, data: Pick<AutomationSummary, 'status'>): Promise<Automation | null> {
|
|
78
|
+
const database = getDatabase();
|
|
79
|
+
|
|
80
|
+
return withTransaction(database, () => {
|
|
81
|
+
const automation = loadAutomation(database, id);
|
|
82
|
+
|
|
83
|
+
if (!automation) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// TODO (NY-1229): Allow updating other fields and actions/edges.
|
|
88
|
+
const updatedAutomation = updateAutomation(database, {
|
|
89
|
+
...automation,
|
|
90
|
+
status: data.status,
|
|
91
|
+
updated_at: new Date().toISOString()
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
return buildAutomation(database, updatedAutomation);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function withTransaction<T>(database: DatabaseSync, operation: () => T): T {
|
|
101
|
+
database.exec('BEGIN TRANSACTION');
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
const result = operation();
|
|
105
|
+
database.exec('COMMIT');
|
|
106
|
+
return result;
|
|
107
|
+
} catch (error) {
|
|
108
|
+
database.exec('ROLLBACK');
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function loadAutomation(database: DatabaseSync, automationId: string): AutomationRow | null {
|
|
114
|
+
const automation = database.prepare(`
|
|
115
|
+
SELECT id, slug, name, status, created_at, updated_at
|
|
116
|
+
FROM automations
|
|
117
|
+
WHERE id = ?
|
|
118
|
+
`).get(automationId) as AutomationRow | undefined;
|
|
119
|
+
|
|
120
|
+
return automation ?? null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function loadAutomations(database: DatabaseSync): AutomationRow[] {
|
|
124
|
+
return database.prepare(`
|
|
125
|
+
SELECT id, slug, name, status, created_at, updated_at
|
|
126
|
+
FROM automations
|
|
127
|
+
ORDER BY created_at, id
|
|
128
|
+
`).all() as unknown as AutomationRow[];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function updateAutomation(database: DatabaseSync, automation: AutomationRow): AutomationRow {
|
|
132
|
+
database.prepare(`
|
|
133
|
+
UPDATE automations
|
|
134
|
+
SET status = :status,
|
|
135
|
+
updated_at = :updated_at
|
|
136
|
+
WHERE id = :id
|
|
137
|
+
`).run({
|
|
138
|
+
id: automation.id,
|
|
139
|
+
status: automation.status,
|
|
140
|
+
updated_at: automation.updated_at
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
return requireAutomation(loadAutomation(database, automation.id), automation.id);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function requireAutomation(automation: AutomationRow | null, id: string): AutomationRow {
|
|
147
|
+
if (!automation) {
|
|
148
|
+
throw new errors.InternalServerError({
|
|
149
|
+
message: `Updated automation "${id}" could not be loaded.`
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return automation;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function buildAutomation(database: DatabaseSync, automation: AutomationRow): Automation {
|
|
157
|
+
return {
|
|
158
|
+
...buildAutomationSummary(automation),
|
|
159
|
+
actions: loadActionRows(database, automation.id).map(row => buildActionPayload(row)),
|
|
160
|
+
edges: loadEdgeRows(database, automation.id).map(row => buildEdgePayload(row))
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function buildAutomationSummary(automation: AutomationRow): AutomationSummary {
|
|
165
|
+
return {
|
|
166
|
+
id: automation.id,
|
|
167
|
+
slug: automation.slug,
|
|
168
|
+
name: automation.name,
|
|
169
|
+
status: automation.status,
|
|
170
|
+
created_at: serializeDate(automation.created_at),
|
|
171
|
+
updated_at: serializeDate(automation.updated_at)
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function serializeDate(date: string) {
|
|
176
|
+
const normalizedDate = new Date(date);
|
|
177
|
+
normalizedDate.setMilliseconds(0);
|
|
178
|
+
return normalizedDate.toISOString();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function loadActionRows(database: DatabaseSync, automationId: string): ActionRow[] {
|
|
182
|
+
return database.prepare(`
|
|
183
|
+
SELECT
|
|
184
|
+
a.id AS id,
|
|
185
|
+
a.type AS type,
|
|
186
|
+
r.wait_hours AS wait_hours,
|
|
187
|
+
r.email_subject AS email_subject,
|
|
188
|
+
r.email_lexical AS email_lexical,
|
|
189
|
+
r.email_sender_name AS email_sender_name,
|
|
190
|
+
r.email_sender_email AS email_sender_email,
|
|
191
|
+
r.email_sender_reply_to AS email_sender_reply_to,
|
|
192
|
+
r.email_design_setting_id AS email_design_setting_id
|
|
193
|
+
FROM automation_actions a
|
|
194
|
+
INNER JOIN automation_action_revisions r ON r.action_id = a.id
|
|
195
|
+
WHERE a.automation_id = ?
|
|
196
|
+
AND a.deleted_at IS NULL
|
|
197
|
+
AND r.created_at = (
|
|
198
|
+
SELECT MAX(created_at)
|
|
199
|
+
FROM automation_action_revisions
|
|
200
|
+
WHERE action_id = a.id
|
|
201
|
+
)
|
|
202
|
+
ORDER BY a.created_at, a.id
|
|
203
|
+
`).all(automationId) as unknown as ActionRow[];
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function loadEdgeRows(database: DatabaseSync, automationId: string): EdgeRow[] {
|
|
207
|
+
return database.prepare(`
|
|
208
|
+
SELECT e.source_action_id, e.target_action_id
|
|
209
|
+
FROM automation_action_edges e
|
|
210
|
+
INNER JOIN automation_actions a ON a.id = e.source_action_id
|
|
211
|
+
AND a.deleted_at IS NULL
|
|
212
|
+
WHERE a.automation_id = ?
|
|
213
|
+
ORDER BY e.source_action_id, e.target_action_id
|
|
214
|
+
`).all(automationId) as unknown as EdgeRow[];
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function buildActionPayload(row: ActionRow): AutomationAction {
|
|
218
|
+
switch (row.type) {
|
|
219
|
+
case 'wait':
|
|
220
|
+
return {
|
|
221
|
+
id: row.id,
|
|
222
|
+
type: 'wait',
|
|
223
|
+
data: {
|
|
224
|
+
wait_hours: requireValue(row.wait_hours, 'wait_hours', row)
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
case 'send_email':
|
|
228
|
+
return {
|
|
229
|
+
id: row.id,
|
|
230
|
+
type: 'send_email',
|
|
231
|
+
data: {
|
|
232
|
+
email_subject: requireValue(row.email_subject, 'email_subject', row),
|
|
233
|
+
email_lexical: requireValue(row.email_lexical, 'email_lexical', row),
|
|
234
|
+
email_sender_name: row.email_sender_name,
|
|
235
|
+
email_sender_email: row.email_sender_email,
|
|
236
|
+
email_sender_reply_to: row.email_sender_reply_to,
|
|
237
|
+
email_design_setting_id: requireValue(row.email_design_setting_id, 'email_design_setting_id', row)
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function requireValue<T>(value: T | null, field: string, row: ActionRow): T {
|
|
244
|
+
if (value === null) {
|
|
245
|
+
throw new errors.InternalServerError({
|
|
246
|
+
message: tpl(messages.invalidAutomationActionRevision, {
|
|
247
|
+
actionId: row.id,
|
|
248
|
+
actionType: row.type,
|
|
249
|
+
field
|
|
250
|
+
})
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return value;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function buildEdgePayload(edge: EdgeRow): AutomationEdge {
|
|
258
|
+
return {
|
|
259
|
+
source_action_id: edge.source_action_id,
|
|
260
|
+
target_action_id: edge.target_action_id
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function buildPagination(total: number) {
|
|
265
|
+
return {
|
|
266
|
+
page: 1,
|
|
267
|
+
pages: 1,
|
|
268
|
+
limit: 'all' as const,
|
|
269
|
+
total,
|
|
270
|
+
prev: null,
|
|
271
|
+
next: null
|
|
272
|
+
};
|
|
273
|
+
}
|
|
@@ -20,6 +20,7 @@ function createTemporaryFakeAutomationsDatabase() {
|
|
|
20
20
|
const {DatabaseSync} = require('node:sqlite');
|
|
21
21
|
|
|
22
22
|
const database = new DatabaseSync(':memory:');
|
|
23
|
+
database.exec('PRAGMA foreign_keys = ON;');
|
|
23
24
|
|
|
24
25
|
const id = () => ObjectId().toHexString();
|
|
25
26
|
const now = () => new Date().toISOString();
|
|
@@ -155,7 +156,7 @@ CREATE TABLE automation_run_steps (
|
|
|
155
156
|
created_at: now(),
|
|
156
157
|
updated_at: now(),
|
|
157
158
|
automation_id: freeAutomationId,
|
|
158
|
-
type: '
|
|
159
|
+
type: 'send_email'
|
|
159
160
|
});
|
|
160
161
|
insertAction.run({
|
|
161
162
|
id: freeAction3Id,
|
|
@@ -169,7 +170,7 @@ CREATE TABLE automation_run_steps (
|
|
|
169
170
|
created_at: now(),
|
|
170
171
|
updated_at: now(),
|
|
171
172
|
automation_id: freeAutomationId,
|
|
172
|
-
type: '
|
|
173
|
+
type: 'send_email'
|
|
173
174
|
});
|
|
174
175
|
insertAction.run({
|
|
175
176
|
id: paidAction1Id,
|
|
@@ -183,7 +184,7 @@ CREATE TABLE automation_run_steps (
|
|
|
183
184
|
created_at: now(),
|
|
184
185
|
updated_at: now(),
|
|
185
186
|
automation_id: paidAutomationId,
|
|
186
|
-
type: '
|
|
187
|
+
type: 'send_email'
|
|
187
188
|
});
|
|
188
189
|
insertAction.run({
|
|
189
190
|
id: paidAction3Id,
|
|
@@ -197,7 +198,7 @@ CREATE TABLE automation_run_steps (
|
|
|
197
198
|
created_at: now(),
|
|
198
199
|
updated_at: now(),
|
|
199
200
|
automation_id: paidAutomationId,
|
|
200
|
-
type: '
|
|
201
|
+
type: 'send_email'
|
|
201
202
|
});
|
|
202
203
|
|
|
203
204
|
const insertActionRevision = database.prepare(`
|
|
@@ -12,8 +12,7 @@
|
|
|
12
12
|
table.body .content { padding: 0 !important; }
|
|
13
13
|
table.body .container { padding: 0 !important; width: 100% !important; }
|
|
14
14
|
table.body .main { border-radius: 0 !important; }
|
|
15
|
-
table.body p.
|
|
16
|
-
table.body p.small, table.body a.small { font-size: 12px !important; }
|
|
15
|
+
table.body p.small, table.body a.small { font-size: 11px !important; }
|
|
17
16
|
}
|
|
18
17
|
</style>
|
|
19
18
|
</head>
|
|
@@ -40,47 +39,26 @@
|
|
|
40
39
|
{{/if}}
|
|
41
40
|
<tr>
|
|
42
41
|
<td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top;">
|
|
43
|
-
<h1 style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 26px; color: #15212A; font-weight: bold; line-height: 28px; margin: 0; padding-bottom:
|
|
44
|
-
<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; color: #3A464C; font-weight: normal; margin: 0; padding-bottom: 24px;">
|
|
45
|
-
<table width="100%" border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; table-layout: fixed; width: 100%; min-width: 100%; box-sizing: border-box; background: #F4F5F6; border-radius:
|
|
42
|
+
<h1 style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 26px; color: #15212A; font-weight: bold; line-height: 28px; margin: 0; padding-bottom: 16px;">Your gift is ready</h1>
|
|
43
|
+
<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; color: #3A464C; font-weight: normal; line-height: 24px; margin: 0; padding-bottom: 24px;">Thanks for supporting {{siteTitle}}. Share the link below to give someone access to <strong>{{gift.tierName}}</strong> membership for <strong>{{gift.cadenceLabel}}</strong>.</p>
|
|
44
|
+
<table width="100%" border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; table-layout: fixed; width: 100%; min-width: 100%; box-sizing: border-box; background: #F4F5F6; border-radius: 6px;">
|
|
46
45
|
<tbody>
|
|
47
46
|
<tr>
|
|
48
|
-
<td align="left" style="padding:
|
|
49
|
-
<
|
|
50
|
-
<tr>
|
|
51
|
-
<td style="padding-right: 8px; background-color: #F4F5F6; text-align: left; vertical-align: middle;" valign="middle">
|
|
52
|
-
<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 15px; margin: 0; padding-bottom: 4px; color: #15171A; font-weight: 700;">Gift subscription</p>
|
|
53
|
-
<p class="large" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 18px; margin: 0; padding-bottom: 24px; color: #15171A; font-weight: 400;">{{gift.tierName}} • {{gift.cadenceLabel}}</p>
|
|
54
|
-
<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 15px; margin: 0; padding-bottom: 4px; color: #15171A; font-weight: 700;">Gift link</p>
|
|
55
|
-
<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 15px; margin: 0; padding-bottom: 0; color: #738A94; word-break: break-all;"><a href="{{gift.link}}" style="color: {{accentColor}}; text-decoration: none;">{{gift.link}}</a></p>
|
|
56
|
-
</td>
|
|
57
|
-
</tr>
|
|
58
|
-
</table>
|
|
47
|
+
<td align="left" style="padding: 14px 16px;">
|
|
48
|
+
<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 15px; line-height: 22px; color: #15212A; margin: 0; word-break: break-all;">{{gift.link}}</p>
|
|
59
49
|
</td>
|
|
60
50
|
</tr>
|
|
61
51
|
</tbody>
|
|
62
52
|
</table>
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; padding-top: 16px;">
|
|
66
|
-
<tr>
|
|
67
|
-
<td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top;">
|
|
68
|
-
<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 13px; margin: 0; padding-bottom: 0; color: #738A94;">This link expires on {{gift.expiresAt}} and can be redeemed once by anyone who isn't already a paid member of {{siteTitle}}.</p>
|
|
69
|
-
</td>
|
|
70
|
-
</tr>
|
|
71
|
-
</table>
|
|
53
|
+
<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; color: #3A464C; font-weight: normal; line-height: 24px; margin: 0; padding-top: 24px; padding-bottom: 24px;">The link can be redeemed once and expires on <strong>{{gift.expiresAt}}</strong>.</p>
|
|
54
|
+
<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; color: #3A464C; font-weight: normal; line-height: 24px; margin: 0;">Happy gifting.</p>
|
|
72
55
|
</td>
|
|
73
56
|
</tr>
|
|
74
57
|
|
|
75
58
|
<!-- START FOOTER -->
|
|
76
59
|
<tr>
|
|
77
|
-
<td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size:
|
|
78
|
-
<p class="small" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; line-height:
|
|
79
|
-
</td>
|
|
80
|
-
</tr>
|
|
81
|
-
<tr>
|
|
82
|
-
<td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 12px; vertical-align: top;">
|
|
83
|
-
<p class="small" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; line-height: 18px; font-size: 12px; color: #7C8B9A; font-weight: normal; margin: 0;">You received this email because you purchased a gift subscription on <a class="small" href="{{siteUrl}}" style="text-decoration: underline; color: #7C8B9A; font-size: 12px;">{{siteTitle}}</a>.</p>
|
|
60
|
+
<td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top; padding-top: 80px;">
|
|
61
|
+
<p class="small" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; line-height: 16px; font-size: 11px; color: #738A94; font-weight: normal; margin: 0;">This message was sent from <a class="small" href="{{siteUrl}}" style="text-decoration: underline; color: #738A94; font-size: 11px;">{{siteDomain}}</a> to <a class="small" href="mailto:{{toEmail}}" style="text-decoration: underline; color: #738A94; font-size: 11px;">{{toEmail}}</a>.</p>
|
|
84
62
|
</td>
|
|
85
63
|
</tr>
|
|
86
64
|
|