diff --git a/.playwright-mcp/console-2026-03-02T19-29-32-708Z.log b/.playwright-mcp/console-2026-03-02T19-29-32-708Z.log new file mode 100644 index 0000000..39e9af7 --- /dev/null +++ b/.playwright-mcp/console-2026-03-02T19-29-32-708Z.log @@ -0,0 +1,6 @@ +[ 95ms] TypeError: Cannot read properties of null (reading 'appendChild') + at TypedserverStatusPill.show (http://localhost:3000/typedserver/devtools:17607:21) + at TypedserverStatusPill.updateStatus (http://localhost:3000/typedserver/devtools:17567:10) + at ReloadChecker.checkReload (http://localhost:3000/typedserver/devtools:18137:23) + at async ReloadChecker.start (http://localhost:3000/typedserver/devtools:18224:9) +[ 992ms] [ERROR] Error while trying to use the following icon from the Manifest: http://localhost:3000/assetbroker/manifest/icon-144x144.png (Download error or resource isn't a valid image) @ http://localhost:3000/overview:0 diff --git a/.playwright-mcp/console-2026-03-02T19-30-09-759Z.log b/.playwright-mcp/console-2026-03-02T19-30-09-759Z.log new file mode 100644 index 0000000..4f67481 --- /dev/null +++ b/.playwright-mcp/console-2026-03-02T19-30-09-759Z.log @@ -0,0 +1,5 @@ +[ 329ms] [ERROR] method: >>getMergedRoutes<< got an ERROR: "unauthorized" with data undefined @ http://localhost:3000/bundle.js:13 +[ 727ms] [ERROR] Error while trying to use the following icon from the Manifest: http://localhost:3000/assetbroker/manifest/icon-144x144.png (Download error or resource isn't a valid image) @ http://localhost:3000/routes:0 +[ 260513ms] [ERROR] method: >>adminLoginWithUsernameAndPassword<< got an ERROR: "login failed" with data undefined @ http://localhost:3000/bundle.js:13 +[ 260514ms] [ERROR] Login failed: Ns @ http://localhost:3000/bundle.js:38066 +[ 260518ms] [WARNING] FontAwesome icon not found: circle-xmark @ http://localhost:3000/bundle.js:1203 diff --git a/.playwright-mcp/console-2026-03-02T19-34-55-496Z.log b/.playwright-mcp/console-2026-03-02T19-34-55-496Z.log new file mode 100644 index 0000000..f459a8c --- /dev/null +++ b/.playwright-mcp/console-2026-03-02T19-34-55-496Z.log @@ -0,0 +1,3 @@ +[ 397ms] [ERROR] method: >>getMergedRoutes<< got an ERROR: "unauthorized" with data undefined @ http://localhost:3000/bundle.js:13 +[ 657ms] [ERROR] Error while trying to use the following icon from the Manifest: http://localhost:3000/assetbroker/manifest/icon-144x144.png (Download error or resource isn't a valid image) @ http://localhost:3000/routes:0 +[ 24180ms] [WARNING] FontAwesome icon not found: circle-check @ http://localhost:3000/bundle.js:1203 diff --git a/.playwright-mcp/page-2026-03-02T19-32-32-890Z.png b/.playwright-mcp/page-2026-03-02T19-32-32-890Z.png new file mode 100644 index 0000000..e9b5925 Binary files /dev/null and b/.playwright-mcp/page-2026-03-02T19-32-32-890Z.png differ diff --git a/.playwright-mcp/page-2026-03-02T19-33-32-637Z.png b/.playwright-mcp/page-2026-03-02T19-33-32-637Z.png new file mode 100644 index 0000000..e9b5925 Binary files /dev/null and b/.playwright-mcp/page-2026-03-02T19-33-32-637Z.png differ diff --git a/changelog.md b/changelog.md index cc6b815..956414f 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,13 @@ # Changelog +## 2026-03-02 - 10.1.6 - fix(ts_web) +use actionContext for dispatches in web state actions and bump @push.rocks/smartstate to ^2.2.0 + +- Action handlers in ts_web/appstate.ts now accept an actionContext parameter and call await actionContext.dispatch(...) instead of using statePartArg.dispatchAction(...). +- Handlers return the awaited dispatch result (ensuring callers receive refreshed state) instead of returning the previous statePartArg.getState(). +- Dependency bumped in package.json: @push.rocks/smartstate from ^2.1.1 to ^2.2.0. +- Playwright artifacts (logs and page screenshots) were added under .playwright-mcp. + ## 2026-03-02 - 10.1.5 - fix(monitoring) use a per-second ring buffer for DNS query metrics, improve DNS logging rate limiting and security event aggregation, and bump smartmta dependency diff --git a/package.json b/package.json index a65ddaa..0d7b027 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "@push.rocks/smartradius": "^1.1.1", "@push.rocks/smartrequest": "^5.0.1", "@push.rocks/smartrx": "^3.0.10", - "@push.rocks/smartstate": "^2.1.1", + "@push.rocks/smartstate": "^2.2.0", "@push.rocks/smartunique": "^3.0.9", "@serve.zone/catalog": "^2.5.0", "@serve.zone/interfaces": "^5.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a40e00c..7059870 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -87,8 +87,8 @@ importers: specifier: ^3.0.10 version: 3.0.10 '@push.rocks/smartstate': - specifier: ^2.1.1 - version: 2.1.1 + specifier: ^2.2.0 + version: 2.2.0 '@push.rocks/smartunique': specifier: ^3.0.9 version: 3.0.9 @@ -1086,8 +1086,8 @@ packages: '@push.rocks/smartspawn@3.0.3': resolution: {integrity: sha512-DyrGPV69wwOiJgKkyruk5hS3UEGZ99xFAqBE9O2nM8VXCRLbbty3xt1Ug5Z092ZZmJYaaGMSnMw3ijyZJFCT0Q==} - '@push.rocks/smartstate@2.1.1': - resolution: {integrity: sha512-4OM9TXfiiSYIgVz2pQdM2UCTurXwd8o9LCtyZ/o+rnntnXp/X8UTWZ+WyTxgnfuzXhpIYXt83t34bVBJ2EPUOw==} + '@push.rocks/smartstate@2.2.0': + resolution: {integrity: sha512-e41vA1y9b0HBauzjMSh3l0YlRhcG4jhArm43/HHNdT+inxEGIeRL24VGeq+sl2MUr/eFWqgrETXhvL3YrsYFaw==} '@push.rocks/smartstream@2.0.8': resolution: {integrity: sha512-GlF/9cCkvBHwKa3DK4DO5wjfSgqkj6gAS4TrY9uD5NMHu9RQv4WiNrElTYj7iCEpnZgUnLO3tzw1JA3NRIMnnA==} @@ -5013,7 +5013,7 @@ snapshots: '@push.rocks/smartpromise': 4.2.3 '@push.rocks/smartrouter': 1.3.3 '@push.rocks/smartrx': 3.0.10 - '@push.rocks/smartstate': 2.1.1 + '@push.rocks/smartstate': 2.2.0 '@push.rocks/smartstring': 4.1.0 '@push.rocks/smarturl': 3.1.0 '@push.rocks/webrequest': 3.0.37 @@ -6501,7 +6501,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@push.rocks/smartstate@2.1.1': + '@push.rocks/smartstate@2.2.0': dependencies: '@push.rocks/smarthash': 3.2.6 '@push.rocks/smartjson': 6.0.0 diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 823405b..08c64aa 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@serve.zone/dcrouter', - version: '10.1.5', + version: '10.1.6', description: 'A multifaceted routing service handling mail and SMS delivery functions.' } diff --git a/ts_web/00_commitinfo_data.ts b/ts_web/00_commitinfo_data.ts index 823405b..08c64aa 100644 --- a/ts_web/00_commitinfo_data.ts +++ b/ts_web/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@serve.zone/dcrouter', - version: '10.1.5', + version: '10.1.6', description: 'A multifaceted routing service handling mail and SMS delivery functions.' } diff --git a/ts_web/appstate.ts b/ts_web/appstate.ts index eddf256..68e31dd 100644 --- a/ts_web/appstate.ts +++ b/ts_web/appstate.ts @@ -581,7 +581,7 @@ export const fetchCertificateOverviewAction = certificateStatePart.createAction( }); export const reprovisionCertificateAction = certificateStatePart.createAction( - async (statePartArg, domain) => { + async (statePartArg, domain, actionContext) => { const context = getActionContext(); const currentState = statePartArg.getState(); @@ -596,8 +596,7 @@ export const reprovisionCertificateAction = certificateStatePart.createAction( - async (statePartArg, domain) => { + async (statePartArg, domain, actionContext) => { const context = getActionContext(); const currentState = statePartArg.getState(); @@ -623,8 +622,7 @@ export const deleteCertificateAction = certificateStatePart.createAction }); // Re-fetch overview after deletion - await certificateStatePart.dispatchAction(fetchCertificateOverviewAction, null); - return statePartArg.getState(); + return await actionContext.dispatch(fetchCertificateOverviewAction, null); } catch (error) { return { ...currentState, @@ -643,7 +641,7 @@ export const importCertificateAction = certificateStatePart.createAction<{ publicKey: string; csr: string; }>( - async (statePartArg, cert) => { + async (statePartArg, cert, actionContext) => { const context = getActionContext(); const currentState = statePartArg.getState(); @@ -658,8 +656,7 @@ export const importCertificateAction = certificateStatePart.createAction<{ }); // Re-fetch overview after import - await certificateStatePart.dispatchAction(fetchCertificateOverviewAction, null); - return statePartArg.getState(); + return await actionContext.dispatch(fetchCertificateOverviewAction, null); } catch (error) { return { ...currentState, @@ -737,7 +734,7 @@ export const createRemoteIngressAction = remoteIngressStatePart.createAction<{ listenPorts?: number[]; autoDerivePorts?: boolean; tags?: string[]; -}>(async (statePartArg, dataArg) => { +}>(async (statePartArg, dataArg, actionContext) => { const context = getActionContext(); const currentState = statePartArg.getState(); @@ -756,7 +753,7 @@ export const createRemoteIngressAction = remoteIngressStatePart.createAction<{ if (response.success) { // Refresh the list - await remoteIngressStatePart.dispatchAction(fetchRemoteIngressAction, null); + await actionContext.dispatch(fetchRemoteIngressAction, null); return { ...statePartArg.getState(), @@ -774,7 +771,7 @@ export const createRemoteIngressAction = remoteIngressStatePart.createAction<{ }); export const deleteRemoteIngressAction = remoteIngressStatePart.createAction( - async (statePartArg, edgeId) => { + async (statePartArg, edgeId, actionContext) => { const context = getActionContext(); const currentState = statePartArg.getState(); @@ -788,8 +785,7 @@ export const deleteRemoteIngressAction = remoteIngressStatePart.createAction(async (statePartArg, dataArg) => { +}>(async (statePartArg, dataArg, actionContext) => { const context = getActionContext(); const currentState = statePartArg.getState(); @@ -823,8 +819,7 @@ export const updateRemoteIngressAction = remoteIngressStatePart.createAction<{ tags: dataArg.tags, }); - await remoteIngressStatePart.dispatchAction(fetchRemoteIngressAction, null); - return statePartArg.getState(); + return await actionContext.dispatch(fetchRemoteIngressAction, null); } catch (error) { return { ...currentState, @@ -877,7 +872,7 @@ export const clearNewEdgeIdAction = remoteIngressStatePart.createAction( export const toggleRemoteIngressAction = remoteIngressStatePart.createAction<{ id: string; enabled: boolean; -}>(async (statePartArg, dataArg) => { +}>(async (statePartArg, dataArg, actionContext) => { const context = getActionContext(); const currentState = statePartArg.getState(); @@ -892,8 +887,7 @@ export const toggleRemoteIngressAction = remoteIngressStatePart.createAction<{ enabled: dataArg.enabled, }); - await remoteIngressStatePart.dispatchAction(fetchRemoteIngressAction, null); - return statePartArg.getState(); + return await actionContext.dispatch(fetchRemoteIngressAction, null); } catch (error) { return { ...currentState, @@ -939,7 +933,7 @@ export const fetchMergedRoutesAction = routeManagementStatePart.createAction(asy export const createRouteAction = routeManagementStatePart.createAction<{ route: any; enabled?: boolean; -}>(async (statePartArg, dataArg) => { +}>(async (statePartArg, dataArg, actionContext) => { const context = getActionContext(); const currentState = statePartArg.getState(); @@ -954,8 +948,7 @@ export const createRouteAction = routeManagementStatePart.createAction<{ enabled: dataArg.enabled, }); - await routeManagementStatePart.dispatchAction(fetchMergedRoutesAction, null); - return statePartArg.getState(); + return await actionContext.dispatch(fetchMergedRoutesAction, null); } catch (error) { return { ...currentState, @@ -965,7 +958,7 @@ export const createRouteAction = routeManagementStatePart.createAction<{ }); export const deleteRouteAction = routeManagementStatePart.createAction( - async (statePartArg, routeId) => { + async (statePartArg, routeId, actionContext) => { const context = getActionContext(); const currentState = statePartArg.getState(); @@ -979,8 +972,7 @@ export const deleteRouteAction = routeManagementStatePart.createAction( id: routeId, }); - await routeManagementStatePart.dispatchAction(fetchMergedRoutesAction, null); - return statePartArg.getState(); + return await actionContext.dispatch(fetchMergedRoutesAction, null); } catch (error) { return { ...currentState, @@ -993,7 +985,7 @@ export const deleteRouteAction = routeManagementStatePart.createAction( export const toggleRouteAction = routeManagementStatePart.createAction<{ id: string; enabled: boolean; -}>(async (statePartArg, dataArg) => { +}>(async (statePartArg, dataArg, actionContext) => { const context = getActionContext(); const currentState = statePartArg.getState(); @@ -1008,8 +1000,7 @@ export const toggleRouteAction = routeManagementStatePart.createAction<{ enabled: dataArg.enabled, }); - await routeManagementStatePart.dispatchAction(fetchMergedRoutesAction, null); - return statePartArg.getState(); + return await actionContext.dispatch(fetchMergedRoutesAction, null); } catch (error) { return { ...currentState, @@ -1021,7 +1012,7 @@ export const toggleRouteAction = routeManagementStatePart.createAction<{ export const setRouteOverrideAction = routeManagementStatePart.createAction<{ routeName: string; enabled: boolean; -}>(async (statePartArg, dataArg) => { +}>(async (statePartArg, dataArg, actionContext) => { const context = getActionContext(); const currentState = statePartArg.getState(); @@ -1036,8 +1027,7 @@ export const setRouteOverrideAction = routeManagementStatePart.createAction<{ enabled: dataArg.enabled, }); - await routeManagementStatePart.dispatchAction(fetchMergedRoutesAction, null); - return statePartArg.getState(); + return await actionContext.dispatch(fetchMergedRoutesAction, null); } catch (error) { return { ...currentState, @@ -1047,7 +1037,7 @@ export const setRouteOverrideAction = routeManagementStatePart.createAction<{ }); export const removeRouteOverrideAction = routeManagementStatePart.createAction( - async (statePartArg, routeName) => { + async (statePartArg, routeName, actionContext) => { const context = getActionContext(); const currentState = statePartArg.getState(); @@ -1061,8 +1051,7 @@ export const removeRouteOverrideAction = routeManagementStatePart.createAction( - async (statePartArg, tokenId) => { + async (statePartArg, tokenId, actionContext) => { const context = getActionContext(); const currentState = statePartArg.getState(); @@ -1142,8 +1131,7 @@ export const revokeApiTokenAction = routeManagementStatePart.createAction(async (statePartArg, dataArg) => { +}>(async (statePartArg, dataArg, actionContext) => { const context = getActionContext(); const currentState = statePartArg.getState(); @@ -1171,8 +1159,7 @@ export const toggleApiTokenAction = routeManagementStatePart.createAction<{ enabled: dataArg.enabled, }); - await routeManagementStatePart.dispatchAction(fetchApiTokensAction, null); - return statePartArg.getState(); + return await actionContext.dispatch(fetchApiTokensAction, null); } catch (error) { return { ...currentState,