Minor Changes
- c772810: feat(display):
EmailPreview, a captured email shown safely (#4113). The HTML part renders in a sandboxed iframe: no scripts, no forms, an opaque origin. A Content-Security-Policy lets nothing remote load, and remote images wait for a "Load images" toggle. Meta refreshes,<base>and prefetch hints are removed through an inertDOMParserpass, andcid:images point at their attachments. The component also shows the text part and the source, the main headers with every header under a fold, and the attachments with sizes, thumbnails and downloads. It takes a parsed email, a Mailpit message throughfromMailpit(), or raw MIME throughparseMimefrom the new@quazardous/qdadm/emailentry, which needspostal-mime, a new optional peer dependency (>= 3). - c96f448: feat(display):
EntityTimeline, one entity's history across several actors (#4111). It takes the events as an array, or reads an events entity through its manager and rereads it on a remote change, flashing what is new. Events are ordered by time, with day separators and relative times. Each actor gets a colour and an icon, and actors can be hidden, with the filter kept in the URL throughquery-key. Events expand into a#detailslot, andgapsshows the time since the previous event or named durations such as "order → ready to ship: 17 h".mapadapts an app's own event shape. - 6e78e59: feat(display):
LogStream, a live tail of a backend log (#4110). It reads a task log as it is written, through offset polling (poll(from) → { lines, next, done }), server-sent events, a pushsubscribe, or a finishedlinesarray, and keeps following the end until the user scrolls up. It renders ANSI colours (16, 256, truecolor), searches with a "only matching lines" filter, counts and jumps to error lines, dims timestamps, wraps on demand and downloads the log. Only the rows on screen are drawn, so a log of tens of thousands of lines stays smooth.useLogStream()holds the buffer for a page that shares one log between two views, andparseAnsiLine/stripAnsiare exported from the utils. - 45ad7c1: feat(display):
PayloadViewerandPayloadDiff, captured messages in their own format (#4112). The viewer detects the format from the prop, the content type or the body itself, and renders JSON throughJsonViewer, XML indented and highlighted (tokenized by hand, never handed to the DOM), CSV as a table (separator detection, quoted and multi-line fields), form-encoded data as key/value pairs, text with line numbers, and binary content as a hex preview with a download. It shows the HTTP method, URL, status and headers when given. Amaskhook (maskKeys()for the usual secrets) hides values before display, copy and download. The diff normalizes both sides (sorted JSON keys, indented XML, sorted form fields) before a line diff, side by side or inline, with unchanged runs folded. Withcsv-key, CSV rows are matched on a column and compared cell by cell. - 722d3d4:
SdkStorageruns path requests (#4069).manager.request('GET', 'distinct/x'), whichoptionsEndpointfilters make, was read as the SDK method nameGETand failed with "SDK method 'GET' not found", leaving the filter on "No available options". A newrequest: (method, path, options, sdk)option now carries those calls, usually to the SDK's own client; without it the error says what to pass, andaddFilterwarns by name when anoptionsEndpointfilter sits on a storage that cannot reach it. Calling an SDK method by name throughrequest('getStats', params)is unchanged. - 23194aa: feat(tasks): a task runner for long backend tasks (#4114).
useTaskRunner().run({ label, start, task, log?, cancel?, to?, confirm? })queues a task (start()returns its id) and follows the task record to the end: through live entities when the task entity is live, with polling as a fallback, or by polling alone. Status names are mapped, and progress, step, result and error are read from the record. A follow dialog shows the status, progress, step, a live LogStream, the result or the error, a link to the task, and a cancel button. Closing it leaves the task in a "running tasks" tray in the sidebar. A toast reports the end.confirm.typedmakes the user type a name before a dangerous task starts.taskAction()turns run options into an action handler, andregisterTaskKind()lets runs resume after a reload.AppLayoutmountsTaskTrayandTaskHost; other layouts can mount them themselves.
Patch Changes
- 48483ba: fix(debug): the debug bar component no longer triggers "Vue received a Component that was made a reactive object" on every page load (#4117). It was held in a deep
ref, which wrapped it in a reactive proxy; it is now kept in ashallowRefand marked raw.