BeaconClient: fetch-based promise core + standardised API - #448
Merged
Conversation
Add BeaconClient/core/request.js: request() / requestPaginated() / BeaconApiError / toFormUrlEncoded. One fetch-based transport, one place for the Bearer header, JSON handling, error semantics and Beacon's paged-search loop. Rewrite all 23 domain modules to return Promises instead of taking callbacks, delegating transport to the core. Delete BeaconClient/json.js (getJsonPaginated -> requestPaginated). Non-2xx responses reject with BeaconApiError, except the tasking/message write endpoints Beacon spuriously 500s (nullOnError -> resolve null). Call sites updated in follow-up commits. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Update every caller of BeaconClient to the promise API: tasking main.js
(~45 sites), the reporting pages (stats/summary/advexport/nitcexport/
teamsummary), the tasking map layers, IncidentImagesModalVM,
ContentScriptMapManager and the jobs inject scripts.
Callback pyramids collapse to await / .then; the -1/-1 progress-callback
error convention is replaced by real .catch handlers. Paginated searches
(job/team/sector/frao/nitc) now take an { onProgress, onPage } options
object in place of trailing positional callbacks.
npm run lint + npm run dev both pass. Not yet exercised against a live
Beacon backend.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Inputs: every function now takes its resource id(s) / domain args
positionally and a single trailing context object
{ host, userId, token, signal, ...perCallOpts }. No more host/userId/token
scattered through positional slots, no viewModelType wedged mid-list, no
host-first tasking calls. Search options (onProgress/onPage/statusTypes/
typeIds) live in that context object too.
Outputs:
- collection endpoints return { results, totalItems } (core toCollection /
requestPaginated); callers read .results
- single-entity fetches return the entity or null
- mutations (job cancel/reopen/reject/acknowledge/complete, tasking
sequence) resolve on success and reject on failure -- the bare
true/false returns are gone
- the tasking/message writes Beacon spuriously 500s keep nullOnError
- bare-array endpoints (entities.children, notifications.unaccepted,
tags.getGroup) stay arrays
Renames: entities.fetch -> entities.get (fetch shadowed the global);
team.teamSearch -> team.search. Deleted the unused job.searchwithFilter.
main.js gets a beaconCtx(token, extra) helper for the context object.
All call sites and downstream .Results readers updated (tasking main.js,
Team.js, the reporting pages, map layers, inject scripts, stats jobparsing
+ wordcloud).
npm run lint + npm run dev pass. Not yet exercised against live Beacon.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
OSPFNeighbour
force-pushed
the
refactor/beaconclient-core
branch
from
September 9, 2026 00:48
c0deba3 to
fa59598
Compare
Collaborator
Author
|
Rebased onto
Extra checklist item: Tasking → Team & Tasking Filters → team-type filter (Field / Operations / Aviation) still narrows the team list. |
The Beacon API authenticates on the Authorization: Bearer header only. Chrome attaches a host's cookies to fetch() from an extension page whose manifest grants that host, even under the spec-default 'same-origin' credentials mode -- the old jQuery cross-origin XHR never sent them. A stale Beacon session cookie riding along can make the API 401 the request despite a valid bearer token (seen on Team Summary -> job popup from a history row). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Rewrites
BeaconClient(our interface to the Beacon REST API) from callback-style$.ajax/XHR into a singlefetch-based promise layer with a standardised, consistent API surface.Net −600 lines across 41 files. No feature or endpoint changes — same URLs, same payloads, same query strings.
1. New core —
src/shared/BeaconClient/core/request.jsrequest(url, { method, token, json, form, responseType, headers, signal, nullOnError })— one transport, one place for theAuthorization: Bearerheader, JSON/form serialisation and error semantics.requestPaginated(url, { token, pageLimit, pageSize, onProgress, onPage, signal })— replacesjson.js'sgetJsonPaginated; returns{ results, totalItems }.toCollection(payload)— normalises Beacon's{ Results, TotalItems }to{ results, totalItems }.BeaconApiError(carriesstatus,url,body) — thrown on any non-2xx.toFormUrlEncodedmoved here from the barrel (still re-exported).json.jsdeleted.2. All 23 domain modules rewritten
No
$.ajax, no callbacks. Every function returns a Promise.jqueryimport remains only inteam.js(needs$.param(params, true)for traditional array serialisation).3. Standardised inputs
Every function now takes its resource id(s) / domain args positionally and a single trailing context object:
Gone:
host/userId/tokenscattered through positional slots,viewModelTypewedged mid-list, host-firsttasking.*calls, the-1/-1progress-callback error convention.main.jsgets abeaconCtx(token, extra)helper to build the context object.4. Standardised outputs
*.search,getTasking,getHistory,unresolvedActionsLog){ results, totalItems }get,getName,summary,unitBoundary,getMessageById, …)nulljob.cancel/reopen/reject/acknowledge/complete,tasking.sequence,sectors.setSector/unSetSector)true/falsereturns are gonetasking.task/updateTeamStatus/callOffTeam/untaskTeam,messages.send)null— Beacon intermittently 500s these despite applying the change, and callers re-sync from SignalR (nullOnError)entities.children,notifications.unaccepted,tags.getGroup)images.getImageData→Blob;team.getTeamGeoJson→ GeoJSON;asset.filter→ asset array5. Renames
entities.fetch→entities.get(it shadowed the globalfetch)team.teamSearch→team.searchjob.searchwithFilter6. Call sites + downstream readers updated
tasking/main.js(~45 sites),Team.js, the reporting pages (stats/summary/advexport/nitcexport/teamsummary), the tasking map layers,IncidentImagesModalVM,ContentScriptMapManager, the jobs inject scripts, andstatsjobparsing.js+wordcloud.js(now read.results).Behaviour changes to be aware of
$.ajaxcompletehandlers frequently never fired the callback on failure. Every caller got a real.catch/try-catchwired to the existing user-facing alert.icems.acknowledgeIumwas$.param(vm)(deep serialisation), nowtoFormUrlEncoded(flat +key[]arrays only). Fine if the IUM payload is flat — verify the IUM acknowledge flow.asset.jscaching logic rewritten (the 20slocalStoragecache is preserved); a failed radio/telematics sub-fetch now logs + returns partial data.falseused to.Verification done
npm run lint— cleannpm run dev— buildsThere is no automated test suite in the repo. A follow-up will seed Vitest against the new
core/request.js(mockfetch, assert headers/body/error/pagination) as the start of real coverage.Manual test checklist
Load the built extension against testbeacon / devbeacon with a real session. Tick each as verified.
Tasking page (
/Jobs/Tasking) — largest surfaceLoad & refresh
Jobs
Teams & tasking
Sectors
Assets
Map layers (each: toggle on, data draws, toggle off)
Modals & pickers
ICEMS
$.param→toFormUrlEncodedchange — verify the payload lands)People
Reporting pages
Job Summary (
pages/summary.html)?hq=<id>) — loads, all the status counts render?hq=<id>,<id>,<id>) — loads, progress bar advancesJob Statistics (
pages/stats.html)jobs.results)Job Export (
pages/advexport.html)Team Summary (
pages/teamsummary.html)history.results)job.get)NITC Export (
pages/nitcexport.html)Inject scripts (on Beacon pages, main-world)
/Teamsmap → SES teams layer + filtered-assets layer (viaContentScriptMapManager)Regression sweep
BeaconApiErrorin the console that isn't surfaced to the user🤖 Generated with Claude Code