Skip to content

feat: NativeScript support (native overlay, example app, standalone server fixes) - #16

Draft
NathanWalker wants to merge 4 commits into
santoshyadavdev:mainfrom
NathanWalker:feat/nativescript
Draft

NathanWalker wants to merge 4 commits into
santoshyadavdev:mainfrom
NathanWalker:feat/nativescript

Conversation

@NathanWalker

@NathanWalker NathanWalker commented Sep 25, 2026 •

Copy link
Copy Markdown

Summary

Lets the devtools run against a NativeScript Angular app. A NativeScript app has no DOM, so this adds a second overlay that walks the native view tree through Angular's ng debug API and reports over a WebSocket to a devtools server on the developer's machine. The component tree, signal graph, injector tree, highlight tool, MCP tools and resources, and the source scanners all work against the included example app.

What's in here

  • refactor(overlay) – the collectors (component tree, signal graph, injector tree, NgRx) move into overlay-core.ts and read the host tree through a small adapter, so the DOM overlay and the NativeScript overlay only differ in how hosts are named and how children are listed. The browser overlay keeps its exports. Two fixes came with it: injector nodes get a stable id (a selection in the DI panel no longer resets every 3s), and the injector walk dedupes by host and looks through injector-less hosts.
  • feat(overlay) – @santoshyadavdev/ng-devtools/overlay-nativescript. Beyond the tree walk it handles what the runtime lacks: WebSocket must come from the app (@valor/nativescript-websockets), location/navigator are shimmed for devframe's client, and reconnection is built in because devframe's client has none and the app and server restart independently. The DI panel needs Angular's injector profiler, which Angular only wires when window exists during platform creation; the overlay provides a window until core publishes ng.getComponent (the sentinel has to be that property, since provideRouter() publishes onto ng earlier). The signal graph is merged across every component, and environment injectors with their providers sit above the element tree.
  • fix(ui) – two things kept ng-devtools dev from showing anything, on any platform: the UI always looked for its connection at /__ng-devtools/ and never at its own base, and the server could not resolve the built assets package (it is now a workspace devDependency of packages/ng-devtools). The assets build is refreshed.
  • feat – app-nativescript/, an ns create --ng project wired up, with a showcase component (signal, computeds, effect, input, component-level provider). pnpm devtools:nativescript starts the server scanning its sources.

Try it

pnpm install
pnpm devtools:nativescript          # devtools server on http://localhost:9999/
cd app-nativescript && npm install && ns debug ios --no-hmr

Open http://localhost:9999/; the badge turns to Connected once the app reports. Tap the showcase card and the Signals tab updates. ng-devtools_highlight over MCP outlines the native view.

Verified

  • iPhone 17 Pro simulator: component tree rooted at ns-app, signal graph with live values and epochs, injector tree with platform + app environment injectors and the showcase's TapCounter, highlight over MCP, reconnect after a server restart.
  • pnpm format:check, pnpm test (Node 24.15), pnpm test:devtools (135 tests, 12 new for the NativeScript walker, merge, injector dedupe and environment chain), pnpm build, pnpm devtools:build, node bin.mjs --help.

Notes and follow-ups

  • extension/ui was not rebuilt; the extension passes ?baseURL= and is unaffected by the UI fix.
  • tryGetInputs still dumps every non-function field of a component (as before); on NativeScript that includes renderer internals of ListView. Restricting it to declared inputs via getDirectiveMetadata would help both platforms.
ns-ng-devtools.mp4

The component tree, signal graph, injector tree and NgRx collectors now
live in overlay-core and read the host tree through a small adapter
(children, id, tag name, selector), so an overlay for a platform without
a DOM only has to describe its hosts. The DOM overlay keeps its exports
and its behaviour.

Two fixes fell out of the move. Injector nodes take their id from the
host instead of drawing a new random one on every report, so a selection
in the DI panel survives the next refresh. The injector walk also dedupes
by host rather than by injector object, since Angular returns a fresh
NodeInjector from every getInjector call, and it looks through hosts
that bring no injector of their own instead of stopping at them.
A NativeScript Angular app has no DOM, so the browser overlay cannot run
in it. The new `@santoshyadavdev/ng-devtools/overlay-nativescript` entry
walks the native view tree from the root component host through the
shared collectors and reports over a WebSocket to a devtools server on
the developer's machine: component tree, a signal graph merged across
every component, the injector tree with the environment injectors and
their providers above it, NgRx state, and the highlight event, which
outlines the native view.

The runtime needs a few things a browser has for free. A WebSocket global
must come from the app (for example @valor/nativescript-websockets), and
`location` and `navigator` are shimmed for devframe's client. Angular only
wires its injector profiler, which backs the DI panel, when `window`
exists as the platform is created, so a `window` is defined until core
publishes `getComponent` and removed then; the sentinel is that property
rather than the `ng` object itself because provideRouter() publishes its
own utilities onto that object earlier. The devframe client has no
reconnect, and the server and the app restart independently, so a failed
or dropped session is replaced after a pause.

The two new files import their siblings without a `.ts` extension: the
app's own TypeScript compiles them, and a `.ts` specifier is an error
there unless the app's tsconfig opts in.
…build

Two things kept `ng-devtools dev` from showing anything. The UI always
looked for its connection at /__ng-devtools/, which is where the Vite
bridge and the Express mount put it, while the standalone server serves
it next to the page; the UI now tries its own base first and falls back
to /__ng-devtools/. And the server resolves the built UI from the
devframe definition's package, which did not depend on the assets
package, so it fell back to fetching an unpublished version from a CDN
and served nothing. The assets package is now a workspace devDependency
of the devtools package, and the assets build is refreshed with the UI
change.
`app-nativescript/` is an `ns create --ng` project wired to the
NativeScript overlay: the WebSocket polyfill in polyfills.ts, the overlay
started in main.ts before the app runs, plain-HTTP allowances for the
simulator and emulator, and a showcase component with a signal, two
computeds, an effect, an input and a component-level provider so every
panel has something to show.

The app maps the devtools package through tsconfig `paths` rather than
importing it from node_modules. TypeScript never emits `.ts` sources it
resolved through node_modules, so the linked package compiled to an
empty module under @nativescript/webpack; that constraint applies to any
webpack consumer of the package's TypeScript sources.

`pnpm devtools:nativescript` starts the devtools server scanning the
app's sources. Generated directories are left out of the Prettier check.
@coderabbitai

coderabbitai Bot commented Sep 25, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Comment @coderabbitai help to get the list of available commands.

@erkamyaman

erkamyaman commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

That looks like a real badass idea

@erkamyaman

Copy link
Copy Markdown
Contributor

I had an idea to make this devtools work for Capacitor Angular apps as well but this is beyond my wildest dreams. Just watched the video so cool

@NathanWalker

Copy link
Copy Markdown
Author

hey thanks @erkamyaman - these devtools are great - @edusperoni also has great ideas here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants