@btst/stack 2.6.2 → 2.8.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/README.md +1 -0
- package/dist/api/index.d.cts +2 -2
- package/dist/api/index.d.mts +2 -2
- package/dist/api/index.d.ts +2 -2
- package/dist/client/index.d.cts +2 -2
- package/dist/client/index.d.mts +2 -2
- package/dist/client/index.d.ts +2 -2
- package/dist/components/auto-form/index.d.cts +2 -2
- package/dist/components/auto-form/index.d.mts +2 -2
- package/dist/components/auto-form/index.d.ts +2 -2
- package/dist/components/form-builder/index.d.cts +1 -1
- package/dist/components/form-builder/index.d.mts +1 -1
- package/dist/components/form-builder/index.d.ts +1 -1
- package/dist/components/stepped-auto-form/index.d.cts +1 -1
- package/dist/components/stepped-auto-form/index.d.mts +1 -1
- package/dist/components/stepped-auto-form/index.d.ts +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/packages/stack/src/plugins/blog/client/components/loading/post-navigation-skeleton.cjs +13 -0
- package/dist/packages/stack/src/plugins/blog/client/components/loading/post-navigation-skeleton.mjs +11 -0
- package/dist/packages/stack/src/plugins/blog/client/components/loading/recent-posts-carousel-skeleton.cjs +17 -0
- package/dist/packages/stack/src/plugins/blog/client/components/loading/recent-posts-carousel-skeleton.mjs +15 -0
- package/dist/packages/stack/src/plugins/blog/client/components/pages/post-page.internal.cjs +18 -7
- package/dist/packages/stack/src/plugins/blog/client/components/pages/post-page.internal.mjs +18 -7
- package/dist/packages/stack/src/plugins/blog/client/components/shared/post-navigation.cjs +48 -52
- package/dist/packages/stack/src/plugins/blog/client/components/shared/post-navigation.mjs +49 -53
- package/dist/packages/stack/src/plugins/blog/client/components/shared/recent-posts-carousel.cjs +34 -37
- package/dist/packages/stack/src/plugins/blog/client/components/shared/recent-posts-carousel.mjs +35 -38
- package/dist/packages/stack/src/plugins/blog/client/hooks/blog-hooks.cjs +4 -21
- package/dist/packages/stack/src/plugins/blog/client/hooks/blog-hooks.mjs +4 -21
- package/dist/packages/stack/src/plugins/comments/api/getters.cjs +284 -0
- package/dist/packages/stack/src/plugins/comments/api/getters.mjs +280 -0
- package/dist/packages/stack/src/plugins/comments/api/mutations.cjs +118 -0
- package/dist/packages/stack/src/plugins/comments/api/mutations.mjs +112 -0
- package/dist/packages/stack/src/plugins/comments/api/plugin.cjs +335 -0
- package/dist/packages/stack/src/plugins/comments/api/plugin.mjs +333 -0
- package/dist/packages/stack/src/plugins/comments/api/query-key-defs.cjs +60 -0
- package/dist/packages/stack/src/plugins/comments/api/query-key-defs.mjs +55 -0
- package/dist/packages/stack/src/plugins/comments/api/serializers.cjs +23 -0
- package/dist/packages/stack/src/plugins/comments/api/serializers.mjs +21 -0
- package/dist/packages/stack/src/plugins/comments/client/components/comment-count.cjs +46 -0
- package/dist/packages/stack/src/plugins/comments/client/components/comment-count.mjs +44 -0
- package/dist/packages/stack/src/plugins/comments/client/components/comment-form.cjs +86 -0
- package/dist/packages/stack/src/plugins/comments/client/components/comment-form.mjs +84 -0
- package/dist/packages/stack/src/plugins/comments/client/components/comment-thread.cjs +540 -0
- package/dist/packages/stack/src/plugins/comments/client/components/comment-thread.mjs +538 -0
- package/dist/packages/stack/src/plugins/comments/client/components/pages/moderation-page.cjs +64 -0
- package/dist/packages/stack/src/plugins/comments/client/components/pages/moderation-page.internal.cjs +426 -0
- package/dist/packages/stack/src/plugins/comments/client/components/pages/moderation-page.internal.mjs +424 -0
- package/dist/packages/stack/src/plugins/comments/client/components/pages/moderation-page.mjs +62 -0
- package/dist/packages/stack/src/plugins/comments/client/components/pages/my-comments-page.cjs +66 -0
- package/dist/packages/stack/src/plugins/comments/client/components/pages/my-comments-page.internal.cjs +256 -0
- package/dist/packages/stack/src/plugins/comments/client/components/pages/my-comments-page.internal.mjs +254 -0
- package/dist/packages/stack/src/plugins/comments/client/components/pages/my-comments-page.mjs +64 -0
- package/dist/packages/stack/src/plugins/comments/client/components/pages/resource-comments-page.cjs +86 -0
- package/dist/packages/stack/src/plugins/comments/client/components/pages/resource-comments-page.internal.cjs +191 -0
- package/dist/packages/stack/src/plugins/comments/client/components/pages/resource-comments-page.internal.mjs +189 -0
- package/dist/packages/stack/src/plugins/comments/client/components/pages/resource-comments-page.mjs +84 -0
- package/dist/packages/stack/src/plugins/comments/client/components/shared/page-wrapper.cjs +27 -0
- package/dist/packages/stack/src/plugins/comments/client/components/shared/page-wrapper.mjs +25 -0
- package/dist/packages/stack/src/plugins/comments/client/components/shared/pagination.cjs +37 -0
- package/dist/packages/stack/src/plugins/comments/client/components/shared/pagination.mjs +35 -0
- package/dist/packages/stack/src/plugins/comments/client/hooks/use-comments.cjs +476 -0
- package/dist/packages/stack/src/plugins/comments/client/hooks/use-comments.mjs +464 -0
- package/dist/packages/stack/src/plugins/comments/client/localization/comments-moderation.cjs +67 -0
- package/dist/packages/stack/src/plugins/comments/client/localization/comments-moderation.mjs +65 -0
- package/dist/packages/stack/src/plugins/comments/client/localization/comments-my.cjs +27 -0
- package/dist/packages/stack/src/plugins/comments/client/localization/comments-my.mjs +25 -0
- package/dist/packages/stack/src/plugins/comments/client/localization/comments-thread.cjs +30 -0
- package/dist/packages/stack/src/plugins/comments/client/localization/comments-thread.mjs +28 -0
- package/dist/packages/stack/src/plugins/comments/client/localization/index.cjs +13 -0
- package/dist/packages/stack/src/plugins/comments/client/localization/index.mjs +11 -0
- package/dist/packages/stack/src/plugins/comments/client/plugin.cjs +116 -0
- package/dist/packages/stack/src/plugins/comments/client/plugin.mjs +114 -0
- package/dist/packages/stack/src/plugins/comments/client/utils.cjs +41 -0
- package/dist/packages/stack/src/plugins/comments/client/utils.mjs +37 -0
- package/dist/packages/stack/src/plugins/comments/db.cjs +75 -0
- package/dist/packages/stack/src/plugins/comments/db.mjs +73 -0
- package/dist/packages/stack/src/plugins/comments/schemas.cjs +45 -0
- package/dist/packages/stack/src/plugins/comments/schemas.mjs +38 -0
- package/dist/packages/stack/src/plugins/kanban/api/plugin.cjs +5 -4
- package/dist/packages/stack/src/plugins/kanban/api/plugin.mjs +5 -4
- package/dist/packages/stack/src/plugins/kanban/client/components/forms/task-form.cjs +0 -1
- package/dist/packages/stack/src/plugins/kanban/client/components/forms/task-form.mjs +0 -1
- package/dist/packages/stack/src/plugins/kanban/client/components/pages/board-page.internal.cjs +39 -22
- package/dist/packages/stack/src/plugins/kanban/client/components/pages/board-page.internal.mjs +40 -23
- package/dist/packages/ui/src/components/avatar.mjs +1 -1
- package/dist/packages/ui/src/components/pagination-controls.cjs +64 -0
- package/dist/packages/ui/src/components/pagination-controls.mjs +62 -0
- package/dist/packages/ui/src/components/when-visible.cjs +39 -0
- package/dist/packages/ui/src/components/when-visible.mjs +37 -0
- package/dist/plugins/ai-chat/api/index.d.cts +4 -6
- package/dist/plugins/ai-chat/api/index.d.mts +4 -6
- package/dist/plugins/ai-chat/api/index.d.ts +4 -6
- package/dist/plugins/ai-chat/client/hooks/index.d.cts +1 -3
- package/dist/plugins/ai-chat/client/hooks/index.d.mts +1 -3
- package/dist/plugins/ai-chat/client/hooks/index.d.ts +1 -3
- package/dist/plugins/ai-chat/query-keys.d.cts +1 -3
- package/dist/plugins/ai-chat/query-keys.d.mts +1 -3
- package/dist/plugins/ai-chat/query-keys.d.ts +1 -3
- package/dist/plugins/api/index.d.cts +3 -3
- package/dist/plugins/api/index.d.mts +3 -3
- package/dist/plugins/api/index.d.ts +3 -3
- package/dist/plugins/blog/api/index.d.cts +3 -3
- package/dist/plugins/blog/api/index.d.mts +3 -3
- package/dist/plugins/blog/api/index.d.ts +3 -3
- package/dist/plugins/blog/client/hooks/index.d.cts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.mts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.ts +2 -2
- package/dist/plugins/blog/client/index.d.cts +25 -3
- package/dist/plugins/blog/client/index.d.mts +25 -3
- package/dist/plugins/blog/client/index.d.ts +25 -3
- package/dist/plugins/blog/query-keys.d.cts +3 -3
- package/dist/plugins/blog/query-keys.d.mts +3 -3
- package/dist/plugins/blog/query-keys.d.ts +3 -3
- package/dist/plugins/client/index.d.cts +2 -2
- package/dist/plugins/client/index.d.mts +2 -2
- package/dist/plugins/client/index.d.ts +2 -2
- package/dist/plugins/cms/api/index.d.cts +1 -1
- package/dist/plugins/cms/api/index.d.mts +1 -1
- package/dist/plugins/cms/api/index.d.ts +1 -1
- package/dist/plugins/cms/client/index.d.cts +1 -1
- package/dist/plugins/cms/client/index.d.mts +1 -1
- package/dist/plugins/cms/client/index.d.ts +1 -1
- package/dist/plugins/cms/query-keys.d.cts +1 -1
- package/dist/plugins/cms/query-keys.d.mts +1 -1
- package/dist/plugins/cms/query-keys.d.ts +1 -1
- package/dist/plugins/comments/api/index.cjs +21 -0
- package/dist/plugins/comments/api/index.d.cts +126 -0
- package/dist/plugins/comments/api/index.d.mts +126 -0
- package/dist/plugins/comments/api/index.d.ts +126 -0
- package/dist/plugins/comments/api/index.mjs +5 -0
- package/dist/plugins/comments/client/components/index.cjs +15 -0
- package/dist/plugins/comments/client/components/index.d.cts +125 -0
- package/dist/plugins/comments/client/components/index.d.mts +125 -0
- package/dist/plugins/comments/client/components/index.d.ts +125 -0
- package/dist/plugins/comments/client/components/index.mjs +5 -0
- package/dist/plugins/comments/client/hooks/index.cjs +17 -0
- package/dist/plugins/comments/client/hooks/index.d.cts +200 -0
- package/dist/plugins/comments/client/hooks/index.d.mts +200 -0
- package/dist/plugins/comments/client/hooks/index.d.ts +200 -0
- package/dist/plugins/comments/client/hooks/index.mjs +1 -0
- package/dist/plugins/comments/client/index.cjs +9 -0
- package/dist/plugins/comments/client/index.d.cts +262 -0
- package/dist/plugins/comments/client/index.d.mts +262 -0
- package/dist/plugins/comments/client/index.d.ts +262 -0
- package/dist/plugins/comments/client/index.mjs +2 -0
- package/dist/plugins/comments/client.css +2 -0
- package/dist/plugins/comments/query-keys.cjs +113 -0
- package/dist/plugins/comments/query-keys.d.cts +71 -0
- package/dist/plugins/comments/query-keys.d.mts +71 -0
- package/dist/plugins/comments/query-keys.d.ts +71 -0
- package/dist/plugins/comments/query-keys.mjs +111 -0
- package/dist/plugins/comments/style.css +15 -0
- package/dist/plugins/form-builder/api/index.d.cts +2 -2
- package/dist/plugins/form-builder/api/index.d.mts +2 -2
- package/dist/plugins/form-builder/api/index.d.ts +2 -2
- package/dist/plugins/form-builder/client/components/index.d.cts +1 -1
- package/dist/plugins/form-builder/client/components/index.d.mts +1 -1
- package/dist/plugins/form-builder/client/components/index.d.ts +1 -1
- package/dist/plugins/form-builder/client/index.d.cts +1 -1
- package/dist/plugins/form-builder/client/index.d.mts +1 -1
- package/dist/plugins/form-builder/client/index.d.ts +1 -1
- package/dist/plugins/form-builder/query-keys.d.cts +1 -1
- package/dist/plugins/form-builder/query-keys.d.mts +1 -1
- package/dist/plugins/form-builder/query-keys.d.ts +1 -1
- package/dist/plugins/kanban/api/index.d.cts +2 -2
- package/dist/plugins/kanban/api/index.d.mts +2 -2
- package/dist/plugins/kanban/api/index.d.ts +2 -2
- package/dist/plugins/kanban/client/hooks/index.d.cts +1 -1
- package/dist/plugins/kanban/client/hooks/index.d.mts +1 -1
- package/dist/plugins/kanban/client/hooks/index.d.ts +1 -1
- package/dist/plugins/kanban/client/index.d.cts +1 -1
- package/dist/plugins/kanban/client/index.d.mts +1 -1
- package/dist/plugins/kanban/client/index.d.ts +1 -1
- package/dist/plugins/kanban/query-keys.d.cts +2 -2
- package/dist/plugins/kanban/query-keys.d.mts +2 -2
- package/dist/plugins/kanban/query-keys.d.ts +2 -2
- package/dist/plugins/open-api/api/index.d.cts +3 -3
- package/dist/plugins/open-api/api/index.d.mts +3 -3
- package/dist/plugins/open-api/api/index.d.ts +3 -3
- package/dist/plugins/route-docs/client/index.d.cts +1 -1
- package/dist/plugins/route-docs/client/index.d.mts +1 -1
- package/dist/plugins/route-docs/client/index.d.ts +1 -1
- package/dist/plugins/ui-builder/client/components/index.d.cts +2 -2
- package/dist/plugins/ui-builder/client/components/index.d.mts +2 -2
- package/dist/plugins/ui-builder/client/components/index.d.ts +2 -2
- package/dist/plugins/ui-builder/client/hooks/index.d.cts +3 -3
- package/dist/plugins/ui-builder/client/hooks/index.d.mts +3 -3
- package/dist/plugins/ui-builder/client/hooks/index.d.ts +3 -3
- package/dist/plugins/ui-builder/client/index.d.cts +3 -3
- package/dist/plugins/ui-builder/client/index.d.mts +3 -3
- package/dist/plugins/ui-builder/client/index.d.ts +3 -3
- package/dist/plugins/ui-builder/index.d.cts +3 -3
- package/dist/plugins/ui-builder/index.d.mts +3 -3
- package/dist/plugins/ui-builder/index.d.ts +3 -3
- package/dist/shared/{stack.B1srlBud.d.mts → stack.BFoBvGML.d.mts} +1 -1
- package/dist/shared/{stack.DmpPDPxA.d.cts → stack.BOCvd9HK.d.cts} +1 -1
- package/dist/shared/{stack.n1_i1p2B.d.cts → stack.BOokfhZD.d.cts} +170 -110
- package/dist/shared/{stack.DXnclTG7.d.ts → stack.BSqJrCTM.d.cts} +120 -59
- package/dist/shared/{stack.B58oHdqm.d.mts → stack.BX7MHi0J.d.mts} +90 -45
- package/dist/shared/{stack.cfCkioTe.d.mts → stack.BXxrFL9R.d.ts} +120 -59
- package/dist/shared/{stack.CSx98K5H.d.cts → stack.BYN8wCV6.d.cts} +87 -58
- package/dist/shared/{stack.FVWf2JhZ.d.mts → stack.BgQrdSlo.d.mts} +60 -45
- package/dist/shared/{stack.BK9Z2dcL.d.ts → stack.BmMB0LNC.d.ts} +1 -1
- package/dist/shared/{stack.j75TpKh2.d.ts → stack.BvCR4-9H.d.ts} +170 -110
- package/dist/shared/{stack.FeaWkglm.d.ts → stack.BxFl46lB.d.cts} +24 -1
- package/dist/shared/stack.C-b3Sn8j.d.cts +142 -0
- package/dist/shared/stack.C-b3Sn8j.d.mts +142 -0
- package/dist/shared/stack.C-b3Sn8j.d.ts +142 -0
- package/dist/shared/{stack.CFECM0ew.d.cts → stack.C1nXGBr6.d.cts} +1 -1
- package/dist/shared/{stack.C9Mg2Q46.d.cts → stack.C9zoS1TN.d.cts} +90 -45
- package/dist/shared/stack.CJE9sAjV.d.ts +335 -0
- package/dist/shared/{stack.fdi94T4S.d.mts → stack.CPsYC2-Z.d.cts} +7 -7
- package/dist/shared/{stack.fdi94T4S.d.ts → stack.CPsYC2-Z.d.mts} +7 -7
- package/dist/shared/{stack.fdi94T4S.d.cts → stack.CPsYC2-Z.d.ts} +7 -7
- package/dist/shared/{stack.7n9Y_u7N.d.cts → stack.CQnwAN7x.d.cts} +6 -6
- package/dist/shared/{stack.7n9Y_u7N.d.mts → stack.CQnwAN7x.d.mts} +6 -6
- package/dist/shared/{stack.7n9Y_u7N.d.ts → stack.CQnwAN7x.d.ts} +6 -6
- package/dist/shared/{stack.CxaFNQCV.d.mts → stack.CWxAl9K3.d.mts} +170 -110
- package/dist/shared/{stack.D-b5zbPm.d.cts → stack.Cbsrl06u.d.cts} +60 -45
- package/dist/shared/stack.CmHRdhl8.d.cts +335 -0
- package/dist/shared/{stack.BgTmujxW.d.mts → stack.D88yU4FT.d.mts} +87 -58
- package/dist/shared/{stack.DVtk5CNw.d.mts → stack.DLPa6Gzm.d.mts} +1 -1
- package/dist/shared/{stack.BAT540yW.d.ts → stack.DOZ1EXjM.d.mts} +9 -15
- package/dist/shared/{stack.FeaWkglm.d.mts → stack.DRpeDS6X.d.ts} +24 -1
- package/dist/shared/{stack.B8vT-Yt4.d.mts → stack.DX-tQ93o.d.cts} +9 -15
- package/dist/shared/stack.Dcz6636A.d.mts +335 -0
- package/dist/shared/{stack.ASwEoINr.d.ts → stack.DxJ-tHLt.d.ts} +1 -1
- package/dist/shared/{stack.DaZM10cp.d.cts → stack.DzOhpIYM.d.mts} +120 -59
- package/dist/shared/{stack.CTDVxbrA.d.ts → stack.Fl2Kl_bt.d.ts} +60 -45
- package/dist/shared/{stack.FeaWkglm.d.cts → stack.Jb0kQDJC.d.mts} +24 -1
- package/dist/shared/stack.Ldfkr5b2.d.cts +112 -0
- package/dist/shared/stack.Ldfkr5b2.d.mts +112 -0
- package/dist/shared/stack.Ldfkr5b2.d.ts +112 -0
- package/dist/shared/{stack.CLQuVdwK.d.ts → stack.RuQ9JCLo.d.ts} +87 -58
- package/dist/shared/{stack.BwA7trxA.d.cts → stack.VF6FhyZw.d.ts} +9 -15
- package/dist/shared/{stack.sO33ZDhK.d.ts → stack.fQjVhw5a.d.ts} +90 -45
- package/package.json +70 -5
- package/src/__tests__/plugins.test.tsx +5 -1
- package/src/__tests__/stack-api.test.ts +1 -1
- package/src/plugins/ai-chat/__tests__/getters.test.ts +1 -1
- package/src/plugins/ai-chat/api/getters.ts +1 -1
- package/src/plugins/ai-chat/api/plugin.ts +1 -1
- package/src/plugins/api/index.ts +5 -1
- package/src/plugins/blog/__tests__/getters.test.ts +1 -1
- package/src/plugins/blog/api/getters.ts +1 -1
- package/src/plugins/blog/api/plugin.ts +1 -1
- package/src/plugins/blog/client/components/loading/post-navigation-skeleton.tsx +10 -0
- package/src/plugins/blog/client/components/loading/recent-posts-carousel-skeleton.tsx +18 -0
- package/src/plugins/blog/client/components/pages/post-page.internal.tsx +23 -8
- package/src/plugins/blog/client/components/shared/post-navigation.tsx +0 -5
- package/src/plugins/blog/client/components/shared/recent-posts-carousel.tsx +1 -5
- package/src/plugins/blog/client/hooks/blog-hooks.tsx +8 -33
- package/src/plugins/blog/client/overrides.ts +26 -1
- package/src/plugins/cms/__tests__/getters.test.ts +1 -1
- package/src/plugins/cms/api/getters.ts +1 -1
- package/src/plugins/cms/api/mutations.ts +1 -1
- package/src/plugins/cms/api/plugin.ts +1 -1
- package/src/plugins/cms/client/components/shared/pagination.tsx +14 -42
- package/src/plugins/comments/api/getters.ts +444 -0
- package/src/plugins/comments/api/index.ts +21 -0
- package/src/plugins/comments/api/mutations.ts +206 -0
- package/src/plugins/comments/api/plugin.ts +628 -0
- package/src/plugins/comments/api/query-key-defs.ts +143 -0
- package/src/plugins/comments/api/serializers.ts +37 -0
- package/src/plugins/comments/client/components/comment-count.tsx +66 -0
- package/src/plugins/comments/client/components/comment-form.tsx +112 -0
- package/src/plugins/comments/client/components/comment-thread.tsx +799 -0
- package/src/plugins/comments/client/components/index.tsx +11 -0
- package/src/plugins/comments/client/components/pages/moderation-page.internal.tsx +550 -0
- package/src/plugins/comments/client/components/pages/moderation-page.tsx +70 -0
- package/src/plugins/comments/client/components/pages/my-comments-page.internal.tsx +367 -0
- package/src/plugins/comments/client/components/pages/my-comments-page.tsx +72 -0
- package/src/plugins/comments/client/components/pages/resource-comments-page.internal.tsx +225 -0
- package/src/plugins/comments/client/components/pages/resource-comments-page.tsx +97 -0
- package/src/plugins/comments/client/components/shared/page-wrapper.tsx +32 -0
- package/src/plugins/comments/client/components/shared/pagination.tsx +44 -0
- package/src/plugins/comments/client/hooks/index.tsx +13 -0
- package/src/plugins/comments/client/hooks/use-comments.tsx +717 -0
- package/src/plugins/comments/client/index.ts +14 -0
- package/src/plugins/comments/client/localization/comments-moderation.ts +75 -0
- package/src/plugins/comments/client/localization/comments-my.ts +32 -0
- package/src/plugins/comments/client/localization/comments-thread.ts +32 -0
- package/src/plugins/comments/client/localization/index.ts +11 -0
- package/src/plugins/comments/client/overrides.ts +164 -0
- package/src/plugins/comments/client/plugin.tsx +195 -0
- package/src/plugins/comments/client/utils.ts +67 -0
- package/src/plugins/comments/client.css +2 -0
- package/src/plugins/comments/db.ts +77 -0
- package/src/plugins/comments/query-keys.ts +189 -0
- package/src/plugins/comments/schemas.ts +72 -0
- package/src/plugins/comments/style.css +15 -0
- package/src/plugins/comments/types.ts +73 -0
- package/src/plugins/form-builder/__tests__/getters.test.ts +1 -1
- package/src/plugins/form-builder/api/getters.ts +1 -1
- package/src/plugins/form-builder/api/plugin.ts +1 -1
- package/src/plugins/kanban/__tests__/getters.test.ts +1 -1
- package/src/plugins/kanban/api/getters.ts +1 -1
- package/src/plugins/kanban/api/mutations.ts +1 -1
- package/src/plugins/kanban/api/plugin.ts +6 -5
- package/src/plugins/kanban/client/components/forms/task-form.tsx +0 -1
- package/src/plugins/kanban/client/components/pages/board-page.internal.tsx +46 -27
- package/src/plugins/kanban/client/overrides.ts +27 -1
- package/src/types.ts +5 -1
- package/dist/shared/{stack.BQmuNl5p.d.mts → stack.BWp0hcm9.d.cts} +3 -3
- package/dist/shared/{stack.BQmuNl5p.d.ts → stack.BWp0hcm9.d.mts} +3 -3
- package/dist/shared/{stack.BQmuNl5p.d.cts → stack.BWp0hcm9.d.ts} +3 -3
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const api = require('@btst/stack/plugins/api');
|
|
4
|
+
const z = require('zod');
|
|
5
|
+
const db = require('../db.cjs');
|
|
6
|
+
const schemas = require('../schemas.cjs');
|
|
7
|
+
const getters = require('./getters.cjs');
|
|
8
|
+
const mutations = require('./mutations.cjs');
|
|
9
|
+
const utils = require('../../utils.cjs');
|
|
10
|
+
|
|
11
|
+
const commentsBackendPlugin = (options) => {
|
|
12
|
+
const postingEnabled = options.allowPosting !== false;
|
|
13
|
+
const editingEnabled = options.allowEditing !== false;
|
|
14
|
+
const onBeforePost = options.allowPosting !== false ? options.onBeforePost : void 0;
|
|
15
|
+
const resolveCurrentUserId = options.allowPosting !== false ? options.resolveCurrentUserId : void 0;
|
|
16
|
+
return api.defineBackendPlugin({
|
|
17
|
+
name: "comments",
|
|
18
|
+
dbPlugin: db.commentsSchema,
|
|
19
|
+
api: (adapter) => ({
|
|
20
|
+
listComments: (params) => getters.listComments(adapter, params, options?.resolveUser),
|
|
21
|
+
getCommentById: (id, currentUserId) => getters.getCommentById(adapter, id, options?.resolveUser, currentUserId),
|
|
22
|
+
getCommentCount: (params) => getters.getCommentCount(adapter, params)
|
|
23
|
+
}),
|
|
24
|
+
routes: (adapter) => {
|
|
25
|
+
const listCommentsEndpoint = api.createEndpoint(
|
|
26
|
+
"/comments",
|
|
27
|
+
{
|
|
28
|
+
method: "GET",
|
|
29
|
+
query: schemas.CommentListQuerySchema
|
|
30
|
+
},
|
|
31
|
+
async (ctx) => {
|
|
32
|
+
const context = {
|
|
33
|
+
query: ctx.query,
|
|
34
|
+
request: ctx.request,
|
|
35
|
+
headers: ctx.headers
|
|
36
|
+
};
|
|
37
|
+
if (ctx.query.authorId) {
|
|
38
|
+
if (!options?.onBeforeListByAuthor) {
|
|
39
|
+
throw ctx.error(403, {
|
|
40
|
+
message: "Forbidden: authorId filter requires onBeforeListByAuthor hook"
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
await utils.runHookWithShim(
|
|
44
|
+
() => options.onBeforeListByAuthor(
|
|
45
|
+
ctx.query.authorId,
|
|
46
|
+
ctx.query,
|
|
47
|
+
context
|
|
48
|
+
),
|
|
49
|
+
ctx.error,
|
|
50
|
+
"Forbidden: Cannot list comments for this author"
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
if (ctx.query.status && ctx.query.status !== "approved") {
|
|
54
|
+
if (!options?.onBeforeList) {
|
|
55
|
+
throw ctx.error(403, {
|
|
56
|
+
message: "Forbidden: status filter requires authorization"
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
await utils.runHookWithShim(
|
|
60
|
+
() => options.onBeforeList(ctx.query, context),
|
|
61
|
+
ctx.error,
|
|
62
|
+
"Forbidden: Cannot list comments with this status filter"
|
|
63
|
+
);
|
|
64
|
+
} else if (options?.onBeforeList && !ctx.query.authorId) {
|
|
65
|
+
await utils.runHookWithShim(
|
|
66
|
+
() => options.onBeforeList(ctx.query, context),
|
|
67
|
+
ctx.error,
|
|
68
|
+
"Forbidden: Cannot list comments"
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
let resolvedCurrentUserId;
|
|
72
|
+
if (resolveCurrentUserId) {
|
|
73
|
+
try {
|
|
74
|
+
const result = await resolveCurrentUserId(context);
|
|
75
|
+
resolvedCurrentUserId = result ?? void 0;
|
|
76
|
+
} catch {
|
|
77
|
+
resolvedCurrentUserId = void 0;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return await getters.listComments(
|
|
81
|
+
adapter,
|
|
82
|
+
{ ...ctx.query, currentUserId: resolvedCurrentUserId },
|
|
83
|
+
options?.resolveUser
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
const createCommentEndpoint = api.createEndpoint(
|
|
88
|
+
"/comments",
|
|
89
|
+
{
|
|
90
|
+
method: "POST",
|
|
91
|
+
body: schemas.createCommentSchema
|
|
92
|
+
},
|
|
93
|
+
async (ctx) => {
|
|
94
|
+
if (!postingEnabled) {
|
|
95
|
+
throw ctx.error(403, { message: "Posting comments is disabled" });
|
|
96
|
+
}
|
|
97
|
+
const context = {
|
|
98
|
+
body: ctx.body,
|
|
99
|
+
headers: ctx.headers
|
|
100
|
+
};
|
|
101
|
+
const { authorId } = await utils.runHookWithShim(
|
|
102
|
+
() => onBeforePost(ctx.body, context),
|
|
103
|
+
ctx.error,
|
|
104
|
+
"Unauthorized: Cannot post comment"
|
|
105
|
+
);
|
|
106
|
+
const status = options?.autoApprove ? "approved" : "pending";
|
|
107
|
+
const comment = await mutations.createComment(adapter, {
|
|
108
|
+
...ctx.body,
|
|
109
|
+
authorId,
|
|
110
|
+
status
|
|
111
|
+
});
|
|
112
|
+
if (options?.onAfterPost) {
|
|
113
|
+
await options.onAfterPost(comment, context);
|
|
114
|
+
}
|
|
115
|
+
const serialized = await getters.getCommentById(
|
|
116
|
+
adapter,
|
|
117
|
+
comment.id,
|
|
118
|
+
options?.resolveUser
|
|
119
|
+
);
|
|
120
|
+
if (!serialized) {
|
|
121
|
+
throw ctx.error(500, {
|
|
122
|
+
message: "Failed to retrieve created comment"
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
return serialized;
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
const updateCommentEndpoint = api.createEndpoint(
|
|
129
|
+
"/comments/:id",
|
|
130
|
+
{
|
|
131
|
+
method: "PATCH",
|
|
132
|
+
body: schemas.updateCommentSchema
|
|
133
|
+
},
|
|
134
|
+
async (ctx) => {
|
|
135
|
+
if (!editingEnabled) {
|
|
136
|
+
throw ctx.error(403, { message: "Editing comments is disabled" });
|
|
137
|
+
}
|
|
138
|
+
const { id } = ctx.params;
|
|
139
|
+
const context = {
|
|
140
|
+
params: ctx.params,
|
|
141
|
+
body: ctx.body,
|
|
142
|
+
headers: ctx.headers
|
|
143
|
+
};
|
|
144
|
+
if (!options?.onBeforeEdit) {
|
|
145
|
+
throw ctx.error(403, {
|
|
146
|
+
message: "Forbidden: editing comments requires the onBeforeEdit hook"
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
await utils.runHookWithShim(
|
|
150
|
+
() => options.onBeforeEdit(id, { body: ctx.body.body }, context),
|
|
151
|
+
ctx.error,
|
|
152
|
+
"Unauthorized: Cannot edit comment"
|
|
153
|
+
);
|
|
154
|
+
const updated = await mutations.updateComment(adapter, id, ctx.body.body);
|
|
155
|
+
if (!updated) {
|
|
156
|
+
throw ctx.error(404, { message: "Comment not found" });
|
|
157
|
+
}
|
|
158
|
+
if (options?.onAfterEdit) {
|
|
159
|
+
await options.onAfterEdit(updated, context);
|
|
160
|
+
}
|
|
161
|
+
const serialized = await getters.getCommentById(
|
|
162
|
+
adapter,
|
|
163
|
+
updated.id,
|
|
164
|
+
options?.resolveUser
|
|
165
|
+
);
|
|
166
|
+
if (!serialized) {
|
|
167
|
+
throw ctx.error(500, {
|
|
168
|
+
message: "Failed to retrieve updated comment"
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
return serialized;
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
const getCommentCountEndpoint = api.createEndpoint(
|
|
175
|
+
"/comments/count",
|
|
176
|
+
{
|
|
177
|
+
method: "GET",
|
|
178
|
+
query: schemas.CommentCountQuerySchema
|
|
179
|
+
},
|
|
180
|
+
async (ctx) => {
|
|
181
|
+
const context = {
|
|
182
|
+
query: ctx.query,
|
|
183
|
+
headers: ctx.headers
|
|
184
|
+
};
|
|
185
|
+
if (ctx.query.status && ctx.query.status !== "approved") {
|
|
186
|
+
if (!options?.onBeforeList) {
|
|
187
|
+
throw ctx.error(403, {
|
|
188
|
+
message: "Forbidden: status filter requires authorization"
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
await utils.runHookWithShim(
|
|
192
|
+
() => options.onBeforeList(
|
|
193
|
+
{ ...ctx.query, status: ctx.query.status },
|
|
194
|
+
context
|
|
195
|
+
),
|
|
196
|
+
ctx.error,
|
|
197
|
+
"Forbidden: Cannot count comments with this status filter"
|
|
198
|
+
);
|
|
199
|
+
} else if (options?.onBeforeList) {
|
|
200
|
+
await utils.runHookWithShim(
|
|
201
|
+
() => options.onBeforeList(
|
|
202
|
+
{ ...ctx.query, status: ctx.query.status },
|
|
203
|
+
context
|
|
204
|
+
),
|
|
205
|
+
ctx.error,
|
|
206
|
+
"Forbidden: Cannot count comments"
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
const count = await getters.getCommentCount(adapter, ctx.query);
|
|
210
|
+
return { count };
|
|
211
|
+
}
|
|
212
|
+
);
|
|
213
|
+
const toggleLikeEndpoint = api.createEndpoint(
|
|
214
|
+
"/comments/:id/like",
|
|
215
|
+
{
|
|
216
|
+
method: "POST",
|
|
217
|
+
body: z.z.object({ authorId: z.z.string().min(1) })
|
|
218
|
+
},
|
|
219
|
+
async (ctx) => {
|
|
220
|
+
const { id } = ctx.params;
|
|
221
|
+
const context = {
|
|
222
|
+
params: ctx.params,
|
|
223
|
+
body: ctx.body,
|
|
224
|
+
headers: ctx.headers
|
|
225
|
+
};
|
|
226
|
+
if (!options?.onBeforeLike) {
|
|
227
|
+
throw ctx.error(403, {
|
|
228
|
+
message: "Forbidden: toggling likes requires the onBeforeLike hook"
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
await utils.runHookWithShim(
|
|
232
|
+
() => options.onBeforeLike(id, ctx.body.authorId, context),
|
|
233
|
+
ctx.error,
|
|
234
|
+
"Unauthorized: Cannot like comment"
|
|
235
|
+
);
|
|
236
|
+
const result = await mutations.toggleCommentLike(
|
|
237
|
+
adapter,
|
|
238
|
+
id,
|
|
239
|
+
ctx.body.authorId
|
|
240
|
+
);
|
|
241
|
+
return result;
|
|
242
|
+
}
|
|
243
|
+
);
|
|
244
|
+
const updateStatusEndpoint = api.createEndpoint(
|
|
245
|
+
"/comments/:id/status",
|
|
246
|
+
{
|
|
247
|
+
method: "PATCH",
|
|
248
|
+
body: schemas.updateCommentStatusSchema
|
|
249
|
+
},
|
|
250
|
+
async (ctx) => {
|
|
251
|
+
const { id } = ctx.params;
|
|
252
|
+
const context = {
|
|
253
|
+
params: ctx.params,
|
|
254
|
+
body: ctx.body,
|
|
255
|
+
headers: ctx.headers
|
|
256
|
+
};
|
|
257
|
+
if (!options?.onBeforeStatusChange) {
|
|
258
|
+
throw ctx.error(403, {
|
|
259
|
+
message: "Forbidden: changing comment status requires the onBeforeStatusChange hook"
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
await utils.runHookWithShim(
|
|
263
|
+
() => options.onBeforeStatusChange(id, ctx.body.status, context),
|
|
264
|
+
ctx.error,
|
|
265
|
+
"Unauthorized: Cannot change comment status"
|
|
266
|
+
);
|
|
267
|
+
const updated = await mutations.updateCommentStatus(
|
|
268
|
+
adapter,
|
|
269
|
+
id,
|
|
270
|
+
ctx.body.status
|
|
271
|
+
);
|
|
272
|
+
if (!updated) {
|
|
273
|
+
throw ctx.error(404, { message: "Comment not found" });
|
|
274
|
+
}
|
|
275
|
+
if (ctx.body.status === "approved" && options?.onAfterApprove) {
|
|
276
|
+
await options.onAfterApprove(updated, context);
|
|
277
|
+
}
|
|
278
|
+
const serialized = await getters.getCommentById(
|
|
279
|
+
adapter,
|
|
280
|
+
updated.id,
|
|
281
|
+
options?.resolveUser
|
|
282
|
+
);
|
|
283
|
+
if (!serialized) {
|
|
284
|
+
throw ctx.error(500, {
|
|
285
|
+
message: "Failed to retrieve updated comment"
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
return serialized;
|
|
289
|
+
}
|
|
290
|
+
);
|
|
291
|
+
const deleteCommentEndpoint = api.createEndpoint(
|
|
292
|
+
"/comments/:id",
|
|
293
|
+
{
|
|
294
|
+
method: "DELETE"
|
|
295
|
+
},
|
|
296
|
+
async (ctx) => {
|
|
297
|
+
const { id } = ctx.params;
|
|
298
|
+
const context = {
|
|
299
|
+
params: ctx.params,
|
|
300
|
+
headers: ctx.headers
|
|
301
|
+
};
|
|
302
|
+
if (!options?.onBeforeDelete) {
|
|
303
|
+
throw ctx.error(403, {
|
|
304
|
+
message: "Forbidden: deleting comments requires the onBeforeDelete hook"
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
await utils.runHookWithShim(
|
|
308
|
+
() => options.onBeforeDelete(id, context),
|
|
309
|
+
ctx.error,
|
|
310
|
+
"Unauthorized: Cannot delete comment"
|
|
311
|
+
);
|
|
312
|
+
const deleted = await mutations.deleteComment(adapter, id);
|
|
313
|
+
if (!deleted) {
|
|
314
|
+
throw ctx.error(404, { message: "Comment not found" });
|
|
315
|
+
}
|
|
316
|
+
if (options?.onAfterDelete) {
|
|
317
|
+
await options.onAfterDelete(id, context);
|
|
318
|
+
}
|
|
319
|
+
return { success: true };
|
|
320
|
+
}
|
|
321
|
+
);
|
|
322
|
+
return {
|
|
323
|
+
listComments: listCommentsEndpoint,
|
|
324
|
+
...postingEnabled && { createComment: createCommentEndpoint },
|
|
325
|
+
...editingEnabled && { updateComment: updateCommentEndpoint },
|
|
326
|
+
getCommentCount: getCommentCountEndpoint,
|
|
327
|
+
toggleLike: toggleLikeEndpoint,
|
|
328
|
+
updateCommentStatus: updateStatusEndpoint,
|
|
329
|
+
deleteComment: deleteCommentEndpoint
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
exports.commentsBackendPlugin = commentsBackendPlugin;
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import { defineBackendPlugin, createEndpoint } from '@btst/stack/plugins/api';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { commentsSchema } from '../db.mjs';
|
|
4
|
+
import { CommentListQuerySchema, createCommentSchema, updateCommentSchema, CommentCountQuerySchema, updateCommentStatusSchema } from '../schemas.mjs';
|
|
5
|
+
import { getCommentCount, getCommentById, listComments } from './getters.mjs';
|
|
6
|
+
import { createComment, updateComment, toggleCommentLike, updateCommentStatus, deleteComment } from './mutations.mjs';
|
|
7
|
+
import { runHookWithShim } from '../../utils.mjs';
|
|
8
|
+
|
|
9
|
+
const commentsBackendPlugin = (options) => {
|
|
10
|
+
const postingEnabled = options.allowPosting !== false;
|
|
11
|
+
const editingEnabled = options.allowEditing !== false;
|
|
12
|
+
const onBeforePost = options.allowPosting !== false ? options.onBeforePost : void 0;
|
|
13
|
+
const resolveCurrentUserId = options.allowPosting !== false ? options.resolveCurrentUserId : void 0;
|
|
14
|
+
return defineBackendPlugin({
|
|
15
|
+
name: "comments",
|
|
16
|
+
dbPlugin: commentsSchema,
|
|
17
|
+
api: (adapter) => ({
|
|
18
|
+
listComments: (params) => listComments(adapter, params, options?.resolveUser),
|
|
19
|
+
getCommentById: (id, currentUserId) => getCommentById(adapter, id, options?.resolveUser, currentUserId),
|
|
20
|
+
getCommentCount: (params) => getCommentCount(adapter, params)
|
|
21
|
+
}),
|
|
22
|
+
routes: (adapter) => {
|
|
23
|
+
const listCommentsEndpoint = createEndpoint(
|
|
24
|
+
"/comments",
|
|
25
|
+
{
|
|
26
|
+
method: "GET",
|
|
27
|
+
query: CommentListQuerySchema
|
|
28
|
+
},
|
|
29
|
+
async (ctx) => {
|
|
30
|
+
const context = {
|
|
31
|
+
query: ctx.query,
|
|
32
|
+
request: ctx.request,
|
|
33
|
+
headers: ctx.headers
|
|
34
|
+
};
|
|
35
|
+
if (ctx.query.authorId) {
|
|
36
|
+
if (!options?.onBeforeListByAuthor) {
|
|
37
|
+
throw ctx.error(403, {
|
|
38
|
+
message: "Forbidden: authorId filter requires onBeforeListByAuthor hook"
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
await runHookWithShim(
|
|
42
|
+
() => options.onBeforeListByAuthor(
|
|
43
|
+
ctx.query.authorId,
|
|
44
|
+
ctx.query,
|
|
45
|
+
context
|
|
46
|
+
),
|
|
47
|
+
ctx.error,
|
|
48
|
+
"Forbidden: Cannot list comments for this author"
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
if (ctx.query.status && ctx.query.status !== "approved") {
|
|
52
|
+
if (!options?.onBeforeList) {
|
|
53
|
+
throw ctx.error(403, {
|
|
54
|
+
message: "Forbidden: status filter requires authorization"
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
await runHookWithShim(
|
|
58
|
+
() => options.onBeforeList(ctx.query, context),
|
|
59
|
+
ctx.error,
|
|
60
|
+
"Forbidden: Cannot list comments with this status filter"
|
|
61
|
+
);
|
|
62
|
+
} else if (options?.onBeforeList && !ctx.query.authorId) {
|
|
63
|
+
await runHookWithShim(
|
|
64
|
+
() => options.onBeforeList(ctx.query, context),
|
|
65
|
+
ctx.error,
|
|
66
|
+
"Forbidden: Cannot list comments"
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
let resolvedCurrentUserId;
|
|
70
|
+
if (resolveCurrentUserId) {
|
|
71
|
+
try {
|
|
72
|
+
const result = await resolveCurrentUserId(context);
|
|
73
|
+
resolvedCurrentUserId = result ?? void 0;
|
|
74
|
+
} catch {
|
|
75
|
+
resolvedCurrentUserId = void 0;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return await listComments(
|
|
79
|
+
adapter,
|
|
80
|
+
{ ...ctx.query, currentUserId: resolvedCurrentUserId },
|
|
81
|
+
options?.resolveUser
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
const createCommentEndpoint = createEndpoint(
|
|
86
|
+
"/comments",
|
|
87
|
+
{
|
|
88
|
+
method: "POST",
|
|
89
|
+
body: createCommentSchema
|
|
90
|
+
},
|
|
91
|
+
async (ctx) => {
|
|
92
|
+
if (!postingEnabled) {
|
|
93
|
+
throw ctx.error(403, { message: "Posting comments is disabled" });
|
|
94
|
+
}
|
|
95
|
+
const context = {
|
|
96
|
+
body: ctx.body,
|
|
97
|
+
headers: ctx.headers
|
|
98
|
+
};
|
|
99
|
+
const { authorId } = await runHookWithShim(
|
|
100
|
+
() => onBeforePost(ctx.body, context),
|
|
101
|
+
ctx.error,
|
|
102
|
+
"Unauthorized: Cannot post comment"
|
|
103
|
+
);
|
|
104
|
+
const status = options?.autoApprove ? "approved" : "pending";
|
|
105
|
+
const comment = await createComment(adapter, {
|
|
106
|
+
...ctx.body,
|
|
107
|
+
authorId,
|
|
108
|
+
status
|
|
109
|
+
});
|
|
110
|
+
if (options?.onAfterPost) {
|
|
111
|
+
await options.onAfterPost(comment, context);
|
|
112
|
+
}
|
|
113
|
+
const serialized = await getCommentById(
|
|
114
|
+
adapter,
|
|
115
|
+
comment.id,
|
|
116
|
+
options?.resolveUser
|
|
117
|
+
);
|
|
118
|
+
if (!serialized) {
|
|
119
|
+
throw ctx.error(500, {
|
|
120
|
+
message: "Failed to retrieve created comment"
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return serialized;
|
|
124
|
+
}
|
|
125
|
+
);
|
|
126
|
+
const updateCommentEndpoint = createEndpoint(
|
|
127
|
+
"/comments/:id",
|
|
128
|
+
{
|
|
129
|
+
method: "PATCH",
|
|
130
|
+
body: updateCommentSchema
|
|
131
|
+
},
|
|
132
|
+
async (ctx) => {
|
|
133
|
+
if (!editingEnabled) {
|
|
134
|
+
throw ctx.error(403, { message: "Editing comments is disabled" });
|
|
135
|
+
}
|
|
136
|
+
const { id } = ctx.params;
|
|
137
|
+
const context = {
|
|
138
|
+
params: ctx.params,
|
|
139
|
+
body: ctx.body,
|
|
140
|
+
headers: ctx.headers
|
|
141
|
+
};
|
|
142
|
+
if (!options?.onBeforeEdit) {
|
|
143
|
+
throw ctx.error(403, {
|
|
144
|
+
message: "Forbidden: editing comments requires the onBeforeEdit hook"
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
await runHookWithShim(
|
|
148
|
+
() => options.onBeforeEdit(id, { body: ctx.body.body }, context),
|
|
149
|
+
ctx.error,
|
|
150
|
+
"Unauthorized: Cannot edit comment"
|
|
151
|
+
);
|
|
152
|
+
const updated = await updateComment(adapter, id, ctx.body.body);
|
|
153
|
+
if (!updated) {
|
|
154
|
+
throw ctx.error(404, { message: "Comment not found" });
|
|
155
|
+
}
|
|
156
|
+
if (options?.onAfterEdit) {
|
|
157
|
+
await options.onAfterEdit(updated, context);
|
|
158
|
+
}
|
|
159
|
+
const serialized = await getCommentById(
|
|
160
|
+
adapter,
|
|
161
|
+
updated.id,
|
|
162
|
+
options?.resolveUser
|
|
163
|
+
);
|
|
164
|
+
if (!serialized) {
|
|
165
|
+
throw ctx.error(500, {
|
|
166
|
+
message: "Failed to retrieve updated comment"
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
return serialized;
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
const getCommentCountEndpoint = createEndpoint(
|
|
173
|
+
"/comments/count",
|
|
174
|
+
{
|
|
175
|
+
method: "GET",
|
|
176
|
+
query: CommentCountQuerySchema
|
|
177
|
+
},
|
|
178
|
+
async (ctx) => {
|
|
179
|
+
const context = {
|
|
180
|
+
query: ctx.query,
|
|
181
|
+
headers: ctx.headers
|
|
182
|
+
};
|
|
183
|
+
if (ctx.query.status && ctx.query.status !== "approved") {
|
|
184
|
+
if (!options?.onBeforeList) {
|
|
185
|
+
throw ctx.error(403, {
|
|
186
|
+
message: "Forbidden: status filter requires authorization"
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
await runHookWithShim(
|
|
190
|
+
() => options.onBeforeList(
|
|
191
|
+
{ ...ctx.query, status: ctx.query.status },
|
|
192
|
+
context
|
|
193
|
+
),
|
|
194
|
+
ctx.error,
|
|
195
|
+
"Forbidden: Cannot count comments with this status filter"
|
|
196
|
+
);
|
|
197
|
+
} else if (options?.onBeforeList) {
|
|
198
|
+
await runHookWithShim(
|
|
199
|
+
() => options.onBeforeList(
|
|
200
|
+
{ ...ctx.query, status: ctx.query.status },
|
|
201
|
+
context
|
|
202
|
+
),
|
|
203
|
+
ctx.error,
|
|
204
|
+
"Forbidden: Cannot count comments"
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
const count = await getCommentCount(adapter, ctx.query);
|
|
208
|
+
return { count };
|
|
209
|
+
}
|
|
210
|
+
);
|
|
211
|
+
const toggleLikeEndpoint = createEndpoint(
|
|
212
|
+
"/comments/:id/like",
|
|
213
|
+
{
|
|
214
|
+
method: "POST",
|
|
215
|
+
body: z.object({ authorId: z.string().min(1) })
|
|
216
|
+
},
|
|
217
|
+
async (ctx) => {
|
|
218
|
+
const { id } = ctx.params;
|
|
219
|
+
const context = {
|
|
220
|
+
params: ctx.params,
|
|
221
|
+
body: ctx.body,
|
|
222
|
+
headers: ctx.headers
|
|
223
|
+
};
|
|
224
|
+
if (!options?.onBeforeLike) {
|
|
225
|
+
throw ctx.error(403, {
|
|
226
|
+
message: "Forbidden: toggling likes requires the onBeforeLike hook"
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
await runHookWithShim(
|
|
230
|
+
() => options.onBeforeLike(id, ctx.body.authorId, context),
|
|
231
|
+
ctx.error,
|
|
232
|
+
"Unauthorized: Cannot like comment"
|
|
233
|
+
);
|
|
234
|
+
const result = await toggleCommentLike(
|
|
235
|
+
adapter,
|
|
236
|
+
id,
|
|
237
|
+
ctx.body.authorId
|
|
238
|
+
);
|
|
239
|
+
return result;
|
|
240
|
+
}
|
|
241
|
+
);
|
|
242
|
+
const updateStatusEndpoint = createEndpoint(
|
|
243
|
+
"/comments/:id/status",
|
|
244
|
+
{
|
|
245
|
+
method: "PATCH",
|
|
246
|
+
body: updateCommentStatusSchema
|
|
247
|
+
},
|
|
248
|
+
async (ctx) => {
|
|
249
|
+
const { id } = ctx.params;
|
|
250
|
+
const context = {
|
|
251
|
+
params: ctx.params,
|
|
252
|
+
body: ctx.body,
|
|
253
|
+
headers: ctx.headers
|
|
254
|
+
};
|
|
255
|
+
if (!options?.onBeforeStatusChange) {
|
|
256
|
+
throw ctx.error(403, {
|
|
257
|
+
message: "Forbidden: changing comment status requires the onBeforeStatusChange hook"
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
await runHookWithShim(
|
|
261
|
+
() => options.onBeforeStatusChange(id, ctx.body.status, context),
|
|
262
|
+
ctx.error,
|
|
263
|
+
"Unauthorized: Cannot change comment status"
|
|
264
|
+
);
|
|
265
|
+
const updated = await updateCommentStatus(
|
|
266
|
+
adapter,
|
|
267
|
+
id,
|
|
268
|
+
ctx.body.status
|
|
269
|
+
);
|
|
270
|
+
if (!updated) {
|
|
271
|
+
throw ctx.error(404, { message: "Comment not found" });
|
|
272
|
+
}
|
|
273
|
+
if (ctx.body.status === "approved" && options?.onAfterApprove) {
|
|
274
|
+
await options.onAfterApprove(updated, context);
|
|
275
|
+
}
|
|
276
|
+
const serialized = await getCommentById(
|
|
277
|
+
adapter,
|
|
278
|
+
updated.id,
|
|
279
|
+
options?.resolveUser
|
|
280
|
+
);
|
|
281
|
+
if (!serialized) {
|
|
282
|
+
throw ctx.error(500, {
|
|
283
|
+
message: "Failed to retrieve updated comment"
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
return serialized;
|
|
287
|
+
}
|
|
288
|
+
);
|
|
289
|
+
const deleteCommentEndpoint = createEndpoint(
|
|
290
|
+
"/comments/:id",
|
|
291
|
+
{
|
|
292
|
+
method: "DELETE"
|
|
293
|
+
},
|
|
294
|
+
async (ctx) => {
|
|
295
|
+
const { id } = ctx.params;
|
|
296
|
+
const context = {
|
|
297
|
+
params: ctx.params,
|
|
298
|
+
headers: ctx.headers
|
|
299
|
+
};
|
|
300
|
+
if (!options?.onBeforeDelete) {
|
|
301
|
+
throw ctx.error(403, {
|
|
302
|
+
message: "Forbidden: deleting comments requires the onBeforeDelete hook"
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
await runHookWithShim(
|
|
306
|
+
() => options.onBeforeDelete(id, context),
|
|
307
|
+
ctx.error,
|
|
308
|
+
"Unauthorized: Cannot delete comment"
|
|
309
|
+
);
|
|
310
|
+
const deleted = await deleteComment(adapter, id);
|
|
311
|
+
if (!deleted) {
|
|
312
|
+
throw ctx.error(404, { message: "Comment not found" });
|
|
313
|
+
}
|
|
314
|
+
if (options?.onAfterDelete) {
|
|
315
|
+
await options.onAfterDelete(id, context);
|
|
316
|
+
}
|
|
317
|
+
return { success: true };
|
|
318
|
+
}
|
|
319
|
+
);
|
|
320
|
+
return {
|
|
321
|
+
listComments: listCommentsEndpoint,
|
|
322
|
+
...postingEnabled && { createComment: createCommentEndpoint },
|
|
323
|
+
...editingEnabled && { updateComment: updateCommentEndpoint },
|
|
324
|
+
getCommentCount: getCommentCountEndpoint,
|
|
325
|
+
toggleLike: toggleLikeEndpoint,
|
|
326
|
+
updateCommentStatus: updateStatusEndpoint,
|
|
327
|
+
deleteComment: deleteCommentEndpoint
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
export { commentsBackendPlugin };
|