@btst/stack 2.3.0 → 2.5.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/dist/packages/stack/src/client/components/compose.cjs +1 -2
- package/dist/packages/stack/src/client/components/compose.mjs +1 -2
- package/dist/packages/stack/src/plugins/ai-chat/api/page-tools.cjs +71 -0
- package/dist/packages/stack/src/plugins/ai-chat/api/page-tools.mjs +68 -0
- package/dist/packages/stack/src/plugins/ai-chat/api/plugin.cjs +87 -54
- package/dist/packages/stack/src/plugins/ai-chat/api/plugin.mjs +87 -54
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-input.cjs +2 -2
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-input.mjs +2 -2
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-interface.cjs +89 -22
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-interface.mjs +90 -23
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-layout.cjs +110 -33
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-layout.mjs +112 -35
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-sidebar.cjs +1 -1
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-sidebar.mjs +1 -1
- package/dist/packages/stack/src/plugins/ai-chat/client/plugin.cjs +14 -21
- package/dist/packages/stack/src/plugins/ai-chat/client/plugin.mjs +15 -22
- package/dist/packages/stack/src/plugins/ai-chat/schemas.cjs +17 -1
- package/dist/packages/stack/src/plugins/ai-chat/schemas.mjs +17 -1
- package/dist/packages/stack/src/plugins/blog/api/plugin.cjs +28 -45
- package/dist/packages/stack/src/plugins/blog/api/plugin.mjs +22 -39
- package/dist/packages/stack/src/plugins/blog/client/components/forms/post-forms.cjs +15 -2
- package/dist/packages/stack/src/plugins/blog/client/components/forms/post-forms.mjs +16 -3
- package/dist/packages/stack/src/plugins/blog/client/components/pages/edit-post-page.internal.cjs +24 -1
- package/dist/packages/stack/src/plugins/blog/client/components/pages/edit-post-page.internal.mjs +24 -1
- package/dist/packages/stack/src/plugins/blog/client/components/pages/fill-blog-form-handler.cjs +26 -0
- package/dist/packages/stack/src/plugins/blog/client/components/pages/fill-blog-form-handler.mjs +24 -0
- package/dist/packages/stack/src/plugins/blog/client/components/pages/new-post-page.internal.cjs +30 -1
- package/dist/packages/stack/src/plugins/blog/client/components/pages/new-post-page.internal.mjs +30 -1
- package/dist/packages/stack/src/plugins/blog/client/components/pages/post-page.internal.cjs +18 -0
- package/dist/packages/stack/src/plugins/blog/client/components/pages/post-page.internal.mjs +18 -0
- package/dist/packages/stack/src/plugins/blog/client/plugin.cjs +23 -27
- package/dist/packages/stack/src/plugins/blog/client/plugin.mjs +24 -28
- package/dist/packages/stack/src/plugins/cms/api/mutations.cjs +48 -0
- package/dist/packages/stack/src/plugins/cms/api/mutations.mjs +46 -0
- package/dist/packages/stack/src/plugins/cms/api/plugin.cjs +21 -18
- package/dist/packages/stack/src/plugins/cms/api/plugin.mjs +21 -18
- package/dist/packages/stack/src/plugins/cms/client/plugin.cjs +11 -15
- package/dist/packages/stack/src/plugins/cms/client/plugin.mjs +12 -16
- package/dist/packages/stack/src/plugins/form-builder/api/plugin.cjs +58 -62
- package/dist/packages/stack/src/plugins/form-builder/api/plugin.mjs +58 -62
- package/dist/packages/stack/src/plugins/form-builder/client/plugin.cjs +12 -12
- package/dist/packages/stack/src/plugins/form-builder/client/plugin.mjs +13 -13
- package/dist/packages/stack/src/plugins/kanban/api/mutations.cjs +91 -0
- package/dist/packages/stack/src/plugins/kanban/api/mutations.mjs +87 -0
- package/dist/packages/stack/src/plugins/kanban/api/plugin.cjs +92 -118
- package/dist/packages/stack/src/plugins/kanban/api/plugin.mjs +89 -115
- package/dist/packages/stack/src/plugins/kanban/client/hooks/kanban-hooks.cjs +7 -3
- package/dist/packages/stack/src/plugins/kanban/client/hooks/kanban-hooks.mjs +7 -3
- package/dist/packages/stack/src/plugins/kanban/client/plugin.cjs +22 -29
- package/dist/packages/stack/src/plugins/kanban/client/plugin.mjs +23 -30
- package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.cjs +89 -0
- package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.mjs +89 -0
- package/dist/packages/stack/src/plugins/ui-builder/client/plugin.cjs +8 -8
- package/dist/packages/stack/src/plugins/ui-builder/client/plugin.mjs +9 -9
- package/dist/packages/stack/src/plugins/utils.cjs +42 -0
- package/dist/packages/stack/src/plugins/utils.mjs +41 -1
- package/dist/plugins/ai-chat/api/index.d.cts +1 -1
- package/dist/plugins/ai-chat/api/index.d.mts +1 -1
- package/dist/plugins/ai-chat/api/index.d.ts +1 -1
- package/dist/plugins/ai-chat/client/components/index.d.cts +1 -1
- package/dist/plugins/ai-chat/client/components/index.d.mts +1 -1
- package/dist/plugins/ai-chat/client/components/index.d.ts +1 -1
- package/dist/plugins/ai-chat/client/context/page-ai-context.cjs +92 -0
- package/dist/plugins/ai-chat/client/context/page-ai-context.d.cts +84 -0
- package/dist/plugins/ai-chat/client/context/page-ai-context.d.mts +84 -0
- package/dist/plugins/ai-chat/client/context/page-ai-context.d.ts +84 -0
- package/dist/plugins/ai-chat/client/context/page-ai-context.mjs +88 -0
- package/dist/plugins/ai-chat/client/hooks/index.d.cts +1 -1
- package/dist/plugins/ai-chat/client/hooks/index.d.mts +1 -1
- package/dist/plugins/ai-chat/client/hooks/index.d.ts +1 -1
- package/dist/plugins/ai-chat/client/index.d.cts +10 -10
- package/dist/plugins/ai-chat/client/index.d.mts +10 -10
- package/dist/plugins/ai-chat/client/index.d.ts +10 -10
- package/dist/plugins/ai-chat/query-keys.d.cts +1 -1
- package/dist/plugins/ai-chat/query-keys.d.mts +1 -1
- package/dist/plugins/ai-chat/query-keys.d.ts +1 -1
- package/dist/plugins/blog/api/index.d.cts +2 -2
- package/dist/plugins/blog/api/index.d.mts +2 -2
- package/dist/plugins/blog/api/index.d.ts +2 -2
- 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 +13 -13
- package/dist/plugins/blog/client/index.d.mts +13 -13
- package/dist/plugins/blog/client/index.d.ts +13 -13
- package/dist/plugins/blog/query-keys.d.cts +2 -2
- package/dist/plugins/blog/query-keys.d.mts +2 -2
- package/dist/plugins/blog/query-keys.d.ts +2 -2
- package/dist/plugins/client/index.cjs +1 -0
- package/dist/plugins/client/index.d.cts +8 -1
- package/dist/plugins/client/index.d.mts +8 -1
- package/dist/plugins/client/index.d.ts +8 -1
- package/dist/plugins/client/index.mjs +1 -1
- package/dist/plugins/cms/api/index.cjs +2 -0
- package/dist/plugins/cms/api/index.d.cts +2 -2
- package/dist/plugins/cms/api/index.d.mts +2 -2
- package/dist/plugins/cms/api/index.d.ts +2 -2
- package/dist/plugins/cms/api/index.mjs +1 -0
- package/dist/plugins/cms/client/hooks/index.d.cts +1 -1
- package/dist/plugins/cms/client/hooks/index.d.mts +1 -1
- package/dist/plugins/cms/client/hooks/index.d.ts +1 -1
- package/dist/plugins/cms/client/index.d.cts +6 -6
- package/dist/plugins/cms/client/index.d.mts +6 -6
- package/dist/plugins/cms/client/index.d.ts +6 -6
- package/dist/plugins/cms/query-keys.d.cts +2 -2
- package/dist/plugins/cms/query-keys.d.mts +2 -2
- package/dist/plugins/cms/query-keys.d.ts +2 -2
- 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/hooks/index.d.cts +1 -1
- package/dist/plugins/form-builder/client/hooks/index.d.mts +1 -1
- package/dist/plugins/form-builder/client/hooks/index.d.ts +1 -1
- package/dist/plugins/form-builder/client/index.d.cts +6 -6
- package/dist/plugins/form-builder/client/index.d.mts +6 -6
- package/dist/plugins/form-builder/client/index.d.ts +6 -6
- package/dist/plugins/form-builder/query-keys.d.cts +2 -2
- package/dist/plugins/form-builder/query-keys.d.mts +2 -2
- package/dist/plugins/form-builder/query-keys.d.ts +2 -2
- package/dist/plugins/kanban/api/index.cjs +4 -0
- package/dist/plugins/kanban/api/index.d.cts +1 -1
- package/dist/plugins/kanban/api/index.d.mts +1 -1
- package/dist/plugins/kanban/api/index.d.ts +1 -1
- package/dist/plugins/kanban/api/index.mjs +1 -0
- package/dist/plugins/kanban/client/index.d.cts +12 -12
- package/dist/plugins/kanban/client/index.d.mts +12 -12
- package/dist/plugins/kanban/client/index.d.ts +12 -12
- package/dist/plugins/kanban/query-keys.d.cts +1 -1
- package/dist/plugins/kanban/query-keys.d.mts +1 -1
- package/dist/plugins/kanban/query-keys.d.ts +1 -1
- package/dist/plugins/ui-builder/client/hooks/index.d.cts +1 -1
- package/dist/plugins/ui-builder/client/hooks/index.d.mts +1 -1
- package/dist/plugins/ui-builder/client/hooks/index.d.ts +1 -1
- 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 +2 -2
- package/dist/plugins/ui-builder/index.d.mts +2 -2
- package/dist/plugins/ui-builder/index.d.ts +2 -2
- package/dist/shared/{stack.C-WUPMT6.d.cts → stack.B2xZTSiO.d.cts} +4 -4
- package/dist/shared/{stack.B1EeBt1b.d.ts → stack.B58oHdqm.d.mts} +33 -3
- package/dist/shared/{stack.CVDTkMoO.d.mts → stack.B8QD11QU.d.cts} +7 -7
- package/dist/shared/{stack.CVDTkMoO.d.cts → stack.B8QD11QU.d.mts} +7 -7
- package/dist/shared/{stack.CVDTkMoO.d.ts → stack.B8QD11QU.d.ts} +7 -7
- package/dist/shared/{stack.CIP6QS9l.d.ts → stack.BDVEpue1.d.ts} +1 -1
- package/dist/shared/{stack.C5dtIncc.d.mts → stack.BTvbxZvw.d.cts} +1 -1
- package/dist/shared/{stack.DaOcgmrM.d.ts → stack.BV9hnvu4.d.cts} +31 -7
- package/dist/shared/{stack.DaOcgmrM.d.cts → stack.BV9hnvu4.d.mts} +31 -7
- package/dist/shared/{stack.DaOcgmrM.d.mts → stack.BV9hnvu4.d.ts} +31 -7
- package/dist/shared/{stack.DdI5W6MB.d.mts → stack.BozPgbrZ.d.cts} +19 -19
- package/dist/shared/{stack.DdI5W6MB.d.ts → stack.BozPgbrZ.d.mts} +19 -19
- package/dist/shared/{stack.DdI5W6MB.d.cts → stack.BozPgbrZ.d.ts} +19 -19
- package/dist/shared/{stack.CP68pFEH.d.mts → stack.C9Mg2Q46.d.cts} +33 -3
- package/dist/shared/{stack.BeSm90va.d.ts → stack.CTDVxbrA.d.ts} +72 -14
- package/dist/shared/{stack.C-Ptrz8s.d.ts → stack.Cj_zKww4.d.ts} +4 -4
- package/dist/shared/{stack.TIBF2AOx.d.ts → stack.CxaFNQCV.d.mts} +89 -34
- package/dist/shared/{stack.CMh_EdxW.d.cts → stack.D-b5zbPm.d.cts} +72 -14
- package/dist/shared/{stack.Dw0Ly2TM.d.cts → stack.DTtmJPQO.d.mts} +1 -1
- package/dist/shared/{stack.BKfolAyK.d.ts → stack.DXnclTG7.d.ts} +11 -11
- package/dist/shared/{stack.snB1EDP7.d.cts → stack.DaZM10cp.d.cts} +11 -11
- package/dist/shared/{stack.Dg09R0oB.d.mts → stack.FVWf2JhZ.d.mts} +72 -14
- package/dist/shared/{stack.BIXEI6v_.d.mts → stack.cfCkioTe.d.mts} +11 -11
- package/dist/shared/{stack.6fUOjLs9.d.mts → stack.dH7u-TJH.d.mts} +4 -4
- package/dist/shared/{stack.BpolpQpf.d.cts → stack.j75TpKh2.d.ts} +89 -34
- package/dist/shared/{stack.rTy7-wQU.d.mts → stack.n1_i1p2B.d.cts} +89 -34
- package/dist/shared/{stack.IdtKDRka.d.cts → stack.sO33ZDhK.d.ts} +33 -3
- package/package.json +14 -1
- package/src/client/components/compose.tsx +7 -4
- package/src/plugins/ai-chat/api/page-tools.ts +111 -0
- package/src/plugins/ai-chat/api/plugin.ts +228 -72
- package/src/plugins/ai-chat/client/components/chat-input.tsx +2 -2
- package/src/plugins/ai-chat/client/components/chat-interface.tsx +154 -58
- package/src/plugins/ai-chat/client/components/chat-layout.tsx +166 -32
- package/src/plugins/ai-chat/client/components/chat-sidebar.tsx +1 -1
- package/src/plugins/ai-chat/client/context/page-ai-context.tsx +240 -0
- package/src/plugins/ai-chat/client/plugin.tsx +23 -31
- package/src/plugins/ai-chat/schemas.ts +16 -0
- package/src/plugins/blog/api/plugin.ts +31 -47
- package/src/plugins/blog/client/components/forms/post-forms.tsx +29 -2
- package/src/plugins/blog/client/components/pages/edit-post-page.internal.tsx +28 -0
- package/src/plugins/blog/client/components/pages/fill-blog-form-handler.ts +38 -0
- package/src/plugins/blog/client/components/pages/new-post-page.internal.tsx +33 -1
- package/src/plugins/blog/client/components/pages/post-page.internal.tsx +20 -0
- package/src/plugins/blog/client/plugin.tsx +36 -39
- package/src/plugins/client/index.ts +5 -1
- package/src/plugins/cms/api/index.ts +4 -0
- package/src/plugins/cms/api/mutations.ts +84 -0
- package/src/plugins/cms/api/plugin.ts +23 -17
- package/src/plugins/cms/client/plugin.tsx +18 -21
- package/src/plugins/cms/types.ts +7 -7
- package/src/plugins/form-builder/api/plugin.ts +64 -64
- package/src/plugins/form-builder/client/plugin.tsx +19 -18
- package/src/plugins/form-builder/types.ts +19 -24
- package/src/plugins/kanban/api/index.ts +6 -0
- package/src/plugins/kanban/api/mutations.ts +169 -0
- package/src/plugins/kanban/api/plugin.ts +123 -136
- package/src/plugins/kanban/client/hooks/kanban-hooks.tsx +4 -0
- package/src/plugins/kanban/client/plugin.tsx +35 -41
- package/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.tsx +132 -0
- package/src/plugins/ui-builder/client/plugin.tsx +11 -10
- package/src/plugins/ui-builder/types.ts +4 -4
- package/src/plugins/utils.ts +92 -1
- package/dist/shared/{stack.CBON0dWL.d.mts → stack.BQmuNl5p.d.cts} +2 -2
- package/dist/shared/{stack.CBON0dWL.d.ts → stack.BQmuNl5p.d.mts} +2 -2
- package/dist/shared/{stack.CBON0dWL.d.cts → stack.BQmuNl5p.d.ts} +2 -2
|
@@ -1,27 +1,37 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import { useState, useCallback } from 'react';
|
|
4
4
|
import { Button } from '../../../../../../ui/src/components/button.mjs';
|
|
5
|
+
import { Badge } from '../../../../../../ui/src/components/badge.mjs';
|
|
5
6
|
import { Sheet, SheetTrigger, SheetContent } from '../../../../../../ui/src/components/sheet.mjs';
|
|
6
|
-
import { Menu, PanelLeftClose, PanelLeft } from 'lucide-react';
|
|
7
|
+
import { Sparkles, Trash2, X, Menu, PanelLeftClose, PanelLeft } from 'lucide-react';
|
|
7
8
|
import { cn } from '../../../../../../ui/src/lib/utils.mjs';
|
|
8
9
|
import { ChatSidebar } from './chat-sidebar.mjs';
|
|
9
10
|
import { ChatInterface } from './chat-interface.mjs';
|
|
11
|
+
import { usePageAIContext } from '../../../../../../../plugins/ai-chat/client/context/page-ai-context.mjs';
|
|
10
12
|
|
|
11
|
-
function ChatLayout({
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
13
|
+
function ChatLayout(props) {
|
|
14
|
+
const {
|
|
15
|
+
apiBaseURL,
|
|
16
|
+
apiBasePath,
|
|
17
|
+
conversationId,
|
|
18
|
+
layout = "full",
|
|
19
|
+
className,
|
|
20
|
+
showSidebar = true,
|
|
21
|
+
initialMessages,
|
|
22
|
+
onMessagesChange
|
|
23
|
+
} = props;
|
|
24
|
+
const widgetHeight = props.layout === "widget" ? props.widgetHeight ?? "600px" : "600px";
|
|
25
|
+
const widgetWidth = props.layout === "widget" ? props.widgetWidth ?? "380px" : "380px";
|
|
26
|
+
const defaultOpen = props.layout === "widget" ? props.defaultOpen ?? false : false;
|
|
27
|
+
const showTrigger = props.layout === "widget" ? props.showTrigger ?? true : true;
|
|
22
28
|
const [sidebarOpen, setSidebarOpen] = useState(true);
|
|
23
29
|
const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
|
|
24
30
|
const [chatResetKey, setChatResetKey] = useState(0);
|
|
31
|
+
const [widgetOpen, setWidgetOpen] = useState(defaultOpen);
|
|
32
|
+
const [widgetResetKey, setWidgetResetKey] = useState(0);
|
|
33
|
+
const [widgetEverOpened, setWidgetEverOpened] = useState(defaultOpen);
|
|
34
|
+
const pageAIContext = usePageAIContext();
|
|
25
35
|
const apiPath = `${apiBaseURL}${apiBasePath}/chat`;
|
|
26
36
|
const handleNewChat = useCallback(() => {
|
|
27
37
|
if (!conversationId) {
|
|
@@ -29,26 +39,81 @@ function ChatLayout({
|
|
|
29
39
|
}
|
|
30
40
|
}, [conversationId]);
|
|
31
41
|
if (layout === "widget") {
|
|
32
|
-
return /* @__PURE__ */
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
42
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col items-end gap-3", className), children: [
|
|
43
|
+
/* @__PURE__ */ jsxs(
|
|
44
|
+
"div",
|
|
45
|
+
{
|
|
46
|
+
className: cn(
|
|
47
|
+
"flex flex-col border rounded-xl overflow-hidden bg-background shadow-xl",
|
|
48
|
+
widgetOpen ? "flex" : "hidden"
|
|
49
|
+
),
|
|
50
|
+
style: { height: widgetHeight, width: widgetWidth },
|
|
51
|
+
children: [
|
|
52
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 px-3 py-1.5 border-b bg-muted/40", children: [
|
|
53
|
+
/* @__PURE__ */ jsx(Sparkles, { className: "h-3 w-3 text-muted-foreground" }),
|
|
54
|
+
pageAIContext ? /* @__PURE__ */ jsx(
|
|
55
|
+
Badge,
|
|
56
|
+
{
|
|
57
|
+
variant: "secondary",
|
|
58
|
+
className: "text-xs",
|
|
59
|
+
"data-testid": "page-context-badge",
|
|
60
|
+
children: pageAIContext.routeName
|
|
61
|
+
}
|
|
62
|
+
) : /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground font-medium", children: "AI Chat" }),
|
|
63
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
64
|
+
/* @__PURE__ */ jsx(
|
|
65
|
+
Button,
|
|
66
|
+
{
|
|
67
|
+
variant: "ghost",
|
|
68
|
+
size: "icon",
|
|
69
|
+
className: "h-5 w-5",
|
|
70
|
+
onClick: () => setWidgetResetKey((prev) => prev + 1),
|
|
71
|
+
"aria-label": "Clear chat",
|
|
72
|
+
title: "Clear chat",
|
|
73
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5" })
|
|
74
|
+
}
|
|
75
|
+
),
|
|
76
|
+
/* @__PURE__ */ jsx(
|
|
77
|
+
Button,
|
|
78
|
+
{
|
|
79
|
+
variant: "ghost",
|
|
80
|
+
size: "icon",
|
|
81
|
+
className: "h-5 w-5",
|
|
82
|
+
onClick: () => setWidgetOpen(false),
|
|
83
|
+
"aria-label": "Close chat",
|
|
84
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" })
|
|
85
|
+
}
|
|
86
|
+
)
|
|
87
|
+
] }),
|
|
88
|
+
widgetEverOpened && /* @__PURE__ */ jsx(
|
|
89
|
+
ChatInterface,
|
|
90
|
+
{
|
|
91
|
+
apiPath,
|
|
92
|
+
id: conversationId,
|
|
93
|
+
variant: "widget",
|
|
94
|
+
initialMessages,
|
|
95
|
+
onMessagesChange
|
|
96
|
+
},
|
|
97
|
+
`widget-${conversationId ?? "new"}-${widgetResetKey}`
|
|
98
|
+
)
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
),
|
|
102
|
+
showTrigger && /* @__PURE__ */ jsx(
|
|
103
|
+
Button,
|
|
104
|
+
{
|
|
105
|
+
size: "icon",
|
|
106
|
+
className: "h-12 w-12 rounded-full shadow-lg",
|
|
107
|
+
onClick: () => {
|
|
108
|
+
setWidgetOpen((prev) => !prev);
|
|
109
|
+
setWidgetEverOpened(true);
|
|
110
|
+
},
|
|
111
|
+
"aria-label": widgetOpen ? "Close chat" : "Open chat",
|
|
112
|
+
"data-testid": "widget-trigger",
|
|
113
|
+
children: widgetOpen ? /* @__PURE__ */ jsx(X, { className: "h-5 w-5" }) : /* @__PURE__ */ jsx(Sparkles, { className: "h-5 w-5" })
|
|
114
|
+
}
|
|
115
|
+
)
|
|
116
|
+
] });
|
|
52
117
|
}
|
|
53
118
|
return /* @__PURE__ */ jsxs(
|
|
54
119
|
"div",
|
|
@@ -77,7 +142,7 @@ function ChatLayout({
|
|
|
77
142
|
}
|
|
78
143
|
),
|
|
79
144
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col min-w-0", children: [
|
|
80
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 p-2 border-b bg-background/95 backdrop-blur supports-
|
|
145
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 p-2 border-b bg-background/95 backdrop-blur supports-backdrop-filter:bg-background/60", children: [
|
|
81
146
|
showSidebar && /* @__PURE__ */ jsxs(Sheet, { open: mobileSidebarOpen, onOpenChange: setMobileSidebarOpen, children: [
|
|
82
147
|
/* @__PURE__ */ jsx(SheetTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
83
148
|
Button,
|
|
@@ -111,7 +176,19 @@ function ChatLayout({
|
|
|
111
176
|
children: sidebarOpen ? /* @__PURE__ */ jsx(PanelLeftClose, { className: "h-5 w-5" }) : /* @__PURE__ */ jsx(PanelLeft, { className: "h-5 w-5" })
|
|
112
177
|
}
|
|
113
178
|
),
|
|
114
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1" })
|
|
179
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
180
|
+
pageAIContext && /* @__PURE__ */ jsxs(
|
|
181
|
+
Badge,
|
|
182
|
+
{
|
|
183
|
+
variant: "secondary",
|
|
184
|
+
className: "text-xs gap-1 mr-2",
|
|
185
|
+
"data-testid": "page-context-badge",
|
|
186
|
+
children: [
|
|
187
|
+
/* @__PURE__ */ jsx(Sparkles, { className: "h-3 w-3" }),
|
|
188
|
+
pageAIContext.routeName
|
|
189
|
+
]
|
|
190
|
+
}
|
|
191
|
+
)
|
|
115
192
|
] }),
|
|
116
193
|
/* @__PURE__ */ jsx(
|
|
117
194
|
ChatInterface,
|
|
@@ -108,7 +108,7 @@ function ChatSidebar({
|
|
|
108
108
|
]
|
|
109
109
|
}
|
|
110
110
|
) }),
|
|
111
|
-
/* @__PURE__ */ jsxRuntime.jsx(scrollArea.ScrollArea, { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2", children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 text-center text-sm text-muted-foreground", children: localization.CHAT_LOADING }) : conversations.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 text-center text-sm text-muted-foreground", children: localization.SIDEBAR_NO_CONVERSATIONS }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1", children: conversations.map((conversation) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
111
|
+
/* @__PURE__ */ jsxRuntime.jsx(scrollArea.ScrollArea, { className: "flex-1 [&_[data-slot=scroll-area-viewport]>div]:!block", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2", children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 text-center text-sm text-muted-foreground", children: localization.CHAT_LOADING }) : conversations.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 text-center text-sm text-muted-foreground", children: localization.SIDEBAR_NO_CONVERSATIONS }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1", children: conversations.map((conversation) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
112
112
|
"div",
|
|
113
113
|
{
|
|
114
114
|
className: utils.cn(
|
|
@@ -106,7 +106,7 @@ function ChatSidebar({
|
|
|
106
106
|
]
|
|
107
107
|
}
|
|
108
108
|
) }),
|
|
109
|
-
/* @__PURE__ */ jsx(ScrollArea, { className: "flex-1", children: /* @__PURE__ */ jsx("div", { className: "p-2", children: isLoading ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-sm text-muted-foreground", children: localization.CHAT_LOADING }) : conversations.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-sm text-muted-foreground", children: localization.SIDEBAR_NO_CONVERSATIONS }) : /* @__PURE__ */ jsx("div", { className: "space-y-1", children: conversations.map((conversation) => /* @__PURE__ */ jsxs(
|
|
109
|
+
/* @__PURE__ */ jsx(ScrollArea, { className: "flex-1 [&_[data-slot=scroll-area-viewport]>div]:!block", children: /* @__PURE__ */ jsx("div", { className: "p-2", children: isLoading ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-sm text-muted-foreground", children: localization.CHAT_LOADING }) : conversations.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-sm text-muted-foreground", children: localization.SIDEBAR_NO_CONVERSATIONS }) : /* @__PURE__ */ jsx("div", { className: "space-y-1", children: conversations.map((conversation) => /* @__PURE__ */ jsxs(
|
|
110
110
|
"div",
|
|
111
111
|
{
|
|
112
112
|
className: cn(
|
|
@@ -22,10 +22,10 @@ function createConversationsLoader(config) {
|
|
|
22
22
|
};
|
|
23
23
|
try {
|
|
24
24
|
if (hooks?.beforeLoadConversations) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
await client.runClientHookWithShim(
|
|
26
|
+
() => hooks.beforeLoadConversations(context),
|
|
27
|
+
"Load prevented by beforeLoadConversations hook"
|
|
28
|
+
);
|
|
29
29
|
}
|
|
30
30
|
const client$1 = client.createApiClient({
|
|
31
31
|
baseURL: apiBaseURL,
|
|
@@ -38,13 +38,10 @@ function createConversationsLoader(config) {
|
|
|
38
38
|
const conversations = queryClient.getQueryData(
|
|
39
39
|
listQuery.queryKey
|
|
40
40
|
) || null;
|
|
41
|
-
|
|
42
|
-
conversations,
|
|
43
|
-
|
|
41
|
+
await client.runClientHookWithShim(
|
|
42
|
+
() => hooks.afterLoadConversations(conversations, context),
|
|
43
|
+
"Load prevented by afterLoadConversations hook"
|
|
44
44
|
);
|
|
45
|
-
if (canContinue === false) {
|
|
46
|
-
throw new Error("Load prevented by afterLoadConversations hook");
|
|
47
|
-
}
|
|
48
45
|
}
|
|
49
46
|
const queryState = queryClient.getQueryState(listQuery.queryKey);
|
|
50
47
|
if (queryState?.error && hooks?.onLoadError) {
|
|
@@ -73,10 +70,10 @@ function createConversationLoader(id, config) {
|
|
|
73
70
|
};
|
|
74
71
|
try {
|
|
75
72
|
if (hooks?.beforeLoadConversation) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
73
|
+
await client.runClientHookWithShim(
|
|
74
|
+
() => hooks.beforeLoadConversation(id, context),
|
|
75
|
+
"Load prevented by beforeLoadConversation hook"
|
|
76
|
+
);
|
|
80
77
|
}
|
|
81
78
|
const client$1 = client.createApiClient({
|
|
82
79
|
baseURL: apiBaseURL,
|
|
@@ -91,14 +88,10 @@ function createConversationLoader(id, config) {
|
|
|
91
88
|
]);
|
|
92
89
|
if (hooks?.afterLoadConversation) {
|
|
93
90
|
const conversation = queryClient.getQueryData(conversationQuery.queryKey) || null;
|
|
94
|
-
|
|
95
|
-
conversation,
|
|
96
|
-
|
|
97
|
-
context
|
|
91
|
+
await client.runClientHookWithShim(
|
|
92
|
+
() => hooks.afterLoadConversation(conversation, id, context),
|
|
93
|
+
"Load prevented by afterLoadConversation hook"
|
|
98
94
|
);
|
|
99
|
-
if (canContinue === false) {
|
|
100
|
-
throw new Error("Load prevented by afterLoadConversation hook");
|
|
101
|
-
}
|
|
102
95
|
}
|
|
103
96
|
const queryState = queryClient.getQueryState(
|
|
104
97
|
conversationQuery.queryKey
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { defineClientPlugin, createApiClient } from '@btst/stack/plugins/client';
|
|
2
|
+
import { defineClientPlugin, runClientHookWithShim, createApiClient } from '@btst/stack/plugins/client';
|
|
3
3
|
import { createRoute } from '@btst/yar';
|
|
4
4
|
import { createAiChatQueryKeys } from '../../../../../../plugins/ai-chat/query-keys.mjs';
|
|
5
5
|
import { ChatLayout } from './components/chat-layout.mjs';
|
|
@@ -20,10 +20,10 @@ function createConversationsLoader(config) {
|
|
|
20
20
|
};
|
|
21
21
|
try {
|
|
22
22
|
if (hooks?.beforeLoadConversations) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
await runClientHookWithShim(
|
|
24
|
+
() => hooks.beforeLoadConversations(context),
|
|
25
|
+
"Load prevented by beforeLoadConversations hook"
|
|
26
|
+
);
|
|
27
27
|
}
|
|
28
28
|
const client = createApiClient({
|
|
29
29
|
baseURL: apiBaseURL,
|
|
@@ -36,13 +36,10 @@ function createConversationsLoader(config) {
|
|
|
36
36
|
const conversations = queryClient.getQueryData(
|
|
37
37
|
listQuery.queryKey
|
|
38
38
|
) || null;
|
|
39
|
-
|
|
40
|
-
conversations,
|
|
41
|
-
|
|
39
|
+
await runClientHookWithShim(
|
|
40
|
+
() => hooks.afterLoadConversations(conversations, context),
|
|
41
|
+
"Load prevented by afterLoadConversations hook"
|
|
42
42
|
);
|
|
43
|
-
if (canContinue === false) {
|
|
44
|
-
throw new Error("Load prevented by afterLoadConversations hook");
|
|
45
|
-
}
|
|
46
43
|
}
|
|
47
44
|
const queryState = queryClient.getQueryState(listQuery.queryKey);
|
|
48
45
|
if (queryState?.error && hooks?.onLoadError) {
|
|
@@ -71,10 +68,10 @@ function createConversationLoader(id, config) {
|
|
|
71
68
|
};
|
|
72
69
|
try {
|
|
73
70
|
if (hooks?.beforeLoadConversation) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
71
|
+
await runClientHookWithShim(
|
|
72
|
+
() => hooks.beforeLoadConversation(id, context),
|
|
73
|
+
"Load prevented by beforeLoadConversation hook"
|
|
74
|
+
);
|
|
78
75
|
}
|
|
79
76
|
const client = createApiClient({
|
|
80
77
|
baseURL: apiBaseURL,
|
|
@@ -89,14 +86,10 @@ function createConversationLoader(id, config) {
|
|
|
89
86
|
]);
|
|
90
87
|
if (hooks?.afterLoadConversation) {
|
|
91
88
|
const conversation = queryClient.getQueryData(conversationQuery.queryKey) || null;
|
|
92
|
-
|
|
93
|
-
conversation,
|
|
94
|
-
|
|
95
|
-
context
|
|
89
|
+
await runClientHookWithShim(
|
|
90
|
+
() => hooks.afterLoadConversation(conversation, id, context),
|
|
91
|
+
"Load prevented by afterLoadConversation hook"
|
|
96
92
|
);
|
|
97
|
-
if (canContinue === false) {
|
|
98
|
-
throw new Error("Load prevented by afterLoadConversation hook");
|
|
99
|
-
}
|
|
100
93
|
}
|
|
101
94
|
const queryState = queryClient.getQueryState(
|
|
102
95
|
conversationQuery.queryKey
|
|
@@ -34,7 +34,23 @@ const chatRequestSchema = z.z.object({
|
|
|
34
34
|
])
|
|
35
35
|
),
|
|
36
36
|
conversationId: z.z.string().optional(),
|
|
37
|
-
model: z.z.string().optional()
|
|
37
|
+
model: z.z.string().optional(),
|
|
38
|
+
/**
|
|
39
|
+
* Description of the current page context, injected into the AI system prompt.
|
|
40
|
+
* Sent by ChatInterface when a page has registered context via useRegisterPageAIContext.
|
|
41
|
+
*/
|
|
42
|
+
pageContext: z.z.string().max(16e3).optional(),
|
|
43
|
+
/**
|
|
44
|
+
* Names of client-side tools currently available on the page.
|
|
45
|
+
* The server includes matching tool schemas in the streamText call.
|
|
46
|
+
*/
|
|
47
|
+
availableTools: z.z.array(z.z.string()).optional(),
|
|
48
|
+
/**
|
|
49
|
+
* The routeName registered by the page via useRegisterPageAIContext.
|
|
50
|
+
* Cross-validated server-side against each built-in tool's route allowlist
|
|
51
|
+
* to prevent a page from claiming tools intended for a different route.
|
|
52
|
+
*/
|
|
53
|
+
routeName: z.z.string().optional()
|
|
38
54
|
});
|
|
39
55
|
|
|
40
56
|
exports.chatRequestSchema = chatRequestSchema;
|
|
@@ -32,7 +32,23 @@ const chatRequestSchema = z.object({
|
|
|
32
32
|
])
|
|
33
33
|
),
|
|
34
34
|
conversationId: z.string().optional(),
|
|
35
|
-
model: z.string().optional()
|
|
35
|
+
model: z.string().optional(),
|
|
36
|
+
/**
|
|
37
|
+
* Description of the current page context, injected into the AI system prompt.
|
|
38
|
+
* Sent by ChatInterface when a page has registered context via useRegisterPageAIContext.
|
|
39
|
+
*/
|
|
40
|
+
pageContext: z.string().max(16e3).optional(),
|
|
41
|
+
/**
|
|
42
|
+
* Names of client-side tools currently available on the page.
|
|
43
|
+
* The server includes matching tool schemas in the streamText call.
|
|
44
|
+
*/
|
|
45
|
+
availableTools: z.array(z.string()).optional(),
|
|
46
|
+
/**
|
|
47
|
+
* The routeName registered by the page via useRegisterPageAIContext.
|
|
48
|
+
* Cross-validated server-side against each built-in tool's route allowlist
|
|
49
|
+
* to prevent a page from claiming tools intended for a different route.
|
|
50
|
+
*/
|
|
51
|
+
routeName: z.string().optional()
|
|
36
52
|
});
|
|
37
53
|
|
|
38
54
|
export { chatRequestSchema, createConversationSchema, updateConversationSchema };
|
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
const api = require('@btst/stack/plugins/api');
|
|
4
4
|
const z = require('zod');
|
|
5
5
|
const db = require('../db.cjs');
|
|
6
|
-
const utils = require('../utils.cjs');
|
|
6
|
+
const utils$1 = require('../utils.cjs');
|
|
7
7
|
const schemas = require('../schemas.cjs');
|
|
8
8
|
const getters = require('./getters.cjs');
|
|
9
9
|
const queryKeyDefs = require('./query-key-defs.cjs');
|
|
10
10
|
const serializers = require('./serializers.cjs');
|
|
11
|
+
const utils = require('../../utils.cjs');
|
|
11
12
|
|
|
12
13
|
function createBlogPrefetchForRoute(adapter) {
|
|
13
14
|
return async function prefetchForRoute(key, qc, params) {
|
|
@@ -113,7 +114,7 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
113
114
|
for (const tag of allTags) {
|
|
114
115
|
tagMapBySlug.set(tag.slug, tag);
|
|
115
116
|
}
|
|
116
|
-
const tagSlugs = tagsToFindOrCreate.map((tag) => utils.slugify(tag.name));
|
|
117
|
+
const tagSlugs = tagsToFindOrCreate.map((tag) => utils$1.slugify(tag.name));
|
|
117
118
|
const foundTags = [];
|
|
118
119
|
for (const slug of tagSlugs) {
|
|
119
120
|
const tag = tagMapBySlug.get(slug);
|
|
@@ -126,7 +127,7 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
126
127
|
...foundTags.map((tag) => tag.slug)
|
|
127
128
|
]);
|
|
128
129
|
const tagsToCreate = tagsToFindOrCreate.filter(
|
|
129
|
-
(tag) => !existingSlugs.has(utils.slugify(tag.name))
|
|
130
|
+
(tag) => !existingSlugs.has(utils$1.slugify(tag.name))
|
|
130
131
|
);
|
|
131
132
|
const createdTags = [];
|
|
132
133
|
for (const tag of tagsToCreate) {
|
|
@@ -135,7 +136,7 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
135
136
|
model: "tag",
|
|
136
137
|
data: {
|
|
137
138
|
name: normalizedName,
|
|
138
|
-
slug: utils.slugify(normalizedName),
|
|
139
|
+
slug: utils$1.slugify(normalizedName),
|
|
139
140
|
createdAt: /* @__PURE__ */ new Date(),
|
|
140
141
|
updatedAt: /* @__PURE__ */ new Date()
|
|
141
142
|
}
|
|
@@ -155,12 +156,11 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
155
156
|
const context = { query, headers };
|
|
156
157
|
try {
|
|
157
158
|
if (hooks?.onBeforeListPosts) {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
159
|
+
await utils.runHookWithShim(
|
|
160
|
+
() => hooks.onBeforeListPosts(query, context),
|
|
161
|
+
ctx.error,
|
|
162
|
+
"Unauthorized: Cannot list posts"
|
|
163
|
+
);
|
|
164
164
|
}
|
|
165
165
|
const result = await getters.getAllPosts(adapter, query);
|
|
166
166
|
if (hooks?.onPostsRead) {
|
|
@@ -188,19 +188,15 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
188
188
|
};
|
|
189
189
|
try {
|
|
190
190
|
if (hooks?.onBeforeCreatePost) {
|
|
191
|
-
|
|
192
|
-
ctx.body,
|
|
193
|
-
|
|
191
|
+
await utils.runHookWithShim(
|
|
192
|
+
() => hooks.onBeforeCreatePost(ctx.body, context),
|
|
193
|
+
ctx.error,
|
|
194
|
+
"Unauthorized: Cannot create post"
|
|
194
195
|
);
|
|
195
|
-
if (!canCreate) {
|
|
196
|
-
throw ctx.error(403, {
|
|
197
|
-
message: "Unauthorized: Cannot create post"
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
196
|
}
|
|
201
197
|
const { tags, ...postData } = ctx.body;
|
|
202
198
|
const tagNames = tags || [];
|
|
203
|
-
const slug = utils.slugify(postData.slug || postData.title);
|
|
199
|
+
const slug = utils$1.slugify(postData.slug || postData.title);
|
|
204
200
|
if (!slug) {
|
|
205
201
|
throw ctx.error(400, {
|
|
206
202
|
message: "Invalid slug: must contain at least one alphanumeric character"
|
|
@@ -259,20 +255,15 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
259
255
|
};
|
|
260
256
|
try {
|
|
261
257
|
if (hooks?.onBeforeUpdatePost) {
|
|
262
|
-
|
|
263
|
-
ctx.params.id,
|
|
264
|
-
ctx.
|
|
265
|
-
|
|
258
|
+
await utils.runHookWithShim(
|
|
259
|
+
() => hooks.onBeforeUpdatePost(ctx.params.id, ctx.body, context),
|
|
260
|
+
ctx.error,
|
|
261
|
+
"Unauthorized: Cannot update post"
|
|
266
262
|
);
|
|
267
|
-
if (!canUpdate) {
|
|
268
|
-
throw ctx.error(403, {
|
|
269
|
-
message: "Unauthorized: Cannot update post"
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
263
|
}
|
|
273
264
|
const { tags, slug: rawSlug, ...restPostData } = ctx.body;
|
|
274
265
|
const tagNames = tags || [];
|
|
275
|
-
const slugified = rawSlug ? utils.slugify(rawSlug) : void 0;
|
|
266
|
+
const slugified = rawSlug ? utils$1.slugify(rawSlug) : void 0;
|
|
276
267
|
if (rawSlug && !slugified) {
|
|
277
268
|
throw ctx.error(400, {
|
|
278
269
|
message: "Invalid slug: must contain at least one alphanumeric character"
|
|
@@ -364,15 +355,11 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
364
355
|
};
|
|
365
356
|
try {
|
|
366
357
|
if (hooks?.onBeforeDeletePost) {
|
|
367
|
-
|
|
368
|
-
ctx.params.id,
|
|
369
|
-
|
|
358
|
+
await utils.runHookWithShim(
|
|
359
|
+
() => hooks.onBeforeDeletePost(ctx.params.id, context),
|
|
360
|
+
ctx.error,
|
|
361
|
+
"Unauthorized: Cannot delete post"
|
|
370
362
|
);
|
|
371
|
-
if (!canDelete) {
|
|
372
|
-
throw ctx.error(403, {
|
|
373
|
-
message: "Unauthorized: Cannot delete post"
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
363
|
}
|
|
377
364
|
await adapter.delete({
|
|
378
365
|
model: "post",
|
|
@@ -401,15 +388,11 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
|
|
|
401
388
|
const context = { query, headers };
|
|
402
389
|
try {
|
|
403
390
|
if (hooks?.onBeforeListPosts) {
|
|
404
|
-
|
|
405
|
-
{ published: true },
|
|
406
|
-
|
|
391
|
+
await utils.runHookWithShim(
|
|
392
|
+
() => hooks.onBeforeListPosts({ published: true }, context),
|
|
393
|
+
ctx.error,
|
|
394
|
+
"Unauthorized: Cannot list posts"
|
|
407
395
|
);
|
|
408
|
-
if (!canList) {
|
|
409
|
-
throw ctx.error(403, {
|
|
410
|
-
message: "Unauthorized: Cannot list posts"
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
396
|
}
|
|
414
397
|
const date = query.date;
|
|
415
398
|
const previousPosts = await adapter.findMany({
|
|
@@ -6,6 +6,7 @@ import { createPostSchema, updatePostSchema } from '../schemas.mjs';
|
|
|
6
6
|
import { getAllTags, getPostBySlug, getAllPosts } from './getters.mjs';
|
|
7
7
|
import { BLOG_QUERY_KEYS } from './query-key-defs.mjs';
|
|
8
8
|
import { serializePost, serializeTag } from './serializers.mjs';
|
|
9
|
+
import { runHookWithShim } from '../../utils.mjs';
|
|
9
10
|
|
|
10
11
|
function createBlogPrefetchForRoute(adapter) {
|
|
11
12
|
return async function prefetchForRoute(key, qc, params) {
|
|
@@ -153,12 +154,11 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
153
154
|
const context = { query, headers };
|
|
154
155
|
try {
|
|
155
156
|
if (hooks?.onBeforeListPosts) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
157
|
+
await runHookWithShim(
|
|
158
|
+
() => hooks.onBeforeListPosts(query, context),
|
|
159
|
+
ctx.error,
|
|
160
|
+
"Unauthorized: Cannot list posts"
|
|
161
|
+
);
|
|
162
162
|
}
|
|
163
163
|
const result = await getAllPosts(adapter, query);
|
|
164
164
|
if (hooks?.onPostsRead) {
|
|
@@ -186,15 +186,11 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
186
186
|
};
|
|
187
187
|
try {
|
|
188
188
|
if (hooks?.onBeforeCreatePost) {
|
|
189
|
-
|
|
190
|
-
ctx.body,
|
|
191
|
-
|
|
189
|
+
await runHookWithShim(
|
|
190
|
+
() => hooks.onBeforeCreatePost(ctx.body, context),
|
|
191
|
+
ctx.error,
|
|
192
|
+
"Unauthorized: Cannot create post"
|
|
192
193
|
);
|
|
193
|
-
if (!canCreate) {
|
|
194
|
-
throw ctx.error(403, {
|
|
195
|
-
message: "Unauthorized: Cannot create post"
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
194
|
}
|
|
199
195
|
const { tags, ...postData } = ctx.body;
|
|
200
196
|
const tagNames = tags || [];
|
|
@@ -257,16 +253,11 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
257
253
|
};
|
|
258
254
|
try {
|
|
259
255
|
if (hooks?.onBeforeUpdatePost) {
|
|
260
|
-
|
|
261
|
-
ctx.params.id,
|
|
262
|
-
ctx.
|
|
263
|
-
|
|
256
|
+
await runHookWithShim(
|
|
257
|
+
() => hooks.onBeforeUpdatePost(ctx.params.id, ctx.body, context),
|
|
258
|
+
ctx.error,
|
|
259
|
+
"Unauthorized: Cannot update post"
|
|
264
260
|
);
|
|
265
|
-
if (!canUpdate) {
|
|
266
|
-
throw ctx.error(403, {
|
|
267
|
-
message: "Unauthorized: Cannot update post"
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
261
|
}
|
|
271
262
|
const { tags, slug: rawSlug, ...restPostData } = ctx.body;
|
|
272
263
|
const tagNames = tags || [];
|
|
@@ -362,15 +353,11 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
362
353
|
};
|
|
363
354
|
try {
|
|
364
355
|
if (hooks?.onBeforeDeletePost) {
|
|
365
|
-
|
|
366
|
-
ctx.params.id,
|
|
367
|
-
|
|
356
|
+
await runHookWithShim(
|
|
357
|
+
() => hooks.onBeforeDeletePost(ctx.params.id, context),
|
|
358
|
+
ctx.error,
|
|
359
|
+
"Unauthorized: Cannot delete post"
|
|
368
360
|
);
|
|
369
|
-
if (!canDelete) {
|
|
370
|
-
throw ctx.error(403, {
|
|
371
|
-
message: "Unauthorized: Cannot delete post"
|
|
372
|
-
});
|
|
373
|
-
}
|
|
374
361
|
}
|
|
375
362
|
await adapter.delete({
|
|
376
363
|
model: "post",
|
|
@@ -399,15 +386,11 @@ const blogBackendPlugin = (hooks) => defineBackendPlugin({
|
|
|
399
386
|
const context = { query, headers };
|
|
400
387
|
try {
|
|
401
388
|
if (hooks?.onBeforeListPosts) {
|
|
402
|
-
|
|
403
|
-
{ published: true },
|
|
404
|
-
|
|
389
|
+
await runHookWithShim(
|
|
390
|
+
() => hooks.onBeforeListPosts({ published: true }, context),
|
|
391
|
+
ctx.error,
|
|
392
|
+
"Unauthorized: Cannot list posts"
|
|
405
393
|
);
|
|
406
|
-
if (!canList) {
|
|
407
|
-
throw ctx.error(403, {
|
|
408
|
-
message: "Unauthorized: Cannot list posts"
|
|
409
|
-
});
|
|
410
|
-
}
|
|
411
394
|
}
|
|
412
395
|
const date = query.date;
|
|
413
396
|
const previousPosts = await adapter.findMany({
|