ghost 6.40.0 → 6.41.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/core/boot.js +8 -8
- package/core/built/admin/assets/{PolarAngleAxis-D7m1zwVk.js → PolarAngleAxis-Bh28wbPV.js} +1 -1
- package/core/built/admin/assets/{_baseAssignValue-BDsvYKNK.js → _baseAssignValue-hdDG700N.js} +1 -1
- package/core/built/admin/assets/{a-large-small-DxRNdz0F.js → a-large-small-BiK5_5LV.js} +1 -1
- package/core/built/admin/assets/{account-migration-SYnE1jBW.js → account-migration-DsSHanIB.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-Bj9rgbLw.mjs → code-editor-view-BEIdFhw3.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{index-BrZ9YAzd.mjs → index-BEh3nFEy.mjs} +3 -3
- package/core/built/admin/assets/admin-x-settings/{index-DRndIh9T.mjs → index-BLF2n6YB.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{index-CIl25Teq.mjs → index-BmPIWs5F.mjs} +3 -3
- package/core/built/admin/assets/admin-x-settings/{index-CNyNY3Wh.mjs → index-CP9YnNzc.mjs} +3 -3
- package/core/built/admin/assets/admin-x-settings/{index-SGr5sE2h.mjs → index-Cd2Ns-D2.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{index-PGoLP2kh.mjs → index-CjqAcKpK.mjs} +5 -5
- package/core/built/admin/assets/admin-x-settings/{index-pCIv_7bB.mjs → index-CnMcD9aj.mjs} +6212 -6158
- package/core/built/admin/assets/admin-x-settings/{index-CPCcgad-.mjs → index-LzsrZC40.mjs} +3 -3
- package/core/built/admin/assets/admin-x-settings/{index-DPqY4h5h.mjs → index-ZYW0UW7I.mjs} +3 -3
- package/core/built/admin/assets/admin-x-settings/{modals-lo32WZLi.mjs → modals-C48Tq1rW.mjs} +9 -9
- package/core/built/admin/assets/{arrow-right-BixoEua4.js → arrow-right-Bk43nMGd.js} +1 -1
- package/core/built/admin/assets/{at-sign-BsHNViA_.js → at-sign-DWOf36uj.js} +1 -1
- package/core/built/admin/assets/{audience-0RCWjbIK.js → audience-CvP78Gug.js} +1 -1
- package/core/built/admin/assets/{automations-DTUfYvf6.js → automations-BBWZhrha.js} +1 -1
- package/core/built/admin/assets/{automations-DiGkcVt-.js → automations-CmulGWwu.js} +1 -1
- package/core/built/admin/assets/{avatar-flipboard-BgoH-wIq.js → avatar-flipboard-CVf-N6wp.js} +1 -1
- package/core/built/admin/assets/{bluesky-sharing-C2xwSoS-.js → bluesky-sharing-DVC3I9Um.js} +1 -1
- package/core/built/admin/assets/{chart-X5cLIH1X.js → chart-CUKSNmKY.js} +1 -1
- package/core/built/admin/assets/{checkbox-DMamS4oG.js → checkbox-B_yDSM8z.js} +1 -1
- package/core/built/admin/assets/{chevron-up-CVgBkTk5.js → chevron-up-DuaKtE_M.js} +1 -1
- package/core/built/admin/assets/{chunk.941.f47098cbbce89a049e03.js → chunk.331.2ec2e2702eda02de96cd.js} +3 -3
- package/core/built/admin/assets/{chunk.524.a1d668dcc84709a5d702.js → chunk.524.49cc01002e1a5dba8ef9.js} +4 -4
- package/core/built/admin/assets/{chunk.582.180bf2525cf552f5ac5f.js → chunk.582.4bbc54c5f7d3dfb93288.js} +6 -6
- package/core/built/admin/assets/{circle-alert-Dg3UkvRP.js → circle-alert-bcK_Yqap.js} +1 -1
- package/core/built/admin/assets/{code-editor-view-CAICoZJe.js → code-editor-view-Bl4Jzjhk.js} +1 -1
- package/core/built/admin/assets/{comments-BHru9ZQ8.js → comments-DMea0nul.js} +1 -1
- package/core/built/admin/assets/{content-helpers-BByMp-Y5.js → content-helpers-B2yRzdvJ.js} +1 -1
- package/core/built/admin/assets/{copy-D7jqplrv.js → copy-DVtQi_VJ.js} +1 -1
- package/core/built/admin/assets/{data-list-DUaY9nlT.js → data-list-BF4GeUmt.js} +1 -1
- package/core/built/admin/assets/{deleted-feed-item-jLcSKuul.js → deleted-feed-item-DO2u3qmi.js} +1 -1
- package/core/built/admin/assets/{dropzone-DSPf3N_o.js → dropzone-Cs4DrURS.js} +1 -1
- package/core/built/admin/assets/{edit-profile-BvU2-lW5.js → edit-profile-CnuBNQhO.js} +1 -1
- package/core/built/admin/assets/{editor-D3fcjt_F.js → editor-CTO9FIUW.js} +1 -1
- package/core/built/admin/assets/{empty-indicator-2Pjmce3n.js → empty-indicator-BvyaMcmw.js} +1 -1
- package/core/built/admin/assets/{en-Bu-6PYn5.js → en-CjPXRj8j.js} +1 -1
- package/core/built/admin/assets/{feed-CygLK1Ad.js → feed-D2wk4cCS.js} +1 -1
- package/core/built/admin/assets/{filter-query-core-a0PNU2EO.js → filter-query-core-VEnwTCyO.js} +1 -1
- package/core/built/admin/assets/{filters-jiyRsLMH.js → filters-DtIsuqv5.js} +1 -1
- package/core/built/admin/assets/{gh-chart-CEhBBu3F.js → gh-chart-JxzKqaoO.js} +1 -1
- package/core/built/admin/assets/{ghost-0ab96884815339963364804ab266c99f.js → ghost-30c3dedbe1cca943b92efa7efd2710e4.js} +36 -21
- package/core/built/admin/assets/{growth-Fz3Oatml.js → growth-CPNrBpHK.js} +1 -1
- package/core/built/admin/assets/{hash-CeFrjo3C.js → hash-CJzbTA5k.js} +1 -1
- package/core/built/admin/assets/{inbox-CCirPaG2.js → inbox-CVVAkCmd.js} +1 -1
- package/core/built/admin/assets/{index-Dd2BJRZH.js → index-AkQJUr1z.js} +1 -1
- package/core/built/admin/assets/{index-CYPN5csJ.js → index-BLWOUf31.js} +1 -1
- package/core/built/admin/assets/{index-D7Ui3Fih.js → index-BRBRkRqa.js} +1 -1
- package/core/built/admin/assets/{index-CFEzD2_M.js → index-BkbhBpVC.js} +3 -3
- package/core/built/admin/assets/{index-BYwL7gFN.js → index-BxFFWYdP.js} +1 -1
- package/core/built/admin/assets/{index-D3LfHeBl.js → index-C5_ZKpC1.js} +1 -1
- package/core/built/admin/assets/{index-Bjw2qAph.js → index-Cdbufdfy.js} +1 -1
- package/core/built/admin/assets/{index-BTf6YUBb.js → index-Cq5vsvxE.js} +1 -1
- package/core/built/admin/assets/{index-DPbi4ie_.js → index-CuGoX8Ub.js} +1 -1
- package/core/built/admin/assets/{index-CsaU9dfl.js → index-CuH5raTz.js} +1 -1
- package/core/built/admin/assets/{index-Bf83suMc.js → index-D3A8RTi0.js} +1 -1
- package/core/built/admin/assets/{index-Dskrbhv3.js → index-DIyK69JM.js} +1 -1
- package/core/built/admin/assets/{index-GExKMpy_.js → index-DLFVpwt3.js} +1 -1
- package/core/built/admin/assets/{index-BOMdiHRG.js → index-DQZp_NsL.js} +1 -1
- package/core/built/admin/assets/{index-2qcjFCQs.js → index-DR74ulj2.js} +1 -1
- package/core/built/admin/assets/{index-WKMARia9.js → index-DYE2untj.js} +1 -1
- package/core/built/admin/assets/{index-DNZUJQ8v.js → index-DssW7xhk.js} +1 -1
- package/core/built/admin/assets/{index-Cq4mS7QK.js → index-DvyNqFct.js} +1 -1
- package/core/built/admin/assets/{index-C7xLyJVb.js → index-DxB7NHpG.js} +1 -1
- package/core/built/admin/assets/{index-Bw4DM4Pr.js → index-IDaHqjnu.js} +1 -1
- package/core/built/admin/assets/{index-ClOB5u8L.js → index-TtBMzSeP.js} +1 -1
- package/core/built/admin/assets/{index-takfwHSn.js → index-UMWVIyz7.js} +1 -1
- package/core/built/admin/assets/{koenig-lexical-BJM9wAwQ.js → koenig-lexical-DVAmevhl.js} +1 -1
- package/core/built/admin/assets/{kpi-card-BP-2yicn.js → kpi-card-D3CzvsrI.js} +1 -1
- package/core/built/admin/assets/{kpi-card-DOplXdDT.js → kpi-card-DV-nN7xT.js} +1 -1
- package/core/built/admin/assets/{kpi-tabs-Rq5jJW2Z.js → kpi-tabs-B3NkaTwb.js} +1 -1
- package/core/built/admin/assets/{kpis-yHgME_iy.js → kpis-CVwF08QL.js} +1 -1
- package/core/built/admin/assets/{label-fijjy1Mb.js → label-BiPpMny2.js} +1 -1
- package/core/built/admin/assets/{links-s3IeAkbo.js → links-BY0Uo6O5.js} +1 -1
- package/core/built/admin/assets/{list-page-CUcB5ebB.js → list-page-COHNMpOi.js} +1 -1
- package/core/built/admin/assets/{loader-circle-C7mWzo52.js → loader-circle-B1uEfpbZ.js} +1 -1
- package/core/built/admin/assets/{mail-9TFkAaAh.js → mail-ccQhEr7k.js} +1 -1
- package/core/built/admin/assets/{main-layout-XtviVkg1.js → main-layout-BYKdA6Z1.js} +1 -1
- package/core/built/admin/assets/{members-XkHao5Yf.js → members-DkpEnvG5.js} +1 -1
- package/core/built/admin/assets/minus-C68D81nx.js +1 -0
- package/core/built/admin/assets/{modals-B6R7oqvb.js → modals-X6RSWn5Y.js} +3 -3
- package/core/built/admin/assets/{moderation-B2Tixfce.js → moderation-BFrrwfvx.js} +1 -1
- package/core/built/admin/assets/{newsletter-CbESXhxf.js → newsletter-n7kc6cxR.js} +1 -1
- package/core/built/admin/assets/{newsletters-DOIL_cOY.js → newsletters-CSCa3QdE.js} +1 -1
- package/core/built/admin/assets/{note-mUikaB-p.js → note-CMZjeK8e.js} +1 -1
- package/core/built/admin/assets/{onboarding-route-Dqv2nP7b.js → onboarding-route-BaX0a-pu.js} +1 -1
- package/core/built/admin/assets/{overview-yZ-7KJdx.js → overview-CS9dmE_6.js} +1 -1
- package/core/built/admin/assets/{pagemenu-TxGvHwRO.js → pagemenu-O_y8Jm4v.js} +1 -1
- package/core/built/admin/assets/{pencil-CKTgzafp.js → pencil-BcymGPnE.js} +1 -1
- package/core/built/admin/assets/{pin-BU_u-xRX.js → pin-Bl3nSr7I.js} +1 -1
- package/core/built/admin/assets/{post-analytics-CWA8invj.js → post-analytics-DW-TKu-t.js} +1 -1
- package/core/built/admin/assets/{post-analytics-context-BWDhMRq_.js → post-analytics-context-D7PgEMo8.js} +1 -1
- package/core/built/admin/assets/{post-analytics-header-Bm0mcxjK.js → post-analytics-header-B8C0vA5Y.js} +1 -1
- package/core/built/admin/assets/{post-share-modal-D8BtRD2u.js → post-share-modal-D0OlASBQ.js} +1 -1
- package/core/built/admin/assets/{posts-u-CAKddc.js → posts-BZaw4-dc.js} +1 -1
- package/core/built/admin/assets/{power-DR9gpiQR.js → power-DWm6pts5.js} +1 -1
- package/core/built/admin/assets/{referrers-DV_Ihg9y.js → referrers-BsZ85Z0a.js} +1 -1
- package/core/built/admin/assets/{repeat-uXmOJ6y8.js → repeat-DQay9e22.js} +1 -1
- package/core/built/admin/assets/{reply-9ZyqaxI-.js → reply-CoNqmExw.js} +1 -1
- package/core/built/admin/assets/{rocket-DMOr1OCt.js → rocket-Dne6P_8f.js} +1 -1
- package/core/built/admin/assets/{select-CPSy44ld.js → select-BfWJkrKc.js} +1 -1
- package/core/built/admin/assets/{settings-krk0432u.js → settings-BoXzKMhL.js} +1 -1
- package/core/built/admin/assets/{settings-66Zv8QvL.js → settings-rRY210wx.js} +25 -25
- package/core/built/admin/assets/{share-modal-BRmGllZq.js → share-modal-CtdLQbnQ.js} +1 -1
- package/core/built/admin/assets/{sort-button-5fyeViQL.js → sort-button-7pVgpa0d.js} +1 -1
- package/core/built/admin/assets/{source-icon-DeeHyZRn.js → source-icon-Dtua85oN.js} +1 -1
- package/core/built/admin/assets/{sprout-956Q4On2.js → sprout-CpwUJAPT.js} +1 -1
- package/core/built/admin/assets/{square-BaCvbKJY.js → square-CDrQjv8R.js} +1 -1
- package/core/built/admin/assets/{stats-BVKNZJO6.js → stats-Yo9Gco0_.js} +1 -1
- package/core/built/admin/assets/{stats-view-gtyaqudG.js → stats-view-DubukX9V.js} +1 -1
- package/core/built/admin/assets/{step-1-09wdjzdX.js → step-1-CH8jWKi7.js} +1 -1
- package/core/built/admin/assets/{step-2-8iaQ0efq.js → step-2-CWy7Qi0Q.js} +1 -1
- package/core/built/admin/assets/{step-3-BuHAZbdD.js → step-3-CNiDFH17.js} +1 -1
- package/core/built/admin/assets/{table-DTofVyjA.js → table-qQi9EXB1.js} +1 -1
- package/core/built/admin/assets/{tabs-CL5eaCGL.js → tabs-M6kFEqPE.js} +1 -1
- package/core/built/admin/assets/{tags-DJrbEw5-.js → tags-74U6lgwY.js} +1 -1
- package/core/built/admin/assets/{tags-U3lciBmd.js → tags-DuMshkTz.js} +1 -1
- package/core/built/admin/assets/{textarea-DdDuNixZ.js → textarea-CGBp9nOo.js} +1 -1
- package/core/built/admin/assets/{tiers-DXKbghdk.js → tiers-D2DYHaeO.js} +1 -1
- package/core/built/admin/assets/{toggle-group-DaZKTYDS.js → toggle-group-GYp_w6Po.js} +1 -1
- package/core/built/admin/assets/{topic-filter-BzqiVOAU.js → topic-filter-N3CzJ01P.js} +1 -1
- package/core/built/admin/assets/{trash-CKK_p9G5.js → trash-CUqAK3SQ.js} +1 -1
- package/core/built/admin/assets/{underline-Bq0P-5Zy.js → underline-CwuJG-Ql.js} +1 -1
- package/core/built/admin/assets/{undo-2-CcBtw-tW.js → undo-2-D6ZRqONE.js} +1 -1
- package/core/built/admin/assets/{upload-BcylHEMw.js → upload-BLiT66bJ.js} +1 -1
- package/core/built/admin/assets/{use-growth-stats-Ci0gymWp.js → use-growth-stats-u18So4Gq.js} +1 -1
- package/core/built/admin/assets/{use-simple-pagination-ByaFwxfZ.js → use-simple-pagination-Dp2sTt2S.js} +1 -1
- package/core/built/admin/assets/{user-round-check-D0I7NO1g.js → user-round-check-BDomHaso.js} +1 -1
- package/core/built/admin/assets/{user-round-x-DeGVH29o.js → user-round-x-Cc0RL-V9.js} +1 -1
- package/core/built/admin/assets/{virtual-list-window-S0xZxQAf.js → virtual-list-window-BnjCoNIr.js} +1 -1
- package/core/built/admin/assets/{wallet-cards-B9TQg4x3.js → wallet-cards-CVZ99Nm3.js} +1 -1
- package/core/built/admin/assets/{web-BRN2mUpo.js → web-B_MLxGxZ.js} +1 -1
- package/core/built/admin/index.html +5 -5
- package/core/server/{services/custom-redirects/file-store.js → adapters/redirects/FileStore.js} +6 -5
- package/core/server/{services/custom-redirects/file-store.ts → adapters/redirects/FileStore.ts} +6 -4
- package/core/server/adapters/redirects/RedirectsStoreBase.d.ts +9 -0
- package/core/server/adapters/redirects/RedirectsStoreBase.js +8 -0
- package/core/server/{services/custom-redirects/gcs-store.js → adapters/redirects/S3RedirectsStore.js} +50 -18
- package/core/server/adapters/redirects/S3RedirectsStore.ts +163 -0
- package/core/server/adapters/scheduling/scheduling-base.js +41 -0
- package/core/server/adapters/scheduling/types.js +2 -0
- package/core/server/adapters/scheduling/types.ts +36 -0
- package/core/server/api/endpoints/authentication.js +26 -5
- package/core/server/api/endpoints/schedules.js +0 -30
- package/core/server/api/endpoints/utils/serializers/output/authentication.js +10 -0
- package/core/server/data/migrations/versions/6.41/2026-05-13-12-00-00-rename-reset-all-passwords-permission.js +21 -0
- package/core/server/data/schema/fixtures/fixtures.json +3 -3
- package/core/server/models/api-key.js +18 -0
- package/core/server/models/user.js +18 -0
- package/core/server/services/adapter-manager/config.js +6 -0
- package/core/server/services/adapter-manager/index.js +1 -0
- package/core/server/services/auth/index.js +4 -0
- package/core/server/services/auth/reset-authentication.js +50 -0
- package/core/server/services/auth/reset-authentication.ts +75 -0
- package/core/server/services/automations/index.js +21 -15
- package/core/server/services/custom-redirects/index.js +2 -4
- package/core/server/services/gifts/gift-bookshelf-repository.js +7 -0
- package/core/server/services/gifts/gift-bookshelf-repository.ts +10 -0
- package/core/server/services/gifts/gift-reminder-scheduler.js +94 -0
- package/core/server/services/gifts/gift-reminder-scheduler.ts +109 -0
- package/core/server/services/gifts/gift-repository.ts +1 -0
- package/core/server/services/gifts/gift-service-wrapper.js +10 -7
- package/core/server/services/gifts/gift-service.js +1 -32
- package/core/server/services/gifts/gift-service.ts +3 -59
- package/core/server/services/internal-keys/index.js +1 -3
- package/core/server/services/internal-keys/index.ts +11 -3
- package/core/server/services/post-scheduling/index.js +16 -28
- package/core/server/services/post-scheduling/index.ts +14 -0
- package/core/server/services/post-scheduling/post-scheduling.js +115 -0
- package/core/server/services/post-scheduling/post-scheduling.ts +138 -0
- package/core/server/services/users.js +29 -16
- package/core/server/web/api/endpoints/admin/middleware.js +8 -4
- package/core/server/web/api/endpoints/admin/routes.js +1 -1
- package/core/shared/config/defaults.json +5 -0
- package/core/shared/labs.js +2 -1
- package/package.json +1 -1
- package/core/built/admin/assets/minus-DPrXh11r.js +0 -1
- package/core/server/services/custom-redirects/gcs-store.ts +0 -117
- package/core/server/services/post-scheduling/post-scheduler-service.js +0 -126
package/core/built/admin/assets/{user-round-check-D0I7NO1g.js → user-round-check-BDomHaso.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{aq as e}from"./index-
|
|
1
|
+
import{aq as e}from"./index-BkbhBpVC.js";const c=[["path",{d:"m2 9 3-3 3 3",key:"1ltn5i"}],["path",{d:"M13 18H7a2 2 0 0 1-2-2V6",key:"1r6tfw"}],["path",{d:"m22 15-3 3-3-3",key:"4rnwn2"}],["path",{d:"M11 6h6a2 2 0 0 1 2 2v10",key:"2f72bc"}]],o=e("repeat-2",c);const t=[["path",{d:"M2 21a8 8 0 0 1 13.292-6",key:"bjp14o"}],["circle",{cx:"10",cy:"8",r:"5",key:"o932ke"}],["path",{d:"m16 19 2 2 4-4",key:"1b14m6"}]],n=e("user-round-check",t);export{o as R,n as U};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{aq as e}from"./index-
|
|
1
|
+
import{aq as e}from"./index-BkbhBpVC.js";const o=[["path",{d:"M2 21a8 8 0 0 1 11.873-7",key:"74fkxq"}],["circle",{cx:"10",cy:"8",r:"5",key:"o932ke"}],["path",{d:"m17 17 5 5",key:"p7ous7"}],["path",{d:"m22 17-5 5",key:"gqnmv0"}]],r=e("user-round-x",o);export{r as U};
|
package/core/built/admin/assets/{virtual-list-window-S0xZxQAf.js → virtual-list-window-BnjCoNIr.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{j as C,B as j,r as S,aB as V,cE as B}from"./index-
|
|
1
|
+
import{j as C,B as j,r as S,aB as V,cE as B}from"./index-BkbhBpVC.js";const it=({isLoading:l,onClick:r})=>{const t=!!l;return C.jsx("div",{className:"flex justify-center px-4 py-6",children:C.jsx(j,{disabled:t,variant:"outline",onClick:r,children:t?"Loading more...":"Load more"})})};function T(l){const t=l instanceof HTMLElement&&window.getComputedStyle(l).overflowY,e=t!=="visible"&&t!=="hidden";if(l){if(e&&l.scrollHeight>=l.clientHeight)return l}else return null;return T(l.parentNode)||document.body}function E(l,r,t){let e=t.initialDeps??[],s,n=!0;function i(){var o,a,c;let u;t.key&&((o=t.debug)!=null&&o.call(t))&&(u=Date.now());const d=l();if(!(d.length!==e.length||d.some((f,v)=>e[v]!==f)))return s;e=d;let h;if(t.key&&((a=t.debug)!=null&&a.call(t))&&(h=Date.now()),s=r(...d),t.key&&((c=t.debug)!=null&&c.call(t))){const f=Math.round((Date.now()-u)*100)/100,v=Math.round((Date.now()-h)*100)/100,g=v/16,b=(p,w)=>{for(p=String(p);p.length<w;)p=" "+p;return p};console.info(`%c⏱ ${b(v,5)} /${b(f,5)} ms`,`
|
|
2
2
|
font-size: .6rem;
|
|
3
3
|
font-weight: bold;
|
|
4
4
|
color: hsl(${Math.max(0,Math.min(120-120*g,120))}deg 100% 31%);`,t?.key)}return t?.onChange&&!(n&&t.skipInitialOnChange)&&t.onChange(s),n=!1,s}return i.updateDeps=o=>{e=o},i}function z(l,r){if(l===void 0)throw new Error("Unexpected undefined");return l}const H=(l,r)=>Math.abs(l-r)<1.01,N=(l,r,t)=>{let e;return function(...s){l.clearTimeout(e),e=l.setTimeout(()=>r.apply(this,s),t)}},A=l=>{const{offsetWidth:r,offsetHeight:t}=l;return{width:r,height:t}},K=l=>l,P=l=>{const r=Math.max(l.startIndex-l.overscan,0),t=Math.min(l.endIndex+l.overscan,l.count-1),e=[];for(let s=r;s<=t;s++)e.push(s);return e},U=(l,r)=>{const t=l.scrollElement;if(!t)return;const e=l.targetWindow;if(!e)return;const s=i=>{const{width:o,height:a}=i;r({width:Math.round(o),height:Math.round(a)})};if(s(A(t)),!e.ResizeObserver)return()=>{};const n=new e.ResizeObserver(i=>{const o=()=>{const a=i[0];if(a?.borderBoxSize){const c=a.borderBoxSize[0];if(c){s({width:c.inlineSize,height:c.blockSize});return}}s(A(t))};l.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(o):o()});return n.observe(t,{box:"border-box"}),()=>{n.unobserve(t)}},R={passive:!0},_=typeof window>"u"?!0:"onscrollend"in window,$=(l,r)=>{const t=l.scrollElement;if(!t)return;const e=l.targetWindow;if(!e)return;let s=0;const n=l.options.useScrollendEvent&&_?()=>{}:N(e,()=>{r(s,!1)},l.options.isScrollingResetDelay),i=u=>()=>{const{horizontal:d,isRtl:m}=l.options;s=d?t.scrollLeft*(m&&-1||1):t.scrollTop,n(),r(s,u)},o=i(!0),a=i(!1);t.addEventListener("scroll",o,R);const c=l.options.useScrollendEvent&&_;return c&&t.addEventListener("scrollend",a,R),()=>{t.removeEventListener("scroll",o),c&&t.removeEventListener("scrollend",a)}},q=(l,r,t)=>{if(r?.borderBoxSize){const e=r.borderBoxSize[0];if(e)return Math.round(e[t.options.horizontal?"inlineSize":"blockSize"])}return l[t.options.horizontal?"offsetWidth":"offsetHeight"]},Y=(l,{adjustments:r=0,behavior:t},e)=>{var s,n;const i=l+r;(n=(s=e.scrollElement)==null?void 0:s.scrollTo)==null||n.call(s,{[e.options.horizontal?"left":"top"]:i,behavior:t})};class X{constructor(r){this.unsubs=[],this.scrollElement=null,this.targetWindow=null,this.isScrolling=!1,this.scrollState=null,this.measurementsCache=[],this.itemSizeCache=new Map,this.laneAssignments=new Map,this.pendingMeasuredCacheIndexes=[],this.prevLanes=void 0,this.lanesChangedFlag=!1,this.lanesSettling=!1,this.scrollRect=null,this.scrollOffset=null,this.scrollDirection=null,this.scrollAdjustments=0,this.elementsCache=new Map,this.now=()=>{var t,e,s;return((s=(e=(t=this.targetWindow)==null?void 0:t.performance)==null?void 0:e.now)==null?void 0:s.call(e))??Date.now()},this.observer=(()=>{let t=null;const e=()=>t||(!this.targetWindow||!this.targetWindow.ResizeObserver?null:t=new this.targetWindow.ResizeObserver(s=>{s.forEach(n=>{const i=()=>{const o=n.target,a=this.indexFromElement(o);if(!o.isConnected){this.observer.unobserve(o);return}this.shouldMeasureDuringScroll(a)&&this.resizeItem(a,this.options.measureElement(o,n,this))};this.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(i):i()})}));return{disconnect:()=>{var s;(s=e())==null||s.disconnect(),t=null},observe:s=>{var n;return(n=e())==null?void 0:n.observe(s,{box:"border-box"})},unobserve:s=>{var n;return(n=e())==null?void 0:n.unobserve(s)}}})(),this.range=null,this.setOptions=t=>{Object.entries(t).forEach(([e,s])=>{typeof s>"u"&&delete t[e]}),this.options={debug:!1,initialOffset:0,overscan:1,paddingStart:0,paddingEnd:0,scrollPaddingStart:0,scrollPaddingEnd:0,horizontal:!1,getItemKey:K,rangeExtractor:P,onChange:()=>{},measureElement:q,initialRect:{width:0,height:0},scrollMargin:0,gap:0,indexAttribute:"data-index",initialMeasurementsCache:[],lanes:1,isScrollingResetDelay:150,enabled:!0,isRtl:!1,useScrollendEvent:!1,useAnimationFrameWithResizeObserver:!1,laneAssignmentMode:"estimate",...t}},this.notify=t=>{var e,s;(s=(e=this.options).onChange)==null||s.call(e,this,t)},this.maybeNotify=E(()=>(this.calculateRange(),[this.isScrolling,this.range?this.range.startIndex:null,this.range?this.range.endIndex:null]),t=>{this.notify(t)},{key:!1,debug:()=>this.options.debug,initialDeps:[this.isScrolling,this.range?this.range.startIndex:null,this.range?this.range.endIndex:null]}),this.cleanup=()=>{this.unsubs.filter(Boolean).forEach(t=>t()),this.unsubs=[],this.observer.disconnect(),this.rafId!=null&&this.targetWindow&&(this.targetWindow.cancelAnimationFrame(this.rafId),this.rafId=null),this.scrollState=null,this.scrollElement=null,this.targetWindow=null},this._didMount=()=>()=>{this.cleanup()},this._willUpdate=()=>{var t;const e=this.options.enabled?this.options.getScrollElement():null;if(this.scrollElement!==e){if(this.cleanup(),!e){this.maybeNotify();return}this.scrollElement=e,this.scrollElement&&"ownerDocument"in this.scrollElement?this.targetWindow=this.scrollElement.ownerDocument.defaultView:this.targetWindow=((t=this.scrollElement)==null?void 0:t.window)??null,this.elementsCache.forEach(s=>{this.observer.observe(s)}),this.unsubs.push(this.options.observeElementRect(this,s=>{this.scrollRect=s,this.maybeNotify()})),this.unsubs.push(this.options.observeElementOffset(this,(s,n)=>{this.scrollAdjustments=0,this.scrollDirection=n?this.getScrollOffset()<s?"forward":"backward":null,this.scrollOffset=s,this.isScrolling=n,this.scrollState&&this.scheduleScrollReconcile(),this.maybeNotify()})),this._scrollToOffset(this.getScrollOffset(),{adjustments:void 0,behavior:void 0})}},this.rafId=null,this.getSize=()=>this.options.enabled?(this.scrollRect=this.scrollRect??this.options.initialRect,this.scrollRect[this.options.horizontal?"width":"height"]):(this.scrollRect=null,0),this.getScrollOffset=()=>this.options.enabled?(this.scrollOffset=this.scrollOffset??(typeof this.options.initialOffset=="function"?this.options.initialOffset():this.options.initialOffset),this.scrollOffset):(this.scrollOffset=null,0),this.getFurthestMeasurement=(t,e)=>{const s=new Map,n=new Map;for(let i=e-1;i>=0;i--){const o=t[i];if(s.has(o.lane))continue;const a=n.get(o.lane);if(a==null||o.end>a.end?n.set(o.lane,o):o.end<a.end&&s.set(o.lane,!0),s.size===this.options.lanes)break}return n.size===this.options.lanes?Array.from(n.values()).sort((i,o)=>i.end===o.end?i.index-o.index:i.end-o.end)[0]:void 0},this.getMeasurementOptions=E(()=>[this.options.count,this.options.paddingStart,this.options.scrollMargin,this.options.getItemKey,this.options.enabled,this.options.lanes,this.options.laneAssignmentMode],(t,e,s,n,i,o,a)=>(this.prevLanes!==void 0&&this.prevLanes!==o&&(this.lanesChangedFlag=!0),this.prevLanes=o,this.pendingMeasuredCacheIndexes=[],{count:t,paddingStart:e,scrollMargin:s,getItemKey:n,enabled:i,lanes:o,laneAssignmentMode:a}),{key:!1}),this.getMeasurements=E(()=>[this.getMeasurementOptions(),this.itemSizeCache],({count:t,paddingStart:e,scrollMargin:s,getItemKey:n,enabled:i,lanes:o,laneAssignmentMode:a},c)=>{if(!i)return this.measurementsCache=[],this.itemSizeCache.clear(),this.laneAssignments.clear(),[];if(this.laneAssignments.size>t)for(const h of this.laneAssignments.keys())h>=t&&this.laneAssignments.delete(h);this.lanesChangedFlag&&(this.lanesChangedFlag=!1,this.lanesSettling=!0,this.measurementsCache=[],this.itemSizeCache.clear(),this.laneAssignments.clear(),this.pendingMeasuredCacheIndexes=[]),this.measurementsCache.length===0&&!this.lanesSettling&&(this.measurementsCache=this.options.initialMeasurementsCache,this.measurementsCache.forEach(h=>{this.itemSizeCache.set(h.key,h.size)}));const u=this.lanesSettling?0:this.pendingMeasuredCacheIndexes.length>0?Math.min(...this.pendingMeasuredCacheIndexes):0;this.pendingMeasuredCacheIndexes=[],this.lanesSettling&&this.measurementsCache.length===t&&(this.lanesSettling=!1);const d=this.measurementsCache.slice(0,u),m=new Array(o).fill(void 0);for(let h=0;h<u;h++){const f=d[h];f&&(m[f.lane]=h)}for(let h=u;h<t;h++){const f=n(h),v=this.laneAssignments.get(h);let g,b;const p=a==="estimate"||c.has(f);if(v!==void 0&&this.options.lanes>1){g=v;const x=m[g],O=x!==void 0?d[x]:void 0;b=O?O.end+this.options.gap:e+s}else{const x=this.options.lanes===1?d[h-1]:this.getFurthestMeasurement(d,h);b=x?x.end+this.options.gap:e+s,g=x?x.lane:h%this.options.lanes,this.options.lanes>1&&p&&this.laneAssignments.set(h,g)}const w=c.get(f),y=typeof w=="number"?w:this.options.estimateSize(h),D=b+y;d[h]={index:h,start:b,size:y,end:D,key:f,lane:g},m[g]=h}return this.measurementsCache=d,d},{key:!1,debug:()=>this.options.debug}),this.calculateRange=E(()=>[this.getMeasurements(),this.getSize(),this.getScrollOffset(),this.options.lanes],(t,e,s,n)=>this.range=t.length>0&&e>0?Z({measurements:t,outerSize:e,scrollOffset:s,lanes:n}):null,{key:!1,debug:()=>this.options.debug}),this.getVirtualIndexes=E(()=>{let t=null,e=null;const s=this.calculateRange();return s&&(t=s.startIndex,e=s.endIndex),this.maybeNotify.updateDeps([this.isScrolling,t,e]),[this.options.rangeExtractor,this.options.overscan,this.options.count,t,e]},(t,e,s,n,i)=>n===null||i===null?[]:t({startIndex:n,endIndex:i,overscan:e,count:s}),{key:!1,debug:()=>this.options.debug}),this.indexFromElement=t=>{const e=this.options.indexAttribute,s=t.getAttribute(e);return s?parseInt(s,10):(console.warn(`Missing attribute name '${e}={index}' on measured element.`),-1)},this.shouldMeasureDuringScroll=t=>{var e;if(!this.scrollState||this.scrollState.behavior!=="smooth")return!0;const s=this.scrollState.index??((e=this.getVirtualItemForOffset(this.scrollState.lastTargetOffset))==null?void 0:e.index);if(s!==void 0&&this.range){const n=Math.max(this.options.overscan,Math.ceil((this.range.endIndex-this.range.startIndex)/2)),i=Math.max(0,s-n),o=Math.min(this.options.count-1,s+n);return t>=i&&t<=o}return!0},this.measureElement=t=>{if(!t){this.elementsCache.forEach((i,o)=>{i.isConnected||(this.observer.unobserve(i),this.elementsCache.delete(o))});return}const e=this.indexFromElement(t),s=this.options.getItemKey(e),n=this.elementsCache.get(s);n!==t&&(n&&this.observer.unobserve(n),this.observer.observe(t),this.elementsCache.set(s,t)),(!this.isScrolling||this.scrollState)&&this.shouldMeasureDuringScroll(e)&&this.resizeItem(e,this.options.measureElement(t,void 0,this))},this.resizeItem=(t,e)=>{var s;const n=this.measurementsCache[t];if(!n)return;const i=this.itemSizeCache.get(n.key)??n.size,o=e-i;o!==0&&(((s=this.scrollState)==null?void 0:s.behavior)!=="smooth"&&(this.shouldAdjustScrollPositionOnItemSizeChange!==void 0?this.shouldAdjustScrollPositionOnItemSizeChange(n,o,this):n.start<this.getScrollOffset()+this.scrollAdjustments)&&this._scrollToOffset(this.getScrollOffset(),{adjustments:this.scrollAdjustments+=o,behavior:void 0}),this.pendingMeasuredCacheIndexes.push(n.index),this.itemSizeCache=new Map(this.itemSizeCache.set(n.key,e)),this.notify(!1))},this.getVirtualItems=E(()=>[this.getVirtualIndexes(),this.getMeasurements()],(t,e)=>{const s=[];for(let n=0,i=t.length;n<i;n++){const o=t[n],a=e[o];s.push(a)}return s},{key:!1,debug:()=>this.options.debug}),this.getVirtualItemForOffset=t=>{const e=this.getMeasurements();if(e.length!==0)return z(e[W(0,e.length-1,s=>z(e[s]).start,t)])},this.getMaxScrollOffset=()=>{if(!this.scrollElement)return 0;if("scrollHeight"in this.scrollElement)return this.options.horizontal?this.scrollElement.scrollWidth-this.scrollElement.clientWidth:this.scrollElement.scrollHeight-this.scrollElement.clientHeight;{const t=this.scrollElement.document.documentElement;return this.options.horizontal?t.scrollWidth-this.scrollElement.innerWidth:t.scrollHeight-this.scrollElement.innerHeight}},this.getOffsetForAlignment=(t,e,s=0)=>{if(!this.scrollElement)return 0;const n=this.getSize(),i=this.getScrollOffset();e==="auto"&&(e=t>=i+n?"end":"start"),e==="center"?t+=(s-n)/2:e==="end"&&(t-=n);const o=this.getMaxScrollOffset();return Math.max(Math.min(o,t),0)},this.getOffsetForIndex=(t,e="auto")=>{t=Math.max(0,Math.min(t,this.options.count-1));const s=this.getSize(),n=this.getScrollOffset(),i=this.measurementsCache[t];if(!i)return;if(e==="auto")if(i.end>=n+s-this.options.scrollPaddingEnd)e="end";else if(i.start<=n+this.options.scrollPaddingStart)e="start";else return[n,e];if(e==="end"&&t===this.options.count-1)return[this.getMaxScrollOffset(),e];const o=e==="end"?i.end+this.options.scrollPaddingEnd:i.start-this.options.scrollPaddingStart;return[this.getOffsetForAlignment(o,e,i.size),e]},this.scrollToOffset=(t,{align:e="start",behavior:s="auto"}={})=>{const n=this.getOffsetForAlignment(t,e),i=this.now();this.scrollState={index:null,align:e,behavior:s,startedAt:i,lastTargetOffset:n,stableFrames:0},this._scrollToOffset(n,{adjustments:void 0,behavior:s}),this.scheduleScrollReconcile()},this.scrollToIndex=(t,{align:e="auto",behavior:s="auto"}={})=>{t=Math.max(0,Math.min(t,this.options.count-1));const n=this.getOffsetForIndex(t,e);if(!n)return;const[i,o]=n,a=this.now();this.scrollState={index:t,align:o,behavior:s,startedAt:a,lastTargetOffset:i,stableFrames:0},this._scrollToOffset(i,{adjustments:void 0,behavior:s}),this.scheduleScrollReconcile()},this.scrollBy=(t,{behavior:e="auto"}={})=>{const s=this.getScrollOffset()+t,n=this.now();this.scrollState={index:null,align:"start",behavior:e,startedAt:n,lastTargetOffset:s,stableFrames:0},this._scrollToOffset(s,{adjustments:void 0,behavior:e}),this.scheduleScrollReconcile()},this.getTotalSize=()=>{var t;const e=this.getMeasurements();let s;if(e.length===0)s=this.options.paddingStart;else if(this.options.lanes===1)s=((t=e[e.length-1])==null?void 0:t.end)??0;else{const n=Array(this.options.lanes).fill(null);let i=e.length-1;for(;i>=0&&n.some(o=>o===null);){const o=e[i];n[o.lane]===null&&(n[o.lane]=o.end),i--}s=Math.max(...n.filter(o=>o!==null))}return Math.max(s-this.options.scrollMargin+this.options.paddingEnd,0)},this._scrollToOffset=(t,{adjustments:e,behavior:s})=>{this.options.scrollToFn(t,{behavior:s,adjustments:e},this)},this.measure=()=>{this.itemSizeCache=new Map,this.laneAssignments=new Map,this.notify(!1)},this.setOptions(r)}scheduleScrollReconcile(){if(!this.targetWindow){this.scrollState=null;return}this.rafId==null&&(this.rafId=this.targetWindow.requestAnimationFrame(()=>{this.rafId=null,this.reconcileScroll()}))}reconcileScroll(){if(!this.scrollState||!this.scrollElement)return;if(this.now()-this.scrollState.startedAt>5e3){this.scrollState=null;return}const e=this.scrollState.index!=null?this.getOffsetForIndex(this.scrollState.index,this.scrollState.align):void 0,s=e?e[0]:this.scrollState.lastTargetOffset,n=1,i=s!==this.scrollState.lastTargetOffset;if(!i&&H(s,this.getScrollOffset())){if(this.scrollState.stableFrames++,this.scrollState.stableFrames>=n){this.scrollState=null;return}}else this.scrollState.stableFrames=0,i&&(this.scrollState.lastTargetOffset=s,this.scrollState.behavior="auto",this._scrollToOffset(s,{adjustments:void 0,behavior:"auto"}));this.scheduleScrollReconcile()}}const W=(l,r,t,e)=>{for(;l<=r;){const s=(l+r)/2|0,n=t(s);if(n<e)l=s+1;else if(n>e)r=s-1;else return s}return l>0?l-1:0};function Z({measurements:l,outerSize:r,scrollOffset:t,lanes:e}){const s=l.length-1,n=a=>l[a].start;if(l.length<=e)return{startIndex:0,endIndex:s};let i=W(0,s,n,t),o=i;if(e===1)for(;o<s&&l[o].end<t+r;)o++;else if(e>1){const a=Array(e).fill(0);for(;o<s&&a.some(u=>u<t+r);){const u=l[o];a[u.lane]=u.end,o++}const c=Array(e).fill(t+r);for(;i>=0&&c.some(u=>u>=t);){const u=l[i];c[u.lane]=u.start,i--}i=Math.max(0,i-i%e),o=Math.min(s,o+(e-1-o%e))}return{startIndex:i,endIndex:o}}const L=typeof document<"u"?S.useLayoutEffect:S.useEffect;function G({useFlushSync:l=!0,...r}){const t=S.useReducer(()=>({}),{})[1],e={...r,onChange:(n,i)=>{var o;l&&i?V.flushSync(t):t(),(o=r.onChange)==null||o.call(r,n,i)}},[s]=S.useState(()=>new X(e));return s.setOptions(e),L(()=>s._didMount(),[]),L(()=>s._willUpdate()),s}function J(l){return G({observeElementRect:U,observeElementOffset:$,scrollToFn:Y,...l})}function ot({items:l,totalItems:r,parentRef:t,hasNextPage:e,isFetchingNextPage:s,fetchNextPage:n,estimateSize:i=()=>100,overscan:o=5}){const a=J({count:r,getScrollElement:()=>T(t.current),estimateSize:i,overscan:o}),c=a.getVirtualItems(),u=c.length>0?(c.at(0)?.start??0)-a.options.scrollMargin:0,d=c.length>0?a.getTotalSize()-(c.at(-1)?.end??0):0,m=c.map(f=>({virtualItem:f,key:f.key,item:l[f.index],props:{ref:a.measureElement,"data-index":f.index}})),h=m.at(-1)&&!m.at(-1)?.item;return S.useEffect(()=>{e&&h&&!s&&n()},[e,h,s,n]),{visibleItems:m,virtualizer:a,spaceBefore:u,spaceAfter:d}}const k=1e3,I="ghostVirtualListWindow";function Q({totalItems:l,unlockedItemCount:r}){const t=Math.min(l,r);return{visibleItemCount:t,canLoadMore:l>t}}function tt(l){return l+k}function et(l,r){return`${l}::${r}`}function F(l,r,t=k){const e=l?.[I];if(!e||typeof e!="object")return t;const s=e[r];return typeof s!="number"||!Number.isFinite(s)?t:Math.max(1,Math.floor(s))}function st(l,r,t){if(typeof window>"u")return;const e=l?.[I],s={...l??{},[I]:{...e&&typeof e=="object"?e:{},[r]:t}};window.history.replaceState(s,"")}function M(){if(!(typeof window>"u"))return window.history.state}function lt(l,{resetKey:r}={}){const{key:t,pathname:e,search:s}=B(),i=et(e,r??s),[o,a]=S.useState(()=>F(M(),i)),c=S.useRef(i);S.useEffect(()=>{if(c.current!==i){c.current=i,a(F(M(),i));return}st(M(),i,o)},[i,t,o]);const{visibleItemCount:u,canLoadMore:d}=Q({totalItems:l,unlockedItemCount:o});return{visibleItemCount:u,canLoadMore:d,loadMore:()=>a(m=>tt(m))}}export{it as L,ot as a,T as g,lt as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{aq as t}from"./index-
|
|
1
|
+
import{aq as t}from"./index-BkbhBpVC.js";const c=[["path",{d:"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2",key:"169zse"}]],i=t("activity",c);const a=[["path",{d:"M13.744 17.736a6 6 0 1 1-7.48-7.48",key:"bq4yh3"}],["path",{d:"M15 6h1v4",key:"11y1tn"}],["path",{d:"m6.134 14.768.866-.5 2 3.464",key:"17snzx"}],["circle",{cx:"16",cy:"8",r:"6",key:"14bfc9"}]],s=t("coins",a);const e=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M3 9a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2",key:"4125el"}],["path",{d:"M3 11h3c.8 0 1.6.3 2.1.9l1.1.9c1.6 1.6 4.1 1.6 5.7 0l1.1-.9c.5-.5 1.3-.9 2.1-.9H21",key:"1dpki6"}]],d=t("wallet-cards",e);export{i as A,s as C,d as W};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as t,b0 as be,a$ as xe,bU as Se,bV as je,B as oe,bW as _e,bX as Ce,bY as Ne,bZ as ve,ct as Le,ao as ye,an as Te,b2 as Fe,r as l,cu as Ee,b1 as q,c1 as Oe,c0 as ke,ak as ne,al as K,cv as De,bg as Me,aZ as Ie,u as Ae,b3 as we,a_ as Pe}from"./index-CFEzD2_M.js";import{u as W,S as ie,a as re,A as J,b as z,c as X,U as le}from"./post-analytics-context-BWDhMRq_.js";import{S as Ue,a as Ve,b as Re,c as Be,d as ze,e as $e,f as Ke}from"./select-CPSy44ld.js";import{C as Ge,F as We}from"./loader-circle-C7mWzo52.js";import{g as He,a as Qe,S as Ye,b as Xe}from"./kpis-yHgME_iy.js";import{F as Ze,c as H,e as ce}from"./en-Bu-6PYn5.js";import{C as ue,a as qe,b as Je,g as et,c as de,h as tt,T as st,u as $,i as ee}from"./pagemenu-TxGvHwRO.js";import{D as at,h as ot,i as te,a as nt,b as it,c as rt,d as lt,e as ct,f as ut,g as dt}from"./data-list-DUaY9nlT.js";import{P as mt,a as pt}from"./post-analytics-header-Bm0mcxjK.js";import{F as ht,c as gt}from"./filters-jiyRsLMH.js";import{b as ft,c as bt,F as xt,S as St,d as jt}from"./gh-chart-CEhBBu3F.js";import{M as _t}from"./upload-BcylHEMw.js";import{F as Ct}from"./pin-BU_u-xRX.js";import{E as Nt}from"./empty-indicator-2Pjmce3n.js";import"./posts-u-CAKddc.js";import"./chevron-up-CVgBkTk5.js";import"./source-icon-DeeHyZRn.js";import"./mail-9TFkAaAh.js";import"./source-utils-B1S3ZHA2.js";import"./arrow-right-BixoEua4.js";import"./tabs-CL5eaCGL.js";import"./kpi-tabs-Rq5jJW2Z.js";import"./post-share-modal-D8BtRD2u.js";import"./share-modal-BRmGllZq.js";import"./copy-D7jqplrv.js";import"./get-site-timezone-BDBAcjmq.js";import"./post-helpers-DR3PcyZg.js";import"./trash-CKK_p9G5.js";import"./sprout-956Q4On2.js";import"./circle-alert-Dg3UkvRP.js";import"./a-large-small-DxRNdz0F.js";import"./wallet-cards-B9TQg4x3.js";import"./undo-2-CcBtw-tW.js";import"./chart-X5cLIH1X.js";import"./_baseAssignValue-BDsvYKNK.js";import"./index-WKMARia9.js";import"./value-BGBiTkF3.js";import"./at-sign-BsHNViA_.js";import"./underline-Bq0P-5Zy.js";import"./power-DR9gpiQR.js";import"./hash-CeFrjo3C.js";import"./inbox-CCirPaG2.js";import"./minus-DPrXh11r.js";import"./pencil-CKTgzafp.js";import"./square-BaCvbKJY.js";import"./user-round-check-D0I7NO1g.js";import"./repeat-uXmOJ6y8.js";import"./reply-9ZyqaxI-.js";import"./rocket-DMOr1OCt.js";import"./tags-U3lciBmd.js";import"./user-round-x-DeGVH29o.js";const se=()=>{const{range:e,setRange:s}=W();return t.jsxs(Ue,{value:`${e}`,onValueChange:a=>{s(Number(a))},children:[t.jsxs(Ve,{className:"w-auto",children:[t.jsx(Ge,{className:"mr-2",size:16,strokeWidth:1.5}),t.jsx(Re,{placeholder:"Select a period"})]}),t.jsx(Be,{align:"end",children:t.jsxs(ze,{children:[t.jsx($e,{children:"Period"}),Object.values(ie).map(a=>t.jsx(Ke,{value:`${a.value}`,children:a.name},a.value))]})})]})};H.registerLocale(ce);const vt=e=>re[e]||H.getName(e,"en")||"Unknown",Lt=e=>{const s={"UNITED STATES":"US","UNITED STATES OF AMERICA":"US",USA:"US","UNITED KINGDOM":"GB",UK:"GB","GREAT BRITAIN":"GB",NETHERLANDS:"NL"},a=e.toUpperCase();return s[a]||(e.length>2?e.substring(0,2):e)},ae=({tableHeader:e,data:s,onLocationClick:a})=>t.jsxs(at,{children:[e&&t.jsxs(ot,{children:[t.jsx(te,{children:"Country"}),t.jsx(te,{children:"Visitors"})]}),t.jsx(nt,{children:s.map(i=>{const o=vt(`${i.location}`),r=a&&i.location!=="Unknown",c=i.location?i.location.toLowerCase():"unknown";return t.jsxs(it,{className:r?"cursor-pointer":"","data-testid":`location-row-${c}`,onClick:r?()=>a(i.location):void 0,children:[t.jsx(rt,{style:{width:`${i.percentage?Math.round(i.percentage*100):0}%`}}),t.jsx(lt,{className:"group-hover/data:max-w-[calc(100%-140px)]",children:t.jsxs("div",{className:"flex items-center space-x-3 overflow-hidden",title:o,children:[t.jsx(Ze,{countryCode:`${Lt(i.location)}`,fallback:t.jsx("span",{className:"flex h-[14px] w-[22px] items-center justify-center rounded-[2px] bg-black text-white",children:t.jsx(Le.SkullAndBones,{className:"size-3"})})}),t.jsx("div",{className:"truncate font-medium",children:o})]})}),t.jsxs(ct,{children:[t.jsx(ut,{children:ye(Number(i.visits))}),t.jsx(dt,{children:Te(i.percentage)})]})]},i.location||"unknown")})})]}),yt=({data:e,isLoading:s,onLocationClick:a})=>{const i=e.slice(0,10);return t.jsx(t.Fragment,{children:s?"":t.jsx(t.Fragment,{children:e&&e.length>0&&t.jsxs(ue,{className:"group/datalist","data-testid":"locations-card",children:[t.jsxs("div",{className:"flex items-center justify-between p-6",children:[t.jsxs(qe,{className:"p-0",children:[t.jsx(Je,{children:"Locations"}),t.jsx(et,{children:"Where are the readers of this post"})]}),t.jsx(be,{className:"mr-2",children:"Visitors"})]}),t.jsxs(de,{className:"overflow-hidden",children:[t.jsx(xe,{}),t.jsx(ae,{data:i,tableHeader:!1,onLocationClick:a})]}),e.length>10&&t.jsx(tt,{children:t.jsxs(Se,{children:[t.jsx(je,{asChild:!0,children:t.jsxs(oe,{variant:"outline",children:["View all ",t.jsx(st,{})]})}),t.jsxs(_e,{className:"overflow-y-auto pt-0 sm:max-w-[600px]",children:[t.jsxs(Ce,{className:"sticky top-0 z-40 -mx-6 bg-background/60 p-6 backdrop-blur",children:[t.jsx(Ne,{children:"Top locations"}),t.jsx(ve,{children:"Where are the readers of this post"})]}),t.jsx("div",{className:"group/datalist",children:t.jsx(ae,{data:e,tableHeader:!0,onLocationClick:a})})]})]})})]})})})},me=e=>!e||e.length===0?J:z.filter(s=>e.includes(s.value)).reduce((s,a)=>s|a.bit,0)||J,pe=e=>{const s=[];return(e&X.PUBLIC)!==0&&s.push(z[0].value),(e&X.FREE)!==0&&s.push(z[1].value),(e&X.PAID)!==0&&s.push(z[2].value),s.join(",")};H.registerLocale(ce);const Tt=e=>re[e]||H.getName(e,"en")||e,Ft=({visits:e})=>t.jsx("span",{className:"order-2 font-mono text-xs text-muted-foreground",children:e.toLocaleString()}),Et={utm_source:{endpoint:"api_top_utm_sources",valueKey:"utm_source",transformValue:e=>({value:e||"(not set)",label:e||"(not set)"})},utm_medium:{endpoint:"api_top_utm_mediums",valueKey:"utm_medium",transformValue:e=>({value:e||"(not set)",label:e||"(not set)"})},utm_campaign:{endpoint:"api_top_utm_campaigns",valueKey:"utm_campaign",transformValue:e=>({value:e||"(not set)",label:e||"(not set)"})},utm_content:{endpoint:"api_top_utm_contents",valueKey:"utm_content",transformValue:e=>({value:e||"(not set)",label:e||"(not set)"})},utm_term:{endpoint:"api_top_utm_terms",valueKey:"utm_term",transformValue:e=>({value:e||"(not set)",label:e||"(not set)"})},source:{endpoint:"api_top_sources",valueKey:"source",transformValue:e=>({value:e||"",label:e||"Direct"})},location:{endpoint:"api_top_locations",valueKey:"location",filterItem(e){const s=String(e.location||"");return s!==""&&!le.includes(s)},transformValue:e=>({value:e,label:Tt(e)})},device:{endpoint:"api_top_devices",valueKey:"device",transformValue:e=>({value:e,label:e==="mobile-ios"?"iOS":e==="mobile-android"?"Android":e==="desktop"?"Desktop":e==="bot"?"Bot":e})}},Ot=(e,s,a)=>{const i={...a};return e.forEach(o=>{if(o.field===s||o.values.length===0)return;const r=o.values[0];o.field!=="audience"&&(o.field==="source"||o.field==="device"||o.field==="location"||o.field.startsWith("utm_"))&&(i[o.field]=r)}),i},O=(e,s=[],a,i={})=>{const{enabled:o=!0}=i,{statsConfig:r,range:c}=W(),{startDate:b,endDate:m,timezone:x}=ne(c),p=Et[e],d=l.useMemo(()=>{const j=s.find(h=>h.field==="audience");return me(j?.values)},[s]),S=l.useMemo(()=>{const j={site_uuid:r?.id||"",date_from:K(b),date_to:K(m),timezone:x,member_status:pe(d),limit:"50"};return a&&(j.post_uuid=a),Ot(s,e,j)},[r?.id,b,m,x,d,s,e,a]),{data:v,loading:k}=$({endpoint:p?.endpoint||"",statsConfig:r,params:S,enabled:o&&!!p});return{options:l.useMemo(()=>p?(v||[]).filter(h=>p.filterItem?p.filterItem(h):!0).map(h=>{const F=String(h[p.valueKey]??""),A=Number(h.visits)||0,{value:E,label:y}=p.transformValue?p.transformValue(F):{value:F,label:F};return{label:y,value:E,icon:t.jsx(Ft,{visits:A})}}):[],[v,p]),loading:k}};function kt({filters:e,onChange:s,...a}){const{appSettings:i}=Fe(),{post:o}=W(),r=o?.uuid,[c,b]=l.useState(null),[m,x]=l.useState(!1);l.useEffect(()=>{const g=window.matchMedia("(max-width: 1024px)"),C=T=>{x(T.matches)};return C(g),g.addEventListener("change",C),()=>g.removeEventListener("change",C)},[]);const p=l.useMemo(()=>{const g=[{value:"undefined",label:"Public visitors",icon:t.jsx(q,{className:"text-gray-700"})},{value:"free",label:"Free members",icon:t.jsx(Oe,{className:"text-green"})},{value:"paid",label:"Paid members",icon:t.jsx(ke,{className:"text-orange"})}];return i?.paidMembersEnabled?g:g.filter(C=>C.value!=="paid")},[i?.paidMembersEnabled]),d=l.useCallback(g=>{const C=c===g,T=e.some(n=>n.field===g);return C||T},[c,e]),{options:S,loading:v}=O("utm_source",e,r,{enabled:d("utm_source")}),{options:k,loading:I}=O("utm_medium",e,r,{enabled:d("utm_medium")}),{options:j,loading:h}=O("utm_campaign",e,r,{enabled:d("utm_campaign")}),{options:F,loading:A}=O("utm_content",e,r,{enabled:d("utm_content")}),{options:E,loading:y}=O("utm_term",e,r,{enabled:d("utm_term")}),{options:R,loading:D}=O("source",e,r,{enabled:d("source")}),{options:U,loading:M}=O("device",e,r,{enabled:d("device")}),{options:B,loading:w}=O("location",e,r,{enabled:d("location")}),_=l.useMemo(()=>[{value:"is",label:"is"}],[]),Q=l.useMemo(()=>{const g=[{key:"utm_source",label:"UTM Source",type:"select",icon:t.jsx(_t,{className:"size-4"}),placeholder:"Select source",operators:_,defaultOperator:"is",hideOperatorSelect:!0,options:S,isLoading:v,searchable:!0,selectedOptionsClassName:"hidden"},{key:"utm_medium",label:"UTM Medium",type:"select",icon:t.jsx(St,{className:"size-4"}),placeholder:"Select medium",operators:_,defaultOperator:"is",hideOperatorSelect:!0,options:k,isLoading:I,className:"w-60",popoverContentClassName:"w-60",searchable:!0,selectedOptionsClassName:"hidden"},{key:"utm_campaign",label:"UTM Campaign",type:"select",icon:t.jsx(Ct,{className:"size-4"}),placeholder:"Select campaign",operators:_,defaultOperator:"is",hideOperatorSelect:!0,options:j,isLoading:h,className:"w-60",popoverContentClassName:"w-60",searchable:!0,selectedOptionsClassName:"hidden"},{key:"utm_content",label:"UTM Content",type:"select",icon:t.jsx(jt,{className:"size-4"}),placeholder:"Select content",operators:_,defaultOperator:"is",hideOperatorSelect:!0,options:F,isLoading:A,className:"w-60",popoverContentClassName:"w-60",searchable:!0,selectedOptionsClassName:"hidden"},{key:"utm_term",label:"UTM Term",type:"select",icon:t.jsx(De,{className:"size-4"}),placeholder:"Select term",operators:_,defaultOperator:"is",hideOperatorSelect:!0,options:E,isLoading:y,className:"w-60",popoverContentClassName:"w-60",searchable:!0,selectedOptionsClassName:"hidden"}];return[{group:"Basic",fields:[{key:"audience",label:"Audience",type:"multiselect",icon:t.jsx(Ee,{}),options:p.map(({value:C,label:T,icon:n})=>({value:C,label:T,icon:n})),defaultOperator:"is any of",hideOperatorSelect:!0,autoCloseOnSelect:!0},{key:"source",label:"Source",type:"select",icon:t.jsx(q,{className:"size-4"}),placeholder:"Select source",operators:_,defaultOperator:"is",hideOperatorSelect:!0,options:R,isLoading:D,className:"w-60",popoverContentClassName:"w-60",searchable:!0,selectedOptionsClassName:"hidden"},{key:"device",label:"Device",type:"select",icon:t.jsx(ft,{className:"size-4"}),placeholder:"Select device",operators:_,defaultOperator:"is",hideOperatorSelect:!0,options:U,isLoading:M,selectedOptionsClassName:"hidden"},{key:"location",label:"Location",type:"select",icon:t.jsx(bt,{className:"size-4"}),placeholder:"Select location",operators:_,defaultOperator:"is",hideOperatorSelect:!0,options:B,isLoading:w,searchable:!0,selectedOptionsClassName:"hidden"}]},{group:"UTM parameters",fields:g}]},[S,v,k,I,j,h,F,A,E,y,_,p,R,D,U,M,B,w]),P=e.length>0,Y=l.useCallback(()=>{s&&s([])},[s]);return t.jsxs("div",{className:"mt-3 flex w-full justify-between gap-2 lg:mt-0","data-testid":"stats-filter-container",children:[t.jsx(ht,{addButtonIcon:t.jsx(We,{}),addButtonText:P?"Add filter":"Filter",allowMultiple:!1,className:`[&>button]:order-last ${P&&"[&>button]:border-none"}`,fields:Q,filters:e,keyboardShortcut:"f",popoverAlign:m||P?"start":"end",showSearchInput:!1,onActiveFieldChange:b,onChange:s||(()=>{}),...a}),P&&t.jsxs(oe,{className:"hidden font-normal text-muted-foreground lg:flex","data-testid":"stats-filter-clear-button",variant:"ghost",onClick:Y,children:[t.jsx(xt,{}),"Clear"]})]})}const G=["audience","source","device","location","utm_source","utm_medium","utm_campaign","utm_content","utm_term"],he="__empty__",ge="%2C";function Dt(e){const s=new URLSearchParams;return e.forEach(a=>{if(G.includes(a.field)&&a.values.length>0){const i=a.values.map(o=>o===""?he:String(o).replace(/,/g,ge)).join(",");s.set(a.field,i)}}),s}const Z=new Map;function Mt(e){return Z.has(e)||Z.set(e,`url-${e}-${Date.now()}-${Math.random().toString(36).substring(2,11)}`),Z.get(e)}function It(e){const s=[],a=new Set(G);return e.forEach((i,o)=>{if(!a.has(o))return;const r=i.split(",").map(c=>c===he?"":c.replace(new RegExp(ge,"g"),","));if(r.length>0){const c=o==="audience"?"is any of":"is";s.push({id:Mt(o),field:o,operator:c,values:r})}}),s}function At(e={}){const[s,a]=Me(),{onFiltersChange:i}=e,o=l.useRef(!1),r=l.useMemo(()=>It(s),[s]);l.useEffect(()=>{!o.current&&i&&i(r)},[r,i]);const c=l.useCallback(m=>{o.current=!0;const x=typeof m=="function"?m(r):m,p=Dt(x),d=new URLSearchParams(s);G.forEach(S=>{d.delete(S)}),p.forEach((S,v)=>{d.set(v,S)}),a(d,{replace:!0}),setTimeout(()=>{o.current=!1},0)},[r,s,a]),b=l.useCallback(()=>{o.current=!0;const m=new URLSearchParams(s);G.forEach(x=>{m.delete(x)}),a(m,{replace:!0}),setTimeout(()=>{o.current=!1},0)},[s,a]);return{filters:r,setFilters:c,clearFilters:b}}const Ms=()=>{const e=Ie(),{postId:s}=Ae(),{statsConfig:a,isLoading:i,range:o,data:r,post:c,isPostLoading:b}=W(),{filters:m,setFilters:x}=At(),p=l.useMemo(()=>{const n=m.find(f=>f.field==="audience");return me(n?.values)},[m]);l.useEffect(()=>{!b&&c?.email_only&&e(`/posts/analytics/${s}`)},[b,c?.email_only,e,s]);const d=l.useMemo(()=>{if(!c?.published_at)return ie.ALL_TIME.value;const n=we(c.published_at);return o>n?n:o},[c?.published_at,o]),{startDate:S,endDate:v,timezone:k}=ne(d),I=l.useCallback(()=>{const n=document.querySelector(".overflow-y-scroll");n&&n.scrollTo({top:0,behavior:"smooth"})},[]),j=l.useMemo(()=>{const n={};return m.forEach(f=>{const N=f.field,L=f.values;if(N==="audience")return;const u=L&&L.length>0&&L[0]!==null&&L[0]!==void 0,V=N==="source"&&L?.[0]==="";if(u&&(L[0]!==""||V)){const fe=String(L[0]);n[N]=fe}}),n},[m]),h=l.useCallback((n,f)=>{x(N=>N.find(u=>u.field===n)?N.map(u=>u.field===n?{...u,values:[f]}:u):[...N,gt(n,"is",[f])]),I()},[x,I]),F=l.useCallback(n=>h("location",n),[h]),A=l.useCallback(n=>h("source",n),[h]),E=l.useMemo(()=>{const n={site_uuid:a?.id||"",date_from:K(S),date_to:K(v),timezone:k,member_status:pe(p),post_uuid:"",...j};return!b&&c?.uuid?{...n,post_uuid:c.uuid}:n},[b,c,a?.id,S,v,k,p,j]),{data:y,loading:R}=$({endpoint:"api_kpis",statsConfig:a||{id:""},params:E}),{data:D,loading:U}=$({endpoint:"api_top_locations",statsConfig:a||{id:""},params:E}),{data:M,loading:B}=$({endpoint:"api_top_sources",statsConfig:a||{id:""},params:E}),w=l.useMemo(()=>D?.reduce((n,f)=>n+Number(f.visits),0)||0,[D]),_=l.useMemo(()=>M?M.reduce((n,f)=>n+Number(f.visits||0),0):0,[M]),Q=r?.url,P=r?.icon,Y=l.useMemo(()=>{const n=D?.map(u=>({location:String(u.location),visits:Number(u.visits),percentage:w>0?Number(u.visits)/w:0,isUnknown:le.includes(String(u.location))}))||[],f=n.filter(u=>!u.isUnknown),N=n.filter(u=>u.isUnknown),L=N.length>0?[{location:"Unknown",visits:N.reduce((u,V)=>u+V.visits,0),percentage:N.reduce((u,V)=>u+V.percentage,0)}]:[];return[...f,...L]},[D,w]),g=i||b||R||U||B,C=He(y),T=m.length>0;return t.jsxs(t.Fragment,{children:[t.jsxs(mt,{currentTab:"Web",children:[T&&t.jsx(ee,{children:t.jsx(se,{})}),t.jsxs(ee,{className:`${T?"mt-0! [grid-area:subactions] lg:mt-[25px]!":"[grid-area:actions]"}`,children:[t.jsx(kt,{filters:m,onChange:x}),!T&&t.jsx(se,{})]})]}),t.jsx(pt,{children:g?t.jsx(ue,{className:"size-full",variant:"plain",children:t.jsx(de,{className:"size-full items-center justify-center",children:t.jsx(Pe,{})})}):y&&y.length!==0&&C.visits!=="0"?t.jsxs(t.Fragment,{children:[t.jsx(Qe,{data:y,range:d}),t.jsxs("div",{className:"flex flex-col gap-6 lg:grid lg:grid-cols-2",children:[t.jsx(yt,{data:Y,isLoading:U,onLocationClick:F}),t.jsx(Ye,{data:M,range:d,siteIcon:P,siteUrl:Q,totalVisitors:_,onSourceClick:A})]})]}):t.jsx("div",{className:"grow",children:t.jsx(Nt,{className:"h-full",description:"Try adjusting filters to see more data.",title:`No visitors ${Xe(o)}`,children:t.jsx(q,{strokeWidth:1.5})})})})]})};export{Ms as default};
|
|
1
|
+
import{j as t,b0 as be,a$ as xe,bU as Se,bV as je,B as oe,bW as _e,bX as Ce,bY as Ne,bZ as ve,ct as Le,ao as ye,an as Te,b2 as Fe,r as l,cu as Ee,b1 as q,c1 as Oe,c0 as ke,ak as ne,al as K,cv as De,bg as Me,aZ as Ie,u as Ae,b3 as we,a_ as Pe}from"./index-BkbhBpVC.js";import{u as W,S as ie,a as re,A as J,b as z,c as X,U as le}from"./post-analytics-context-D7PgEMo8.js";import{S as Ue,a as Ve,b as Re,c as Be,d as ze,e as $e,f as Ke}from"./select-BfWJkrKc.js";import{C as Ge,F as We}from"./loader-circle-B1uEfpbZ.js";import{g as He,a as Qe,S as Ye,b as Xe}from"./kpis-CVwF08QL.js";import{F as Ze,c as H,e as ce}from"./en-CjPXRj8j.js";import{C as ue,a as qe,b as Je,g as et,c as de,h as tt,T as st,u as $,i as ee}from"./pagemenu-O_y8Jm4v.js";import{D as at,h as ot,i as te,a as nt,b as it,c as rt,d as lt,e as ct,f as ut,g as dt}from"./data-list-BF4GeUmt.js";import{P as mt,a as pt}from"./post-analytics-header-B8C0vA5Y.js";import{F as ht,c as gt}from"./filters-DtIsuqv5.js";import{b as ft,c as bt,F as xt,S as St,d as jt}from"./gh-chart-JxzKqaoO.js";import{M as _t}from"./upload-BLiT66bJ.js";import{F as Ct}from"./pin-Bl3nSr7I.js";import{E as Nt}from"./empty-indicator-BvyaMcmw.js";import"./posts-BZaw4-dc.js";import"./chevron-up-DuaKtE_M.js";import"./source-icon-Dtua85oN.js";import"./mail-ccQhEr7k.js";import"./source-utils-B1S3ZHA2.js";import"./arrow-right-Bk43nMGd.js";import"./tabs-M6kFEqPE.js";import"./kpi-tabs-B3NkaTwb.js";import"./post-share-modal-D0OlASBQ.js";import"./share-modal-CtdLQbnQ.js";import"./copy-DVtQi_VJ.js";import"./get-site-timezone-BDBAcjmq.js";import"./post-helpers-DR3PcyZg.js";import"./trash-CUqAK3SQ.js";import"./sprout-CpwUJAPT.js";import"./circle-alert-bcK_Yqap.js";import"./a-large-small-BiK5_5LV.js";import"./wallet-cards-CVZ99Nm3.js";import"./undo-2-D6ZRqONE.js";import"./chart-CUKSNmKY.js";import"./_baseAssignValue-hdDG700N.js";import"./index-DYE2untj.js";import"./value-BGBiTkF3.js";import"./at-sign-DWOf36uj.js";import"./underline-CwuJG-Ql.js";import"./power-DWm6pts5.js";import"./hash-CJzbTA5k.js";import"./inbox-CVVAkCmd.js";import"./minus-C68D81nx.js";import"./pencil-BcymGPnE.js";import"./square-CDrQjv8R.js";import"./user-round-check-BDomHaso.js";import"./repeat-DQay9e22.js";import"./reply-CoNqmExw.js";import"./rocket-Dne6P_8f.js";import"./tags-DuMshkTz.js";import"./user-round-x-Cc0RL-V9.js";const se=()=>{const{range:e,setRange:s}=W();return t.jsxs(Ue,{value:`${e}`,onValueChange:a=>{s(Number(a))},children:[t.jsxs(Ve,{className:"w-auto",children:[t.jsx(Ge,{className:"mr-2",size:16,strokeWidth:1.5}),t.jsx(Re,{placeholder:"Select a period"})]}),t.jsx(Be,{align:"end",children:t.jsxs(ze,{children:[t.jsx($e,{children:"Period"}),Object.values(ie).map(a=>t.jsx(Ke,{value:`${a.value}`,children:a.name},a.value))]})})]})};H.registerLocale(ce);const vt=e=>re[e]||H.getName(e,"en")||"Unknown",Lt=e=>{const s={"UNITED STATES":"US","UNITED STATES OF AMERICA":"US",USA:"US","UNITED KINGDOM":"GB",UK:"GB","GREAT BRITAIN":"GB",NETHERLANDS:"NL"},a=e.toUpperCase();return s[a]||(e.length>2?e.substring(0,2):e)},ae=({tableHeader:e,data:s,onLocationClick:a})=>t.jsxs(at,{children:[e&&t.jsxs(ot,{children:[t.jsx(te,{children:"Country"}),t.jsx(te,{children:"Visitors"})]}),t.jsx(nt,{children:s.map(i=>{const o=vt(`${i.location}`),r=a&&i.location!=="Unknown",c=i.location?i.location.toLowerCase():"unknown";return t.jsxs(it,{className:r?"cursor-pointer":"","data-testid":`location-row-${c}`,onClick:r?()=>a(i.location):void 0,children:[t.jsx(rt,{style:{width:`${i.percentage?Math.round(i.percentage*100):0}%`}}),t.jsx(lt,{className:"group-hover/data:max-w-[calc(100%-140px)]",children:t.jsxs("div",{className:"flex items-center space-x-3 overflow-hidden",title:o,children:[t.jsx(Ze,{countryCode:`${Lt(i.location)}`,fallback:t.jsx("span",{className:"flex h-[14px] w-[22px] items-center justify-center rounded-[2px] bg-black text-white",children:t.jsx(Le.SkullAndBones,{className:"size-3"})})}),t.jsx("div",{className:"truncate font-medium",children:o})]})}),t.jsxs(ct,{children:[t.jsx(ut,{children:ye(Number(i.visits))}),t.jsx(dt,{children:Te(i.percentage)})]})]},i.location||"unknown")})})]}),yt=({data:e,isLoading:s,onLocationClick:a})=>{const i=e.slice(0,10);return t.jsx(t.Fragment,{children:s?"":t.jsx(t.Fragment,{children:e&&e.length>0&&t.jsxs(ue,{className:"group/datalist","data-testid":"locations-card",children:[t.jsxs("div",{className:"flex items-center justify-between p-6",children:[t.jsxs(qe,{className:"p-0",children:[t.jsx(Je,{children:"Locations"}),t.jsx(et,{children:"Where are the readers of this post"})]}),t.jsx(be,{className:"mr-2",children:"Visitors"})]}),t.jsxs(de,{className:"overflow-hidden",children:[t.jsx(xe,{}),t.jsx(ae,{data:i,tableHeader:!1,onLocationClick:a})]}),e.length>10&&t.jsx(tt,{children:t.jsxs(Se,{children:[t.jsx(je,{asChild:!0,children:t.jsxs(oe,{variant:"outline",children:["View all ",t.jsx(st,{})]})}),t.jsxs(_e,{className:"overflow-y-auto pt-0 sm:max-w-[600px]",children:[t.jsxs(Ce,{className:"sticky top-0 z-40 -mx-6 bg-background/60 p-6 backdrop-blur",children:[t.jsx(Ne,{children:"Top locations"}),t.jsx(ve,{children:"Where are the readers of this post"})]}),t.jsx("div",{className:"group/datalist",children:t.jsx(ae,{data:e,tableHeader:!0,onLocationClick:a})})]})]})})]})})})},me=e=>!e||e.length===0?J:z.filter(s=>e.includes(s.value)).reduce((s,a)=>s|a.bit,0)||J,pe=e=>{const s=[];return(e&X.PUBLIC)!==0&&s.push(z[0].value),(e&X.FREE)!==0&&s.push(z[1].value),(e&X.PAID)!==0&&s.push(z[2].value),s.join(",")};H.registerLocale(ce);const Tt=e=>re[e]||H.getName(e,"en")||e,Ft=({visits:e})=>t.jsx("span",{className:"order-2 font-mono text-xs text-muted-foreground",children:e.toLocaleString()}),Et={utm_source:{endpoint:"api_top_utm_sources",valueKey:"utm_source",transformValue:e=>({value:e||"(not set)",label:e||"(not set)"})},utm_medium:{endpoint:"api_top_utm_mediums",valueKey:"utm_medium",transformValue:e=>({value:e||"(not set)",label:e||"(not set)"})},utm_campaign:{endpoint:"api_top_utm_campaigns",valueKey:"utm_campaign",transformValue:e=>({value:e||"(not set)",label:e||"(not set)"})},utm_content:{endpoint:"api_top_utm_contents",valueKey:"utm_content",transformValue:e=>({value:e||"(not set)",label:e||"(not set)"})},utm_term:{endpoint:"api_top_utm_terms",valueKey:"utm_term",transformValue:e=>({value:e||"(not set)",label:e||"(not set)"})},source:{endpoint:"api_top_sources",valueKey:"source",transformValue:e=>({value:e||"",label:e||"Direct"})},location:{endpoint:"api_top_locations",valueKey:"location",filterItem(e){const s=String(e.location||"");return s!==""&&!le.includes(s)},transformValue:e=>({value:e,label:Tt(e)})},device:{endpoint:"api_top_devices",valueKey:"device",transformValue:e=>({value:e,label:e==="mobile-ios"?"iOS":e==="mobile-android"?"Android":e==="desktop"?"Desktop":e==="bot"?"Bot":e})}},Ot=(e,s,a)=>{const i={...a};return e.forEach(o=>{if(o.field===s||o.values.length===0)return;const r=o.values[0];o.field!=="audience"&&(o.field==="source"||o.field==="device"||o.field==="location"||o.field.startsWith("utm_"))&&(i[o.field]=r)}),i},O=(e,s=[],a,i={})=>{const{enabled:o=!0}=i,{statsConfig:r,range:c}=W(),{startDate:b,endDate:m,timezone:x}=ne(c),p=Et[e],d=l.useMemo(()=>{const j=s.find(h=>h.field==="audience");return me(j?.values)},[s]),S=l.useMemo(()=>{const j={site_uuid:r?.id||"",date_from:K(b),date_to:K(m),timezone:x,member_status:pe(d),limit:"50"};return a&&(j.post_uuid=a),Ot(s,e,j)},[r?.id,b,m,x,d,s,e,a]),{data:v,loading:k}=$({endpoint:p?.endpoint||"",statsConfig:r,params:S,enabled:o&&!!p});return{options:l.useMemo(()=>p?(v||[]).filter(h=>p.filterItem?p.filterItem(h):!0).map(h=>{const F=String(h[p.valueKey]??""),A=Number(h.visits)||0,{value:E,label:y}=p.transformValue?p.transformValue(F):{value:F,label:F};return{label:y,value:E,icon:t.jsx(Ft,{visits:A})}}):[],[v,p]),loading:k}};function kt({filters:e,onChange:s,...a}){const{appSettings:i}=Fe(),{post:o}=W(),r=o?.uuid,[c,b]=l.useState(null),[m,x]=l.useState(!1);l.useEffect(()=>{const g=window.matchMedia("(max-width: 1024px)"),C=T=>{x(T.matches)};return C(g),g.addEventListener("change",C),()=>g.removeEventListener("change",C)},[]);const p=l.useMemo(()=>{const g=[{value:"undefined",label:"Public visitors",icon:t.jsx(q,{className:"text-gray-700"})},{value:"free",label:"Free members",icon:t.jsx(Oe,{className:"text-green"})},{value:"paid",label:"Paid members",icon:t.jsx(ke,{className:"text-orange"})}];return i?.paidMembersEnabled?g:g.filter(C=>C.value!=="paid")},[i?.paidMembersEnabled]),d=l.useCallback(g=>{const C=c===g,T=e.some(n=>n.field===g);return C||T},[c,e]),{options:S,loading:v}=O("utm_source",e,r,{enabled:d("utm_source")}),{options:k,loading:I}=O("utm_medium",e,r,{enabled:d("utm_medium")}),{options:j,loading:h}=O("utm_campaign",e,r,{enabled:d("utm_campaign")}),{options:F,loading:A}=O("utm_content",e,r,{enabled:d("utm_content")}),{options:E,loading:y}=O("utm_term",e,r,{enabled:d("utm_term")}),{options:R,loading:D}=O("source",e,r,{enabled:d("source")}),{options:U,loading:M}=O("device",e,r,{enabled:d("device")}),{options:B,loading:w}=O("location",e,r,{enabled:d("location")}),_=l.useMemo(()=>[{value:"is",label:"is"}],[]),Q=l.useMemo(()=>{const g=[{key:"utm_source",label:"UTM Source",type:"select",icon:t.jsx(_t,{className:"size-4"}),placeholder:"Select source",operators:_,defaultOperator:"is",hideOperatorSelect:!0,options:S,isLoading:v,searchable:!0,selectedOptionsClassName:"hidden"},{key:"utm_medium",label:"UTM Medium",type:"select",icon:t.jsx(St,{className:"size-4"}),placeholder:"Select medium",operators:_,defaultOperator:"is",hideOperatorSelect:!0,options:k,isLoading:I,className:"w-60",popoverContentClassName:"w-60",searchable:!0,selectedOptionsClassName:"hidden"},{key:"utm_campaign",label:"UTM Campaign",type:"select",icon:t.jsx(Ct,{className:"size-4"}),placeholder:"Select campaign",operators:_,defaultOperator:"is",hideOperatorSelect:!0,options:j,isLoading:h,className:"w-60",popoverContentClassName:"w-60",searchable:!0,selectedOptionsClassName:"hidden"},{key:"utm_content",label:"UTM Content",type:"select",icon:t.jsx(jt,{className:"size-4"}),placeholder:"Select content",operators:_,defaultOperator:"is",hideOperatorSelect:!0,options:F,isLoading:A,className:"w-60",popoverContentClassName:"w-60",searchable:!0,selectedOptionsClassName:"hidden"},{key:"utm_term",label:"UTM Term",type:"select",icon:t.jsx(De,{className:"size-4"}),placeholder:"Select term",operators:_,defaultOperator:"is",hideOperatorSelect:!0,options:E,isLoading:y,className:"w-60",popoverContentClassName:"w-60",searchable:!0,selectedOptionsClassName:"hidden"}];return[{group:"Basic",fields:[{key:"audience",label:"Audience",type:"multiselect",icon:t.jsx(Ee,{}),options:p.map(({value:C,label:T,icon:n})=>({value:C,label:T,icon:n})),defaultOperator:"is any of",hideOperatorSelect:!0,autoCloseOnSelect:!0},{key:"source",label:"Source",type:"select",icon:t.jsx(q,{className:"size-4"}),placeholder:"Select source",operators:_,defaultOperator:"is",hideOperatorSelect:!0,options:R,isLoading:D,className:"w-60",popoverContentClassName:"w-60",searchable:!0,selectedOptionsClassName:"hidden"},{key:"device",label:"Device",type:"select",icon:t.jsx(ft,{className:"size-4"}),placeholder:"Select device",operators:_,defaultOperator:"is",hideOperatorSelect:!0,options:U,isLoading:M,selectedOptionsClassName:"hidden"},{key:"location",label:"Location",type:"select",icon:t.jsx(bt,{className:"size-4"}),placeholder:"Select location",operators:_,defaultOperator:"is",hideOperatorSelect:!0,options:B,isLoading:w,searchable:!0,selectedOptionsClassName:"hidden"}]},{group:"UTM parameters",fields:g}]},[S,v,k,I,j,h,F,A,E,y,_,p,R,D,U,M,B,w]),P=e.length>0,Y=l.useCallback(()=>{s&&s([])},[s]);return t.jsxs("div",{className:"mt-3 flex w-full justify-between gap-2 lg:mt-0","data-testid":"stats-filter-container",children:[t.jsx(ht,{addButtonIcon:t.jsx(We,{}),addButtonText:P?"Add filter":"Filter",allowMultiple:!1,className:`[&>button]:order-last ${P&&"[&>button]:border-none"}`,fields:Q,filters:e,keyboardShortcut:"f",popoverAlign:m||P?"start":"end",showSearchInput:!1,onActiveFieldChange:b,onChange:s||(()=>{}),...a}),P&&t.jsxs(oe,{className:"hidden font-normal text-muted-foreground lg:flex","data-testid":"stats-filter-clear-button",variant:"ghost",onClick:Y,children:[t.jsx(xt,{}),"Clear"]})]})}const G=["audience","source","device","location","utm_source","utm_medium","utm_campaign","utm_content","utm_term"],he="__empty__",ge="%2C";function Dt(e){const s=new URLSearchParams;return e.forEach(a=>{if(G.includes(a.field)&&a.values.length>0){const i=a.values.map(o=>o===""?he:String(o).replace(/,/g,ge)).join(",");s.set(a.field,i)}}),s}const Z=new Map;function Mt(e){return Z.has(e)||Z.set(e,`url-${e}-${Date.now()}-${Math.random().toString(36).substring(2,11)}`),Z.get(e)}function It(e){const s=[],a=new Set(G);return e.forEach((i,o)=>{if(!a.has(o))return;const r=i.split(",").map(c=>c===he?"":c.replace(new RegExp(ge,"g"),","));if(r.length>0){const c=o==="audience"?"is any of":"is";s.push({id:Mt(o),field:o,operator:c,values:r})}}),s}function At(e={}){const[s,a]=Me(),{onFiltersChange:i}=e,o=l.useRef(!1),r=l.useMemo(()=>It(s),[s]);l.useEffect(()=>{!o.current&&i&&i(r)},[r,i]);const c=l.useCallback(m=>{o.current=!0;const x=typeof m=="function"?m(r):m,p=Dt(x),d=new URLSearchParams(s);G.forEach(S=>{d.delete(S)}),p.forEach((S,v)=>{d.set(v,S)}),a(d,{replace:!0}),setTimeout(()=>{o.current=!1},0)},[r,s,a]),b=l.useCallback(()=>{o.current=!0;const m=new URLSearchParams(s);G.forEach(x=>{m.delete(x)}),a(m,{replace:!0}),setTimeout(()=>{o.current=!1},0)},[s,a]);return{filters:r,setFilters:c,clearFilters:b}}const Ms=()=>{const e=Ie(),{postId:s}=Ae(),{statsConfig:a,isLoading:i,range:o,data:r,post:c,isPostLoading:b}=W(),{filters:m,setFilters:x}=At(),p=l.useMemo(()=>{const n=m.find(f=>f.field==="audience");return me(n?.values)},[m]);l.useEffect(()=>{!b&&c?.email_only&&e(`/posts/analytics/${s}`)},[b,c?.email_only,e,s]);const d=l.useMemo(()=>{if(!c?.published_at)return ie.ALL_TIME.value;const n=we(c.published_at);return o>n?n:o},[c?.published_at,o]),{startDate:S,endDate:v,timezone:k}=ne(d),I=l.useCallback(()=>{const n=document.querySelector(".overflow-y-scroll");n&&n.scrollTo({top:0,behavior:"smooth"})},[]),j=l.useMemo(()=>{const n={};return m.forEach(f=>{const N=f.field,L=f.values;if(N==="audience")return;const u=L&&L.length>0&&L[0]!==null&&L[0]!==void 0,V=N==="source"&&L?.[0]==="";if(u&&(L[0]!==""||V)){const fe=String(L[0]);n[N]=fe}}),n},[m]),h=l.useCallback((n,f)=>{x(N=>N.find(u=>u.field===n)?N.map(u=>u.field===n?{...u,values:[f]}:u):[...N,gt(n,"is",[f])]),I()},[x,I]),F=l.useCallback(n=>h("location",n),[h]),A=l.useCallback(n=>h("source",n),[h]),E=l.useMemo(()=>{const n={site_uuid:a?.id||"",date_from:K(S),date_to:K(v),timezone:k,member_status:pe(p),post_uuid:"",...j};return!b&&c?.uuid?{...n,post_uuid:c.uuid}:n},[b,c,a?.id,S,v,k,p,j]),{data:y,loading:R}=$({endpoint:"api_kpis",statsConfig:a||{id:""},params:E}),{data:D,loading:U}=$({endpoint:"api_top_locations",statsConfig:a||{id:""},params:E}),{data:M,loading:B}=$({endpoint:"api_top_sources",statsConfig:a||{id:""},params:E}),w=l.useMemo(()=>D?.reduce((n,f)=>n+Number(f.visits),0)||0,[D]),_=l.useMemo(()=>M?M.reduce((n,f)=>n+Number(f.visits||0),0):0,[M]),Q=r?.url,P=r?.icon,Y=l.useMemo(()=>{const n=D?.map(u=>({location:String(u.location),visits:Number(u.visits),percentage:w>0?Number(u.visits)/w:0,isUnknown:le.includes(String(u.location))}))||[],f=n.filter(u=>!u.isUnknown),N=n.filter(u=>u.isUnknown),L=N.length>0?[{location:"Unknown",visits:N.reduce((u,V)=>u+V.visits,0),percentage:N.reduce((u,V)=>u+V.percentage,0)}]:[];return[...f,...L]},[D,w]),g=i||b||R||U||B,C=He(y),T=m.length>0;return t.jsxs(t.Fragment,{children:[t.jsxs(mt,{currentTab:"Web",children:[T&&t.jsx(ee,{children:t.jsx(se,{})}),t.jsxs(ee,{className:`${T?"mt-0! [grid-area:subactions] lg:mt-[25px]!":"[grid-area:actions]"}`,children:[t.jsx(kt,{filters:m,onChange:x}),!T&&t.jsx(se,{})]})]}),t.jsx(pt,{children:g?t.jsx(ue,{className:"size-full",variant:"plain",children:t.jsx(de,{className:"size-full items-center justify-center",children:t.jsx(Pe,{})})}):y&&y.length!==0&&C.visits!=="0"?t.jsxs(t.Fragment,{children:[t.jsx(Qe,{data:y,range:d}),t.jsxs("div",{className:"flex flex-col gap-6 lg:grid lg:grid-cols-2",children:[t.jsx(yt,{data:Y,isLoading:U,onLocationClick:F}),t.jsx(Ye,{data:M,range:d,siteIcon:P,siteUrl:Q,totalVisitors:_,onSourceClick:A})]})]}):t.jsx("div",{className:"grow",children:t.jsx(Nt,{className:"h-full",description:"Try adjusting filters to see more data.",title:`No visitors ${Xe(o)}`,children:t.jsx(q,{strokeWidth:1.5})})})})]})};export{Ms as default};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<link rel="stylesheet" href="./assets/vendor-3bf602dfa6463c3400ffd81697767274.css">
|
|
5
5
|
<link rel="stylesheet" href="./assets/ghost-807a0be0d26802d1bf3fb560ec46236f.css">
|
|
6
|
-
<meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22editorUrl%22%3A%22%22%2C%22rootURL%22%3A%22%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%226.
|
|
6
|
+
<meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22editorUrl%22%3A%22%22%2C%22rootURL%22%3A%22%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%226.41%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%7D%2C%22%40sentry%2Fember%22%3A%7B%22disablePerformance%22%3Atrue%2C%22sentry%22%3A%7B%7D%7D%2C%22ember-cli-mirage%22%3A%7B%22usingProxy%22%3Afalse%2C%22useDefaultPassthroughs%22%3Atrue%7D%2C%22exportApplicationGlobal%22%3Afalse%2C%22ember-load%22%3A%7B%22loadingIndicatorClass%22%3A%22ember-load-indicator%22%7D%2C%22editorFilename%22%3A%22koenig-lexical.umd.js%22%2C%22editorHash%22%3A%224bef7cc61a%22%2C%22adminXSettingsFilename%22%3A%22admin-x-settings.js%22%2C%22adminXSettingsHash%22%3A%22a228b4c08e%22%2C%22activitypubFilename%22%3A%22activitypub.js%22%2C%22activitypubHash%22%3A%2270f274dc02%22%2C%22postsFilename%22%3A%22posts.js%22%2C%22postsHash%22%3A%224233bbfe86%22%2C%22statsFilename%22%3A%22stats.js%22%2C%22statsHash%22%3A%22f061de3e8e%22%2C%22activitypubRemoteConfigUrl%22%3A%22%2F.ghost%2Factivitypub%2Fstable%2Fclient-config%22%7D">
|
|
7
7
|
|
|
8
8
|
<meta charset="UTF-8" />
|
|
9
9
|
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
<link rel="shortcut icon" href="assets/img/favicon.ico" />
|
|
22
22
|
<link rel="apple-touch-icon" href="assets/img/apple-touch-icon.png" />
|
|
23
|
-
<script type="module" crossorigin src="./assets/index-
|
|
23
|
+
<script type="module" crossorigin src="./assets/index-BkbhBpVC.js"></script>
|
|
24
24
|
<link rel="stylesheet" crossorigin href="./assets/index-C2Ws6omJ.css">
|
|
25
25
|
</head>
|
|
26
26
|
<body class="react-admin">
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
<div id="ember-notifications-wormhole"></div>
|
|
43
43
|
<script src="./assets/vendor-a431e7f6d0600135a1b4add53d76c532.js"></script>
|
|
44
44
|
<script src="./assets/chunk.54.26681edace435172ce09.js"></script>
|
|
45
|
-
<script src="./assets/chunk.
|
|
46
|
-
<script src="./assets/chunk.524.
|
|
47
|
-
<script src="./assets/ghost-
|
|
45
|
+
<script src="./assets/chunk.331.2ec2e2702eda02de96cd.js"></script>
|
|
46
|
+
<script src="./assets/chunk.524.49cc01002e1a5dba8ef9.js"></script>
|
|
47
|
+
<script src="./assets/ghost-30c3dedbe1cca943b92efa7efd2710e4.js"></script>
|
|
48
48
|
</body>
|
|
49
49
|
</html>
|
package/core/server/{services/custom-redirects/file-store.js → adapters/redirects/FileStore.js}
RENAMED
|
@@ -3,11 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.FileStore = void 0;
|
|
7
6
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
7
|
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const
|
|
10
|
-
const
|
|
8
|
+
const RedirectsStoreBase_1 = __importDefault(require("./RedirectsStoreBase"));
|
|
9
|
+
const redirect_config_parser_1 = require("../../services/custom-redirects/redirect-config-parser");
|
|
10
|
+
const utils_1 = require("../../services/custom-redirects/utils");
|
|
11
11
|
const YAML_FILENAME = 'redirects.yaml';
|
|
12
12
|
const JSON_FILENAME = 'redirects.json';
|
|
13
13
|
/**
|
|
@@ -16,10 +16,11 @@ const JSON_FILENAME = 'redirects.json';
|
|
|
16
16
|
* `.json`. The previous canonical file becomes a timestamped backup on
|
|
17
17
|
* every successive `replaceAll`.
|
|
18
18
|
*/
|
|
19
|
-
class FileStore {
|
|
19
|
+
class FileStore extends RedirectsStoreBase_1.default {
|
|
20
20
|
basePath;
|
|
21
21
|
getBackupFilePath;
|
|
22
22
|
constructor({ basePath, getBackupFilePath = utils_1.getBackupRedirectsFilePath }) {
|
|
23
|
+
super();
|
|
23
24
|
this.basePath = basePath;
|
|
24
25
|
this.getBackupFilePath = getBackupFilePath;
|
|
25
26
|
}
|
|
@@ -95,4 +96,4 @@ class FileStore {
|
|
|
95
96
|
}
|
|
96
97
|
}
|
|
97
98
|
}
|
|
98
|
-
exports.
|
|
99
|
+
exports.default = FileStore;
|
package/core/server/{services/custom-redirects/file-store.ts → adapters/redirects/FileStore.ts}
RENAMED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
4
|
+
import RedirectsStoreBase from './RedirectsStoreBase';
|
|
5
|
+
import {parseJson, parseYaml} from '../../services/custom-redirects/redirect-config-parser';
|
|
6
|
+
import {getBackupRedirectsFilePath} from '../../services/custom-redirects/utils';
|
|
7
|
+
import type {RedirectConfig, RedirectsStore} from '../../services/custom-redirects/types';
|
|
7
8
|
|
|
8
9
|
const YAML_FILENAME = 'redirects.yaml';
|
|
9
10
|
const JSON_FILENAME = 'redirects.json';
|
|
@@ -19,11 +20,12 @@ interface FileStoreOptions {
|
|
|
19
20
|
* `.json`. The previous canonical file becomes a timestamped backup on
|
|
20
21
|
* every successive `replaceAll`.
|
|
21
22
|
*/
|
|
22
|
-
export class FileStore implements RedirectsStore {
|
|
23
|
+
export default class FileStore extends RedirectsStoreBase implements RedirectsStore {
|
|
23
24
|
private readonly basePath: string;
|
|
24
25
|
private readonly getBackupFilePath: (filePath: string) => string;
|
|
25
26
|
|
|
26
27
|
constructor({basePath, getBackupFilePath = getBackupRedirectsFilePath}: FileStoreOptions) {
|
|
28
|
+
super();
|
|
27
29
|
this.basePath = basePath;
|
|
28
30
|
this.getBackupFilePath = getBackupFilePath;
|
|
29
31
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/* eslint-disable ghost/filenames/match-regex --
|
|
2
|
+
* PascalCase mirrors the runtime `RedirectsStoreBase.js` so the TS
|
|
3
|
+
* adapter can default-import via the matching declaration file.
|
|
4
|
+
*/
|
|
5
|
+
declare class RedirectsStoreBase {
|
|
6
|
+
readonly requiredFns: ReadonlyArray<string>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default RedirectsStoreBase;
|
|
@@ -36,49 +36,76 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.GCSStore = void 0;
|
|
40
39
|
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
41
40
|
const tpl_1 = __importDefault(require("@tryghost/tpl"));
|
|
42
41
|
const errors = __importStar(require("@tryghost/errors"));
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
const
|
|
42
|
+
const RedirectsStoreBase_1 = __importDefault(require("./RedirectsStoreBase"));
|
|
43
|
+
const redirect_config_parser_1 = require("../../services/custom-redirects/redirect-config-parser");
|
|
44
|
+
const utils_1 = require("../../services/custom-redirects/utils");
|
|
45
|
+
const DEFAULT_FILENAME = 'redirects.json';
|
|
46
46
|
const messages = {
|
|
47
|
-
missingBucket: '
|
|
48
|
-
|
|
47
|
+
missingBucket: 'S3RedirectsStore requires a bucket name',
|
|
48
|
+
missingStaticFileURLPrefix: 'S3RedirectsStore requires a staticFileURLPrefix',
|
|
49
|
+
partialCredentials: 'S3RedirectsStore requires both accessKeyId and secretAccessKey when either is provided',
|
|
49
50
|
missingResponseBody: 'S3 GetObject returned no body'
|
|
50
51
|
};
|
|
52
|
+
const stripLeadingAndTrailingSlashes = (value = '') => value.replace(/^\/+|\/+$/g, '');
|
|
51
53
|
/**
|
|
52
54
|
* Implements RedirectsStore against an S3-compatible bucket. Reads and
|
|
53
55
|
* writes a single JSON object at the configured key, keeping a
|
|
54
56
|
* timestamped server-side copy of the previous contents on each
|
|
55
57
|
* overwrite.
|
|
56
58
|
*/
|
|
57
|
-
class
|
|
59
|
+
class S3RedirectsStore extends RedirectsStoreBase_1.default {
|
|
58
60
|
client;
|
|
59
61
|
bucket;
|
|
60
|
-
|
|
62
|
+
staticFileURLPrefix;
|
|
63
|
+
tenantPrefix;
|
|
61
64
|
constructor(options) {
|
|
65
|
+
super();
|
|
62
66
|
if (!options.bucket) {
|
|
63
67
|
throw new errors.IncorrectUsageError({
|
|
64
68
|
message: (0, tpl_1.default)(messages.missingBucket)
|
|
65
69
|
});
|
|
66
70
|
}
|
|
67
|
-
|
|
71
|
+
const staticFileURLPrefix = stripLeadingAndTrailingSlashes(options.staticFileURLPrefix);
|
|
72
|
+
if (!staticFileURLPrefix) {
|
|
68
73
|
throw new errors.IncorrectUsageError({
|
|
69
|
-
message: (0, tpl_1.default)(messages.
|
|
74
|
+
message: (0, tpl_1.default)(messages.missingStaticFileURLPrefix)
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
const hasAccessKey = Boolean(options.accessKeyId);
|
|
78
|
+
const hasSecretKey = Boolean(options.secretAccessKey);
|
|
79
|
+
const hasSessionToken = Boolean(options.sessionToken);
|
|
80
|
+
const hasCredentialPair = hasAccessKey && hasSecretKey;
|
|
81
|
+
if ((hasAccessKey || hasSecretKey || hasSessionToken) && !hasCredentialPair) {
|
|
82
|
+
throw new errors.IncorrectUsageError({
|
|
83
|
+
message: (0, tpl_1.default)(messages.partialCredentials)
|
|
70
84
|
});
|
|
71
85
|
}
|
|
72
86
|
this.bucket = options.bucket;
|
|
73
|
-
this.
|
|
74
|
-
this.
|
|
87
|
+
this.staticFileURLPrefix = staticFileURLPrefix;
|
|
88
|
+
this.tenantPrefix = stripLeadingAndTrailingSlashes(options.tenantPrefix);
|
|
89
|
+
const clientConfig = {
|
|
90
|
+
region: options.region,
|
|
91
|
+
endpoint: options.endpoint,
|
|
92
|
+
forcePathStyle: options.forcePathStyle
|
|
93
|
+
};
|
|
94
|
+
if (hasCredentialPair) {
|
|
95
|
+
clientConfig.credentials = {
|
|
96
|
+
accessKeyId: options.accessKeyId,
|
|
97
|
+
secretAccessKey: options.secretAccessKey,
|
|
98
|
+
sessionToken: options.sessionToken
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
this.client = new client_s3_1.S3Client(clientConfig);
|
|
75
102
|
}
|
|
76
103
|
async getAll() {
|
|
77
104
|
let body;
|
|
78
105
|
try {
|
|
79
106
|
const response = await this.client.send(new client_s3_1.GetObjectCommand({
|
|
80
107
|
Bucket: this.bucket,
|
|
81
|
-
Key:
|
|
108
|
+
Key: this.buildKey()
|
|
82
109
|
}));
|
|
83
110
|
if (!response.Body) {
|
|
84
111
|
throw new errors.InternalServerError({
|
|
@@ -96,25 +123,30 @@ class GCSStore {
|
|
|
96
123
|
return (0, redirect_config_parser_1.parseJson)(body);
|
|
97
124
|
}
|
|
98
125
|
async replaceAll(redirects) {
|
|
126
|
+
const key = this.buildKey();
|
|
99
127
|
if (await this._canonicalExists()) {
|
|
100
128
|
await this.client.send(new client_s3_1.CopyObjectCommand({
|
|
101
129
|
Bucket: this.bucket,
|
|
102
|
-
Key:
|
|
103
|
-
CopySource: `${this.bucket}/${
|
|
130
|
+
Key: (0, utils_1.getBackupRedirectsFilePath)(key),
|
|
131
|
+
CopySource: `${this.bucket}/${key}`
|
|
104
132
|
}));
|
|
105
133
|
}
|
|
106
134
|
await this.client.send(new client_s3_1.PutObjectCommand({
|
|
107
135
|
Bucket: this.bucket,
|
|
108
|
-
Key:
|
|
136
|
+
Key: key,
|
|
109
137
|
Body: JSON.stringify(redirects),
|
|
110
138
|
ContentType: 'application/json'
|
|
111
139
|
}));
|
|
112
140
|
}
|
|
141
|
+
buildKey() {
|
|
142
|
+
const parts = [this.tenantPrefix, this.staticFileURLPrefix, DEFAULT_FILENAME].filter(Boolean);
|
|
143
|
+
return parts.join('/');
|
|
144
|
+
}
|
|
113
145
|
async _canonicalExists() {
|
|
114
146
|
try {
|
|
115
147
|
await this.client.send(new client_s3_1.HeadObjectCommand({
|
|
116
148
|
Bucket: this.bucket,
|
|
117
|
-
Key:
|
|
149
|
+
Key: this.buildKey()
|
|
118
150
|
}));
|
|
119
151
|
return true;
|
|
120
152
|
}
|
|
@@ -129,4 +161,4 @@ class GCSStore {
|
|
|
129
161
|
return err instanceof client_s3_1.NotFound || err instanceof client_s3_1.NoSuchKey;
|
|
130
162
|
}
|
|
131
163
|
}
|
|
132
|
-
exports.
|
|
164
|
+
exports.default = S3RedirectsStore;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CopyObjectCommand,
|
|
3
|
+
GetObjectCommand,
|
|
4
|
+
HeadObjectCommand,
|
|
5
|
+
NoSuchKey,
|
|
6
|
+
NotFound,
|
|
7
|
+
PutObjectCommand,
|
|
8
|
+
S3Client,
|
|
9
|
+
S3ClientConfig
|
|
10
|
+
} from '@aws-sdk/client-s3';
|
|
11
|
+
import tpl from '@tryghost/tpl';
|
|
12
|
+
import * as errors from '@tryghost/errors';
|
|
13
|
+
|
|
14
|
+
import RedirectsStoreBase from './RedirectsStoreBase';
|
|
15
|
+
import {parseJson} from '../../services/custom-redirects/redirect-config-parser';
|
|
16
|
+
import {getBackupRedirectsFilePath} from '../../services/custom-redirects/utils';
|
|
17
|
+
import type {RedirectConfig, RedirectsStore} from '../../services/custom-redirects/types';
|
|
18
|
+
|
|
19
|
+
const DEFAULT_FILENAME = 'redirects.json';
|
|
20
|
+
|
|
21
|
+
const messages = {
|
|
22
|
+
missingBucket: 'S3RedirectsStore requires a bucket name',
|
|
23
|
+
missingStaticFileURLPrefix: 'S3RedirectsStore requires a staticFileURLPrefix',
|
|
24
|
+
partialCredentials: 'S3RedirectsStore requires both accessKeyId and secretAccessKey when either is provided',
|
|
25
|
+
missingResponseBody: 'S3 GetObject returned no body'
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const stripLeadingAndTrailingSlashes = (value = '') => value.replace(/^\/+|\/+$/g, '');
|
|
29
|
+
|
|
30
|
+
export interface S3RedirectsStoreOptions {
|
|
31
|
+
bucket: string;
|
|
32
|
+
staticFileURLPrefix: string;
|
|
33
|
+
region?: string;
|
|
34
|
+
endpoint?: string;
|
|
35
|
+
forcePathStyle?: boolean;
|
|
36
|
+
accessKeyId?: string;
|
|
37
|
+
secretAccessKey?: string;
|
|
38
|
+
sessionToken?: string;
|
|
39
|
+
tenantPrefix?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Implements RedirectsStore against an S3-compatible bucket. Reads and
|
|
44
|
+
* writes a single JSON object at the configured key, keeping a
|
|
45
|
+
* timestamped server-side copy of the previous contents on each
|
|
46
|
+
* overwrite.
|
|
47
|
+
*/
|
|
48
|
+
export default class S3RedirectsStore extends RedirectsStoreBase implements RedirectsStore {
|
|
49
|
+
private readonly client: S3Client;
|
|
50
|
+
private readonly bucket: string;
|
|
51
|
+
private readonly staticFileURLPrefix: string;
|
|
52
|
+
private readonly tenantPrefix: string;
|
|
53
|
+
|
|
54
|
+
constructor(options: S3RedirectsStoreOptions) {
|
|
55
|
+
super();
|
|
56
|
+
if (!options.bucket) {
|
|
57
|
+
throw new errors.IncorrectUsageError({
|
|
58
|
+
message: tpl(messages.missingBucket)
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const staticFileURLPrefix = stripLeadingAndTrailingSlashes(options.staticFileURLPrefix);
|
|
63
|
+
if (!staticFileURLPrefix) {
|
|
64
|
+
throw new errors.IncorrectUsageError({
|
|
65
|
+
message: tpl(messages.missingStaticFileURLPrefix)
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const hasAccessKey = Boolean(options.accessKeyId);
|
|
70
|
+
const hasSecretKey = Boolean(options.secretAccessKey);
|
|
71
|
+
const hasSessionToken = Boolean(options.sessionToken);
|
|
72
|
+
const hasCredentialPair = hasAccessKey && hasSecretKey;
|
|
73
|
+
if ((hasAccessKey || hasSecretKey || hasSessionToken) && !hasCredentialPair) {
|
|
74
|
+
throw new errors.IncorrectUsageError({
|
|
75
|
+
message: tpl(messages.partialCredentials)
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
this.bucket = options.bucket;
|
|
80
|
+
this.staticFileURLPrefix = staticFileURLPrefix;
|
|
81
|
+
this.tenantPrefix = stripLeadingAndTrailingSlashes(options.tenantPrefix);
|
|
82
|
+
|
|
83
|
+
const clientConfig: S3ClientConfig = {
|
|
84
|
+
region: options.region,
|
|
85
|
+
endpoint: options.endpoint,
|
|
86
|
+
forcePathStyle: options.forcePathStyle
|
|
87
|
+
};
|
|
88
|
+
if (hasCredentialPair) {
|
|
89
|
+
clientConfig.credentials = {
|
|
90
|
+
accessKeyId: options.accessKeyId!,
|
|
91
|
+
secretAccessKey: options.secretAccessKey!,
|
|
92
|
+
sessionToken: options.sessionToken
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
this.client = new S3Client(clientConfig);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async getAll(): Promise<RedirectConfig[]> {
|
|
99
|
+
let body: string;
|
|
100
|
+
try {
|
|
101
|
+
const response = await this.client.send(new GetObjectCommand({
|
|
102
|
+
Bucket: this.bucket,
|
|
103
|
+
Key: this.buildKey()
|
|
104
|
+
}));
|
|
105
|
+
if (!response.Body) {
|
|
106
|
+
throw new errors.InternalServerError({
|
|
107
|
+
message: tpl(messages.missingResponseBody)
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
body = await response.Body.transformToString('utf-8');
|
|
111
|
+
} catch (err) {
|
|
112
|
+
if (this._isNotFound(err)) {
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
throw err;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return parseJson(body);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async replaceAll(redirects: RedirectConfig[]): Promise<void> {
|
|
122
|
+
const key = this.buildKey();
|
|
123
|
+
|
|
124
|
+
if (await this._canonicalExists()) {
|
|
125
|
+
await this.client.send(new CopyObjectCommand({
|
|
126
|
+
Bucket: this.bucket,
|
|
127
|
+
Key: getBackupRedirectsFilePath(key),
|
|
128
|
+
CopySource: `${this.bucket}/${key}`
|
|
129
|
+
}));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
await this.client.send(new PutObjectCommand({
|
|
133
|
+
Bucket: this.bucket,
|
|
134
|
+
Key: key,
|
|
135
|
+
Body: JSON.stringify(redirects),
|
|
136
|
+
ContentType: 'application/json'
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private buildKey(): string {
|
|
141
|
+
const parts = [this.tenantPrefix, this.staticFileURLPrefix, DEFAULT_FILENAME].filter(Boolean);
|
|
142
|
+
return parts.join('/');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
private async _canonicalExists(): Promise<boolean> {
|
|
146
|
+
try {
|
|
147
|
+
await this.client.send(new HeadObjectCommand({
|
|
148
|
+
Bucket: this.bucket,
|
|
149
|
+
Key: this.buildKey()
|
|
150
|
+
}));
|
|
151
|
+
return true;
|
|
152
|
+
} catch (err) {
|
|
153
|
+
if (this._isNotFound(err)) {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
throw err;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private _isNotFound(err: unknown): boolean {
|
|
161
|
+
return err instanceof NotFound || err instanceof NoSuchKey;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
@@ -1,8 +1,49 @@
|
|
|
1
|
+
const logging = require('@tryghost/logging');
|
|
2
|
+
|
|
1
3
|
function SchedulingBase() {
|
|
2
4
|
Object.defineProperty(this, 'requiredFns', {
|
|
3
5
|
value: ['schedule', 'unschedule', 'run'],
|
|
4
6
|
writable: false
|
|
5
7
|
});
|
|
8
|
+
this._reschedulers = new Set();
|
|
6
9
|
}
|
|
7
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Register a subsystem that can rebuild its scheduler queue on demand.
|
|
13
|
+
*
|
|
14
|
+
* Scheduler-users (post-scheduling, automations, gifts) call this at
|
|
15
|
+
* construction so the adapter knows who to ask when queued URLs need
|
|
16
|
+
* regenerating (e.g. after internal API key rotation). The convention is
|
|
17
|
+
* that a registered rescheduler exposes a `rescheduleAll(opts)` method.
|
|
18
|
+
*
|
|
19
|
+
* @param {{rescheduleAll: (opts: {previousKey?: {id: string; secret: string}}) => Promise<void>}} rescheduler
|
|
20
|
+
*/
|
|
21
|
+
SchedulingBase.prototype.register = function (rescheduler) {
|
|
22
|
+
this._reschedulers.add(rescheduler);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Ask every registered rescheduler to rebuild its queue under the current
|
|
27
|
+
* key. Best-effort: a failure in one doesn't block the others.
|
|
28
|
+
*
|
|
29
|
+
* @param {{previousKey?: {id: string; secret: string}}} [opts]
|
|
30
|
+
* @returns {Promise<PromiseSettledResult<void>[]>}
|
|
31
|
+
*/
|
|
32
|
+
SchedulingBase.prototype.rescheduleAll = async function (opts = {}) {
|
|
33
|
+
const reschedulers = Array.from(this._reschedulers);
|
|
34
|
+
const results = await Promise.allSettled(
|
|
35
|
+
reschedulers.map(r => r.rescheduleAll(opts))
|
|
36
|
+
);
|
|
37
|
+
results.forEach((result, i) => {
|
|
38
|
+
if (result.status === 'rejected') {
|
|
39
|
+
logging.error({
|
|
40
|
+
event: {name: 'scheduler.reschedule_all.failed'},
|
|
41
|
+
err: result.reason,
|
|
42
|
+
rescheduler: reschedulers[i].constructor?.name ?? 'unknown'
|
|
43
|
+
}, 'Rescheduler failed');
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
return results;
|
|
47
|
+
};
|
|
48
|
+
|
|
8
49
|
module.exports = SchedulingBase;
|