import type { Route, RouteGap } from "./routes.js"; /** * Ask the framework where its endpoints are. * * Everything in this file reads an answer the framework itself computed and * wrote down. None of it parses application source to derive a URL, and that is * the whole point of the file existing. * * The reason is measured, not stylistic. Next.js discovery started as a walk of * `app/**` and `pages/api/**`, which is exact about the tree and blind to * everything that moves a URL outside it. On one real application with a * `basePath` the tree yielded 6 URLs and the build manifest yielded 14, and the * overlap between the two sets was **zero**: six endpoints probed that do not * exist, fourteen real ones never probed, and a report that looked like a clean * API plane. A source parser's failure mode is silence, and silence is the one * thing this tool must never produce. * * Every framework here already writes its route table down somewhere: * * - SvelteKit: `.svelte-kit/types/route_meta_data.json`, written by * `svelte-kit sync` — which runs on `npm install`, `dev` and `build`. * - Nuxt and any Nitro app: `.nuxt/types/nitro-routes.d.ts`, in which Nitro * has already resolved each handler to the URL *and the method* it serves. * - Anything that emits OpenAPI — FastAPI, NestJS, Django REST, Go — an * `openapi.json` beside the project. * * ## Running a command is not on offer * * `rails routes`, `php artisan route:list` and `manage.py show_urls` would each * answer this question exactly, and each one boots the application to do it: * initializers run, database connections open, and in Rails' and Laravel's case * a misconfigured environment can migrate or seed a developer's database on the * way. Crossline is a test that must be safe to run on every commit by someone * who has not read its source, so it does not execute the project under * examination. Nothing in this file runs anything; it opens files. * * The frameworks that only answer to a command are therefore *declined by * name*, in the report, with the command to run and where to put the result — * see {@link declinedFrameworks}. Coming back with zero routes and no * explanation is the failure this file exists to remove; coming back with zero * routes and the sentence "this is a Rails application, Crossline cannot * enumerate its routes without booting it, here is what to do" is honest. */ /** A route before `params` is filled in — the caller derives that from `path`. */ export type FrameworkRoute = Omit; export interface FrameworkDiscovery { routes: FrameworkRoute[]; gaps: RouteGap[]; /** Sentences for the coverage note. Never a finding; always for the reader. */ notes: string[]; } /** Read every framework answer present in one directory. */ export declare function discoverFrameworks(dir: string, reportRoot: string): FrameworkDiscovery;