class

Analyzer::Javascript::Fresh

Inherits Analyzer::Javascript::JavascriptEngine < Analyzer < FileHelper < Reference < Object

Fresh is Deno's filesystem-routed framework. Routes live under routes/ and the URL is derived from the directory layout:

routes/index.tsx → GET / routes/about.tsx → GET /about routes/users/index.tsx → GET /users routes/users/[id].tsx → GET /users/{id} routes/api/users.ts → handler-driven verbs routes/[...slug].tsx → GET /{slug}

Verb shape:

  • Page files (.tsx / .jsx) with a export default component render HTML — emit GET.

  • Resource files export a handler object whose keys are HTTP verbs:

    export const handler: Handlers = {
        GET(req, ctx) { ... },
        async POST(req, ctx) { ... },
        PUT: async (req) => { ... },
    };

    Each verb-shaped key (method shorthand or property assignment) registers a route.

  • If handler is a single function (no object), Fresh dispatches every method to it — fall back to the standard handler set (GET / POST / PUT / DELETE / PATCH).

Underscore-prefixed files (_app.tsx, _layout.tsx, _404.tsx, _500.tsx, _middleware.ts) are framework plumbing — not user-facing routes — and skipped.

Out of scope for this first cut:

  • Per-handler request-helper scanning. Fresh handlers receive (req, ctx) — accurate read tracking needs cross-call value flow. Path placeholders still surface via the optimizer.
  • Route groups ((group) directories — same convention as SvelteKit). Add when fixtures show real-world usage.

Constants

API_EXTENSIONS = [".ts", ".js", ".mjs"]
DENO_MANIFEST_BASENAMES = ["deno.json", "deno.jsonc"]
EXTENSIONS = PAGE_EXTENSIONS + API_EXTENSIONS
FALLBACK_HANDLER_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH"]
FRESH_APP_IMPORT = /from\s+["'](?:fresh|jsr:@fresh\/core[^"']*|@fresh\/core)["']/
FRESH_APP_MARKER = /\bnew\s+App\b/

Fresh 2's programmatic router: const app = new App() imported from fresh, then app.get("/api2/:name", handler) beside app.fsRoutes().

FRESH_IMPORT_MARKER = /\$fresh\/|@fresh\//

Fresh 1 maps $fresh/; Fresh 2 (jsr:@fresh/init) maps the bare fresh specifier to jsr:@fresh/core.

HTTP_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]
PAGE_EXTENSIONS = [".tsx", ".jsx"]
ROOT_CONFIG_BASENAMES = ["fresh.config.ts", "fresh.config.js", "fresh.config.mjs"]

A Fresh project is anchored by fresh.config.{ts,js}, or by a Deno manifest that pulls in $fresh/. Same shape the detector already treats as authoritative.

SKIPPED_LEAVES = ["_app", "_layout", "_404", "_500", "_middleware"]

Files that are framework plumbing rather than routes.

TEST_FILE_PATTERN = /[._]test\.(?:[tj]sx?|[mc][tj]s)$/

Fresh's own default ignore for the routes tree (TEST_FILE_PATTERN in constants.ts): routes/foo.test.ts and routes/index_test.tsx are never served.

Class methods

tech_name
Source

Instance methods

analyze
Source
tech

Instance-side view of the same declaration. The per-file rescues live on this base class, which has no way to name the analyzer that is running inside them, so a skipped file could not be attributed to a tech. Deriving it from analyzer_for keeps the name written exactly once.

Source