Skip to content

Commit 4ea9df5

Browse files
committed
Continue server API migration and remove remaining browser mock data paths - PR_26158_022-server-api-migration-pass-2
1 parent e200cb1 commit 4ea9df5

50 files changed

Lines changed: 728 additions & 427 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

admin/db-viewer.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ async function loadLocalDbViewer() {
3838
showGatewayStatus("Mock DB is available only in Local mode.");
3939
return;
4040
}
41-
const module = await import("../src/dev-runtime/admin/db-viewer.js");
42-
module.startDevRuntimeDbViewer(document);
41+
const module = await import("../src/engine/api/mock-db-viewer-ui.js");
42+
module.startMockDbViewer(document);
4343
}
4444

4545
loadLocalDbViewer().catch((error) => {

admin/tools-progress.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import {
22
getToolProgressReadiness,
33
getActiveToolRegistry,
4+
getToolRegistryApiDiagnostic,
45
getToolRoute,
56
toolRegistryMetadataDiagnostic
6-
} from "../toolbox/toolRegistry.js";
7+
} from "../toolbox/tool-registry-api-client.js";
78

89
const swatchByGroup = Object.freeze({
910
AI: "swatch-purple",
@@ -102,6 +103,20 @@ function renderToolsProgress() {
102103
return;
103104
}
104105

106+
const registryDiagnostic = getToolRegistryApiDiagnostic();
107+
if (registryDiagnostic) {
108+
progressBody.replaceChildren();
109+
const row = document.createElement("tr");
110+
const cell = createCell("td", `Tool registry could not load from the server API: ${registryDiagnostic}`);
111+
cell.colSpan = 5;
112+
row.append(cell);
113+
progressBody.append(row);
114+
if (progressSummary) {
115+
progressSummary.textContent = "Tool registry API unavailable. Start the Local/DEV server API and refresh.";
116+
}
117+
return;
118+
}
119+
105120
const tools = getActiveToolRegistry();
106121
progressBody.replaceChildren();
107122
tools.forEach((tool) => {
Lines changed: 162 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,169 @@
1-
function devRuntimeAllowed() {
2-
const host = window.location.hostname;
3-
return window.GameFoundryDevRuntime?.enabled === true ||
4-
window.location.protocol === "file:" ||
5-
host === "localhost" ||
6-
host === "127.0.0.1";
1+
import {
2+
getSessionCurrent,
3+
getSessionModes,
4+
getSessionUsers,
5+
setSessionMode,
6+
setSessionUser,
7+
} from "../../../src/engine/api/session-api-client.js";
8+
9+
const modeButtons = Array.from(document.querySelectorAll("[data-login-mode]"));
10+
const modeTitle = document.querySelector("[data-login-mode-title]");
11+
const modeDescription = document.querySelector("[data-login-mode-description]");
12+
const modeStatus = document.querySelector("[data-login-mode-status]");
13+
const userControls = document.querySelector("[data-login-user-controls]");
14+
const userStatus = document.querySelector("[data-login-user-status]");
15+
const continueLink = document.querySelector("[data-login-continue]");
16+
17+
function currentReturnTo() {
18+
const params = new URLSearchParams(window.location.search);
19+
const value = params.get("returnTo") || "";
20+
if (!value || value.startsWith("/") || value.includes("://") || value.includes("..")) {
21+
return "toolbox/index.html";
22+
}
23+
return value;
24+
}
25+
26+
function updateContinueLink() {
27+
if (continueLink) {
28+
continueLink.href = currentReturnTo();
29+
}
30+
}
31+
32+
function dispatchSessionChanged() {
33+
window.dispatchEvent(new CustomEvent("gamefoundry:mock-db-session-user-changed", {
34+
detail: getSessionCurrent(),
35+
}));
36+
}
37+
38+
function dispatchModeChanged() {
39+
window.dispatchEvent(new CustomEvent("gamefoundry:mock-db-session-mode-changed", {
40+
detail: getSessionCurrent(),
41+
}));
742
}
843

9-
async function loadLocalLoginSession() {
10-
if (!devRuntimeAllowed()) {
44+
function setSelectedButton(button, selected) {
45+
button.classList.toggle("primary", selected);
46+
button.setAttribute("aria-pressed", String(selected));
47+
if (selected) {
48+
button.setAttribute("aria-current", "true");
49+
} else {
50+
button.removeAttribute("aria-current");
51+
}
52+
}
53+
54+
function renderUserButtons(mode) {
55+
if (!userControls) {
1156
return;
1257
}
13-
await import("../../../src/dev-runtime/auth/login-session.js");
58+
59+
userControls.replaceChildren();
60+
if (mode.id === "dev") {
61+
userControls.hidden = true;
62+
if (userStatus) {
63+
userStatus.textContent = "DEV mode uses read-only/demo JSON access. No users are selectable.";
64+
}
65+
return;
66+
}
67+
68+
userControls.hidden = false;
69+
const sessionUser = getSessionCurrent();
70+
getSessionUsers().forEach((user) => {
71+
const button = document.createElement("button");
72+
button.className = "btn btn--compact";
73+
button.type = "button";
74+
button.textContent = user.label;
75+
button.dataset.loginUser = user.userKey || "";
76+
setSelectedButton(button, (user.userKey || "") === (sessionUser.userKey || ""));
77+
userControls.append(button);
78+
});
79+
if (userStatus) {
80+
userStatus.textContent = sessionUser.userKey
81+
? `Selected local user: ${sessionUser.label}.`
82+
: "Guest is unauthenticated and is not stored in the users table.";
83+
}
1484
}
1585

16-
loadLocalLoginSession().catch((error) => {
17-
console.error("Unable to load Local login session.", error);
86+
function renderModeButtons(mode) {
87+
modeButtons.forEach((button) => {
88+
setSelectedButton(button, button.dataset.loginMode === mode.id);
89+
});
90+
}
91+
92+
function renderError(error) {
93+
const message = error instanceof Error ? error.message : String(error || "Session API unavailable.");
94+
modeButtons.forEach((button) => {
95+
button.disabled = true;
96+
button.setAttribute("aria-disabled", "true");
97+
});
98+
if (userControls) {
99+
userControls.replaceChildren();
100+
userControls.hidden = true;
101+
}
102+
if (modeTitle) {
103+
modeTitle.textContent = "Session API unavailable";
104+
}
105+
if (modeDescription) {
106+
modeDescription.textContent = "Start the Local/DEV server API to select a session.";
107+
}
108+
if (modeStatus) {
109+
modeStatus.textContent = `Login/session diagnostic: ${message}`;
110+
}
111+
if (userStatus) {
112+
userStatus.textContent = "No local users are available until /api/session responds.";
113+
}
114+
updateContinueLink();
115+
}
116+
117+
function render() {
118+
try {
119+
const session = getSessionCurrent();
120+
const mode = getSessionModes().find((item) => item.id === session.mode) || {
121+
description: "",
122+
id: session.mode,
123+
label: session.mode,
124+
};
125+
renderModeButtons(mode);
126+
if (modeTitle) {
127+
modeTitle.textContent = mode.label;
128+
}
129+
if (modeDescription) {
130+
modeDescription.textContent = mode.description;
131+
}
132+
if (modeStatus) {
133+
modeStatus.textContent = `${mode.label} mode selected.`;
134+
}
135+
renderUserButtons(mode);
136+
updateContinueLink();
137+
} catch (error) {
138+
renderError(error);
139+
}
140+
}
141+
142+
modeButtons.forEach((button) => {
143+
button.addEventListener("click", () => {
144+
try {
145+
setSessionMode(button.dataset.loginMode || "local");
146+
dispatchModeChanged();
147+
render();
148+
} catch (error) {
149+
renderError(error);
150+
}
151+
});
18152
});
153+
154+
userControls?.addEventListener("click", (event) => {
155+
const button = event.target.closest("[data-login-user]");
156+
if (!button) {
157+
return;
158+
}
159+
try {
160+
setSessionMode("local");
161+
setSessionUser(button.dataset.loginUser || "");
162+
dispatchSessionChanged();
163+
render();
164+
} catch (error) {
165+
renderError(error);
166+
}
167+
});
168+
169+
render();

assets/theme-v2/js/tool-display-mode.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,18 @@
120120
badge.alt = registryName + " badge";
121121
fullscreenName.textContent = registryName;
122122
character.alt = registryName + " character";
123-
description.textContent = registryDescription;
123+
description.textContent = registryName;
124124
badge.src = registry.getToolImageSource(registryTool, "badge");
125125
character.src = registry.getToolImageSource(registryTool, "tool");
126126
}
127127

128128
async function renderToolNavigation() {
129129
try {
130-
const registry = await import("/toolbox/toolRegistry.js");
130+
const registry = await import("/toolbox/tool-registry-api-client.js");
131+
const registryDiagnostic = registry.getToolRegistryApiDiagnostic();
132+
if (registryDiagnostic) {
133+
throw new Error(registryDiagnostic);
134+
}
131135
const navigation = registry.getToolNavigationTargets(toolSlug);
132136
applyRegistryImages(registry);
133137
const navigationRow = document.createElement("nav");
@@ -141,6 +145,11 @@
141145
body.appendChild(navigationRow);
142146
} catch (error) {
143147
console.warn("Tool navigation could not be loaded.", error);
148+
const diagnostic = document.createElement("p");
149+
diagnostic.className = "status";
150+
diagnostic.setAttribute("role", "status");
151+
diagnostic.textContent = "Tool navigation could not load from the server API. Start the Local/DEV server API and refresh.";
152+
body.appendChild(diagnostic);
144153
}
145154
}
146155

Lines changed: 22 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,27 @@
1-
# API Contract Validation Report
1+
# PR_26158_022 API Contract Validation Report
22

3-
## Summary
3+
## Result
44

5-
Status: PASS
5+
PASS
66

7-
Validation confirmed each touched browser tool can initialize a server repository and call expected methods through the `/api/toolbox/...` contract. Session and Mock DB contracts were also validated.
7+
## Validated Endpoints
88

9-
## Contract Checks
10-
11-
| Contract | Methods/Routes | Result |
9+
| Endpoint | Status | Evidence |
1210
| --- | --- | --- |
13-
| Project Workspace | constants, repository init, `getActiveProject`, `getProjectProgress`, `getTables` | PASS |
14-
| Game Design | constants, repository init, `getSnapshot`, `getProjectProgressHandoff`, `getTables` | PASS |
15-
| Game Configuration | constants, repository init, `getSnapshot`, `getProjectProgressHandoff`, `getTables` | PASS |
16-
| Project Journey | constants, repository init, `getSessionUser`, `listNotes`, `getTables` | PASS |
17-
| Palette | constants, repository init, `getSnapshot`, `getTables`, `sourcePaletteOptions` | PASS |
18-
| Asset | constants, repository init, `getSnapshot`, `getTables`, `getProgressHandoff` | PASS |
19-
| Session | `/api/session/current`, `/api/session/users` | PASS |
20-
| Mock DB | `/api/mock-db/snapshot` | PASS |
21-
22-
## Command Evidence
23-
24-
Custom Node validation script using `startRepoServer()` and `fetch()`:
25-
26-
```text
27-
PASS project-workspace.getActiveProject
28-
PASS project-workspace.getProjectProgress
29-
PASS project-workspace.getTables
30-
PASS game-design.getSnapshot
31-
PASS game-design.getProjectProgressHandoff
32-
PASS game-design.getTables
33-
PASS game-configuration.getSnapshot
34-
PASS game-configuration.getProjectProgressHandoff
35-
PASS game-configuration.getTables
36-
PASS project-journey.getSessionUser
37-
PASS project-journey.listNotes
38-
PASS project-journey.getTables
39-
PASS palette.getSnapshot
40-
PASS palette.getTables
41-
PASS palette.sourcePaletteOptions
42-
PASS assets.getSnapshot
43-
PASS assets.getTables
44-
PASS assets.getProgressHandoff
45-
PASS /api/session/current
46-
PASS /api/session/users
47-
PASS /api/mock-db/snapshot
48-
```
11+
| `GET /api/toolbox/registry/snapshot` | PASS | Returned active tools, all tools, image fallback, route fields, image diagnostics, and readiness map. |
12+
| `GET /api/session/current` | PASS | Returned server session data with `data` wrapper. |
13+
| `GET /api/session/modes` | PASS | Returned Local/DEV modes from server auth boundary. |
14+
| `GET /api/session/users` | PASS | Returned Guest/session users through server auth boundary. |
15+
| `GET /api/mock-db/snapshot` | PASS | Returned server-backed Mock DB snapshot. |
16+
| `POST /api/toolbox/<tool>/repositories` | PASS | Returned repository ids for Project Workspace, Game Design, Game Configuration, Project Journey, Palette, and Assets. |
17+
| `POST /api/toolbox/<tool>/repositories/<id>/methods/<method>` | PASS | Returned method result wrappers for representative repository methods. |
18+
| `GET /api/toolbox/<tool>/constants` | PASS | Returned required constants for each migrated tool client. |
19+
| `POST /api/toolbox/palette/functions/normalizePaletteSwatchInput` | PASS | Returned server function result wrapper. |
20+
21+
## Command
22+
23+
Custom Node API contract script using `tests/helpers/playwrightRepoServer.mjs`.
24+
25+
## Output
26+
27+
`PASS api contract validation for PR_26158_022`
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# PR_26158_022 Browser Mock Remaining Audit
2+
3+
## Audit Scope
4+
5+
Active browser/tool files changed or adjacent to PR_26158_020/021:
6+
7+
- `admin/db-viewer.js`
8+
- `assets/theme-v2/js/login-session.js`
9+
- `assets/theme-v2/js/tool-display-mode.js`
10+
- `admin/tools-progress.js`
11+
- `toolbox/tools-page-accordions.js`
12+
- `toolbox/project-journey/project-journey.js`
13+
- toolbox API clients under `toolbox/*/*-api-client.js`
14+
- engine API clients under `src/engine/api/`
15+
16+
## Findings
17+
18+
| Check | Status | Evidence |
19+
| --- | --- | --- |
20+
| Active browser files import `src/dev-runtime` directly. | PASS | Focused `rg` found no active browser entry imports after migration. |
21+
| Active browser files import mock repositories directly. | PASS | Remaining `*-mock-repository.js` imports are repository/server-dev implementation files only. |
22+
| Active browser files import `mock-db-store` or dev persistence. | PASS | `src/engine/persistence/mock-db-store.js` was removed; browser files use API clients. |
23+
| Active browser files import static Toolbox registry records directly. | PASS | Toolbox page, Project Journey, Admin Tools Progress, and Tool Display Mode now use `toolbox/tool-registry-api-client.js`. |
24+
| Active browser files keep page-local mock DB snapshots or fake records. | PASS | Palette invalid/empty source modes are server-owned; DB Viewer reads `/api/mock-db/snapshot`. |
25+
| Active browser files use `localStorage`/`sessionStorage` for mock DB/session fallback. | PASS | Migrated files use session/Mock DB API clients; permitted Workspace/sessionStorage contracts in unrelated shared runtime files were not modified. |
26+
27+
## Remaining Matches And Classification
28+
29+
`rg` still finds mock/dev strings in these categories:
30+
31+
- `src/dev-runtime/server/mock-api-router.mjs`: PASS, server/dev runtime API owner.
32+
- `toolbox/*/*-mock-repository.js`, `toolbox/colors/palette-workspace-repository.js`, `toolbox/colors/palette-source-mock-db.js`: PASS, server/dev-only repository/data source modules imported by the dev server router.
33+
- `src/shared/toolbox/*` imports of `toolbox/toolRegistry.js`: AUDIT NOTE, product registry/shared shell metadata outside the active browser files changed by this migration pass. The adjacent active consumers were migrated to the server-backed registry endpoint.
34+
35+
## Command Evidence
36+
37+
- `rg -n "dev-runtime|toolRegistry\\.js|mock-db-store|mock-repository|palette-workspace-repository|palette-source-mock-db|localStorage|sessionStorage" admin assets/theme-v2/js toolbox src/engine/api -g "*.js" -g "*.mjs" --glob "!archive/**" --glob "!**/start_of_day/**" --glob "!node_modules/**" --glob "!tmp/**"`
38+
- Remaining results were only server/dev repository implementation modules.

0 commit comments

Comments
 (0)