@lukoweb/apitogo 0.2.31 → 0.2.34
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/cli/cli.js +436 -153
- package/dist/declarations/app/entry.server.d.ts +2 -2
- package/dist/declarations/app/main.d.ts +3 -1
- package/dist/declarations/cli/platform/client/platform-api.d.ts +0 -4
- package/dist/declarations/cli/platform/helpers/deploy-artifact-hash.d.ts +1 -1
- package/dist/declarations/cli/platform/helpers/package-files.d.ts +1 -1
- package/dist/declarations/cli/platform/helpers/zip.d.ts +1 -1
- package/dist/declarations/cli/platform/tools/infrastructure.d.ts +0 -4
- package/dist/declarations/config/effective-redirects.d.ts +6 -0
- package/dist/declarations/config/header-navigation-guard.d.ts +2 -0
- package/dist/declarations/config/resolve-modules.d.ts +1 -4
- package/dist/declarations/config/validators/HeaderNavigationSchema.d.ts +1 -2
- package/docs/cli/commands.md +19 -0
- package/docs/configuration/gateway.md +52 -0
- package/docs/guides/customer-account.md +11 -1
- package/docs/mcp/tools.md +101 -102
- package/package.json +2 -1
- package/src/app/demo.tsx +78 -77
- package/src/app/entry.client.tsx +115 -107
- package/src/app/entry.server.tsx +164 -160
- package/src/app/main.tsx +175 -167
- package/src/app/standalone.tsx +61 -60
- package/src/config/effective-redirects.ts +31 -0
- package/src/config/header-navigation-guard.ts +13 -0
- package/src/config/resolve-modules.ts +331 -354
- package/src/config/v2/home-redirect.ts +104 -98
- package/src/config/v2/index.ts +127 -126
- package/src/config/v2/ledger.ts +242 -235
- package/src/config/v2/resolve.ts +12 -4
- package/src/config/v2/rules.ts +716 -714
- package/src/config/v2/services.ts +799 -663
- package/src/config/v2/workspace.ts +17 -1
- package/src/config/validators/HeaderNavigationSchema.ts +42 -44
- package/src/lib/assets/powered-by-icon.png +0 -0
- package/src/lib/authentication/providers/dev-portal-auth-pages.tsx +667 -602
- package/src/lib/authentication/providers/dev-portal.tsx +476 -448
- package/src/lib/components/HeaderNavigation.tsx +176 -176
- package/src/lib/components/MobileTopNavigation.tsx +283 -283
- package/src/lib/components/navigation/PoweredByZudoku.tsx +42 -39
- package/src/vite/plugin-offroot-resolve.ts +68 -67
- package/src/vite/prerender/prerender.ts +242 -242
|
@@ -1,176 +1,176 @@
|
|
|
1
|
-
import type { LucideIcon } from "lucide-react";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
} from "../../config/validators/HeaderNavigationSchema.js";
|
|
8
|
-
import { withoutMarketingCtaHeaderNavigation } from "../authentication/header-nav-filter.js";
|
|
9
|
-
import { useAuth } from "../authentication/hook.js";
|
|
10
|
-
import type { ZudokuContext } from "../core/ZudokuContext.js";
|
|
11
|
-
import {
|
|
12
|
-
NavigationMenu,
|
|
13
|
-
NavigationMenuContent,
|
|
14
|
-
NavigationMenuItem,
|
|
15
|
-
NavigationMenuLink,
|
|
16
|
-
NavigationMenuList,
|
|
17
|
-
NavigationMenuTrigger,
|
|
18
|
-
} from "../ui/NavigationMenu.js";
|
|
19
|
-
import { cn } from "../util/cn.js";
|
|
20
|
-
import { AnchorLink } from "./AnchorLink.js";
|
|
21
|
-
import { useZudoku } from "./context/ZudokuContext.js";
|
|
22
|
-
import { shouldShowItem } from "./navigation/utils.js";
|
|
23
|
-
|
|
24
|
-
const marketingNavLinkClassName =
|
|
25
|
-
"inline-flex items-center gap-2 rounded-lg px-3 py-2 text-sm font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground";
|
|
26
|
-
|
|
27
|
-
const NavLinkItem = ({ item }: { item: HeaderNavLinkItem }) => {
|
|
28
|
-
const Icon = item.icon as LucideIcon | undefined;
|
|
29
|
-
return (
|
|
30
|
-
<NavigationMenuLink asChild>
|
|
31
|
-
<AnchorLink
|
|
32
|
-
to={item.to}
|
|
33
|
-
target={item.target}
|
|
34
|
-
rel={item.target === "_blank" ? "noopener noreferrer" : undefined}
|
|
35
|
-
className="block select-none rounded-md p-3 leading-none no-underline outline-hidden transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground"
|
|
36
|
-
>
|
|
37
|
-
<div className="flex items-center gap-2">
|
|
38
|
-
{Icon && (
|
|
39
|
-
<Icon size={16} className="shrink-0 text-muted-foreground" />
|
|
40
|
-
)}
|
|
41
|
-
<div className="text-sm font-medium leading-none">{item.label}</div>
|
|
42
|
-
</div>
|
|
43
|
-
{item.description && (
|
|
44
|
-
<p className="line-clamp-2 text-sm leading-snug text-muted-foreground mt-1.5">
|
|
45
|
-
{item.description}
|
|
46
|
-
</p>
|
|
47
|
-
)}
|
|
48
|
-
</AnchorLink>
|
|
49
|
-
</NavigationMenuLink>
|
|
50
|
-
);
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const DropdownContent = ({
|
|
54
|
-
items,
|
|
55
|
-
}: {
|
|
56
|
-
items: Array<HeaderNavLinkItem | HeaderNavGroup>;
|
|
57
|
-
}) => {
|
|
58
|
-
return items.some(isHeaderNavGroup) ? (
|
|
59
|
-
<div className="flex gap-4 p-4">
|
|
60
|
-
{items.map((item) =>
|
|
61
|
-
isHeaderNavGroup(item) ? (
|
|
62
|
-
<div key={item.label} className="min-w-[200px]">
|
|
63
|
-
<div className="mb-2 px-3 text-sm font-medium text-muted-foreground">
|
|
64
|
-
{item.label}
|
|
65
|
-
</div>
|
|
66
|
-
<ul className="flex flex-col gap-1">
|
|
67
|
-
{item.items.map((subItem) => (
|
|
68
|
-
<li key={subItem.to}>
|
|
69
|
-
<NavLinkItem item={subItem} />
|
|
70
|
-
</li>
|
|
71
|
-
))}
|
|
72
|
-
</ul>
|
|
73
|
-
</div>
|
|
74
|
-
) : (
|
|
75
|
-
<div key={item.to}>
|
|
76
|
-
<NavLinkItem item={item} />
|
|
77
|
-
</div>
|
|
78
|
-
),
|
|
79
|
-
)}
|
|
80
|
-
</div>
|
|
81
|
-
) : (
|
|
82
|
-
<ul className="grid gap-1 p-3 w-[400px] md:grid-cols-2">
|
|
83
|
-
{items.flatMap((item) =>
|
|
84
|
-
!isHeaderNavGroup(item) ? (
|
|
85
|
-
<li key={item.to}>
|
|
86
|
-
<NavLinkItem item={item} />
|
|
87
|
-
</li>
|
|
88
|
-
) : (
|
|
89
|
-
[]
|
|
90
|
-
),
|
|
91
|
-
)}
|
|
92
|
-
</ul>
|
|
93
|
-
);
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
const HeaderNavItemComponent = ({
|
|
97
|
-
item,
|
|
98
|
-
auth,
|
|
99
|
-
context,
|
|
100
|
-
}: {
|
|
101
|
-
item: HeaderNavItem;
|
|
102
|
-
auth: ReturnType<typeof useAuth>;
|
|
103
|
-
context: ZudokuContext;
|
|
104
|
-
}) => {
|
|
105
|
-
if ("to" in item) {
|
|
106
|
-
const show = shouldShowItem({ auth, context })({
|
|
107
|
-
type: "link",
|
|
108
|
-
label: item.label,
|
|
109
|
-
to: item.to,
|
|
110
|
-
display: item.display,
|
|
111
|
-
});
|
|
112
|
-
if (!show) return null;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if ("to" in item) {
|
|
116
|
-
const Icon = item.icon as LucideIcon | undefined;
|
|
117
|
-
return (
|
|
118
|
-
<NavigationMenuItem>
|
|
119
|
-
<NavigationMenuLink asChild>
|
|
120
|
-
<AnchorLink
|
|
121
|
-
to={item.to}
|
|
122
|
-
target={item.target}
|
|
123
|
-
rel={item.target === "_blank" ? "noopener noreferrer" : undefined}
|
|
124
|
-
className={marketingNavLinkClassName}
|
|
125
|
-
>
|
|
126
|
-
{Icon && <Icon size={16} />}
|
|
127
|
-
{item.label}
|
|
128
|
-
</AnchorLink>
|
|
129
|
-
</NavigationMenuLink>
|
|
130
|
-
</NavigationMenuItem>
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return (
|
|
135
|
-
<NavigationMenuItem>
|
|
136
|
-
<NavigationMenuTrigger className="bg-transparent">
|
|
137
|
-
{item.label}
|
|
138
|
-
</NavigationMenuTrigger>
|
|
139
|
-
<NavigationMenuContent>
|
|
140
|
-
<DropdownContent items={item.items} />
|
|
141
|
-
</NavigationMenuContent>
|
|
142
|
-
</NavigationMenuItem>
|
|
143
|
-
);
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
export const HeaderNavigation = () => {
|
|
147
|
-
const context = useZudoku();
|
|
148
|
-
const auth = useAuth();
|
|
149
|
-
const items = withoutMarketingCtaHeaderNavigation(
|
|
150
|
-
context.options.header?.navigation ?? [],
|
|
151
|
-
);
|
|
152
|
-
const navPosition = context.options.header?.placements?.navigation ?? "start";
|
|
153
|
-
if (!items || items.length === 0) return null;
|
|
154
|
-
|
|
155
|
-
const viewportAlign =
|
|
156
|
-
navPosition === "end"
|
|
157
|
-
? "**:data-[slot=navigation-menu-viewport-wrapper]:left-auto **:data-[slot=navigation-menu-viewport-wrapper]:right-0"
|
|
158
|
-
: navPosition === "center"
|
|
159
|
-
? "**:data-[slot=navigation-menu-viewport-wrapper]:left-1/2 **:data-[slot=navigation-menu-viewport-wrapper]:-translate-x-1/2"
|
|
160
|
-
: undefined;
|
|
161
|
-
|
|
162
|
-
return (
|
|
163
|
-
<NavigationMenu className={cn("max-w-none", viewportAlign)}>
|
|
164
|
-
<NavigationMenuList className="gap-1">
|
|
165
|
-
{items.map((item) => (
|
|
166
|
-
<HeaderNavItemComponent
|
|
167
|
-
key={"to" in item ? item.to : item.label}
|
|
168
|
-
item={item}
|
|
169
|
-
auth={auth}
|
|
170
|
-
context={context}
|
|
171
|
-
/>
|
|
172
|
-
))}
|
|
173
|
-
</NavigationMenuList>
|
|
174
|
-
</NavigationMenu>
|
|
175
|
-
);
|
|
176
|
-
};
|
|
1
|
+
import type { LucideIcon } from "lucide-react";
|
|
2
|
+
import { isHeaderNavGroup } from "../../config/header-navigation-guard.js";
|
|
3
|
+
import type {
|
|
4
|
+
HeaderNavGroup,
|
|
5
|
+
HeaderNavItem,
|
|
6
|
+
HeaderNavLinkItem,
|
|
7
|
+
} from "../../config/validators/HeaderNavigationSchema.js";
|
|
8
|
+
import { withoutMarketingCtaHeaderNavigation } from "../authentication/header-nav-filter.js";
|
|
9
|
+
import { useAuth } from "../authentication/hook.js";
|
|
10
|
+
import type { ZudokuContext } from "../core/ZudokuContext.js";
|
|
11
|
+
import {
|
|
12
|
+
NavigationMenu,
|
|
13
|
+
NavigationMenuContent,
|
|
14
|
+
NavigationMenuItem,
|
|
15
|
+
NavigationMenuLink,
|
|
16
|
+
NavigationMenuList,
|
|
17
|
+
NavigationMenuTrigger,
|
|
18
|
+
} from "../ui/NavigationMenu.js";
|
|
19
|
+
import { cn } from "../util/cn.js";
|
|
20
|
+
import { AnchorLink } from "./AnchorLink.js";
|
|
21
|
+
import { useZudoku } from "./context/ZudokuContext.js";
|
|
22
|
+
import { shouldShowItem } from "./navigation/utils.js";
|
|
23
|
+
|
|
24
|
+
const marketingNavLinkClassName =
|
|
25
|
+
"inline-flex items-center gap-2 rounded-lg px-3 py-2 text-sm font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground";
|
|
26
|
+
|
|
27
|
+
const NavLinkItem = ({ item }: { item: HeaderNavLinkItem }) => {
|
|
28
|
+
const Icon = item.icon as LucideIcon | undefined;
|
|
29
|
+
return (
|
|
30
|
+
<NavigationMenuLink asChild>
|
|
31
|
+
<AnchorLink
|
|
32
|
+
to={item.to}
|
|
33
|
+
target={item.target}
|
|
34
|
+
rel={item.target === "_blank" ? "noopener noreferrer" : undefined}
|
|
35
|
+
className="block select-none rounded-md p-3 leading-none no-underline outline-hidden transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground"
|
|
36
|
+
>
|
|
37
|
+
<div className="flex items-center gap-2">
|
|
38
|
+
{Icon && (
|
|
39
|
+
<Icon size={16} className="shrink-0 text-muted-foreground" />
|
|
40
|
+
)}
|
|
41
|
+
<div className="text-sm font-medium leading-none">{item.label}</div>
|
|
42
|
+
</div>
|
|
43
|
+
{item.description && (
|
|
44
|
+
<p className="line-clamp-2 text-sm leading-snug text-muted-foreground mt-1.5">
|
|
45
|
+
{item.description}
|
|
46
|
+
</p>
|
|
47
|
+
)}
|
|
48
|
+
</AnchorLink>
|
|
49
|
+
</NavigationMenuLink>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const DropdownContent = ({
|
|
54
|
+
items,
|
|
55
|
+
}: {
|
|
56
|
+
items: Array<HeaderNavLinkItem | HeaderNavGroup>;
|
|
57
|
+
}) => {
|
|
58
|
+
return items.some(isHeaderNavGroup) ? (
|
|
59
|
+
<div className="flex gap-4 p-4">
|
|
60
|
+
{items.map((item) =>
|
|
61
|
+
isHeaderNavGroup(item) ? (
|
|
62
|
+
<div key={item.label} className="min-w-[200px]">
|
|
63
|
+
<div className="mb-2 px-3 text-sm font-medium text-muted-foreground">
|
|
64
|
+
{item.label}
|
|
65
|
+
</div>
|
|
66
|
+
<ul className="flex flex-col gap-1">
|
|
67
|
+
{item.items.map((subItem) => (
|
|
68
|
+
<li key={subItem.to}>
|
|
69
|
+
<NavLinkItem item={subItem} />
|
|
70
|
+
</li>
|
|
71
|
+
))}
|
|
72
|
+
</ul>
|
|
73
|
+
</div>
|
|
74
|
+
) : (
|
|
75
|
+
<div key={item.to}>
|
|
76
|
+
<NavLinkItem item={item} />
|
|
77
|
+
</div>
|
|
78
|
+
),
|
|
79
|
+
)}
|
|
80
|
+
</div>
|
|
81
|
+
) : (
|
|
82
|
+
<ul className="grid gap-1 p-3 w-[400px] md:grid-cols-2">
|
|
83
|
+
{items.flatMap((item) =>
|
|
84
|
+
!isHeaderNavGroup(item) ? (
|
|
85
|
+
<li key={item.to}>
|
|
86
|
+
<NavLinkItem item={item} />
|
|
87
|
+
</li>
|
|
88
|
+
) : (
|
|
89
|
+
[]
|
|
90
|
+
),
|
|
91
|
+
)}
|
|
92
|
+
</ul>
|
|
93
|
+
);
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const HeaderNavItemComponent = ({
|
|
97
|
+
item,
|
|
98
|
+
auth,
|
|
99
|
+
context,
|
|
100
|
+
}: {
|
|
101
|
+
item: HeaderNavItem;
|
|
102
|
+
auth: ReturnType<typeof useAuth>;
|
|
103
|
+
context: ZudokuContext;
|
|
104
|
+
}) => {
|
|
105
|
+
if ("to" in item) {
|
|
106
|
+
const show = shouldShowItem({ auth, context })({
|
|
107
|
+
type: "link",
|
|
108
|
+
label: item.label,
|
|
109
|
+
to: item.to,
|
|
110
|
+
display: item.display,
|
|
111
|
+
});
|
|
112
|
+
if (!show) return null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if ("to" in item) {
|
|
116
|
+
const Icon = item.icon as LucideIcon | undefined;
|
|
117
|
+
return (
|
|
118
|
+
<NavigationMenuItem>
|
|
119
|
+
<NavigationMenuLink asChild>
|
|
120
|
+
<AnchorLink
|
|
121
|
+
to={item.to}
|
|
122
|
+
target={item.target}
|
|
123
|
+
rel={item.target === "_blank" ? "noopener noreferrer" : undefined}
|
|
124
|
+
className={marketingNavLinkClassName}
|
|
125
|
+
>
|
|
126
|
+
{Icon && <Icon size={16} />}
|
|
127
|
+
{item.label}
|
|
128
|
+
</AnchorLink>
|
|
129
|
+
</NavigationMenuLink>
|
|
130
|
+
</NavigationMenuItem>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return (
|
|
135
|
+
<NavigationMenuItem>
|
|
136
|
+
<NavigationMenuTrigger className="bg-transparent">
|
|
137
|
+
{item.label}
|
|
138
|
+
</NavigationMenuTrigger>
|
|
139
|
+
<NavigationMenuContent>
|
|
140
|
+
<DropdownContent items={item.items} />
|
|
141
|
+
</NavigationMenuContent>
|
|
142
|
+
</NavigationMenuItem>
|
|
143
|
+
);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
export const HeaderNavigation = () => {
|
|
147
|
+
const context = useZudoku();
|
|
148
|
+
const auth = useAuth();
|
|
149
|
+
const items = withoutMarketingCtaHeaderNavigation(
|
|
150
|
+
context.options.header?.navigation ?? [],
|
|
151
|
+
);
|
|
152
|
+
const navPosition = context.options.header?.placements?.navigation ?? "start";
|
|
153
|
+
if (!items || items.length === 0) return null;
|
|
154
|
+
|
|
155
|
+
const viewportAlign =
|
|
156
|
+
navPosition === "end"
|
|
157
|
+
? "**:data-[slot=navigation-menu-viewport-wrapper]:left-auto **:data-[slot=navigation-menu-viewport-wrapper]:right-0"
|
|
158
|
+
: navPosition === "center"
|
|
159
|
+
? "**:data-[slot=navigation-menu-viewport-wrapper]:left-1/2 **:data-[slot=navigation-menu-viewport-wrapper]:-translate-x-1/2"
|
|
160
|
+
: undefined;
|
|
161
|
+
|
|
162
|
+
return (
|
|
163
|
+
<NavigationMenu className={cn("max-w-none", viewportAlign)}>
|
|
164
|
+
<NavigationMenuList className="gap-1">
|
|
165
|
+
{items.map((item) => (
|
|
166
|
+
<HeaderNavItemComponent
|
|
167
|
+
key={"to" in item ? item.to : item.label}
|
|
168
|
+
item={item}
|
|
169
|
+
auth={auth}
|
|
170
|
+
context={context}
|
|
171
|
+
/>
|
|
172
|
+
))}
|
|
173
|
+
</NavigationMenuList>
|
|
174
|
+
</NavigationMenu>
|
|
175
|
+
);
|
|
176
|
+
};
|