@agent-native/dispatch 0.23.2 → 0.23.5
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/actions/provider-api-register.d.ts +11 -11
- package/dist/components/app-list-row.d.ts +1 -1
- package/dist/components/app-list-row.d.ts.map +1 -1
- package/dist/components/app-list-row.js +2 -2
- package/dist/components/app-list-row.js.map +1 -1
- package/dist/components/app-open-actions.d.ts.map +1 -1
- package/dist/components/app-open-actions.js +3 -2
- package/dist/components/app-open-actions.js.map +1 -1
- package/dist/components/create-app-popover.d.ts.map +1 -1
- package/dist/components/create-app-popover.js +11 -0
- package/dist/components/create-app-popover.js.map +1 -1
- package/dist/components/dispatch-control-plane.d.ts.map +1 -1
- package/dist/components/dispatch-control-plane.js +3 -2
- package/dist/components/dispatch-control-plane.js.map +1 -1
- package/dist/components/layout/Layout.d.ts +5 -2
- package/dist/components/layout/Layout.d.ts.map +1 -1
- package/dist/components/layout/Layout.js +122 -13
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/components/layout/workspace-apps-rail.d.ts.map +1 -1
- package/dist/components/layout/workspace-apps-rail.js +3 -23
- package/dist/components/layout/workspace-apps-rail.js.map +1 -1
- package/dist/components/other-apps-section.d.ts.map +1 -1
- package/dist/components/other-apps-section.js +5 -1
- package/dist/components/other-apps-section.js.map +1 -1
- package/dist/components/workspace-app-card.d.ts.map +1 -1
- package/dist/components/workspace-app-card.js +3 -4
- package/dist/components/workspace-app-card.js.map +1 -1
- package/dist/components/workspace-template-card.d.ts.map +1 -1
- package/dist/components/workspace-template-card.js +1 -1
- package/dist/components/workspace-template-card.js.map +1 -1
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/lib/other-apps.d.ts.map +1 -1
- package/dist/lib/other-apps.js +2 -0
- package/dist/lib/other-apps.js.map +1 -1
- package/dist/lib/workspace-apps.d.ts +4 -0
- package/dist/lib/workspace-apps.d.ts.map +1 -1
- package/dist/lib/workspace-apps.js +23 -0
- package/dist/lib/workspace-apps.js.map +1 -1
- package/dist/routes/index.js +1 -1
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/pages/agent-integrations.d.ts +5 -0
- package/dist/routes/pages/agent-integrations.d.ts.map +1 -0
- package/dist/routes/pages/agent-integrations.js +15 -0
- package/dist/routes/pages/agent-integrations.js.map +1 -0
- package/dist/routes/pages/apps.$appId.d.ts.map +1 -1
- package/dist/routes/pages/apps.$appId.js +14 -2
- package/dist/routes/pages/apps.$appId.js.map +1 -1
- package/dist/routes/pages/apps.d.ts.map +1 -1
- package/dist/routes/pages/apps.js +2 -1
- package/dist/routes/pages/apps.js.map +1 -1
- package/dist/routes/pages/overview.d.ts +2 -2
- package/dist/routes/pages/settings.d.ts.map +1 -1
- package/dist/routes/pages/settings.js +1 -1
- package/dist/routes/pages/settings.js.map +1 -1
- package/dist/server/plugins/auth.d.ts.map +1 -1
- package/dist/server/plugins/auth.js +1 -0
- package/dist/server/plugins/auth.js.map +1 -1
- package/package.json +3 -3
- package/src/components/app-list-row.tsx +3 -2
- package/src/components/app-open-actions.tsx +3 -2
- package/src/components/create-app-popover.spec.tsx +26 -2
- package/src/components/create-app-popover.tsx +10 -0
- package/src/components/dispatch-control-plane.spec.tsx +1 -0
- package/src/components/dispatch-control-plane.tsx +8 -2
- package/src/components/layout/Layout.spec.tsx +9 -0
- package/src/components/layout/Layout.tsx +181 -19
- package/src/components/layout/workspace-apps-rail.tsx +4 -26
- package/src/components/other-apps-section.tsx +8 -1
- package/src/components/workspace-app-card.spec.tsx +6 -6
- package/src/components/workspace-app-card.tsx +4 -7
- package/src/components/workspace-template-card.spec.tsx +4 -16
- package/src/components/workspace-template-card.tsx +0 -1
- package/src/config.ts +2 -0
- package/src/lib/other-apps.spec.ts +26 -0
- package/src/lib/other-apps.ts +3 -0
- package/src/lib/workspace-apps.spec.ts +44 -0
- package/src/lib/workspace-apps.ts +27 -0
- package/src/routes/index.ts +1 -1
- package/src/routes/pages/agent-integrations.tsx +24 -0
- package/src/routes/pages/apps.$appId.tsx +19 -1
- package/src/routes/pages/apps.tsx +5 -2
- package/src/routes/pages/settings.tsx +1 -19
- package/src/server/plugins/auth.spec.ts +45 -0
- package/src/server/plugins/auth.ts +1 -0
|
@@ -25,7 +25,6 @@ import { toast } from "sonner";
|
|
|
25
25
|
|
|
26
26
|
import { cn } from "../lib/utils";
|
|
27
27
|
import {
|
|
28
|
-
isPendingBuilderHref,
|
|
29
28
|
workspaceAppHref,
|
|
30
29
|
workspaceAppRoute,
|
|
31
30
|
type WorkspaceAppSummary,
|
|
@@ -276,7 +275,6 @@ function WorkspaceAppOpenActions({
|
|
|
276
275
|
href: string | null;
|
|
277
276
|
}) {
|
|
278
277
|
const navigate = useNavigate();
|
|
279
|
-
const openInNewTab = isPendingBuilderHref(app);
|
|
280
278
|
const appRoute = workspaceAppRoute(app.id);
|
|
281
279
|
|
|
282
280
|
if (!href) {
|
|
@@ -290,14 +288,13 @@ function WorkspaceAppOpenActions({
|
|
|
290
288
|
return (
|
|
291
289
|
<AppOpenActions
|
|
292
290
|
name={app.name}
|
|
293
|
-
href={
|
|
294
|
-
target=
|
|
295
|
-
rel=
|
|
296
|
-
showInlineOption
|
|
291
|
+
href={href}
|
|
292
|
+
target="_blank"
|
|
293
|
+
rel="noreferrer"
|
|
294
|
+
showInlineOption
|
|
297
295
|
onOpenInline={() => {
|
|
298
296
|
navigate(appRoute);
|
|
299
297
|
}}
|
|
300
|
-
showNewTabOption={openInNewTab}
|
|
301
298
|
/>
|
|
302
299
|
);
|
|
303
300
|
}
|
|
@@ -153,7 +153,7 @@ describe("WorkspaceTemplateCard", () => {
|
|
|
153
153
|
);
|
|
154
154
|
});
|
|
155
155
|
|
|
156
|
-
it("keeps add app
|
|
156
|
+
it("keeps add app available in catalog cards", async () => {
|
|
157
157
|
await act(async () => {
|
|
158
158
|
root.render(<WorkspaceTemplateCard template={template} catalog />);
|
|
159
159
|
});
|
|
@@ -162,23 +162,11 @@ describe("WorkspaceTemplateCard", () => {
|
|
|
162
162
|
(button) => button.textContent?.includes("Add app"),
|
|
163
163
|
);
|
|
164
164
|
expect(addButton).toBeDefined();
|
|
165
|
-
|
|
166
|
-
const optionsButton = container.querySelector<HTMLButtonElement>(
|
|
167
|
-
'button[aria-label="Open options for Weekly report"]',
|
|
168
|
-
);
|
|
169
|
-
expect(optionsButton).not.toBeNull();
|
|
170
|
-
await act(async () => {
|
|
171
|
-
optionsButton?.dispatchEvent(
|
|
172
|
-
new MouseEvent("pointerdown", { bubbles: true, button: 0 }),
|
|
173
|
-
);
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
const addItem = Array.from(
|
|
177
|
-
document.querySelectorAll<HTMLElement>('[role="menuitem"]'),
|
|
178
|
-
).find((item) => item.textContent?.includes("Add app"));
|
|
179
|
-
expect(addItem).toBeUndefined();
|
|
180
165
|
await act(async () => addButton?.click());
|
|
181
166
|
expect(document.body.textContent).toContain("Choose the URL-safe id");
|
|
167
|
+
expect(
|
|
168
|
+
container.querySelector('a[href="https://reports.example.test"]'),
|
|
169
|
+
).not.toBeNull();
|
|
182
170
|
});
|
|
183
171
|
|
|
184
172
|
it("accepts the list action envelope and renders installed state", async () => {
|
package/src/config.ts
CHANGED
|
@@ -13,6 +13,8 @@ export interface DispatchAuthConfig {
|
|
|
13
13
|
googleOnly?: boolean;
|
|
14
14
|
/** Marketing/branding copy passed straight through to `createAuthPlugin`. */
|
|
15
15
|
marketing?: Record<string, unknown>;
|
|
16
|
+
/** Exact framework routes that perform their own authentication checks. */
|
|
17
|
+
publicPaths?: string[];
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
export interface DispatchIntegrationsConfig {
|
|
@@ -104,4 +104,30 @@ describe("filterOtherApps", () => {
|
|
|
104
104
|
},
|
|
105
105
|
]);
|
|
106
106
|
});
|
|
107
|
+
|
|
108
|
+
it("hides the generic chat starter from connected app launchers", () => {
|
|
109
|
+
expect(
|
|
110
|
+
filterOtherApps(
|
|
111
|
+
[
|
|
112
|
+
{
|
|
113
|
+
id: "chat",
|
|
114
|
+
name: "Chat",
|
|
115
|
+
url: "https://chat.agent-native.com",
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
id: "mail",
|
|
119
|
+
name: "Mail",
|
|
120
|
+
url: "https://mail.agent-native.com",
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
[],
|
|
124
|
+
),
|
|
125
|
+
).toEqual([
|
|
126
|
+
{
|
|
127
|
+
id: "mail",
|
|
128
|
+
name: "Mail",
|
|
129
|
+
url: "https://mail.agent-native.com",
|
|
130
|
+
},
|
|
131
|
+
]);
|
|
132
|
+
});
|
|
107
133
|
});
|
package/src/lib/other-apps.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { isDefaultWorkspaceAppHiddenId } from "./workspace-apps";
|
|
2
|
+
|
|
1
3
|
export interface ConnectedAppSummary {
|
|
2
4
|
id: string;
|
|
3
5
|
name: string;
|
|
@@ -38,6 +40,7 @@ export function filterOtherApps(
|
|
|
38
40
|
const id = app.id.trim().toLowerCase();
|
|
39
41
|
if (
|
|
40
42
|
!id ||
|
|
43
|
+
isDefaultWorkspaceAppHiddenId(id) ||
|
|
41
44
|
HIDDEN_OTHER_APP_IDS.has(id) ||
|
|
42
45
|
workspaceAppIds.has(id) ||
|
|
43
46
|
seen.has(id)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
isDefaultWorkspaceAppHiddenId,
|
|
5
|
+
isDispatchWorkspaceAppId,
|
|
6
|
+
isWorkspaceAppVisibleInDefaultLaunchers,
|
|
7
|
+
workspaceAppIdFromRoute,
|
|
8
|
+
workspaceAppRoute,
|
|
9
|
+
} from "./workspace-apps";
|
|
10
|
+
|
|
11
|
+
describe("workspace app routes", () => {
|
|
12
|
+
it("round-trips encoded app ids", () => {
|
|
13
|
+
const route = workspaceAppRoute("sales ops");
|
|
14
|
+
expect(route).toBe("/apps/sales%20ops");
|
|
15
|
+
expect(workspaceAppIdFromRoute(route)).toBe("sales ops");
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("does not mark app paths or the apps index as an active app route", () => {
|
|
19
|
+
expect(workspaceAppIdFromRoute("/sales-ops")).toBeNull();
|
|
20
|
+
expect(workspaceAppIdFromRoute("/apps")).toBeNull();
|
|
21
|
+
expect(workspaceAppIdFromRoute("/overview")).toBeNull();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("accepts nested app routes while preserving the app id", () => {
|
|
25
|
+
expect(workspaceAppIdFromRoute("/apps/mail/inbox")).toBe("mail");
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("identifies Dispatch regardless of casing or surrounding whitespace", () => {
|
|
29
|
+
expect(isDispatchWorkspaceAppId(" Dispatch ")).toBe(true);
|
|
30
|
+
expect(isDispatchWorkspaceAppId("dispatch-tools")).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("hides the generic chat starter and Dispatch from default launchers", () => {
|
|
34
|
+
expect(isDefaultWorkspaceAppHiddenId(" Chat ")).toBe(true);
|
|
35
|
+
expect(isWorkspaceAppVisibleInDefaultLaunchers({ id: "chat" })).toBe(false);
|
|
36
|
+
expect(
|
|
37
|
+
isWorkspaceAppVisibleInDefaultLaunchers({
|
|
38
|
+
id: "dispatch",
|
|
39
|
+
isDispatch: true,
|
|
40
|
+
}),
|
|
41
|
+
).toBe(false);
|
|
42
|
+
expect(isWorkspaceAppVisibleInDefaultLaunchers({ id: "mail" })).toBe(true);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
@@ -27,10 +27,37 @@ export interface WorkspaceAppSummary {
|
|
|
27
27
|
archived?: boolean;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
export function isDispatchWorkspaceAppId(appId: string): boolean {
|
|
31
|
+
return appId.trim().toLowerCase() === "dispatch";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function isDefaultWorkspaceAppHiddenId(appId: string): boolean {
|
|
35
|
+
const normalized = appId.trim().toLowerCase();
|
|
36
|
+
return normalized === "chat" || isDispatchWorkspaceAppId(normalized);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function isWorkspaceAppVisibleInDefaultLaunchers(
|
|
40
|
+
app: Pick<WorkspaceAppSummary, "id" | "isDispatch">,
|
|
41
|
+
): boolean {
|
|
42
|
+
return !app.isDispatch && !isDefaultWorkspaceAppHiddenId(app.id);
|
|
43
|
+
}
|
|
44
|
+
|
|
30
45
|
export function workspaceAppRoute(appId: string): string {
|
|
31
46
|
return `/apps/${encodeURIComponent(appId)}`;
|
|
32
47
|
}
|
|
33
48
|
|
|
49
|
+
export function workspaceAppIdFromRoute(pathname: string): string | null {
|
|
50
|
+
const match = pathname.match(/^\/apps\/([^/]+)(?:\/|$)/);
|
|
51
|
+
if (!match) return null;
|
|
52
|
+
try {
|
|
53
|
+
const appId = decodeURIComponent(match[1]).trim();
|
|
54
|
+
return appId || null;
|
|
55
|
+
} catch {
|
|
56
|
+
// coercion-ok: malformed app routes are inactive, not app ids.
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
34
61
|
export function workspaceAppHref(app: WorkspaceAppSummary): string | null {
|
|
35
62
|
if (app.status === "pending") {
|
|
36
63
|
return app.builderUrl
|
package/src/routes/index.ts
CHANGED
|
@@ -44,7 +44,7 @@ export const dispatchRoutes: RouteConfig = [
|
|
|
44
44
|
route("automations", "./pages/automations.js"),
|
|
45
45
|
route("approvals", "./pages/approvals.js"),
|
|
46
46
|
route("destinations", "./pages/destinations.js"),
|
|
47
|
-
route("integrations", "./pages/integrations.js"),
|
|
47
|
+
route("integrations", "./pages/agent-integrations.js"),
|
|
48
48
|
route("transactional-email", "./pages/transactional-email.js"),
|
|
49
49
|
route(
|
|
50
50
|
"transactional-email/:appId/:id",
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useAgentSettingsTabs } from "@agent-native/core/client/settings";
|
|
2
|
+
|
|
3
|
+
import { DispatchShell } from "../../components/dispatch-shell";
|
|
4
|
+
|
|
5
|
+
export function meta() {
|
|
6
|
+
return [{ title: "Integrations — Dispatch" }];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default function AgentIntegrationsRoute() {
|
|
10
|
+
const settingsTabs = useAgentSettingsTabs();
|
|
11
|
+
const integrationsTab = settingsTabs.find((tab) => tab.id === "integrations");
|
|
12
|
+
if (!integrationsTab) {
|
|
13
|
+
throw new Error("The shared Integrations settings view is unavailable.");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<DispatchShell
|
|
18
|
+
title="Integrations"
|
|
19
|
+
description="Connect the tools and services available to your agent."
|
|
20
|
+
>
|
|
21
|
+
<div className="mx-auto w-full max-w-5xl">{integrationsTab.content}</div>
|
|
22
|
+
</DispatchShell>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
import { useT } from "@agent-native/core/client/i18n";
|
|
6
6
|
import { withBuilderUtmTrackingParams } from "@agent-native/core/shared/builder-link-tracking";
|
|
7
7
|
import { IconArrowLeft, IconClockHour4 } from "@tabler/icons-react";
|
|
8
|
-
import { useEffect, useMemo, useState } from "react";
|
|
8
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
9
9
|
import { Link, useParams } from "react-router";
|
|
10
10
|
|
|
11
11
|
import { ActionQueryError } from "../../components/action-query-error";
|
|
@@ -52,6 +52,7 @@ export default function WorkspaceAppRoute() {
|
|
|
52
52
|
const [embedUrl, setEmbedUrl] = useState<string | null>(null);
|
|
53
53
|
const [embedError, setEmbedError] = useState<Error | null>(null);
|
|
54
54
|
const [embedAttempt, setEmbedAttempt] = useState(0);
|
|
55
|
+
const embedFrameRef = useRef<HTMLIFrameElement>(null);
|
|
55
56
|
const createEmbedSession = useActionMutation<
|
|
56
57
|
EmbedSessionResult,
|
|
57
58
|
EmbedSessionInput
|
|
@@ -96,6 +97,22 @@ export default function WorkspaceAppRoute() {
|
|
|
96
97
|
embedInput,
|
|
97
98
|
]);
|
|
98
99
|
|
|
100
|
+
useEffect(() => {
|
|
101
|
+
const handleEmbedSessionExpired = (event: MessageEvent) => {
|
|
102
|
+
if (
|
|
103
|
+
event.data?.type !== "agentNative.embedSessionExpired" ||
|
|
104
|
+
event.source !== embedFrameRef.current?.contentWindow
|
|
105
|
+
) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
setEmbedAttempt((attempt) => attempt + 1);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
window.addEventListener("message", handleEmbedSessionExpired);
|
|
112
|
+
return () =>
|
|
113
|
+
window.removeEventListener("message", handleEmbedSessionExpired);
|
|
114
|
+
}, []);
|
|
115
|
+
|
|
99
116
|
if (appsQuery.isError) {
|
|
100
117
|
return (
|
|
101
118
|
<div className="flex h-full min-h-0 items-center justify-center p-6">
|
|
@@ -208,6 +225,7 @@ export default function WorkspaceAppRoute() {
|
|
|
208
225
|
data-dispatch-workspace-app-frame
|
|
209
226
|
src={embedUrl}
|
|
210
227
|
title={app.name}
|
|
228
|
+
ref={embedFrameRef}
|
|
211
229
|
referrerPolicy="no-referrer"
|
|
212
230
|
className="h-full w-full border-0 bg-background"
|
|
213
231
|
/>
|
|
@@ -33,7 +33,10 @@ import type {
|
|
|
33
33
|
} from "../../components/workspace-template-card";
|
|
34
34
|
import type { ConnectedAppSummary } from "../../lib/other-apps";
|
|
35
35
|
import { cn } from "../../lib/utils";
|
|
36
|
-
import
|
|
36
|
+
import {
|
|
37
|
+
isWorkspaceAppVisibleInDefaultLaunchers,
|
|
38
|
+
type WorkspaceAppSummary,
|
|
39
|
+
} from "../../lib/workspace-apps";
|
|
37
40
|
|
|
38
41
|
export function meta() {
|
|
39
42
|
return [{ title: "Apps — Dispatch" }];
|
|
@@ -72,7 +75,7 @@ function AppsRoute() {
|
|
|
72
75
|
const ws = workspace as WorkspaceInfo | undefined;
|
|
73
76
|
const workspaceLabel = ws?.displayName ?? ws?.name ?? null;
|
|
74
77
|
const allApps = (apps as WorkspaceAppSummary[]).filter(
|
|
75
|
-
|
|
78
|
+
isWorkspaceAppVisibleInDefaultLaunchers,
|
|
76
79
|
);
|
|
77
80
|
const visibleApps = allApps.filter((app) => !app.archived);
|
|
78
81
|
const activeApps = visibleApps.filter((app) => app.status !== "pending");
|
|
@@ -68,7 +68,7 @@ export default function SettingsRoute() {
|
|
|
68
68
|
description={t("settings.description")}
|
|
69
69
|
>
|
|
70
70
|
<SettingsTabsPage
|
|
71
|
-
extraTabs={agentSettingsTabs}
|
|
71
|
+
extraTabs={agentSettingsTabs.filter((tab) => tab.id !== "integrations")}
|
|
72
72
|
general={
|
|
73
73
|
<div className="mx-auto w-full max-w-3xl space-y-6">
|
|
74
74
|
<Card>
|
|
@@ -141,24 +141,6 @@ export default function SettingsRoute() {
|
|
|
141
141
|
</CardContent>
|
|
142
142
|
</Card>
|
|
143
143
|
|
|
144
|
-
<Card>
|
|
145
|
-
<CardHeader>
|
|
146
|
-
<CardTitle className="text-base">
|
|
147
|
-
{t("settings.automationsTitle")}
|
|
148
|
-
</CardTitle>
|
|
149
|
-
<CardDescription>
|
|
150
|
-
{t("settings.automationsDescription")}
|
|
151
|
-
</CardDescription>
|
|
152
|
-
</CardHeader>
|
|
153
|
-
<CardContent>
|
|
154
|
-
<Button variant="outline" asChild>
|
|
155
|
-
<Link to="/admin/automations">
|
|
156
|
-
{t("settings.openAutomations")}
|
|
157
|
-
</Link>
|
|
158
|
-
</Button>
|
|
159
|
-
</CardContent>
|
|
160
|
-
</Card>
|
|
161
|
-
|
|
162
144
|
<Card>
|
|
163
145
|
<CardHeader>
|
|
164
146
|
<CardTitle className="text-base">
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
|
|
3
|
+
const mocks = vi.hoisted(() => ({
|
|
4
|
+
authPlugin: vi.fn(),
|
|
5
|
+
createAuthPlugin: vi.fn(),
|
|
6
|
+
getDispatchConfig: vi.fn(),
|
|
7
|
+
}));
|
|
8
|
+
|
|
9
|
+
vi.mock("@agent-native/core/server", () => ({
|
|
10
|
+
createAuthPlugin: mocks.createAuthPlugin,
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
vi.mock("../index.js", () => ({
|
|
14
|
+
getDispatchConfig: mocks.getDispatchConfig,
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
describe("dispatchAuthPlugin", () => {
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
vi.resetModules();
|
|
20
|
+
mocks.authPlugin.mockReset();
|
|
21
|
+
mocks.createAuthPlugin.mockReset();
|
|
22
|
+
mocks.createAuthPlugin.mockReturnValue(mocks.authPlugin);
|
|
23
|
+
mocks.getDispatchConfig.mockReset();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("installs template public routes on the primary auth guard", async () => {
|
|
27
|
+
const { default: dispatchAuthPlugin } = await import("./auth.js");
|
|
28
|
+
const nitroApp = {};
|
|
29
|
+
const publicPaths = [
|
|
30
|
+
"/_agent-native/identity/authorize",
|
|
31
|
+
"/_agent-native/org/apps",
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
mocks.getDispatchConfig.mockReturnValue({
|
|
35
|
+
auth: { googleOnly: true, publicPaths },
|
|
36
|
+
});
|
|
37
|
+
await dispatchAuthPlugin(nitroApp);
|
|
38
|
+
|
|
39
|
+
expect(mocks.createAuthPlugin).toHaveBeenCalledOnce();
|
|
40
|
+
expect(mocks.createAuthPlugin).toHaveBeenCalledWith(
|
|
41
|
+
expect.objectContaining({ googleOnly: true, publicPaths }),
|
|
42
|
+
);
|
|
43
|
+
expect(mocks.authPlugin).toHaveBeenCalledWith(nitroApp);
|
|
44
|
+
});
|
|
45
|
+
});
|