class

Noir::JSParser

Inherits Reference < Object

JSParser is a simple parser for JavaScript route-related patterns

Constants

APP_FACTORIES = Set {"express", "fastify", "Fastify", "Koa", "Hono", "Application", "Router", "Elysia"}
CONTEXTUAL_CLIENT_RECEIVERS = Set {"http", "https", "socket"}

http, https and socket are also ordinary parameter names for an app (module.exports = function registerRoutes(http) { http.get('/ping', handler) }), so for them the call shape decides (request_handler_call?).

HTTP_CLIENT_OPTION_KEYS = Set {"host", "hostname", "port", "protocol", "agent", "socketPath", "headers"}

Top-level keys of an HTTP client options bag. A Restify route spec keeps arbitrary keys (authAction, validation, swagger, ...) on req.route.spec, so only these disqualify one.

HTTP_CLIENT_RECEIVERS = Set {"request", "axios", "superagent", "supertest", "got", "needle", "unirest", "ky", "phin", "chai", "$", "jQuery", "$http", "AJAX", "ajax", "http", "https", "socket", "httpClient", "axiosInstance", "axiosClient"}

Pre-scan tokens to identify router variables Routers are identified by:

  1. Assignment from express.Router(): const router = express.Router()
  2. Having route methods called on them: router.get(...) Receivers that are HTTP clients, never routers. request.get(url, opts) in a test file has the same token shape as router.get(path, handler) — an identifier, a verb, a path-ish first argument and a second argument — so route_handler_arg? cannot separate them and deliberately errs toward keeping the route. The receiver name can: none of these is ever assigned an Express/Koa/Fastify router, and NodeBB's test/*.js alone turns 385 such calls into routes that do not exist. Keep the list to library names that would be perverse to use for a router — a receiver named api or client may well be one (mastodon's streaming server routes on api), so neither is listed. $/jQuery/$http/AJAX are browser clients, http/https the Node modules (http.get(url, cb), k6's http.post(url, data)), socket sails.io's, and httpClient/axiosInstance/axiosClient the injected clients of generated SDKs (this.httpClient.post(...)).
KOA_BARE_PATH_RE = /\A[A-Za-z0-9_][\w.\-~]*\z/
MAX_MOUNT_PREFIXES = 1024

Ceiling on the full prefixes one router resolves to. A diamond lattice of parallel mounts doubles the distinct paths per level; a shared router mounted under many paths stays well below it.

MAX_PREFIX_RESOLUTIONS = 100000

Ceiling on resolver calls per file. Results cut short by a cycle are not memoized, so a densely cyclic mount graph could otherwise enumerate every path; past this budget they are memoized anyway.

REQUEST_PARAM_RE = /\A_?(?:req|request|ctx|context|c)\z/

First parameter names of a request handler: (req, res), (request, reply), (ctx), (c). A client callback names its first parameter after the response or the error: (res), (err, res), (data, jwr).

ROUTING_RECEIVER_NAME = /\A(?:app|router|server|fastify|instance)\z|(?:Router|router|App|Server)\z/

Receivers conventionally holding an app or router.

VALUE_CONTEXT_TOKENS = Set {"return", "await", "yield", "=", ">", "(", ",", ":", "?", "[", "&", "|", "!"}

Tokens right before a receiver that put the call's value to use: return this.get(…), const r = await http.post(…), a || this.get(…). A route registration is a bare statement; a client call is consumed.

Constructors

new(source : String, this_receiver_ok : Bool = true, constants : Hash(String, String) | Nil = nil)

this_receiver_ok is false for a file with no server-framework import: there a bare this.post('/x', data) is the outbound call of an API client class (class ProjectService extends APIService), not a route, unless it passes an inline function or a method reference (this_handler_arg?: Unleash's controllers this.get('/', this.getTags) import only a local base class). constants seeds what the file's own declarations cannot give, such as a constant imported from another module.

Source

Instance methods

detect_framework
Source
hit_max_iterations?
Source
mount_prefixes_capped?
Source
nearest_ancestor(router : String, &) : String | Nil

The router nearest to router (itself first, then the routers it is mounted on, breadth-first) for which the block holds. Only meaningful after parse_routes.

Source
parse_routes
Source