M
Maintaining a large APEX application means living with one nagging question: if I change this page, what else am I about to break? Before you touch page 50 you want to know what links into it. Before you delete page 50 you want to be sure nothing still points at it. How do I even get to page 50?
APEX does not make that easy. Navigation is spread across branches, buttons, lists, navigation bar, breadcrumbs, report column links... There is no single screen that says "here is everything that links into page 50" or "here is everywhere you can go from page 50". So you end up grepping the export or clicking through the builder page by page.
I built a small command into ADT.ai that answers exactly those two questions. It is called "flow", and once it has scraped an app it answers offline, in milliseconds.
What it does
It reads the navigation links of requested application(s) from the database once, stores them in a local SQLite file, and then answers two questions without touching Oracle again. It holds all your applications side by side, keyed by workspace and app_id. So "-app" argument is mandatory for every action, you always say which application you mean.
Building the map
You build (or rebuild) the map with "-refresh":
adtai flow -app 100 -refresh -env DEV
That connects through the default APEX schema, resolves who actually owns the application, reconnects as that schema, and loads the app's metadata, pages, and every navigation edge. A refresh is a full rewrite: the old rows for that app are deleted and replaced in one transaction, never appended. Run it twice and you get the same result, not duplicates.
The store lives at "config/flow.db" and is gitignored, same idea as the discovery log. The database is the source of truth here, populated straight from live Oracle. Each refresh also writes the whole graph to "config/flow/app_<id>.mmd", ".dot", and ".json", so you get diagrams without asking for them.
Asking the two questions
Once an app is loaded, both reads are offline and instant:
adtai flow -app 100 -to 50 adtai flow -app 100 -from 50
The first prints everything that links into page 50, the second prints everywhere page 50 can take you. You get a plain table of the source or target page and the component behind the link, capped to a sane width so the console stays readable.
What counts as a link
A navigation edge is any link from a source component to a target page, and flow pulls them from all the usual places: page branches, buttons, list entries, tabs, navigation bar entries, breadcrumbs, and report column links. Each edge carries a flag for how resolvable its target is:
- "PAGE" – a normal link to another page in the same app, the common case
- "CROSS_APP" – a link into a different application
- "DYNAMIC" – the target page is computed at runtime (item values, substitution strings) and cannot be resolved statically
- "NONE" – the link leaves APEX entirely, or carries no page target at all
This is where I decided to be honest rather than clever. "-to" and "-from" only show you links that actually resolve to a page, so "PAGE" and "CROSS_APP". A link whose target is "&MY_ITEM." is a real link, but I cannot tell you where it lands without running your app, so flow does not pretend. The JSON dump keeps every edge, including the dynamic and the dead ones, so anything you build on top can decide for itself.
Diagrams
Every refresh writes three formats. Mermaid and DOT give you a picture you can drop into docs or render in the browser, just the resolvable edges so the graph stays meaningful. The JSON is the lossless one, every edge with its flag, ready for whatever you want next. Charts are basic now and they need more attention, but you can at least get an idea whats possible.
Few limitations
Shared components like tabs, lists, and the nav bar are reachable from every page, so they do not belong to a single source page, "-from" returns the page-specific links and leaves the global entry points out. Cross-app incoming links are only as complete as the set of apps you have loaded, flow can report what you refreshed and nothing more. Also if your redirections are burried in PL/SQL or JavaScript, they are not covered.
Point it at one of your own apps, refresh it once, and ask where your most-edited page links. You will probably find an edge you forgot about.
If this saved you some clicking through the builder, pass it to someone. Thanks.
Comments
Post a Comment