ghost 6.53.0 → 6.54.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/ghost-storage-base-3.0.0.tgz +0 -0
- package/components/tryghost-adapter-base-cache-0.2.0.tgz +0 -0
- package/components/tryghost-adapter-base-scheduling-0.1.1.tgz +0 -0
- package/components/tryghost-adapter-base-sso-0.1.1.tgz +0 -0
- package/components/tryghost-admin-api-schema-0.0.0.tgz +0 -0
- package/components/tryghost-custom-field-types-0.0.0.tgz +0 -0
- package/components/tryghost-i18n-0.0.0.tgz +0 -0
- package/components/tryghost-kg-converters-1.2.3.tgz +0 -0
- package/components/tryghost-kg-default-nodes-2.1.3.tgz +0 -0
- package/components/tryghost-kg-lexical-html-renderer-1.4.3.tgz +0 -0
- package/core/boot.js +9 -6
- package/core/built/admin/assets/Combination-CJG7Flp-.js +41 -0
- package/core/built/admin/assets/Growth-CSaHoSVD.js +3 -0
- package/core/built/admin/assets/Newsletters-C5cs6FGo.js +1 -0
- package/core/built/admin/assets/Overview-j4NaeUNm.js +1 -0
- package/core/built/admin/assets/{PolarAngleAxis-pciQ0MOy.js → PolarAngleAxis-BGjf7sBu.js} +1 -1
- package/core/built/admin/assets/{RadialBarChart-DWmw2PcX.js → RadialBarChart-zeFf9mBz.js} +1 -1
- package/core/built/admin/assets/Web-_fD935OX.js +2 -0
- package/core/built/admin/assets/account-migration-DLvVA5yq.js +1 -0
- package/core/built/admin/assets/activitypub/{account-migration-BPZG37DJ.js → account-migration-DHbZcxGM.js} +13 -13
- package/core/built/admin/assets/activitypub/activitypub.js +7 -7
- package/core/built/admin/assets/activitypub/{avatar-ZYco0ITb.js → avatar-B3DEDB1l.js} +10 -10
- package/core/built/admin/assets/activitypub/{avatar-flipboard-D541lc4F.js → avatar-flipboard-Cqrg0XMx.js} +3 -3
- package/core/built/admin/assets/activitypub/{bluesky-sharing-NOHUtHjl.js → bluesky-sharing-zfxUey_L.js} +38 -37
- package/core/built/admin/assets/activitypub/{chunk-KS7C4IRE-B-GOFDPZ.js → chunk-KS7C4IRE-D4HEcEwi.js} +716 -710
- package/core/built/admin/assets/activitypub/{content-formatters-bwrp4iEO.js → content-formatters-BpQARh28.js} +229 -181
- package/core/built/admin/assets/activitypub/{copy-C7m7ovHw.js → copy-D9UWIAan.js} +2 -2
- package/core/built/admin/assets/activitypub/{dist-B5ira32t.js → dist-Ba_QxHHl.js} +5 -5
- package/core/built/admin/assets/activitypub/{domain-iqE4YXwD.js → domain-CmwSZLHK.js} +33 -33
- package/core/built/admin/assets/activitypub/{edit-profile-B8MFYh28.js → edit-profile-CXdwNmVG.js} +46 -45
- package/core/built/admin/assets/activitypub/{explore-BbdKodp3.js → explore-DfbjzGM1.js} +20 -20
- package/core/built/admin/assets/activitypub/{feed-Cl3A5owG.js → feed-DSEBJOqf.js} +15 -15
- package/core/built/admin/assets/activitypub/{field-DL6WyR-c.js → field-CY7XVcx6.js} +13 -13
- package/core/built/admin/assets/activitypub/{hash-6G3DzwL9.js → hash-BC9Q0N4c.js} +2 -2
- package/core/built/admin/assets/activitypub/{inbox-YmhuBice.js → inbox-DQ4ZnC1m.js} +2 -2
- package/core/built/admin/assets/activitypub/inbox-DtQ0kytT.js +1221 -0
- package/core/built/admin/assets/activitypub/{label-DGbLjDvE.js → label-Dw96GQ7u.js} +6 -6
- package/core/built/admin/assets/activitypub/layout-IdVq3lRy.js +1 -0
- package/core/built/admin/assets/activitypub/{moderation-qnBtk1zS.js → moderation-Dg_-I-8C.js} +32 -31
- package/core/built/admin/assets/activitypub/{note-C7ZRoSJv.js → note-Cy1-uKMY.js} +21 -21
- package/core/built/admin/assets/activitypub/{notifications-DiEA4b1o.js → notifications-B_fvoLIM.js} +17 -17
- package/core/built/admin/assets/activitypub/{onboarding-_JVgEwgV.js → onboarding-BFDkzeR2.js} +2 -2
- package/core/built/admin/assets/activitypub/{onboarding-DG4zu3qM.js → onboarding-D6rcBdPe.js} +5 -5
- package/core/built/admin/assets/activitypub/{preferences-B3FtocnP.js → preferences-ByJseZp6.js} +1607 -1606
- package/core/built/admin/assets/activitypub/{profile-D8ZJfYXB.js → profile-BFtbnIjz.js} +264 -263
- package/core/built/admin/assets/activitypub/{reply-C1vggenw.js → reply-CpdMeAO5.js} +2 -2
- package/core/built/admin/assets/activitypub/{routes-BOii-V9n.js → routes-Dh3xXfce.js} +1311 -1295
- package/core/built/admin/assets/activitypub/{separator-1gNokN5S.js → separator-BI1FLsYM.js} +4 -4
- package/core/built/admin/assets/activitypub/{settings--9Sb0nbl.js → settings-DTgqJPxM.js} +14 -14
- package/core/built/admin/assets/activitypub/{site-fkMmqv0V.js → site-CdL9ZLqm.js} +10 -10
- package/core/built/admin/assets/activitypub/{step-1-QhivSMw2.js → step-1-DIDg4aHb.js} +15 -15
- package/core/built/admin/assets/activitypub/{step-2-pMk9YwqD.js → step-2-BfGe8BYt.js} +7 -7
- package/core/built/admin/assets/activitypub/{step-3-DvmVC1fo.js → step-3-mE9spAqw.js} +12 -12
- package/core/built/admin/assets/activitypub/{tabs-Dc0FEEYD.js → tabs-ogqwoBlb.js} +241 -237
- package/core/built/admin/assets/activitypub/{topic-filter-CuDyM5bD.js → topic-filter-DLHBZT93.js} +4 -4
- package/core/built/admin/assets/activitypub/use-activity-pub-queries-VzbN99u_.js +1957 -0
- package/core/built/admin/assets/activitypub/{use-navigate-with-base-path-Drx1kdAK.js → use-navigate-with-base-path-CAwXTmqH.js} +165 -175
- package/core/built/admin/assets/activitypub/{use-reply-chain-data-BHkCHcW5.js → use-reply-chain-data-CxonteFD.js} +8 -8
- package/core/built/admin/assets/activitypub/users-BLeiOTHc.js +1464 -0
- package/core/built/admin/assets/activitypub/{x-BHCEe-c2.js → x-C8tAnXly.js} +2 -2
- package/core/built/admin/assets/{audience-adiFehTD.js → audience-BKRdsFmy.js} +1 -1
- package/core/built/admin/assets/{automated-emails-UWM02CMr.js → automated-emails-Cn87L5Md.js} +1 -1
- package/core/built/admin/assets/automations-B7-y3dXt.js +1 -0
- package/core/built/admin/assets/automations-BP_aHamJ.js +1 -0
- package/core/built/admin/assets/{avatar-flipboard-Lz3F9fNT.js → avatar-flipboard-C6Kj3Awu.js} +1 -1
- package/core/built/admin/assets/bluesky-sharing-Bh36XPh4.js +1 -0
- package/core/built/admin/assets/box-BWbhXh21.js +1 -0
- package/core/built/admin/assets/breadcrumb-D34YWnaw.js +1 -0
- package/core/built/admin/assets/card-DGoDJzrn.js +1 -0
- package/core/built/admin/assets/{chart-ChpW-NzQ.js → chart-BuRT2Y6p.js} +14 -14
- package/core/built/admin/assets/chart-helpers-DbklaJw9.js +1 -0
- package/core/built/admin/assets/checkbox-DA4-1UiI.js +1 -0
- package/core/built/admin/assets/chunk.524.45e0875f41b71e46e849.js +25 -0
- package/core/built/admin/assets/chunk.582.51defd4b009f0de8d4d5.js +27 -0
- package/core/built/admin/assets/{chunk.831.0703a12e49f51cec3f3a.js → chunk.589.096f4d0bb775e5229aa9.js} +78 -85
- package/core/built/admin/assets/{chunk.432.c2caa0b20f03e71d1a35.js → chunk.962.b73442b07be930bb5d85.js} +2216 -3188
- package/core/built/admin/assets/{chunk.432.c2caa0b20f03e71d1a35.js.LICENSE.txt → chunk.962.b73442b07be930bb5d85.js.LICENSE.txt} +0 -63
- package/core/built/admin/assets/code-editor-view-BKBrkffZ.js +1 -0
- package/core/built/admin/assets/comments-CzVNIT8b.js +1 -0
- package/core/built/admin/assets/container-BYz2Ed39.js +1 -0
- package/core/built/admin/assets/data-list-16rkJYYi.js +1 -0
- package/core/built/admin/assets/date-range-select-B5vSsrpx.js +1 -0
- package/core/built/admin/assets/disabled-sources-indicator-NkOIoMue.js +1 -0
- package/core/built/admin/assets/{dist-CsekE4FL.js → dist-CQJY6SVY.js} +1 -1
- package/core/built/admin/assets/dist-DGzPJ_bO.js +4 -0
- package/core/built/admin/assets/{dist-BbGrW05X.js → dist-DyViJwIy.js} +1 -1
- package/core/built/admin/assets/dist-Ndy-PuGN.js +1 -0
- package/core/built/admin/assets/dist-P_ohUlTi.js +1 -0
- package/core/built/admin/assets/domain-B7_n5nfx.js +1 -0
- package/core/built/admin/assets/dropzone-DcuJEEUf.js +5 -0
- package/core/built/admin/assets/edit-profile-rvDGrS8J.js +1 -0
- package/core/built/admin/assets/editor-BCiIyFjm.js +8 -0
- package/core/built/admin/assets/empty-indicator-oX1u1Pkn.js +1 -0
- package/core/built/admin/assets/esm-CFX93H5M.js +2 -0
- package/core/built/admin/assets/explore-BZAZOg5X.js +1 -0
- package/core/built/admin/assets/feed-CFV8xDw9.js +1 -0
- package/core/built/admin/assets/field-BW-M2Zwp.js +1 -0
- package/core/built/admin/assets/{filter-sources-v39ihhhV.js → filter-sources-Fx8wiYYw.js} +1 -1
- package/core/built/admin/assets/filters-CGX_pf2N.js +1 -0
- package/core/built/admin/assets/filters-DtcXMZDU.js +1 -0
- package/core/built/admin/assets/framework-provider-CmtnPXIT.js +4 -0
- package/core/built/admin/assets/{ghost-b57f077997b739a8ae9a70772dc016cb.js → ghost-b1dce91ad3232cc259ee5fbbf9526243.js} +294 -290
- package/core/built/admin/assets/ghost-dark-c8d0ab7f515b2010c173e23e9b32ea8a.css +1 -0
- package/core/built/admin/assets/gift-link-modal-Bk8qpnMw.js +1 -0
- package/core/built/admin/assets/{gift-links-CY3GwiVi.js → gift-links-nBxJjZiQ.js} +1 -1
- package/core/built/admin/assets/growth-Ck2s3JjR.js +1 -0
- package/core/built/admin/assets/hooks-BApwwBE0.js +2 -0
- package/core/built/admin/assets/{inbox-TEISAmth.js → inbox-BRp1_aaC.js} +35 -35
- package/core/built/admin/assets/index-BBf502Wg.js +69 -0
- package/core/built/admin/assets/index-BCCZKxP2.css +1 -0
- package/core/built/admin/assets/inline-EMAm3okk.js +1 -0
- package/core/built/admin/assets/input-group-DjuYnNCd.js +1 -0
- package/core/built/admin/assets/{react-dom-C6aoWSfl.js → jsx-runtime-DX3WBWVO.js} +1 -1
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +5 -2
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +2 -2
- package/core/built/admin/assets/{koenig-lexical-Di7b48ED.js → koenig-lexical-CM7UFNdL.js} +2 -2
- package/core/built/admin/assets/kpi-card-BrGH6FsT.js +1 -0
- package/core/built/admin/assets/kpi-card-CIGyijjx.js +1 -0
- package/core/built/admin/assets/kpi-helpers-_HRRsklE.js +1 -0
- package/core/built/admin/assets/kpi-tabs-BSvh9eoq.js +1 -0
- package/core/built/admin/assets/label-BOR9XdKl.js +1 -0
- package/core/built/admin/assets/label-picker-BdNAWuUX.js +1 -0
- package/core/built/admin/assets/{labels-GbxlXWtf.js → labels-Cyayfd-e.js} +1 -1
- package/core/built/admin/assets/layout-Bw4GnxXp.js +1 -0
- package/core/built/admin/assets/limit-service-9fwD33lU.js +20 -0
- package/core/built/admin/assets/link-helpers-tOlxmuH5.js +1 -0
- package/core/built/admin/assets/list-page-B6ANtzkd.js +1 -0
- package/core/built/admin/assets/mailchimp-Ds_NQ04w.svg +9 -0
- package/core/built/admin/assets/member-custom-fields-DvFyamLu.js +1 -0
- package/core/built/admin/assets/member-detail-Cg2vTqvJ.js +1 -0
- package/core/built/admin/assets/members-DsPxYAVm.js +10 -0
- package/core/built/admin/assets/modals-Bf_fyvHZ.js +31 -0
- package/core/built/admin/assets/moderation-Dlp7M5sa.js +1 -0
- package/core/built/admin/assets/multi-select-combobox-CH1o8XXQ.js +1 -0
- package/core/built/admin/assets/newsletter-CQ5CAYUI.js +1 -0
- package/core/built/admin/assets/{newsletters-DZm3yLj8.js → newsletters-D1jbtV-h.js} +1 -1
- package/core/built/admin/assets/note-BrAZ7Z0o.js +1 -0
- package/core/built/admin/assets/notifications-BnbHLOPC.js +1 -0
- package/core/built/admin/assets/nql-lang-B7faUf8D.js +19 -0
- package/core/built/admin/assets/{offers-D11QtPXX.js → offers-CrY6nSRR.js} +1 -1
- package/core/built/admin/assets/onboarding-route-eU146kuA.js +1 -0
- package/core/built/admin/assets/overview-BpbaK-xu.js +1 -0
- package/core/built/admin/assets/page-header-C0jVxtS8.js +1 -0
- package/core/built/admin/assets/{pages-BnObVRrf.js → pages-BbNWFcGj.js} +1 -1
- package/core/built/admin/assets/pintura-CXOmq-5H.svg +15 -0
- package/core/built/admin/assets/post-analytics-Iw7dk1mT.js +1 -0
- package/core/built/admin/assets/post-analytics-header-D9pJ4iNm.js +1 -0
- package/core/built/admin/assets/{post-analytics-provider-DSfBCtnj.js → post-analytics-provider-BDqcfBor.js} +1 -1
- package/core/built/admin/assets/post-share-modal-DBfKl2GZ.js +1 -0
- package/core/built/admin/assets/{posts-CwH8VJvB.js → posts-EWpZIjkr.js} +1 -1
- package/core/built/admin/assets/preferences-D4EANGoc.js +5 -0
- package/core/built/admin/assets/profile-dJ44Bn_W.js +1 -0
- package/core/built/admin/assets/{referrers-nxR52jPI.js → referrers-BCfFYSHc.js} +1 -1
- package/core/built/admin/assets/router-provider-C1R4AZ2o.js +1 -0
- package/core/built/admin/assets/select--2uVN9_-.js +1 -0
- package/core/built/admin/assets/settings-Bz3RZRmE.js +1 -0
- package/core/built/admin/assets/settings-SD9bxIpt.js +4 -0
- package/core/built/admin/assets/share-modal-CkdTTMJd.js +1 -0
- package/core/built/admin/assets/social-urls-BvFZwYcE.js +8 -0
- package/core/built/admin/assets/sort-button-DZp9Y2r1.js +1 -0
- package/core/built/admin/assets/source-icon-CHr9qJ2Y.js +1 -0
- package/core/built/admin/assets/stack-xiN0eQ6Z.js +1 -0
- package/core/built/admin/assets/stats-DGoXZxWE.js +1 -0
- package/core/built/admin/assets/stats-view-D2-1L0ms.js +1 -0
- package/core/built/admin/assets/step-1-RdahbwyG.js +1 -0
- package/core/built/admin/assets/step-2-D83PeRwd.js +1 -0
- package/core/built/admin/assets/step-3-p_Op4wv4.js +2 -0
- package/core/built/admin/assets/switch-qp518gFQ.js +1 -0
- package/core/built/admin/assets/table-B8LgTQJZ.js +1 -0
- package/core/built/admin/assets/tabs-D3ZOYkM7.js +1 -0
- package/core/built/admin/assets/tags-B4l891z2.js +1 -0
- package/core/built/admin/assets/text-DwtjwGkh.js +1 -0
- package/core/built/admin/assets/textarea-CTlb3Uu6.js +1 -0
- package/core/built/admin/assets/{tiers-EghDzCKc.js → tiers-BgYLWRJv.js} +1 -1
- package/core/built/admin/assets/toggle-group-DNXDkAwf.js +1 -0
- package/core/built/admin/assets/topic-filter-DZGjEcz3.js +1 -0
- package/core/built/admin/assets/{use-analytics-data-0l_OHtnR.js → use-analytics-data-CaT8RirX.js} +1 -1
- package/core/built/admin/assets/use-filter-params-DeQ8sX4N.js +1 -0
- package/core/built/admin/assets/use-growth-stats-9Db2CuJe.js +1 -0
- package/core/built/admin/assets/{use-post-referrers-DwI31Ril.js → use-post-referrers-BV54YcQS.js} +1 -1
- package/core/built/admin/assets/use-reply-chain-data-DuYZGDan.js +1 -0
- package/core/built/admin/assets/use-simple-pagination-8fTua9Nt.js +1 -0
- package/core/built/admin/assets/{use-tinybird-query-DvZBBMG7.js → use-tinybird-query-Dz156HvZ.js} +1 -1
- package/core/built/admin/assets/{use-tinybird-token-CQtebkvU.js → use-tinybird-token-C9RUdL_n.js} +1 -1
- package/core/built/admin/assets/{users-Pc8IRjk9.js → users-CcSCQFcQ.js} +1 -1
- package/core/built/admin/assets/virtual-list-BCvP0YF-.js +1 -0
- package/core/built/admin/assets/web-DTZnnUGr.js +1 -0
- package/core/built/admin/index.html +18 -22
- package/core/frontend/apps/private-blogging/index.js +1 -1
- package/core/frontend/apps/private-blogging/lib/middleware.js +1 -1
- package/core/frontend/helpers/split.js +2 -1
- package/core/frontend/meta/asset-url.js +1 -1
- package/core/frontend/meta/author-image.js +1 -1
- package/core/frontend/meta/blog-logo.js +1 -1
- package/core/frontend/meta/canonical-url.js +1 -1
- package/core/frontend/meta/cover-image.js +1 -1
- package/core/frontend/meta/get-meta.js +1 -1
- package/core/frontend/meta/og-image.js +1 -1
- package/core/frontend/meta/paginated-url.js +1 -1
- package/core/frontend/meta/twitter-image.js +1 -1
- package/core/frontend/meta/url.js +1 -1
- package/core/frontend/services/assets-minification/admin-auth-assets.js +1 -1
- package/core/frontend/services/llms/handler.js +1 -1
- package/core/frontend/services/proxy.js +31 -2
- package/core/frontend/services/routing/collection-router.js +1 -1
- package/core/frontend/services/routing/controllers/email-post.js +1 -1
- package/core/frontend/services/routing/controllers/entry/markdown.js +1 -1
- package/core/frontend/services/routing/controllers/entry/markdown.ts +1 -1
- package/core/frontend/services/routing/controllers/entry.js +1 -1
- package/core/frontend/services/routing/controllers/entry.ts +1 -1
- package/core/frontend/services/routing/controllers/previews.js +6 -7
- package/core/frontend/services/routing/controllers/unsubscribe.js +7 -3
- package/core/frontend/services/routing/email-router.js +1 -1
- package/core/frontend/services/routing/events.js +12 -0
- package/core/frontend/services/routing/middleware/page-param.js +1 -1
- package/core/frontend/services/routing/parent-router.js +1 -1
- package/core/frontend/services/routing/preview-router.js +1 -1
- package/core/frontend/services/routing/router-manager.js +4 -8
- package/core/frontend/services/routing/rss-router.js +1 -1
- package/core/frontend/services/routing/static-pages-router.js +1 -1
- package/core/frontend/services/routing/static-routes-router.js +1 -1
- package/core/frontend/services/routing/taxonomy-router.js +1 -1
- package/core/frontend/services/rss/generate-feed.js +1 -1
- package/core/frontend/services/sitemap/base-site-map-generator.js +23 -4
- package/core/frontend/services/sitemap/site-map-index-generator.js +1 -1
- package/core/frontend/services/sitemap/site-map-manager.js +14 -8
- package/core/frontend/services/sitemap/utils.js +1 -1
- package/core/frontend/services/theme-engine/middleware/update-global-template-options.js +1 -1
- package/core/frontend/services/theme-engine/middleware/update-local-template-options.js +1 -1
- package/core/frontend/utils/images.js +1 -1
- package/core/frontend/web/middleware/admin-toolbar.js +1 -1
- package/core/frontend/web/middleware/handle-image-sizes.js +2 -2
- package/core/frontend/web/middleware/redirect-ghost-to-admin.js +1 -1
- package/core/frontend/web/routers/serve-favicon.js +1 -1
- package/core/frontend/web/routers/serve-public-file.js +1 -1
- package/core/frontend/web/site.js +5 -5
- package/core/server/adapters/cache/AdapterCacheMemoryTTL.js +2 -2
- package/core/server/adapters/cache/MemoryCache.js +2 -2
- package/core/server/adapters/cache/Redis.js +1 -1
- package/core/server/adapters/cache/index.js +1 -1
- package/core/server/adapters/lib/redis/AdapterCacheRedis.js +2 -2
- package/core/server/adapters/route-settings/FileStore.js +2 -8
- package/core/server/adapters/route-settings/FileStore.ts +1 -6
- package/core/server/adapters/route-settings/S3RouteSettingsStore.js +206 -0
- package/core/server/adapters/route-settings/S3RouteSettingsStore.ts +199 -0
- package/core/server/adapters/route-settings/utils.js +13 -0
- package/core/server/adapters/route-settings/utils.ts +7 -0
- package/core/server/adapters/scheduling/deps.d.ts +0 -2
- package/core/server/adapters/scheduling/error-capture.js +76 -0
- package/core/server/adapters/scheduling/error-capture.ts +91 -0
- package/core/server/adapters/scheduling/utils.js +18 -34
- package/core/server/adapters/scheduling/utils.ts +36 -0
- package/core/server/adapters/storage/LocalFilesStorage.js +1 -1
- package/core/server/adapters/storage/LocalImagesStorage.js +1 -1
- package/core/server/adapters/storage/LocalMediaStorage.js +1 -1
- package/core/server/adapters/storage/LocalStorageBase.js +3 -3
- package/core/server/adapters/storage/S3Storage.js +2 -2
- package/core/server/adapters/storage/S3Storage.ts +1 -1
- package/core/server/adapters/storage/utils.js +1 -1
- package/core/server/api/endpoints/authentication.js +1 -1
- package/core/server/api/endpoints/featurebase.js +1 -1
- package/core/server/api/endpoints/files.js +2 -2
- package/core/server/api/endpoints/images.js +2 -2
- package/core/server/api/endpoints/libraries.d.ts +0 -1
- package/core/server/api/endpoints/media.js +8 -5
- package/core/server/api/endpoints/member-custom-fields.js +4 -1
- package/core/server/api/endpoints/member-custom-fields.ts +4 -1
- package/core/server/api/endpoints/posts.js +17 -1
- package/core/server/api/endpoints/search-index-public.js +4 -3
- package/core/server/api/endpoints/search-index.js +5 -4
- package/core/server/api/endpoints/settings-public.js +1 -1
- package/core/server/api/endpoints/settings.js +3 -1
- package/core/server/api/endpoints/utils/serializers/input/utils/url.js +9 -1
- package/core/server/api/endpoints/utils/serializers/output/default.js +7 -0
- package/core/server/api/endpoints/utils/serializers/output/files.js +1 -1
- package/core/server/api/endpoints/utils/serializers/output/media.js +1 -1
- package/core/server/api/endpoints/utils/serializers/output/member-custom-fields.js +7 -4
- package/core/server/api/endpoints/utils/serializers/output/member-custom-fields.ts +8 -4
- package/core/server/api/endpoints/utils/serializers/output/members.js +16 -26
- package/core/server/api/endpoints/utils/serializers/output/pages.js +7 -0
- package/core/server/api/endpoints/utils/serializers/output/posts.js +13 -0
- package/core/server/api/endpoints/utils/serializers/output/utils/url.js +1 -1
- package/core/server/api/endpoints/utils/validators/input/members.js +2 -52
- package/core/server/data/db/backup.js +1 -1
- package/core/server/data/importer/handlers/image.js +3 -3
- package/core/server/data/importer/import-manager.js +6 -4
- package/core/server/data/importer/importers/content-file-importer.js +2 -2
- package/core/server/data/migrations/utils/schema.js +4 -2
- package/core/server/data/migrations/versions/6.54/2026-07-19-16-59-00-add-content-import-permission.js +10 -0
- package/core/server/data/migrations/versions/6.54/2026-07-20-13-59-21-drop-email-tracked-sent-count-from-automation-action-revisions.js +7 -0
- package/core/server/data/migrations/versions/6.54/2026-07-21-01-58-20-add-automation-run-steps-poller-index.js +3 -0
- package/core/server/data/migrations/versions/6.54/2026-07-21-21-08-15-add-automated-email-recipients-mailgun-message-id-index.js +3 -0
- package/core/server/data/migrations/versions/6.54/2026-07-22-10-41-08-add-click-tracking-to-automated-email-recipients.js +13 -0
- package/core/server/data/migrations/versions/6.54/2026-07-22-15-10-30-add-email-clicked-count-to-automation-action-revisions.js +7 -0
- package/core/server/data/migrations/versions/6.54/2026-07-23-10-24-18-add-automation-action-revision-to-redirects.js +9 -0
- package/core/server/data/schema/commands.js +37 -3
- package/core/server/data/schema/fixtures/fixtures.json +7 -0
- package/core/server/data/schema/lib/default-index-name.js +20 -0
- package/core/server/data/schema/schema.js +40 -17
- package/core/server/data/seeders/data-generator.js +4 -2
- package/core/server/lib/image/image-size.js +5 -7
- package/core/server/lib/image/image-utils.js +2 -2
- package/core/server/lib/image/index.js +4 -4
- package/core/server/lib/lexical.js +3 -3
- package/core/server/lib/mobiledoc.js +2 -2
- package/core/server/lib/validate-password.js +1 -1
- package/core/server/models/action.js +9 -0
- package/core/server/models/base/plugins/generate-slug.js +1 -1
- package/core/server/models/collection.js +1 -1
- package/core/server/models/custom-theme-setting.js +1 -1
- package/core/server/models/member.js +73 -0
- package/core/server/models/newsletter.js +1 -1
- package/core/server/models/post.js +19 -5
- package/core/server/models/posts-meta.js +1 -1
- package/core/server/models/redirect.js +1 -1
- package/core/server/models/settings.js +1 -1
- package/core/server/models/snippet.js +1 -1
- package/core/server/models/tag.js +1 -1
- package/core/server/models/user.js +1 -1
- package/core/server/models/welcome-email-automated-email.js +1 -1
- package/core/server/services/activitypub/activity-pub-service-wrapper.js +1 -1
- package/core/server/services/adapter-manager/adapter-manager.js +5 -1
- package/core/server/services/adapter-manager/adapter-manager.ts +7 -2
- package/core/server/services/adapter-manager/index.js +18 -15
- package/core/server/services/adapter-manager/index.ts +23 -17
- package/core/server/services/adapter-manager/utils.js +124 -14
- package/core/server/services/adapter-manager/utils.ts +130 -14
- package/core/server/services/api-version-compatibility/mw-version-rewrites.js +1 -1
- package/core/server/services/audience-feedback/index.js +1 -1
- package/core/server/services/auth/passwordreset.js +1 -1
- package/core/server/services/auth/session/express-session.js +1 -1
- package/core/server/services/auth/session/index.js +2 -2
- package/core/server/services/auth/session/session-service.js +1 -1
- package/core/server/services/automations/automations-api.js +2 -19
- package/core/server/services/automations/automations-api.ts +2 -31
- package/core/server/services/automations/automations-repository.ts +15 -0
- package/core/server/services/automations/database-automations-repository.js +30 -2
- package/core/server/services/automations/database-automations-repository.ts +33 -2
- package/core/server/services/automations/poll.js +16 -12
- package/core/server/services/automations/poll.ts +17 -15
- package/core/server/services/automations/service.js +1 -1
- package/core/server/services/automations/service.ts +3 -13
- package/core/server/services/automations/welcome-email-automation-poll.js +2 -1
- package/core/server/services/comments/index.js +1 -1
- package/core/server/services/custom-redirects/index.js +2 -2
- package/core/server/services/email-analytics/email-analytics-service-wrapper.js +14 -13
- package/core/server/services/email-analytics/email-analytics-service.js +1 -1
- package/core/server/services/email-analytics/events/start-email-analytics-job-event.js +11 -15
- package/core/server/services/email-analytics/events/start-email-analytics-job-event.ts +15 -0
- package/core/server/services/email-analytics/index.js +2 -3
- package/core/server/services/email-analytics/index.ts +1 -2
- package/core/server/services/email-analytics/jobs/email-analytics-job-scheduler.js +1 -6
- package/core/server/services/email-analytics/jobs/email-analytics-job-scheduler.ts +0 -9
- package/core/server/services/email-analytics/jobs/fetch-latest/index.js +1 -1
- package/core/server/services/email-analytics/jobs/index.js +0 -2
- package/core/server/services/email-service/email-service-wrapper.js +1 -1
- package/core/server/services/email-service/email-service.js +20 -4
- package/core/server/services/explore-ping/explore-ping-service.js +24 -39
- package/core/server/services/explore-ping/explore-ping-service.ts +198 -0
- package/core/server/services/explore-ping/index.js +11 -11
- package/core/server/services/explore-ping/index.ts +42 -0
- package/core/server/services/gifts/gift-reminder-scheduler.js +1 -1
- package/core/server/services/gifts/gift-reminder-scheduler.ts +1 -1
- package/core/server/services/gifts/gift-service-wrapper.js +1 -1
- package/core/server/services/identity-tokens/identity-token-service-wrapper.js +1 -1
- package/core/server/services/indexnow-ping/constants.js +30 -0
- package/core/server/services/indexnow-ping/constants.ts +32 -0
- package/core/server/services/indexnow-ping/index.js +29 -253
- package/core/server/services/indexnow-ping/index.ts +37 -0
- package/core/server/services/indexnow-ping/indexnow-ping-service.js +229 -0
- package/core/server/services/indexnow-ping/indexnow-ping-service.ts +319 -0
- package/core/server/services/invites/index.js +1 -1
- package/core/server/services/lib/mailgun-client.js +3 -3
- package/core/server/services/link-redirection/index.js +2 -2
- package/core/server/services/link-redirection/link-redirect-repository.js +1 -1
- package/core/server/services/link-redirection/link-redirect.js +12 -13
- package/core/server/services/link-redirection/link-redirect.ts +22 -0
- package/core/server/services/link-redirection/link-redirects-service.js +1 -1
- package/core/server/services/link-tracking/full-post-link.js +2 -2
- package/core/server/services/link-tracking/index.js +1 -1
- package/core/server/services/mail/ghost-mailer.js +1 -1
- package/core/server/services/mail/index.js +1 -1
- package/core/server/services/media-inliner/external-media-inliner.js +2 -2
- package/core/server/services/media-inliner/service.js +4 -3
- package/core/server/services/member-attribution/index.js +1 -1
- package/core/server/services/member-welcome-emails/service.js +1 -1
- package/core/server/services/members/api.js +8 -2
- package/core/server/services/members/csv/index.js +10 -0
- package/core/server/services/members/csv/index.ts +3 -0
- package/core/server/services/members/csv/parse.js +94 -0
- package/core/server/services/members/csv/parse.ts +111 -0
- package/core/server/services/members/csv/types.js +2 -0
- package/core/server/services/members/csv/types.ts +39 -0
- package/core/server/services/members/csv/unparse.js +69 -0
- package/core/server/services/members/csv/unparse.ts +79 -0
- package/core/server/services/members/exporter/query.js +35 -8
- package/core/server/services/members/importer/config.js +35 -0
- package/core/server/services/members/importer/config.ts +39 -0
- package/core/server/services/members/importer/members-csv-importer.js +31 -13
- package/core/server/services/members/members-api/members-api.js +4 -2
- package/core/server/services/members/members-api/repositories/event-repository.js +13 -2
- package/core/server/services/members/members-api/services/member-bread-service.js +42 -19
- package/core/server/services/members/middleware.js +1 -1
- package/core/server/services/members/service.js +15 -2
- package/core/server/services/members/stripe-connect.js +1 -1
- package/core/server/services/members-custom-fields/actions.js +3 -0
- package/core/server/services/members-custom-fields/actions.ts +6 -2
- package/core/server/services/members-custom-fields/config.js +34 -0
- package/core/server/services/members-custom-fields/config.ts +38 -0
- package/core/server/services/members-custom-fields/definitions-service.js +156 -21
- package/core/server/services/members-custom-fields/definitions-service.ts +170 -25
- package/core/server/services/members-custom-fields/index.js +16 -3
- package/core/server/services/members-custom-fields/index.ts +17 -3
- package/core/server/services/members-custom-fields/values-service.js +56 -10
- package/core/server/services/members-custom-fields/values-service.ts +62 -10
- package/core/server/services/mentions/mention-sending-service.js +22 -2
- package/core/server/services/mentions/service.js +21 -5
- package/core/server/services/newsletters/index.js +1 -1
- package/core/server/services/oembed/oembed-service.js +122 -33
- package/core/server/services/oembed/service.js +4 -2
- package/core/server/services/offers/service.js +1 -1
- package/core/server/services/post-scheduling/index.js +4 -3
- package/core/server/services/post-scheduling/index.ts +4 -3
- package/core/server/services/post-scheduling/post-scheduling.js +1 -1
- package/core/server/services/post-scheduling/post-scheduling.ts +1 -1
- package/core/server/services/posts/post-email-handler.js +13 -6
- package/core/server/services/posts/post-scheduling.js +1 -1
- package/core/server/services/posts/posts-service-instance.js +1 -1
- package/core/server/services/posts/posts-service.js +2 -2
- package/core/server/services/posts-public/service.js +1 -1
- package/core/server/services/public-config/site.js +1 -1
- package/core/server/services/recommendations/recommendation-service-wrapper.js +1 -1
- package/core/server/services/recommendations/service/libraries.d.ts +0 -2
- package/core/server/services/route-settings/dynamic-routing-service.js +2 -3
- package/core/server/services/route-settings/index.js +1 -1
- package/core/server/services/route-settings/route-settings-parser.js +134 -124
- package/core/server/services/route-settings/route-settings-parser.ts +160 -125
- package/core/server/services/route-settings/validation-errors.js +178 -0
- package/core/server/services/route-settings/validation-errors.ts +196 -0
- package/core/server/services/settings/settings-service.js +2 -2
- package/core/server/services/settings-helpers/index.js +1 -1
- package/core/server/services/slack-notifications/service.js +1 -1
- package/core/server/services/slack-ping/constants.js +16 -0
- package/core/server/services/slack-ping/constants.ts +15 -0
- package/core/server/services/slack-ping/index.js +26 -204
- package/core/server/services/slack-ping/index.ts +35 -0
- package/core/server/services/slack-ping/slack-ping-service.js +214 -0
- package/core/server/services/slack-ping/slack-ping-service.ts +296 -0
- package/core/server/services/staff/index.js +1 -1
- package/core/server/services/stats/posts-stats-service.js +1 -1
- package/core/server/services/stats/service.js +1 -1
- package/core/server/services/stripe/service.js +1 -1
- package/core/server/services/tags-public/service.js +1 -1
- package/core/server/services/themes/validate.js +1 -1
- package/core/server/services/update-check/index.js +1 -1
- package/core/server/services/url/lazy-url-service.js +66 -6
- package/core/server/services/url/lazy-url-service.ts +73 -6
- package/core/server/services/url/url-generator.js +1 -1
- package/core/server/services/url/url-service-facade.js +68 -3
- package/core/server/services/url/url-service-facade.ts +79 -4
- package/core/server/services/url/url-service.js +1 -1
- package/core/server/services/url/urls.js +1 -1
- package/core/server/services/webhooks/index.js +19 -2
- package/core/server/services/webhooks/listen.js +6 -11
- package/core/server/services/webhooks/payload.js +1 -3
- package/core/server/services/webhooks/serialize.js +16 -1
- package/core/server/web/admin/app.js +1 -1
- package/core/server/web/admin/middleware/redirect-admin-urls.js +1 -1
- package/core/server/web/api/endpoints/admin/routes.js +1 -0
- package/core/server/web/api/middleware/cors.js +1 -1
- package/core/server/web/api/middleware/upload.js +4 -0
- package/core/server/web/gift-preview/controller.js +1 -1
- package/core/server/web/shared/middleware/redirect-amp-urls.js +1 -1
- package/core/server/web/shared/middleware/uncapitalise.js +2 -2
- package/core/server/web/shared/middleware/url-redirects.js +1 -1
- package/core/shared/config/defaults.json +8 -1
- package/core/shared/config/overrides.json +4 -0
- package/core/shared/url-utils.js +19 -15
- package/core/shared/url-utils.ts +20 -0
- package/ghost.js +0 -1
- package/package.json +26 -31
- package/pnpm-lock.yaml +681 -2789
- package/pnpm-workspace.yaml +31 -17
- package/components/tryghost-adapter-base-scheduling-0.0.0.tgz +0 -0
- package/components/tryghost-adapter-base-sso-0.0.0.tgz +0 -0
- package/core/built/admin/assets/Combination--5EZGaDs.js +0 -43
- package/core/built/admin/assets/Growth-C0NoKcHQ.js +0 -3
- package/core/built/admin/assets/Newsletters-Ed8kDjdy.js +0 -1
- package/core/built/admin/assets/Overview-CArPgRZt.js +0 -1
- package/core/built/admin/assets/Web-CjjYoVM3.js +0 -2
- package/core/built/admin/assets/account-migration-mfa5mNI9.js +0 -1
- package/core/built/admin/assets/activitypub/inbox-B3rjKMTv.js +0 -1221
- package/core/built/admin/assets/activitypub/layout-jcurg3rU.js +0 -1
- package/core/built/admin/assets/activitypub/use-activity-pub-queries-yqGRcnLn.js +0 -2569
- package/core/built/admin/assets/activitypub/users-CfyHIsTG.js +0 -1316
- package/core/built/admin/assets/automations-DkUnxNdv.js +0 -1
- package/core/built/admin/assets/automations-vjXofmV_.js +0 -1
- package/core/built/admin/assets/bluesky-sharing-T-pO3RcP.js +0 -1
- package/core/built/admin/assets/breadcrumb-CekPYTCn.js +0 -1
- package/core/built/admin/assets/button--i2uMDDn.js +0 -4
- package/core/built/admin/assets/card-CSWz_BXq.js +0 -1
- package/core/built/admin/assets/chart-helpers-C_4Ka_vT.js +0 -1
- package/core/built/admin/assets/chunk.524.8ce2c741473e2f0929dc.js +0 -25
- package/core/built/admin/assets/chunk.582.453459d6228d2955408b.js +0 -27
- package/core/built/admin/assets/code-editor-view-BfkwQto2.js +0 -1
- package/core/built/admin/assets/command-K75Jzs0G.js +0 -1
- package/core/built/admin/assets/comments-BEIi1DH-.js +0 -1
- package/core/built/admin/assets/container-BNXvlcjA.js +0 -1
- package/core/built/admin/assets/data-list-BmK5QMab.js +0 -1
- package/core/built/admin/assets/date-range-select-5sKzwbt7.js +0 -1
- package/core/built/admin/assets/disabled-sources-indicator-L_ssJTNr.js +0 -1
- package/core/built/admin/assets/dist-BBIJuyPg.js +0 -1
- package/core/built/admin/assets/dist-BHE0dp6o.js +0 -1
- package/core/built/admin/assets/dist-DJ6c4_De.js +0 -1
- package/core/built/admin/assets/dist-DW0QXQO3.js +0 -1
- package/core/built/admin/assets/dist-DxFLceO5.js +0 -1
- package/core/built/admin/assets/dist-QcACAOAD.js +0 -1
- package/core/built/admin/assets/dist-duxRDcQu.js +0 -177
- package/core/built/admin/assets/domain-CLaPZ9Rc.js +0 -1
- package/core/built/admin/assets/dropzone-E0bSX4_a.js +0 -5
- package/core/built/admin/assets/edit-profile-DqNPKaA4.js +0 -1
- package/core/built/admin/assets/editor-CkLXQDRp.js +0 -8
- package/core/built/admin/assets/empty-indicator-BTtOlgIo.js +0 -1
- package/core/built/admin/assets/esm-TSfGW7nz.js +0 -2
- package/core/built/admin/assets/explore-BEstLxKr.js +0 -1
- package/core/built/admin/assets/feed-C58p2voG.js +0 -1
- package/core/built/admin/assets/field-BSbDUHPv.js +0 -1
- package/core/built/admin/assets/filters-BgYv8Gt7.js +0 -1
- package/core/built/admin/assets/filters-DvenFkmK.js +0 -1
- package/core/built/admin/assets/framework-provider-jQktxm9P.js +0 -4
- package/core/built/admin/assets/ghost-dark-8590dea6cd695ff90f27d262c4464538.css +0 -1
- package/core/built/admin/assets/gift-link-modal-BPjXkEFt.js +0 -1
- package/core/built/admin/assets/growth-D4JNiVTe.js +0 -1
- package/core/built/admin/assets/hooks-Cjxexi_I.js +0 -2
- package/core/built/admin/assets/index-BacwlcOy.js +0 -67
- package/core/built/admin/assets/index-DxRNHH0o.css +0 -1
- package/core/built/admin/assets/inline-C22rnPro.js +0 -1
- package/core/built/admin/assets/input-group-CKfrILLP.js +0 -1
- package/core/built/admin/assets/jsx-runtime-CtMZ-PAS.js +0 -1
- package/core/built/admin/assets/kpi-card-DZxQKAIb.js +0 -1
- package/core/built/admin/assets/kpi-card-FidQ5zg3.js +0 -1
- package/core/built/admin/assets/kpi-helpers-C5T8Vaf1.js +0 -1
- package/core/built/admin/assets/kpi-tabs-_VRK6hGV.js +0 -1
- package/core/built/admin/assets/label-Cza7hPgn.js +0 -1
- package/core/built/admin/assets/label-picker-DgC_zLaw.js +0 -1
- package/core/built/admin/assets/layout-BxsXnKFX.js +0 -1
- package/core/built/admin/assets/limit-service-CTurluJQ.js +0 -20
- package/core/built/admin/assets/link-helpers-C3Gqy2cz.js +0 -1
- package/core/built/admin/assets/list-page-BtqCnow_.js +0 -1
- package/core/built/admin/assets/member-custom-fields-9uXFBqSt.js +0 -1
- package/core/built/admin/assets/member-detail-Dq6ZDIxo.js +0 -1
- package/core/built/admin/assets/members-CUWD9jal.js +0 -10
- package/core/built/admin/assets/modals-CIdwHVga.js +0 -31
- package/core/built/admin/assets/moderation-DTt04UDA.js +0 -1
- package/core/built/admin/assets/newsletter-cC8vcc9h.js +0 -1
- package/core/built/admin/assets/note-DZU0IY9e.js +0 -1
- package/core/built/admin/assets/notifications-NoHpBHJ4.js +0 -1
- package/core/built/admin/assets/nql-lang-CvCSOQG3.js +0 -19
- package/core/built/admin/assets/onboarding-route-Deg2hNm8.js +0 -1
- package/core/built/admin/assets/overview-BQPt_9w3.js +0 -1
- package/core/built/admin/assets/page-header-D6bEqPo2.js +0 -1
- package/core/built/admin/assets/post-analytics-header-BPw_B2_D.js +0 -1
- package/core/built/admin/assets/post-analytics-kp2_--XO.js +0 -1
- package/core/built/admin/assets/post-share-modal-Cave3Z4W.js +0 -1
- package/core/built/admin/assets/preferences-C7h3j_uy.js +0 -5
- package/core/built/admin/assets/profile-B2x4q2oB.js +0 -1
- package/core/built/admin/assets/router-provider-5fsX1CYn.js +0 -1
- package/core/built/admin/assets/select-PhPjIBBT.js +0 -1
- package/core/built/admin/assets/settings-D5P9Gwgo.js +0 -6
- package/core/built/admin/assets/settings-zUOzQV5I.js +0 -1
- package/core/built/admin/assets/share-modal-EfpfbuWF.js +0 -1
- package/core/built/admin/assets/social-urls-DgAF08Xc.js +0 -18
- package/core/built/admin/assets/sort-button-WOQYJm2H.js +0 -1
- package/core/built/admin/assets/source-icon-hm8Cj-Gx.js +0 -1
- package/core/built/admin/assets/stats-CnQDb62m.js +0 -1
- package/core/built/admin/assets/stats-view-CCfTJgSe.js +0 -1
- package/core/built/admin/assets/step-1-BGlhY4DS.js +0 -1
- package/core/built/admin/assets/step-2-D3sDEyFH.js +0 -1
- package/core/built/admin/assets/step-3-CvZoUdsc.js +0 -2
- package/core/built/admin/assets/switch-CNjkOmwz.js +0 -1
- package/core/built/admin/assets/table-C5nZYPnW.js +0 -1
- package/core/built/admin/assets/tabs-dtOcExye.js +0 -1
- package/core/built/admin/assets/tags-Dhm0FB_g.js +0 -1
- package/core/built/admin/assets/textarea-CeKw3wmV.js +0 -1
- package/core/built/admin/assets/toggle-group-DfhZIMTW.js +0 -1
- package/core/built/admin/assets/topic-filter-Cxe1Il41.js +0 -1
- package/core/built/admin/assets/typeof-Ca-duI-z.js +0 -1
- package/core/built/admin/assets/use-filter-params-Bub6BqNy.js +0 -1
- package/core/built/admin/assets/use-growth-stats-BJORomv0.js +0 -1
- package/core/built/admin/assets/use-reply-chain-data-B89YjVoo.js +0 -1
- package/core/built/admin/assets/use-simple-pagination-BL2SYXKi.js +0 -1
- package/core/built/admin/assets/virtual-list-DNJOSK9I.js +0 -1
- package/core/built/admin/assets/web-BHUE3YQc.js +0 -1
- package/core/server/adapters/scheduling/scheduling-base.js +0 -5
- package/core/server/adapters/sso/SSOBase.js +0 -5
- package/core/server/adapters/storage/index.js +0 -17
|
@@ -0,0 +1,94 @@
|
|
|
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.default = parse;
|
|
7
|
+
const node_stream_1 = require("node:stream");
|
|
8
|
+
const papaparse_1 = __importDefault(require("papaparse"));
|
|
9
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
10
|
+
const transformValue = (header, value) => {
|
|
11
|
+
if (header === 'labels') {
|
|
12
|
+
if (value && typeof value === 'string') {
|
|
13
|
+
return value.split(',').map(name => ({ name }));
|
|
14
|
+
}
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
if (header === 'subscribed') {
|
|
18
|
+
return value.toLowerCase() !== 'false';
|
|
19
|
+
}
|
|
20
|
+
if (header === 'complimentary_plan') {
|
|
21
|
+
return value.toLowerCase() === 'true';
|
|
22
|
+
}
|
|
23
|
+
if (value === '') {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
if (value === 'undefined') {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
if (value.toLowerCase() === 'false') {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
if (value.toLowerCase() === 'true') {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
return value;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* @param path - The path to the CSV to prepare
|
|
39
|
+
* @param headerMapping - An object whose keys are headers in the input CSV and values are the header to replace it with
|
|
40
|
+
* @param defaultLabels - A list of labels to apply to every parsed member row
|
|
41
|
+
* @returns The parsed member rows, keyed by mapped header
|
|
42
|
+
*/
|
|
43
|
+
function parse(path, headerMapping, defaultLabels = []) {
|
|
44
|
+
return new Promise(function (resolve, reject) {
|
|
45
|
+
const csvFileStream = fs_extra_1.default.createReadStream(path);
|
|
46
|
+
const csvParserStream = papaparse_1.default.parse(papaparse_1.default.NODE_STREAM_INPUT, {
|
|
47
|
+
header: true
|
|
48
|
+
});
|
|
49
|
+
const rows = [];
|
|
50
|
+
const parsedCSVStream = (0, node_stream_1.pipeline)(csvFileStream, csvParserStream, (err) => {
|
|
51
|
+
if (err) {
|
|
52
|
+
return reject(err);
|
|
53
|
+
}
|
|
54
|
+
resolve(rows);
|
|
55
|
+
});
|
|
56
|
+
parsedCSVStream.on('data', (parsedRow) => {
|
|
57
|
+
// a throw here escapes as an uncaught exception and leaves this
|
|
58
|
+
// promise forever unsettled, so it has to become a rejection
|
|
59
|
+
try {
|
|
60
|
+
const row = {};
|
|
61
|
+
for (const [header, value] of Object.entries(parsedRow)) {
|
|
62
|
+
// papaparse gathers the overflow from a row carrying more
|
|
63
|
+
// fields than there are headers under __parsed_extra, as an
|
|
64
|
+
// array rather than a cell any mapping can name
|
|
65
|
+
if (typeof value !== 'string') {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
// hasOwn, not `in`: a column named after an Object.prototype
|
|
69
|
+
// member would otherwise pass as mapped and take a function
|
|
70
|
+
// as its mapped name
|
|
71
|
+
if (!headerMapping || !Object.hasOwn(headerMapping, header)) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const mappedHeader = headerMapping[header];
|
|
75
|
+
row[mappedHeader] = transformValue(mappedHeader, value);
|
|
76
|
+
}
|
|
77
|
+
// skip rows with no data
|
|
78
|
+
if (!Object.keys(row).length) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
// labels is absent when the column is unmapped, and an array otherwise
|
|
82
|
+
const parsedLabels = row.labels;
|
|
83
|
+
row.labels = [
|
|
84
|
+
...(Array.isArray(parsedLabels) ? parsedLabels : []),
|
|
85
|
+
...defaultLabels
|
|
86
|
+
];
|
|
87
|
+
rows.push(row);
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
reject(err);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import {pipeline} from 'node:stream';
|
|
2
|
+
import papaparse from 'papaparse';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import type {Label, MemberCsvRow} from './types';
|
|
5
|
+
|
|
6
|
+
type CsvValue = string | boolean | null | Label[];
|
|
7
|
+
|
|
8
|
+
const transformValue = (header: string, value: string): CsvValue => {
|
|
9
|
+
if (header === 'labels') {
|
|
10
|
+
if (value && typeof value === 'string') {
|
|
11
|
+
return value.split(',').map(name => ({name}));
|
|
12
|
+
}
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (header === 'subscribed') {
|
|
17
|
+
return value.toLowerCase() !== 'false';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (header === 'complimentary_plan') {
|
|
21
|
+
return value.toLowerCase() === 'true';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (value === '') {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (value === 'undefined') {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (value.toLowerCase() === 'false') {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (value.toLowerCase() === 'true') {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return value;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param path - The path to the CSV to prepare
|
|
45
|
+
* @param headerMapping - An object whose keys are headers in the input CSV and values are the header to replace it with
|
|
46
|
+
* @param defaultLabels - A list of labels to apply to every parsed member row
|
|
47
|
+
* @returns The parsed member rows, keyed by mapped header
|
|
48
|
+
*/
|
|
49
|
+
export default function parse(
|
|
50
|
+
path: string,
|
|
51
|
+
headerMapping?: Record<string, string>,
|
|
52
|
+
defaultLabels: Label[] = []
|
|
53
|
+
): Promise<MemberCsvRow[]> {
|
|
54
|
+
return new Promise(function (resolve, reject) {
|
|
55
|
+
const csvFileStream = fs.createReadStream(path);
|
|
56
|
+
const csvParserStream = papaparse.parse(papaparse.NODE_STREAM_INPUT, {
|
|
57
|
+
header: true
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const rows: MemberCsvRow[] = [];
|
|
61
|
+
const parsedCSVStream = pipeline(csvFileStream, csvParserStream, (err) => {
|
|
62
|
+
if (err) {
|
|
63
|
+
return reject(err);
|
|
64
|
+
}
|
|
65
|
+
resolve(rows);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
parsedCSVStream.on('data', (parsedRow: Record<string, unknown>) => {
|
|
69
|
+
// a throw here escapes as an uncaught exception and leaves this
|
|
70
|
+
// promise forever unsettled, so it has to become a rejection
|
|
71
|
+
try {
|
|
72
|
+
const row: MemberCsvRow = {};
|
|
73
|
+
|
|
74
|
+
for (const [header, value] of Object.entries(parsedRow)) {
|
|
75
|
+
// papaparse gathers the overflow from a row carrying more
|
|
76
|
+
// fields than there are headers under __parsed_extra, as an
|
|
77
|
+
// array rather than a cell any mapping can name
|
|
78
|
+
if (typeof value !== 'string') {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// hasOwn, not `in`: a column named after an Object.prototype
|
|
83
|
+
// member would otherwise pass as mapped and take a function
|
|
84
|
+
// as its mapped name
|
|
85
|
+
if (!headerMapping || !Object.hasOwn(headerMapping, header)) {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const mappedHeader = headerMapping[header];
|
|
90
|
+
row[mappedHeader] = transformValue(mappedHeader, value);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// skip rows with no data
|
|
94
|
+
if (!Object.keys(row).length) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// labels is absent when the column is unmapped, and an array otherwise
|
|
99
|
+
const parsedLabels = row.labels;
|
|
100
|
+
row.labels = [
|
|
101
|
+
...(Array.isArray(parsedLabels) ? parsedLabels : []),
|
|
102
|
+
...defaultLabels
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
rows.push(row);
|
|
106
|
+
} catch (err) {
|
|
107
|
+
reject(err);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface Label {
|
|
2
|
+
name: string;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Any column the parser does not special-case is coerced, so a cell reading
|
|
7
|
+
* TRUE or FALSE arrives as a boolean and an empty one as null, whatever the
|
|
8
|
+
* column means. A member genuinely named TRUE parses to `name: true`.
|
|
9
|
+
*/
|
|
10
|
+
export type ParsedValue = string | boolean | null;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The member CSV column vocabulary as it currently stands. Several fields exist
|
|
14
|
+
* on one side only: tiers and deleted_at are written on export and not accepted
|
|
15
|
+
* on import, import_tier is accepted on import and never written, and the email
|
|
16
|
+
* subscription state is called subscribed coming in and subscribed_to_emails
|
|
17
|
+
* going out. The index signature carries custom field columns, which are not
|
|
18
|
+
* known ahead of time.
|
|
19
|
+
*/
|
|
20
|
+
export interface MemberCsvRow {
|
|
21
|
+
id?: ParsedValue;
|
|
22
|
+
email?: ParsedValue;
|
|
23
|
+
name?: ParsedValue;
|
|
24
|
+
note?: ParsedValue;
|
|
25
|
+
subscribed?: boolean;
|
|
26
|
+
subscribed_to_emails?: boolean;
|
|
27
|
+
comped?: boolean;
|
|
28
|
+
complimentary_plan?: boolean;
|
|
29
|
+
stripe_customer_id?: ParsedValue;
|
|
30
|
+
subscriptions?: Array<{customer?: {id?: string}}>;
|
|
31
|
+
created_at?: ParsedValue;
|
|
32
|
+
deleted_at?: ParsedValue;
|
|
33
|
+
labels?: string | Array<string | Label>;
|
|
34
|
+
tiers?: Array<{name: string}>;
|
|
35
|
+
import_tier?: ParsedValue;
|
|
36
|
+
gift_id?: ParsedValue;
|
|
37
|
+
error?: ParsedValue;
|
|
38
|
+
[column: string]: unknown;
|
|
39
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
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.default = unparse;
|
|
7
|
+
const papaparse_1 = __importDefault(require("papaparse"));
|
|
8
|
+
const DEFAULT_COLUMNS = [
|
|
9
|
+
'id',
|
|
10
|
+
'email',
|
|
11
|
+
'name',
|
|
12
|
+
'note',
|
|
13
|
+
'subscribed_to_emails',
|
|
14
|
+
'complimentary_plan',
|
|
15
|
+
'stripe_customer_id',
|
|
16
|
+
'created_at',
|
|
17
|
+
'deleted_at',
|
|
18
|
+
'labels',
|
|
19
|
+
'tiers',
|
|
20
|
+
'gift_id'
|
|
21
|
+
];
|
|
22
|
+
function unparse(rows, columns = DEFAULT_COLUMNS, { escapeFormulae = true } = {}) {
|
|
23
|
+
const outputColumns = columns.map((column) => {
|
|
24
|
+
if (column === 'subscribed') {
|
|
25
|
+
return 'subscribed_to_emails';
|
|
26
|
+
}
|
|
27
|
+
return column;
|
|
28
|
+
});
|
|
29
|
+
if (!outputColumns.includes('error') && rows.some(row => row.error)) {
|
|
30
|
+
outputColumns.push('error');
|
|
31
|
+
}
|
|
32
|
+
const mappedRows = rows.map((row) => {
|
|
33
|
+
let labels = '';
|
|
34
|
+
if (typeof row.labels === 'string') {
|
|
35
|
+
labels = row.labels;
|
|
36
|
+
}
|
|
37
|
+
else if (Array.isArray(row.labels)) {
|
|
38
|
+
labels = row.labels.map((l) => {
|
|
39
|
+
return typeof l === 'string' ? l : l.name;
|
|
40
|
+
}).join(',');
|
|
41
|
+
}
|
|
42
|
+
let tiers = '';
|
|
43
|
+
if (Array.isArray(row.tiers)) {
|
|
44
|
+
tiers = row.tiers.map((tier) => {
|
|
45
|
+
return tier.name;
|
|
46
|
+
}).join(',');
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
id: row.id,
|
|
50
|
+
email: row.email,
|
|
51
|
+
name: row.name,
|
|
52
|
+
note: row.note,
|
|
53
|
+
subscribed_to_emails: 'subscribed' in row ? row.subscribed : row.subscribed_to_emails,
|
|
54
|
+
complimentary_plan: row.comped || row.complimentary_plan,
|
|
55
|
+
stripe_customer_id: row.subscriptions?.[0]?.customer?.id || row.stripe_customer_id,
|
|
56
|
+
created_at: row.created_at,
|
|
57
|
+
deleted_at: row.deleted_at,
|
|
58
|
+
labels,
|
|
59
|
+
tiers,
|
|
60
|
+
import_tier: row.import_tier || null,
|
|
61
|
+
gift_id: row.gift_id || null,
|
|
62
|
+
error: row.error || null
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
return papaparse_1.default.unparse(mappedRows, {
|
|
66
|
+
escapeFormulae,
|
|
67
|
+
columns: outputColumns
|
|
68
|
+
});
|
|
69
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import papaparse from 'papaparse';
|
|
2
|
+
import type {MemberCsvRow} from './types';
|
|
3
|
+
|
|
4
|
+
const DEFAULT_COLUMNS = [
|
|
5
|
+
'id',
|
|
6
|
+
'email',
|
|
7
|
+
'name',
|
|
8
|
+
'note',
|
|
9
|
+
'subscribed_to_emails',
|
|
10
|
+
'complimentary_plan',
|
|
11
|
+
'stripe_customer_id',
|
|
12
|
+
'created_at',
|
|
13
|
+
'deleted_at',
|
|
14
|
+
'labels',
|
|
15
|
+
'tiers',
|
|
16
|
+
'gift_id'
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
interface UnparseOptions {
|
|
20
|
+
// Prefixes a leading =, +, -, @ or tab with an apostrophe so a spreadsheet does
|
|
21
|
+
// not read the value as a formula. On by default: it belongs on any CSV a person
|
|
22
|
+
// opens. The importer's own intermediate file is not one, and turns it off, so a
|
|
23
|
+
// member named "-5" is not read back as "'-5".
|
|
24
|
+
escapeFormulae?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default function unparse(rows: MemberCsvRow[], columns: string[] = DEFAULT_COLUMNS, {escapeFormulae = true}: UnparseOptions = {}): string {
|
|
28
|
+
const outputColumns = columns.map((column) => {
|
|
29
|
+
if (column === 'subscribed') {
|
|
30
|
+
return 'subscribed_to_emails';
|
|
31
|
+
}
|
|
32
|
+
return column;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
if (!outputColumns.includes('error') && rows.some(row => row.error)) {
|
|
36
|
+
outputColumns.push('error');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const mappedRows = rows.map((row) => {
|
|
40
|
+
let labels = '';
|
|
41
|
+
if (typeof row.labels === 'string') {
|
|
42
|
+
labels = row.labels;
|
|
43
|
+
} else if (Array.isArray(row.labels)) {
|
|
44
|
+
labels = row.labels.map((l) => {
|
|
45
|
+
return typeof l === 'string' ? l : l.name;
|
|
46
|
+
}).join(',');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let tiers = '';
|
|
50
|
+
|
|
51
|
+
if (Array.isArray(row.tiers)) {
|
|
52
|
+
tiers = row.tiers.map((tier) => {
|
|
53
|
+
return tier.name;
|
|
54
|
+
}).join(',');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
id: row.id,
|
|
59
|
+
email: row.email,
|
|
60
|
+
name: row.name,
|
|
61
|
+
note: row.note,
|
|
62
|
+
subscribed_to_emails: 'subscribed' in row ? row.subscribed : row.subscribed_to_emails,
|
|
63
|
+
complimentary_plan: row.comped || row.complimentary_plan,
|
|
64
|
+
stripe_customer_id: row.subscriptions?.[0]?.customer?.id || row.stripe_customer_id,
|
|
65
|
+
created_at: row.created_at,
|
|
66
|
+
deleted_at: row.deleted_at,
|
|
67
|
+
labels,
|
|
68
|
+
tiers,
|
|
69
|
+
import_tier: row.import_tier || null,
|
|
70
|
+
gift_id: row.gift_id || null,
|
|
71
|
+
error: row.error || null
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return papaparse.unparse(mappedRows, {
|
|
76
|
+
escapeFormulae,
|
|
77
|
+
columns: outputColumns
|
|
78
|
+
});
|
|
79
|
+
}
|
|
@@ -3,6 +3,8 @@ const {knex} = require('../../../data/db');
|
|
|
3
3
|
const moment = require('moment');
|
|
4
4
|
const logging = require('@tryghost/logging');
|
|
5
5
|
const {Transform} = require('stream');
|
|
6
|
+
const labs = require('../../../../shared/labs');
|
|
7
|
+
const {csvCellsForFields} = require('@tryghost/custom-field-types/csv');
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* Process a batch of members with all their related data
|
|
@@ -14,9 +16,11 @@ const {Transform} = require('stream');
|
|
|
14
16
|
* @param {Map} giftIdMap - Map of member_id to gift id (for gift members only)
|
|
15
17
|
* @param {Object} allProducts - Map of product IDs to product names
|
|
16
18
|
* @param {Object} allLabels - Map of label IDs to label names
|
|
19
|
+
* @param {Array} activeCustomFields - Active custom field definitions
|
|
20
|
+
* @param {Map} customFieldValuesMap - Map of member_id to their custom field values
|
|
17
21
|
* @returns {Array} Processed member records
|
|
18
22
|
*/
|
|
19
|
-
function processMembersData(members, tiersMap, labelsMap, stripeCustomerMap, subscribedSet, giftIdMap, allProducts, allLabels) {
|
|
23
|
+
function processMembersData(members, tiersMap, labelsMap, stripeCustomerMap, subscribedSet, giftIdMap, allProducts, allLabels, activeCustomFields, customFieldValuesMap) {
|
|
20
24
|
for (const row of members) {
|
|
21
25
|
const tierIds = tiersMap.get(row.id) ? tiersMap.get(row.id).split(',') : [];
|
|
22
26
|
const tierDetails = tierIds.map((id) => {
|
|
@@ -40,6 +44,12 @@ function processMembersData(members, tiersMap, labelsMap, stripeCustomerMap, sub
|
|
|
40
44
|
row.gift_id = giftIdMap.get(row.id) || null;
|
|
41
45
|
row.stripe_customer_id = stripeCustomerMap.get(row.id) || null;
|
|
42
46
|
row.created_at = moment(row.created_at).toISOString();
|
|
47
|
+
|
|
48
|
+
// Flattened here rather than in the serializer because the column set is
|
|
49
|
+
// only knowable from the database. Every member carries a cell for every
|
|
50
|
+
// active field's column, so a member with no values still contributes the
|
|
51
|
+
// full set — the CSV header is taken from whichever row streams first.
|
|
52
|
+
row.custom_field_cells = csvCellsForFields(activeCustomFields, customFieldValuesMap.get(row.id) || {});
|
|
43
53
|
}
|
|
44
54
|
return members;
|
|
45
55
|
}
|
|
@@ -49,7 +59,7 @@ function processMembersData(members, tiersMap, labelsMap, stripeCustomerMap, sub
|
|
|
49
59
|
* @param {Object} options - Export options
|
|
50
60
|
* @returns {Promise<Object>} A readable stream of processed members
|
|
51
61
|
*/
|
|
52
|
-
async function createExportStream(options) {
|
|
62
|
+
async function createExportStream(options, {definitions, values}) {
|
|
53
63
|
const hasFilter = options.limit !== 'all' || options.filter || options.search;
|
|
54
64
|
const start = Date.now();
|
|
55
65
|
|
|
@@ -83,6 +93,15 @@ async function createExportStream(options) {
|
|
|
83
93
|
|
|
84
94
|
logging.info('[MembersExporter] Fetched products and labels in ' + (Date.now() - startFetchingProducts) + 'ms');
|
|
85
95
|
|
|
96
|
+
// Definitions are a small, stable table, so they're read once rather than per
|
|
97
|
+
// batch. Reading once also fixes the column set for the whole file: archiving a
|
|
98
|
+
// field mid-export can't leave the header ragged. It can still leave that
|
|
99
|
+
// field's cells empty from the batch after the archive onwards, because the
|
|
100
|
+
// per-batch value read applies its own active filter.
|
|
101
|
+
const activeCustomFields = labs.isSet('membersCustomFields')
|
|
102
|
+
? await definitions.browse()
|
|
103
|
+
: [];
|
|
104
|
+
|
|
86
105
|
// Create a transform stream that will process the members as they come in
|
|
87
106
|
const processMembersTransform = new Transform({
|
|
88
107
|
objectMode: true,
|
|
@@ -92,7 +111,7 @@ async function createExportStream(options) {
|
|
|
92
111
|
const memberIds = batch.map(member => member.id);
|
|
93
112
|
|
|
94
113
|
// Fetch related data for this batch
|
|
95
|
-
const [tiers, labels, stripeCustomers, subscriptions, gifts] = await Promise.all([
|
|
114
|
+
const [tiers, labels, stripeCustomers, subscriptions, gifts, customFieldValuesMap] = await Promise.all([
|
|
96
115
|
knex('members_products')
|
|
97
116
|
.select('member_id', knex.raw('GROUP_CONCAT(product_id) as tiers'))
|
|
98
117
|
.whereIn('member_id', memberIds)
|
|
@@ -115,7 +134,11 @@ async function createExportStream(options) {
|
|
|
115
134
|
knex('gifts')
|
|
116
135
|
.select('id', 'redeemer_member_id')
|
|
117
136
|
.where('status', 'redeemed')
|
|
118
|
-
.whereIn('redeemer_member_id', memberIds)
|
|
137
|
+
.whereIn('redeemer_member_id', memberIds),
|
|
138
|
+
|
|
139
|
+
activeCustomFields.length > 0
|
|
140
|
+
? values.getValuesForMembers(memberIds)
|
|
141
|
+
: new Map()
|
|
119
142
|
]);
|
|
120
143
|
|
|
121
144
|
// Create maps for quick lookups
|
|
@@ -133,8 +156,10 @@ async function createExportStream(options) {
|
|
|
133
156
|
stripeCustomerMap,
|
|
134
157
|
subscribedSet,
|
|
135
158
|
giftIdMap,
|
|
136
|
-
allProducts,
|
|
137
|
-
allLabels
|
|
159
|
+
allProducts,
|
|
160
|
+
allLabels,
|
|
161
|
+
activeCustomFields,
|
|
162
|
+
customFieldValuesMap
|
|
138
163
|
);
|
|
139
164
|
|
|
140
165
|
// Push each member individually to avoid large arrays in memory
|
|
@@ -201,6 +226,8 @@ async function createExportStream(options) {
|
|
|
201
226
|
* @param {Object} options - Export options
|
|
202
227
|
* @returns {Promise<Array|Object>} Array of members or stream of members
|
|
203
228
|
*/
|
|
204
|
-
module.exports =
|
|
205
|
-
return
|
|
229
|
+
module.exports = function createExporter({definitions, values}) {
|
|
230
|
+
return async function (options = {}) {
|
|
231
|
+
return createExportStream(options, {definitions, values});
|
|
232
|
+
};
|
|
206
233
|
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveInlineThreshold = resolveInlineThreshold;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
/**
|
|
6
|
+
* Resolving Ghost's config into the values the importer runs on.
|
|
7
|
+
*
|
|
8
|
+
* Config arrives untyped: defaults.json supplies the shipped value, and any
|
|
9
|
+
* higher layer — an operator's config file, an environment variable, argv — can
|
|
10
|
+
* replace it with anything at all. Turning that into something usable is a
|
|
11
|
+
* config concern, so it happens here, at the boundary. The importer is handed an
|
|
12
|
+
* answer and never learns where it came from.
|
|
13
|
+
*/
|
|
14
|
+
// The row count at or below which an import is performed while the request is
|
|
15
|
+
// still open. Zero is allowed and means every import is deferred. A numeric
|
|
16
|
+
// string is accepted because a value supplied through an environment variable
|
|
17
|
+
// can arrive as one.
|
|
18
|
+
const Threshold = zod_1.z
|
|
19
|
+
.union([zod_1.z.number(), zod_1.z.string().trim().min(1)])
|
|
20
|
+
.transform(Number)
|
|
21
|
+
.pipe(zod_1.z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER));
|
|
22
|
+
// defaults.json is the single source of the shipped threshold: it is the lowest
|
|
23
|
+
// config layer and the file an operator actually reads and edits, so it is read
|
|
24
|
+
// rather than restated. Parsed eagerly because a missing or malformed value
|
|
25
|
+
// there is our bug rather than an operator's, and should fail loudly at boot
|
|
26
|
+
// instead of quietly becoming the fallback for everything below.
|
|
27
|
+
const shippedThreshold = Threshold.parse(require('../../../../shared/config/defaults.json').members.importer.inlineThreshold);
|
|
28
|
+
// A higher layer can override the shipped value with anything. Something
|
|
29
|
+
// unreadable falls back to the shipped threshold rather than throwing, because
|
|
30
|
+
// an operator can correct this live and a bad value must not take member import
|
|
31
|
+
// down with it.
|
|
32
|
+
const InlineThreshold = Threshold.catch(shippedThreshold);
|
|
33
|
+
function resolveInlineThreshold(configured) {
|
|
34
|
+
return InlineThreshold.parse(configured);
|
|
35
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {z} from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Resolving Ghost's config into the values the importer runs on.
|
|
5
|
+
*
|
|
6
|
+
* Config arrives untyped: defaults.json supplies the shipped value, and any
|
|
7
|
+
* higher layer — an operator's config file, an environment variable, argv — can
|
|
8
|
+
* replace it with anything at all. Turning that into something usable is a
|
|
9
|
+
* config concern, so it happens here, at the boundary. The importer is handed an
|
|
10
|
+
* answer and never learns where it came from.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// The row count at or below which an import is performed while the request is
|
|
14
|
+
// still open. Zero is allowed and means every import is deferred. A numeric
|
|
15
|
+
// string is accepted because a value supplied through an environment variable
|
|
16
|
+
// can arrive as one.
|
|
17
|
+
const Threshold = z
|
|
18
|
+
.union([z.number(), z.string().trim().min(1)])
|
|
19
|
+
.transform(Number)
|
|
20
|
+
.pipe(z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER));
|
|
21
|
+
|
|
22
|
+
// defaults.json is the single source of the shipped threshold: it is the lowest
|
|
23
|
+
// config layer and the file an operator actually reads and edits, so it is read
|
|
24
|
+
// rather than restated. Parsed eagerly because a missing or malformed value
|
|
25
|
+
// there is our bug rather than an operator's, and should fail loudly at boot
|
|
26
|
+
// instead of quietly becoming the fallback for everything below.
|
|
27
|
+
const shippedThreshold: number = Threshold.parse(
|
|
28
|
+
require('../../../../shared/config/defaults.json').members.importer.inlineThreshold
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
// A higher layer can override the shipped value with anything. Something
|
|
32
|
+
// unreadable falls back to the shipped threshold rather than throwing, because
|
|
33
|
+
// an operator can correct this live and a bad value must not take member import
|
|
34
|
+
// down with it.
|
|
35
|
+
const InlineThreshold = Threshold.catch(shippedThreshold);
|
|
36
|
+
|
|
37
|
+
export function resolveInlineThreshold(configured: unknown): number {
|
|
38
|
+
return InlineThreshold.parse(configured);
|
|
39
|
+
}
|