@lukoweb/apitogo 0.1.40 → 0.1.42
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 +2 -2
- package/dist/declarations/lib/authentication/state.d.ts +1 -0
- package/dist/declarations/lib/components/context/ZudokuProvider.d.ts +1 -1
- package/package.json +111 -30
- package/src/lib/authentication/providers/dev-portal.tsx +3 -0
- package/src/lib/authentication/state.ts +9 -1
- package/src/lib/components/HeaderNavigation.tsx +3 -4
- package/src/lib/components/Zudoku.tsx +4 -5
- package/src/lib/components/context/ZudokuProvider.tsx +1 -3
- package/src/lib/core/RouteGuard.tsx +14 -1
- package/src/lib/testing/index.tsx +1 -0
- package/src/vite/plugin-auth.ts +1 -5
package/dist/cli/cli.js
CHANGED
|
@@ -4124,7 +4124,7 @@ import {
|
|
|
4124
4124
|
// package.json
|
|
4125
4125
|
var package_default = {
|
|
4126
4126
|
name: "@lukoweb/apitogo",
|
|
4127
|
-
version: "0.1.
|
|
4127
|
+
version: "0.1.42",
|
|
4128
4128
|
type: "module",
|
|
4129
4129
|
sideEffects: [
|
|
4130
4130
|
"**/*.css",
|
|
@@ -6761,7 +6761,7 @@ var viteAuthPlugin = () => {
|
|
|
6761
6761
|
async load(id) {
|
|
6762
6762
|
if (id === resolvedVirtualModuleId4) {
|
|
6763
6763
|
const config2 = getCurrentConfig();
|
|
6764
|
-
if (!config2.authentication ||
|
|
6764
|
+
if (!config2.authentication || config2.__meta.mode === "standalone") {
|
|
6765
6765
|
return `export const configuredAuthProvider = undefined;`;
|
|
6766
6766
|
}
|
|
6767
6767
|
return [
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { PropsWithChildren } from "react";
|
|
2
2
|
import type { ZudokuContext } from "../../core/ZudokuContext.js";
|
|
3
3
|
export declare const ZudokuProvider: ({ children, context, }: PropsWithChildren<{
|
|
4
4
|
context: ZudokuContext;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lukoweb/apitogo",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.42",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"**/*.css",
|
|
@@ -27,48 +27,129 @@
|
|
|
27
27
|
"apitogo": "./cli.js"
|
|
28
28
|
},
|
|
29
29
|
"exports": {
|
|
30
|
-
".":
|
|
30
|
+
".": {
|
|
31
|
+
"types": "./dist/declarations/index.d.ts",
|
|
32
|
+
"default": "./src/index.ts"
|
|
33
|
+
},
|
|
31
34
|
"./package.json": "./package.json",
|
|
32
35
|
"./ui/*": {
|
|
33
|
-
"types": "./
|
|
36
|
+
"types": "./dist/declarations/lib/ui/*.d.ts",
|
|
34
37
|
"default": "./src/lib/ui/*.tsx"
|
|
35
38
|
},
|
|
36
39
|
"./ui/*.js": {
|
|
37
|
-
"types": "./
|
|
40
|
+
"types": "./dist/declarations/lib/ui/*.d.ts",
|
|
38
41
|
"default": "./src/lib/ui/*.tsx"
|
|
39
42
|
},
|
|
40
43
|
"./client": {
|
|
41
44
|
"types": "./client.d.ts"
|
|
42
45
|
},
|
|
43
|
-
"./auth/clerk":
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"./auth/
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"./
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"./
|
|
56
|
-
|
|
57
|
-
|
|
46
|
+
"./auth/clerk": {
|
|
47
|
+
"types": "./dist/declarations/lib/authentication/providers/clerk.d.ts",
|
|
48
|
+
"default": "./src/lib/authentication/providers/clerk.tsx"
|
|
49
|
+
},
|
|
50
|
+
"./auth/auth0": {
|
|
51
|
+
"types": "./dist/declarations/lib/authentication/providers/auth0.d.ts",
|
|
52
|
+
"default": "./src/lib/authentication/providers/auth0.tsx"
|
|
53
|
+
},
|
|
54
|
+
"./auth/openid": {
|
|
55
|
+
"types": "./dist/declarations/lib/authentication/providers/openid.d.ts",
|
|
56
|
+
"default": "./src/lib/authentication/providers/openid.tsx"
|
|
57
|
+
},
|
|
58
|
+
"./auth/supabase": {
|
|
59
|
+
"types": "./dist/declarations/lib/authentication/providers/supabase.d.ts",
|
|
60
|
+
"default": "./src/lib/authentication/providers/supabase.tsx"
|
|
61
|
+
},
|
|
62
|
+
"./auth/azureb2c": {
|
|
63
|
+
"types": "./dist/declarations/lib/authentication/providers/azureb2c.d.ts",
|
|
64
|
+
"default": "./src/lib/authentication/providers/azureb2c.tsx"
|
|
65
|
+
},
|
|
66
|
+
"./auth/firebase": {
|
|
67
|
+
"types": "./dist/declarations/lib/authentication/providers/firebase.d.ts",
|
|
68
|
+
"default": "./src/lib/authentication/providers/firebase.tsx"
|
|
69
|
+
},
|
|
70
|
+
"./auth/dev-portal": {
|
|
71
|
+
"types": "./dist/declarations/lib/authentication/providers/dev-portal.d.ts",
|
|
72
|
+
"default": "./src/lib/authentication/providers/dev-portal.tsx"
|
|
73
|
+
},
|
|
74
|
+
"./plugins": {
|
|
75
|
+
"types": "./dist/declarations/lib/core/plugins.d.ts",
|
|
76
|
+
"default": "./src/lib/core/plugins.ts"
|
|
77
|
+
},
|
|
78
|
+
"./plugins/api-keys": {
|
|
79
|
+
"types": "./dist/declarations/lib/plugins/api-keys/index.d.ts",
|
|
80
|
+
"default": "./src/lib/plugins/api-keys/index.tsx"
|
|
81
|
+
},
|
|
82
|
+
"./plugins/markdown": {
|
|
83
|
+
"types": "./dist/declarations/lib/plugins/markdown/index.d.ts",
|
|
84
|
+
"default": "./src/lib/plugins/markdown/index.tsx"
|
|
85
|
+
},
|
|
86
|
+
"./plugins/openapi": {
|
|
87
|
+
"types": "./dist/declarations/lib/plugins/openapi/index.d.ts",
|
|
88
|
+
"default": "./src/lib/plugins/openapi/index.tsx"
|
|
89
|
+
},
|
|
90
|
+
"./plugins/custom-pages": {
|
|
91
|
+
"types": "./dist/declarations/lib/plugins/custom-pages/index.d.ts",
|
|
92
|
+
"default": "./src/lib/plugins/custom-pages/index.tsx"
|
|
93
|
+
},
|
|
94
|
+
"./plugins/search-inkeep": {
|
|
95
|
+
"types": "./dist/declarations/lib/plugins/search-inkeep/index.d.ts",
|
|
96
|
+
"default": "./src/lib/plugins/search-inkeep/index.tsx"
|
|
97
|
+
},
|
|
98
|
+
"./plugins/search-pagefind": {
|
|
99
|
+
"types": "./dist/declarations/lib/plugins/search-pagefind/index.d.ts",
|
|
100
|
+
"default": "./src/lib/plugins/search-pagefind/index.tsx"
|
|
101
|
+
},
|
|
102
|
+
"./plugins/api-catalog": {
|
|
103
|
+
"types": "./dist/declarations/lib/plugins/api-catalog/index.d.ts",
|
|
104
|
+
"default": "./src/lib/plugins/api-catalog/index.tsx"
|
|
105
|
+
},
|
|
58
106
|
"./modules/landing": "@lukoweb/apitogo-module-landing",
|
|
59
107
|
"./modules/user-panel": "@lukoweb/apitogo-module-user-panel",
|
|
60
|
-
"./components":
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
"./
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
108
|
+
"./components": {
|
|
109
|
+
"types": "./dist/declarations/lib/components/index.d.ts",
|
|
110
|
+
"default": "./src/lib/components/index.ts"
|
|
111
|
+
},
|
|
112
|
+
"./mermaid": {
|
|
113
|
+
"types": "./dist/declarations/lib/components/Mermaid.d.ts",
|
|
114
|
+
"default": "./src/lib/components/Mermaid.tsx"
|
|
115
|
+
},
|
|
116
|
+
"./router": {
|
|
117
|
+
"types": "./dist/declarations/lib/core/router.d.ts",
|
|
118
|
+
"default": "./src/lib/core/router.ts"
|
|
119
|
+
},
|
|
120
|
+
"./react-query": {
|
|
121
|
+
"types": "./dist/declarations/lib/core/react-query.d.ts",
|
|
122
|
+
"default": "./src/lib/core/react-query.ts"
|
|
123
|
+
},
|
|
124
|
+
"./icons": {
|
|
125
|
+
"types": "./dist/declarations/lib/icons.d.ts",
|
|
126
|
+
"default": "./src/lib/icons.ts"
|
|
127
|
+
},
|
|
128
|
+
"./vite": {
|
|
129
|
+
"types": "./dist/declarations/vite/index.d.ts",
|
|
130
|
+
"default": "./src/vite/index.ts"
|
|
131
|
+
},
|
|
132
|
+
"./app/*": {
|
|
133
|
+
"types": "./dist/declarations/app/*.d.ts",
|
|
134
|
+
"default": "./src/app/*"
|
|
135
|
+
},
|
|
136
|
+
"./hooks": {
|
|
137
|
+
"types": "./dist/declarations/lib/hooks/index.d.ts",
|
|
138
|
+
"default": "./src/lib/hooks/index.ts"
|
|
139
|
+
},
|
|
68
140
|
"./main.css": "./src/app/main.css",
|
|
69
|
-
"./processors/*":
|
|
70
|
-
|
|
71
|
-
|
|
141
|
+
"./processors/*": {
|
|
142
|
+
"types": "./dist/declarations/lib/plugins/openapi/processors/*.d.ts",
|
|
143
|
+
"default": "./src/lib/plugins/openapi/processors/*.ts"
|
|
144
|
+
},
|
|
145
|
+
"./with-zuplo": {
|
|
146
|
+
"types": "./dist/declarations/zuplo/with-zuplo.d.ts",
|
|
147
|
+
"default": "./src/zuplo/with-zuplo.ts"
|
|
148
|
+
},
|
|
149
|
+
"./testing": {
|
|
150
|
+
"types": "./dist/declarations/lib/testing/index.d.ts",
|
|
151
|
+
"default": "./src/lib/testing/index.tsx"
|
|
152
|
+
}
|
|
72
153
|
},
|
|
73
154
|
"scripts": {
|
|
74
155
|
"build": "esbuild src/cli/cli.ts src/vite/prerender/worker.ts --outdir=dist/cli --entry-names=[name] --bundle --format=esm --packages=external --target=node20 --platform=node --log-level=error",
|
|
@@ -106,6 +106,7 @@ export class DevPortalAuthenticationProvider
|
|
|
106
106
|
useAuthState.setState({
|
|
107
107
|
isAuthenticated: false,
|
|
108
108
|
isPending: false,
|
|
109
|
+
sessionChecked: true,
|
|
109
110
|
profile: null,
|
|
110
111
|
providerData: this.apiBaseUrl
|
|
111
112
|
? {
|
|
@@ -181,6 +182,7 @@ export class DevPortalAuthenticationProvider
|
|
|
181
182
|
useAuthState.setState({
|
|
182
183
|
isAuthenticated: false,
|
|
183
184
|
isPending: false,
|
|
185
|
+
sessionChecked: true,
|
|
184
186
|
profile: null,
|
|
185
187
|
providerData: {
|
|
186
188
|
type: "dev-portal",
|
|
@@ -208,6 +210,7 @@ export class DevPortalAuthenticationProvider
|
|
|
208
210
|
useAuthState.setState({
|
|
209
211
|
isAuthenticated: true,
|
|
210
212
|
isPending: false,
|
|
213
|
+
sessionChecked: true,
|
|
211
214
|
profile,
|
|
212
215
|
providerData: {
|
|
213
216
|
type: "dev-portal",
|
|
@@ -26,6 +26,8 @@ export type AuthMode = "live" | "preview";
|
|
|
26
26
|
export interface AuthState {
|
|
27
27
|
isAuthenticated: boolean;
|
|
28
28
|
isPending: boolean;
|
|
29
|
+
/** True after the auth provider has finished its first session probe on load. */
|
|
30
|
+
sessionChecked: boolean;
|
|
29
31
|
profile: UserProfile | null;
|
|
30
32
|
providerData: ProviderData | null;
|
|
31
33
|
/** False when dev-portal backend is unavailable (local preview). Defaults true. */
|
|
@@ -57,6 +59,7 @@ function createAuthStateStore(): AuthStateStore {
|
|
|
57
59
|
(set) => ({
|
|
58
60
|
isAuthenticated: false,
|
|
59
61
|
isPending: true,
|
|
62
|
+
sessionChecked: false,
|
|
60
63
|
profile: null,
|
|
61
64
|
providerData: null,
|
|
62
65
|
isBackendAvailable: true,
|
|
@@ -65,6 +68,7 @@ function createAuthStateStore(): AuthStateStore {
|
|
|
65
68
|
set(() => ({
|
|
66
69
|
isAuthenticated: false,
|
|
67
70
|
isPending: false,
|
|
71
|
+
sessionChecked: true,
|
|
68
72
|
profile: null,
|
|
69
73
|
providerData: null,
|
|
70
74
|
isBackendAvailable: true,
|
|
@@ -74,6 +78,7 @@ function createAuthStateStore(): AuthStateStore {
|
|
|
74
78
|
set(() => ({
|
|
75
79
|
isAuthenticated: false,
|
|
76
80
|
isPending: false,
|
|
81
|
+
sessionChecked: true,
|
|
77
82
|
profile: null,
|
|
78
83
|
providerData: null,
|
|
79
84
|
isBackendAvailable: true,
|
|
@@ -83,6 +88,7 @@ function createAuthStateStore(): AuthStateStore {
|
|
|
83
88
|
set(() => ({
|
|
84
89
|
isAuthenticated: true,
|
|
85
90
|
isPending: false,
|
|
91
|
+
sessionChecked: true,
|
|
86
92
|
profile,
|
|
87
93
|
providerData,
|
|
88
94
|
})),
|
|
@@ -113,9 +119,11 @@ function createAuthStateStore(): AuthStateStore {
|
|
|
113
119
|
|
|
114
120
|
// Cookie/session auth is refreshed from the backend on load. Do not
|
|
115
121
|
// restore identity fields from localStorage or OIDC return looks logged out.
|
|
122
|
+
// Keep isPending true until the auth provider finishes /auth/me (or equivalent).
|
|
116
123
|
return {
|
|
117
124
|
...currentState,
|
|
118
|
-
isPending:
|
|
125
|
+
isPending: true,
|
|
126
|
+
sessionChecked: false,
|
|
119
127
|
isAuthenticated: currentState.isAuthenticated,
|
|
120
128
|
profile: currentState.profile,
|
|
121
129
|
providerData: currentState.providerData,
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
type HeaderNavLinkItem,
|
|
8
8
|
} from "../../config/validators/HeaderNavigationSchema.js";
|
|
9
9
|
import { useAuth } from "../authentication/hook.js";
|
|
10
|
-
import { shouldShowItem } from "./navigation/utils.js";
|
|
11
10
|
import type { ZudokuContext } from "../core/ZudokuContext.js";
|
|
12
11
|
import {
|
|
13
12
|
NavigationMenu,
|
|
@@ -20,6 +19,7 @@ import {
|
|
|
20
19
|
} from "../ui/NavigationMenu.js";
|
|
21
20
|
import { cn } from "../util/cn.js";
|
|
22
21
|
import { useZudoku } from "./context/ZudokuContext.js";
|
|
22
|
+
import { shouldShowItem } from "./navigation/utils.js";
|
|
23
23
|
|
|
24
24
|
const NavLinkItem = ({ item }: { item: HeaderNavLinkItem }) => {
|
|
25
25
|
const Icon = item.icon as LucideIcon | undefined;
|
|
@@ -160,10 +160,9 @@ export const HeaderNavigation = () => {
|
|
|
160
160
|
return (
|
|
161
161
|
<NavigationMenu className={viewportAlign}>
|
|
162
162
|
<NavigationMenuList>
|
|
163
|
-
{items.map((item
|
|
164
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: Stable because it's statically defined in the config
|
|
163
|
+
{items.map((item) => (
|
|
165
164
|
<HeaderNavItemComponent
|
|
166
|
-
key={
|
|
165
|
+
key={"to" in item ? item.to : item.label}
|
|
167
166
|
item={item}
|
|
168
167
|
auth={auth}
|
|
169
168
|
context={context}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
type PropsWithChildren,
|
|
7
7
|
useEffect,
|
|
8
8
|
useMemo,
|
|
9
|
+
useRef,
|
|
9
10
|
useState,
|
|
10
11
|
} from "react";
|
|
11
12
|
import { ErrorBoundary } from "react-error-boundary";
|
|
@@ -23,8 +24,6 @@ import { ViewportAnchorProvider } from "./context/ViewportAnchorContext.js";
|
|
|
23
24
|
import { ApitogoProvider } from "./context/ZudokuProvider.js";
|
|
24
25
|
import { PluginHeads } from "./PluginHeads.js";
|
|
25
26
|
|
|
26
|
-
let apitogoContext: ZudokuContext | undefined;
|
|
27
|
-
|
|
28
27
|
const ZudokuInner = memo(
|
|
29
28
|
({
|
|
30
29
|
children,
|
|
@@ -53,6 +52,8 @@ const ZudokuInner = memo(
|
|
|
53
52
|
const [didNavigate, setDidNavigate] = useState(false);
|
|
54
53
|
const navigation = useNavigation();
|
|
55
54
|
const queryClient = useQueryClient();
|
|
55
|
+
const apitogoContextRef = useRef<ZudokuContext | undefined>(undefined);
|
|
56
|
+
apitogoContextRef.current ??= new ZudokuContext(props, queryClient, env);
|
|
56
57
|
|
|
57
58
|
useEffect(() => {
|
|
58
59
|
if (didNavigate || !navigation.location) {
|
|
@@ -61,12 +62,10 @@ const ZudokuInner = memo(
|
|
|
61
62
|
setDidNavigate(true);
|
|
62
63
|
}, [didNavigate, navigation.location]);
|
|
63
64
|
|
|
64
|
-
apitogoContext ??= new ZudokuContext(props, queryClient, env);
|
|
65
|
-
|
|
66
65
|
return (
|
|
67
66
|
<>
|
|
68
67
|
<PluginHeads plugins={props.plugins ?? []} location={location} />
|
|
69
|
-
<ApitogoProvider context={
|
|
68
|
+
<ApitogoProvider context={apitogoContextRef.current}>
|
|
70
69
|
<RouterEventsEmitter />
|
|
71
70
|
<SlotProvider slots={props.slots ?? props.UNSAFE_slotlets}>
|
|
72
71
|
<MDXProvider components={mdxComponents}>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { PropsWithChildren } from "react";
|
|
2
2
|
import type { ZudokuContext } from "../../core/ZudokuContext.js";
|
|
3
3
|
import { ZudokuReactContext } from "./ZudokuReactContext.js";
|
|
4
4
|
|
|
@@ -6,8 +6,6 @@ const ZudokuProviderImpl = ({
|
|
|
6
6
|
children,
|
|
7
7
|
context,
|
|
8
8
|
}: PropsWithChildren<{ context: ZudokuContext }>) => {
|
|
9
|
-
if (context.initialize) use(context.initialize);
|
|
10
|
-
|
|
11
9
|
return (
|
|
12
10
|
<ZudokuReactContext.Provider value={context}>
|
|
13
11
|
{children}
|
|
@@ -179,8 +179,10 @@ export const RouteGuard = () => {
|
|
|
179
179
|
if (
|
|
180
180
|
!auth.isBackendAvailable ||
|
|
181
181
|
auth.isPending ||
|
|
182
|
+
!auth.sessionChecked ||
|
|
182
183
|
!needsAuth ||
|
|
183
|
-
auth.hasDistinctSignUpFlow
|
|
184
|
+
auth.hasDistinctSignUpFlow ||
|
|
185
|
+
!auth.isAuthEnabled
|
|
184
186
|
) {
|
|
185
187
|
unifiedRedirectKeyRef.current = null;
|
|
186
188
|
return;
|
|
@@ -195,7 +197,9 @@ export const RouteGuard = () => {
|
|
|
195
197
|
}, [
|
|
196
198
|
auth.isBackendAvailable,
|
|
197
199
|
auth.isPending,
|
|
200
|
+
auth.sessionChecked,
|
|
198
201
|
auth.hasDistinctSignUpFlow,
|
|
202
|
+
auth.isAuthEnabled,
|
|
199
203
|
auth.login,
|
|
200
204
|
needsAuth,
|
|
201
205
|
redirectTo,
|
|
@@ -210,6 +214,11 @@ export const RouteGuard = () => {
|
|
|
210
214
|
}
|
|
211
215
|
|
|
212
216
|
if (isProtectedRoute && !auth.isAuthEnabled) {
|
|
217
|
+
// Dev SSR can reuse a stale context before auth plugins hydrate; client decides.
|
|
218
|
+
if (typeof window === "undefined") {
|
|
219
|
+
return <BypassRoute isProtectedRoute={isProtectedRoute} />;
|
|
220
|
+
}
|
|
221
|
+
|
|
213
222
|
throw new ZudokuError("Authentication is not enabled", {
|
|
214
223
|
title: "Authentication is not enabled",
|
|
215
224
|
developerHint:
|
|
@@ -217,6 +226,10 @@ export const RouteGuard = () => {
|
|
|
217
226
|
});
|
|
218
227
|
}
|
|
219
228
|
|
|
229
|
+
if (needsToSignIn && !auth.sessionChecked && typeof window !== "undefined") {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
|
|
220
233
|
if (needsToSignIn && auth.isPending && typeof window !== "undefined") {
|
|
221
234
|
return null;
|
|
222
235
|
}
|
package/src/vite/plugin-auth.ts
CHANGED
|
@@ -16,11 +16,7 @@ const viteAuthPlugin = (): Plugin => {
|
|
|
16
16
|
if (id === resolvedVirtualModuleId) {
|
|
17
17
|
const config = getCurrentConfig();
|
|
18
18
|
|
|
19
|
-
if (
|
|
20
|
-
!config.authentication ||
|
|
21
|
-
!config.__resolvedModules.userPanel.userManagement.enabled ||
|
|
22
|
-
config.__meta.mode === "standalone"
|
|
23
|
-
) {
|
|
19
|
+
if (!config.authentication || config.__meta.mode === "standalone") {
|
|
24
20
|
return `export const configuredAuthProvider = undefined;`;
|
|
25
21
|
}
|
|
26
22
|
// TODO: Validate that the authConfig.type is a valid authentication provider
|