@lukoweb/apitogo 0.1.69 → 0.1.71
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 +1 -1
- package/dist/declarations/lib/authentication/providers/dev-portal.d.ts +1 -0
- package/docs/mcp/shape.md +1 -1
- package/docs/mcp/tools.md +1 -1
- package/package.json +1 -1
- package/src/lib/authentication/providers/dev-portal-utils.ts +3 -7
- package/src/lib/authentication/providers/dev-portal.tsx +29 -15
- package/src/lib/authentication/state.ts +26 -33
package/dist/cli/cli.js
CHANGED
|
@@ -34,6 +34,7 @@ export declare class DevPortalAuthenticationProvider extends CoreAuthenticationP
|
|
|
34
34
|
onPageLoad: () => Promise<void>;
|
|
35
35
|
private syncBackendAvailability;
|
|
36
36
|
private setPreviewState;
|
|
37
|
+
private setLiveUnauthenticatedState;
|
|
37
38
|
private setDemoAuthenticatedState;
|
|
38
39
|
private ensureConfiguredBackend;
|
|
39
40
|
refreshUserProfile(): Promise<boolean>;
|
package/docs/mcp/shape.md
CHANGED
|
@@ -60,7 +60,7 @@ Ask only for what is missing:
|
|
|
60
60
|
|
|
61
61
|
Use MCP tools (see [Tools](./tools.md)):
|
|
62
62
|
|
|
63
|
-
- Pages → `add_dev_portal_page` / `update_dev_portal_page` (TSX
|
|
63
|
+
- Pages → `add_dev_portal_page` / `update_dev_portal_page` (TSX only; `template`: docs|guide|marketing)
|
|
64
64
|
- OpenAPI → `set_dev_portal_openapi`
|
|
65
65
|
- Plans / branding → `update_dev_portal_manifest`
|
|
66
66
|
- Theme → `set_dev_portal_theme`
|
package/docs/mcp/tools.md
CHANGED
|
@@ -27,7 +27,7 @@ go-live. Use granular tools for advanced edits, debugging, or CI.
|
|
|
27
27
|
| `update_dev_portal_manifest` | Plans, branding, backend, projectId |
|
|
28
28
|
| `set_dev_portal_openapi` | OpenAPI / API reference |
|
|
29
29
|
| `set_dev_portal_theme` | Colors and fonts |
|
|
30
|
-
| `add_dev_portal_page` | Add a docs page (
|
|
30
|
+
| `add_dev_portal_page` | Add a TSX docs page (site components; `template`: docs\|guide\|marketing) |
|
|
31
31
|
| `update_dev_portal_page` | Edit a docs page |
|
|
32
32
|
| `scaffold_dev_portal_landing_page`| Scaffold missing landing file |
|
|
33
33
|
| `get_dev_portal_landing_guide` | Landing component catalog |
|
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { DevPortalAuthenticationConfig } from "../../../config/config.js";
|
|
2
2
|
import {
|
|
3
3
|
DEV_PORTAL_PLACEHOLDER_API_URL,
|
|
4
|
-
type DevPortalAuthStatusResponse,
|
|
5
4
|
type UserMeResponse,
|
|
6
5
|
} from "./dev-portal-constants.js";
|
|
7
6
|
|
|
@@ -220,12 +219,9 @@ export async function probeDevPortalBackend(
|
|
|
220
219
|
signal: controller.signal,
|
|
221
220
|
});
|
|
222
221
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
const body = (await response.json()) as DevPortalAuthStatusResponse;
|
|
228
|
-
return body.available === true;
|
|
222
|
+
// HTTP 200 means the portal API is reachable. `available` is whether
|
|
223
|
+
// sign-in methods are configured — do not treat empty auth as unpublished.
|
|
224
|
+
return response.ok;
|
|
229
225
|
} catch {
|
|
230
226
|
return false;
|
|
231
227
|
} finally {
|
|
@@ -213,6 +213,28 @@ export class DevPortalAuthenticationProvider
|
|
|
213
213
|
});
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
+
private setLiveUnauthenticatedState(): void {
|
|
217
|
+
if (!this.apiBaseUrl) {
|
|
218
|
+
this.setPreviewState();
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
useAuthState.setState({
|
|
223
|
+
isAuthenticated: false,
|
|
224
|
+
isPending: false,
|
|
225
|
+
sessionChecked: true,
|
|
226
|
+
profile: null,
|
|
227
|
+
providerData: {
|
|
228
|
+
type: "dev-portal",
|
|
229
|
+
apiBaseUrl: this.apiBaseUrl,
|
|
230
|
+
authMode: "live",
|
|
231
|
+
demoMode: this.demoMode,
|
|
232
|
+
},
|
|
233
|
+
isBackendAvailable: true,
|
|
234
|
+
authMode: "live",
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
216
238
|
private setDemoAuthenticatedState(): void {
|
|
217
239
|
activateDemoSession(this.apiBaseUrl);
|
|
218
240
|
}
|
|
@@ -295,25 +317,12 @@ export class DevPortalAuthenticationProvider
|
|
|
295
317
|
response.status === 302 ||
|
|
296
318
|
response.status === 401
|
|
297
319
|
) {
|
|
298
|
-
|
|
299
|
-
isAuthenticated: false,
|
|
300
|
-
isPending: false,
|
|
301
|
-
sessionChecked: true,
|
|
302
|
-
profile: null,
|
|
303
|
-
providerData: {
|
|
304
|
-
type: "dev-portal",
|
|
305
|
-
apiBaseUrl: this.apiBaseUrl,
|
|
306
|
-
authMode: "live",
|
|
307
|
-
demoMode: this.demoMode,
|
|
308
|
-
},
|
|
309
|
-
isBackendAvailable: true,
|
|
310
|
-
authMode: "live",
|
|
311
|
-
});
|
|
320
|
+
this.setLiveUnauthenticatedState();
|
|
312
321
|
return false;
|
|
313
322
|
}
|
|
314
323
|
|
|
315
324
|
if (!response.ok) {
|
|
316
|
-
this.
|
|
325
|
+
this.setLiveUnauthenticatedState();
|
|
317
326
|
return false;
|
|
318
327
|
}
|
|
319
328
|
|
|
@@ -344,6 +353,11 @@ export class DevPortalAuthenticationProvider
|
|
|
344
353
|
return useAuthState.getState().isAuthenticated;
|
|
345
354
|
}
|
|
346
355
|
|
|
356
|
+
if (this.backendAvailable) {
|
|
357
|
+
this.setLiveUnauthenticatedState();
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
360
|
+
|
|
347
361
|
this.setPreviewState();
|
|
348
362
|
return false;
|
|
349
363
|
}
|
|
@@ -94,32 +94,12 @@ function createAuthStateStore(): AuthStateStore {
|
|
|
94
94
|
})),
|
|
95
95
|
}),
|
|
96
96
|
{
|
|
97
|
-
version:
|
|
98
|
-
migrate: (
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
// v0 stored full auth identity in localStorage; keep only backend metadata.
|
|
105
|
-
if (version === 0) {
|
|
106
|
-
return {
|
|
107
|
-
isBackendAvailable: persisted.isBackendAvailable,
|
|
108
|
-
authMode: persisted.authMode,
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return persisted;
|
|
113
|
-
},
|
|
114
|
-
merge: (persistedState, currentState) => {
|
|
115
|
-
const persisted =
|
|
116
|
-
typeof persistedState === "object" && persistedState !== null
|
|
117
|
-
? (persistedState as Partial<AuthState>)
|
|
118
|
-
: {};
|
|
119
|
-
|
|
120
|
-
// Cookie/session auth is refreshed from the backend on load. Do not
|
|
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).
|
|
97
|
+
version: 2,
|
|
98
|
+
migrate: () => ({}),
|
|
99
|
+
merge: (_persistedState, currentState) => {
|
|
100
|
+
// Cookie/session auth is refreshed from the backend on load. Never
|
|
101
|
+
// restore preview flags — a prior empty Auth__ConfigJson used to
|
|
102
|
+
// persist isBackendAvailable: false and lock account routes.
|
|
123
103
|
return {
|
|
124
104
|
...currentState,
|
|
125
105
|
isPending: true,
|
|
@@ -127,15 +107,11 @@ function createAuthStateStore(): AuthStateStore {
|
|
|
127
107
|
isAuthenticated: currentState.isAuthenticated,
|
|
128
108
|
profile: currentState.profile,
|
|
129
109
|
providerData: currentState.providerData,
|
|
130
|
-
isBackendAvailable:
|
|
131
|
-
|
|
132
|
-
authMode: persisted.authMode ?? currentState.authMode,
|
|
110
|
+
isBackendAvailable: currentState.isBackendAvailable,
|
|
111
|
+
authMode: currentState.authMode,
|
|
133
112
|
};
|
|
134
113
|
},
|
|
135
|
-
partialize: (
|
|
136
|
-
isBackendAvailable: state.isBackendAvailable,
|
|
137
|
-
authMode: state.authMode,
|
|
138
|
-
}),
|
|
114
|
+
partialize: () => ({}),
|
|
139
115
|
name: "auth-state",
|
|
140
116
|
storage: createJSONStorage(() => localStorage),
|
|
141
117
|
},
|
|
@@ -158,9 +134,17 @@ export const waitForAuthStateHydration = (): Promise<void> => {
|
|
|
158
134
|
}
|
|
159
135
|
|
|
160
136
|
const { persist } = useAuthState;
|
|
137
|
+
if (!persist) {
|
|
138
|
+
return Promise.resolve();
|
|
139
|
+
}
|
|
161
140
|
|
|
162
141
|
return new Promise((resolve) => {
|
|
142
|
+
let settled = false;
|
|
163
143
|
const finish = () => {
|
|
144
|
+
if (settled) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
settled = true;
|
|
164
148
|
// Let hydration merge flush before /auth/me refresh runs.
|
|
165
149
|
queueMicrotask(resolve);
|
|
166
150
|
};
|
|
@@ -174,6 +158,15 @@ export const waitForAuthStateHydration = (): Promise<void> => {
|
|
|
174
158
|
unsubscribe();
|
|
175
159
|
finish();
|
|
176
160
|
});
|
|
161
|
+
|
|
162
|
+
if (persist.hasHydrated()) {
|
|
163
|
+
unsubscribe();
|
|
164
|
+
finish();
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// happy-dom / some browsers never fire onFinishHydration.
|
|
169
|
+
setTimeout(finish, 50);
|
|
177
170
|
});
|
|
178
171
|
};
|
|
179
172
|
|