magic_devtools 0.0.8
magic_devtools: ^0.0.8 copied to clipboard
Magic adapters for the fluttersdk dev-tooling ecosystem: wires MagicDuskIntegration and MagicTelescopeIntegration into dusk and telescope.
Changelog #
All notable changes to this package are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased] #
0.0.8 - 2026-09-29 #
Security #
- The HTTP adapter no longer hands telescope a login's password or token. It stringified request and response bodies with
toString(), and a DartMapprints as{email: a@b.test, password: hunter2}, which telescope's JSON masking cannot read, so a login body and a Sanctum login answer reached the agent-facing buffer in the clear.onRequest,onResponseandonErrornow mask the body with telescope's hidden request or response parameters before truncating it (TelescopeRedaction.redactParametersfor a Dart structure,redactBodyfor a JSON string, which would otherwise stop parsing once cut at 8 KB); the masked copy is what gets recorded, and the request object the driver sends on is never touched.MagicTelescopeIntegration.install()also hides the header magic'sAuthInterceptorwrites the token under, read fromauth.token.header(defaultAuthorization), so a renamed header is masked too, and it does so on every call, since a telescope store reset drops the addition. Needs the telescope release that shipsTelescopeRedaction. (lib/src/telescope_integration.dart)
Changed #
-
The floors name the releases this work needs.
magicmoves^0.0.22to^0.0.24(MagicPerfHooks, the request ids,AuthRestored.changed, and the removal ofonRefreshUI),fluttersdk_dusk^0.0.16to^0.0.17(PerfModeand the interaction readers),fluttersdk_telescope^0.0.7to^0.0.9(TelescopeRedactionand the record link fields) andfluttersdk_wind^1.7.0to^1.8.0(the size-onlyMediaQueryread themediaQuerySizeinsight describes). Each is a real requirement: this release does not compile, or describes the wrong behaviour, below it. The README install snippet quotes the new dusk and telescope floors. (pubspec.yaml,README.md) -
BREAKING: the perf path reads magic through
MagicPerfHooks.sink, andMagicController.onRefreshUIis gone.MagicPerfIntegrationno longer hooks a single notify site: its session begin hook installs the sink for an attribution session only (a timing session, and an app between sessions, allocate no event and leave wind counting off), and the end hook removes it.perfExtrasReaderreturns dusk's documented key set:controllerNotifies,notifyCauses,queryReloads,actions,events,casts,timerTicks,broadcastsandrouteTransitions. Needs the magic, dusk, telescope and wind releases that shipMagicPerfHooks,PerfMode, record links and per-type wind counters. (lib/src/perf_integration.dart) -
HTTP records pair by request id. The telescope interceptor matches each response or error to its request through
MagicRequest.id/MagicResponse.id/MagicError.id, so two requests completing out of order keep their own URL and duration; only an answer without an id (a hand-built one;Http.fakeinstalls no interceptors) falls back to the oldest request in flight that has no id either, withattributedHeuristically: true. A request with an id is never handed to an id-less answer, since its own answer would then find nothing to pair with and be dropped. Records carryrequestId,startUsandendUs. (lib/src/telescope_integration.dart) -
A span is linked from when it began, not when it ended.
QueryReloaded,ActionRanandEventDispatchedarrive at span end, so resolving the link then dropped a reload that outlived its tap and gave one that ended during the next tap to that tap.MagicPerfIntegration.interactionLink({startUs})now accepts the zone handle when its window[startUs, closedAtUs ?? now]holds the span's start (closed or not), else dusk'sperfInteractionAt(startUs)(frame), elsewindow; an instant with no start keeps the open-handle and active-interaction rules. ThezoneInteractionIdtest seam becomeszoneInteraction(it returns the handle's window), with a newinteractionIdAtseam besideactiveInteractionId. Needs the dusk release that exportsperfInteractionAt. (lib/src/perf_integration.dart) -
The
mediaQuerySizeinsight describes a size-only subscription. wind now readsMediaQuery.sizeOf, so a counted read rebuilds its widget on a resize or a rotation and not on a keyboard inset; the summary and next step said every MediaQuery change, which is no longer true. The metric name, threshold and firing rule are unchanged. (lib/src/perf_insight_rules.dart) -
The install guard is
!kReleaseMode.MagicDevtools.installPre/installPostand the per-tool blocks are documented under!kReleaseModeinstead ofkDebugMode, so a profile build carries dusk and telescope and a perf measurement can run on it; release still tree-shakes both, and the guard still belongs at the call site.lib/src/dusk_integration.dartandlib/src/perf_integration.dartalready said so, and the rest of the package saidkDebugMode. Apps wired underkDebugModekeep working in debug and simply carry no tooling in profile. (CLAUDE.md,README.md,lib/magic_devtools.dart,lib/dusk.dart,lib/telescope.dart,lib/src/magic_devtools.dart,lib/src/telescope_integration.dart)
Added #
- Interaction links on every record. HTTP, query, event, model and cache records, and every sink row, carry
interactionIdandlinkedBy:zonewhen the work read an open dusk interaction off its own zone,framewhen it ran in the frame zone and joined dusk's active interaction,windowwhen neither.MagicPerfIntegration.interactionLink()is the one rule. Gate records are not stamped: telescope'sGateRecordhas no link fields. (lib/src/perf_integration.dart,lib/src/telescope_integration.dart) perfTimelineReaderandperfInsightContributorsare assigned. The timeline reader returns the sink rows (notifies, query reloads, actions, event dispatches, timer ticks, broadcasts) plus one row per telescope HTTP, query, event, model and cache record, in dusk's row schema. The contributor runsPerfInsightRules: wind wrapper emissions per W-widget build,mediaQuerySizereads per frame, parse misses on a warm surface, notify storms by cause, timer-driven notifies per second, uncached query reloads per interaction, attribute casts per frame, and HTTP requests per interaction. Every rule states its threshold inevidence.thresholdand normalises by painted frames. (lib/src/perf_insight_rules.dart)
0.0.7 - 2026-09-27 #
Changed #
- Every sibling floor names this batch's release.
magicmoves^0.0.16to^0.0.22,fluttersdk_dusk^0.0.15to^0.0.16andfluttersdk_wind^1.6.3to^1.7.0;fluttersdk_telescopestays at^0.0.7, still the newest. The old ranges already admitted the new versions, so a freshpub getresolves nothing differently; what changes is that the floors name the releases this package is verified against. Of magic 0.0.22's BREAKING changes, the one that reaches this package isAuth.fake()dispatchingAuthLogin/AuthLogoutthrough the realEventfacade, which only its tests call; the suite passes unchanged. dusk 0.0.16 stopsdusk:fill/dusk:type/dusk:clearwriting into a field on a covered route. (pubspec.yaml,README.md)
0.0.6 - 2026-09-22 #
Changed #
- Every sibling floor names this batch's release.
magicmoves^0.0.15to^0.0.16,fluttersdk_telescope^0.0.6to^0.0.7andfluttersdk_wind^1.6.2to^1.6.3;fluttersdk_duskstays at^0.0.15, still the newest. The old ranges already admitted the new versions, so a freshpub getresolves nothing differently; what changes is that the floors name the releases this package is verified against. telescope 0.0.7 is a documentation fix, and nothing in wind 1.6.3 or magic 0.0.16 touches an API this package calls. (pubspec.yaml,README.md)
0.0.5 - 2026-09-21 #
Changed #
- Every sibling floor names this batch's release.
magicmoves^0.0.7to^0.0.15,fluttersdk_dusk^0.0.12to^0.0.15,fluttersdk_telescope^0.0.5to^0.0.6andfluttersdk_wind^1.5.0to^1.6.2. The old ranges already admitted the new versions, so a freshpub getresolves nothing differently; what changes is that the floors name the releases this package is verified against. magic 0.0.15 is breaking in its database layer (a migration may no longer manage its own transaction, andDB.transactionrefuses a callback that closes the transaction itself); nothing in this package calls either, so no code here changes, but an app below magic 0.0.15 no longer resolves this release. (pubspec.yaml)
0.0.4 - 2026-08-25 #
Added #
MagicPerfIntegration: the wiring that assembles the performance-diagnostic data path across four packages. It setsMagicController.onRefreshUIto a counter keyed by controller runtime type, registers aNavigatorObserverthroughMagicRouter.addObserverthat times each route push to the first post-frame callback after the new route builds, callsWind.installPerfResolver(), registers telescope'sFramePerfWatcher, and assigns the fourfluttersdk_duskpointers (framePerfReader,perfExtrasReader,perfSessionBeginHook,perfSessionEndHook). This package is the only place dusk, telescope, wind and magic are all visible at once, so it is the only place those pointers can be assigned; dusk declares them with no-op defaults and never imports the packages it reports on.MagicDevtools.installPre()now installsMagicPerfIntegration. It belongs in the pre-Magic.init()half becauseMagicRouter.addObserverthrows once the router has been built, and thatStateErroris deliberately not caught: a silently unregistered observer would produce a report with no route transitions and nothing to explain their absence.
Changed #
-
The four sibling dependency floors now state what the code actually needs. They were
magic: ^0.0.6,fluttersdk_dusk: ^0.0.9,fluttersdk_telescope: ^0.0.4andfluttersdk_wind: ^1.2.1, and every one of them was below the release that introduced an APIMagicPerfIntegrationcalls:MagicController.onRefreshUIarrived in magic 0.0.7, the fourperf_readers.dartpointers in dusk 0.0.12,FramePerfWatcherandTelescopeStore.recentFramePerf/clearFramePerfin telescope 0.0.5, andWindPerfCounterswithWind.installPerfResolver()in wind 1.5.0.A caret range resolves to the newest version available, so a fresh resolution always picked up the right siblings and CI stayed green. A consumer whose own constraints hold one of them back would not: pub would report the graph as satisfiable and the build would then fail on undefined symbols. That is not hypothetical, it is what this branch's own CI did while
^1.2.1was still resolving wind 1.4.1, with 18 errors all namingWindPerfCountersorinstallPerfResolver. Now^0.0.7,^0.0.12,^0.0.5and^1.5.0.
0.0.3 - 2026-08-05 #
Documentation only; no runtime change. The package code is identical to 0.0.2.
Changed #
- The README install snippet pins the versions actually shipped rather than a looser range, so a copy-paste resolves to the combination this package is tested against.
.github/workflows/publish.ymlnames the pub.dev prerequisite it cannot check for itself. Automated publishing has to be enabled per package on pub.dev, and without it a tag gets all the way through validate, a clean--dry-runand the upload before pub.dev refuses; that is what left 0.0.2 unpublished for a week while consumers requiring^0.0.2could not resolve at all. That setting is still off, so this release was published by hand as well.
0.0.2 - 2026-07-29 #
Added #
MagicDevtoolsumbrella wiring: a newpackage:magic_devtools/magic_devtools.dartbarrel exposingMagicDevtools.installPre()/MagicDevtools.installPost().installPreboots both tool plugins and registers telescope's opt-inExceptionWatcher+DumpWatcher(call beforeMagic.init());installPostwiresMagicTelescopeIntegration+MagicDuskIntegration(call afterMagic.init()). Collapses the previous fourkDebugModeblocks in a host'slib/main.dartinto two, while preserving the load-bearing pre/post ordering and the call-sitekDebugModeguard (moving the guard inside would defeat the release tree-shake).MagicPreviewframework: a dev-only component preview catalog hosted via two plain pages (/previewand/preview/:component). Newpackage:magic_devtools/preview.dartbarrel exports thePreviewEntrycontract (label,slug,builder), theMagicPreviewCatalogwidget (a scrollable sidebar next to a SINGLE active preview pane — tapping a sidebar item, or deep-linking/preview/<slug>, swaps the pane to that entry; only the selected preview is mounted, so a large screen-heavy catalog stays responsive — plus a global light/dark toggle bound to wind'sWindTheme.of(context).toggleTheme()), and theMagicPreviewregistration entrypoint (registerplusregisterRoutes). The route, catalog, and every registeredPreviewEntryare reachable only throughMagicPreview.registerRoutes, which is guarded bykReleaseModeplusconst bool.fromEnvironment('PREVIEW_ENABLED', defaultValue: kDebugMode), so the whole surface const-folds dead and tree-shakes out of release builds. Entries are held in a function-scoped list (never a top-level const, the dart-lang/sdk#33920 foot-gun). The generated_previews.g.dart(Step 18) feeds aList<PreviewEntry>intoMagicPreview.register. Consumers must callMagicPreview.registerRoutes()from a providerboot()BEFORE the router locks on firstrouterConfigaccess, else/previewsilently never registers.fluttersdk_windis now a direct dependency (the catalog renders onWDiv/WText/WAnchorand binds the theme toggle toWindThemeController).MagicDuskIntegration.install()now registers a navigate adapter viaDuskPlugin.registerNavigateAdaptersoext.dusk.navigate --route <path>drives GoRouter throughMagicRouter.instance.to(path)instead of falling back to theSystemNavigatorplatform broadcast. Returnstrueon success andfalsewhen the router is not yet initialised (catchesStateError).resetForTesting()clears the adapter withDuskPlugin.registerNavigateAdapter(null).
Fixed #
/preview/<slug>deep links now select the right entry: the catalog moved off a persistent ShellRoute (which did not rebuild when only the child route swapped, leaving every deep link stuck on the first entry) to two plain pages; the/preview/:componentbuilder receives the slug and rebuilds on navigation. Known dev-only limitation: feature-SCREEN previews (full controller-backedMagicStatefulViews) emit a couple of non-fatalsetState() during buildwarnings because the catalog mounts the same screen in both the light and dark panes sharing a singleton controller; the screens render correctly and the real app routes are clean (the catalog is stripped from release)./previewroute no longer crashes the app: the catalog group's index child path was/which composed to/preview/, tripping go_router'sroute path may not end with '/'assertion and blanking the entire app on every route. Changed the index child path to''so the composed path is exactly/preview.- Catalog previews now inherit the host theme: each light/dark pane copied a bare
WindThemeDatathat carried no aliases, so component semantic tokens (text-fg,bg-surface, ...) resolved to no-ops and every preview rendered Flutter's red unstyled-text fallback. Panes nowcopyWith(brightness:)the ambient app theme, preserving aliases and brand colors. - Catalog overflow: the preview surface now scrolls vertically and each pane scrolls horizontally, so wide variant matrices no longer trigger RenderFlex overflows in the side-by-side light/dark layout.
0.0.1 - 2026-06-17 #
Added #
- Initial release, extracted from the
magicpackage.MagicDuskIntegration(14 enrichers forfluttersdk_dusksnapshots) andMagicTelescopeIntegration(5 watchers plusMagicHttpFacadeAdapterforfluttersdk_telescope) now live here as a dedicated, debug-only dev-tooling adapter rather than as sub-barrels ofmagic. - Two import barrels:
package:magic_devtools/dusk.dartandpackage:magic_devtools/telescope.dart. - The relocated enricher and watcher test suites moved over unchanged.
Note #
- Local development resolves the
magic,fluttersdk_dusk, andfluttersdk_telescopesiblings throughdependency_overridespath entries. Those overrides are dev-only; version pins replace them at publish (the publish-time pubspec is user-owned).