Constants
BARE_METHOD_KEY = /(?<![\w$.:])method\b(?!\s*:)/
BASE_PATH_RE = /\bbase
Path\s*:\s*(['"`])(\/[^'"`$]*)\1/
CONFIG_BASENAMES = ["next.config.js", "next.config.ts", "next.config.mjs", "next.config.cjs"]
DEFAULT_EXPORT = /export\s+default\s+(?!(?:async|function|class)\b)/
DEFAULT_EXPORT_CALL_OBJECT = /export\s+default\s+(?!(?:async|function|class)\b)[\w$.]+\s*\(\s*\{/
export default withMiddlewares({ GET: ..., POST: ... }): a wrapper
handed a verb-keyed object serves exactly those methods.
DEFAULT_EXPORT_FUNCTION = /export\s+default\s+(?:async\s+)?(?:function\b\s*\*?\s*([\w$]+)?|(?:\([^)]*\)|[\w$]+)(?:\s*:\s*[^=]+?)?\s*=>)/
export default function handler( / export default async (req, res) =>.
DEFAULT_KEY_OBJECT = /\A\{\s*default\s*:\s*(.+?)\s*,?\s*\}\z/m
DESTRUCTURE_FROM_REQUEST = /\{((?:[^{}]++|\{[^{}]*+\})*+)\}\s*=\s*(?:req|request)\b(?!\s*[.\[])/
DYNAMIC_IMPORT = /\A(?:await\s+)?import\s*\(\s*['"`]([^'"`]+)['"`]\s*\)\z/
EXPORT_VERB_BRACE_RES = HTTP_METHODS.map do |m| {m, /export\s+\{[^}]*\b#{m}\b[^}]*\}/} end.to_h
EXPORT_VERB_CONST_ARROW_RES = HTTP_METHODS.map do |m| {m, /export\s+const\s+#{m}\s*=\s*(?:async\s*)?(?:\([^)]*\)|\w+)(?:\s*:\s*[^=]+?)?\s*=>/} end.to_h
EXPORT_VERB_CONST_BRACE_RES = HTTP_METHODS.map do |m| {m, /export\s+const\s+\{[^}]*\b#{m}\b[^}]*\}\s*=/} end.to_h
export const { POST } = serve<Input>(...) — handler(s) destructured
from a factory call (e.g. @upstash/workflow/nextjs). The plain brace
regex misses it because const sits between export and {.
EXPORT_VERB_CONST_RES = HTTP_METHODS.map do |m| {m, /export\s+const\s+#{m}\s*=/} end.to_h
EXPORT_VERB_FUNCTION_RES = HTTP_METHODS.map do |m| {m, /export\s+(?:async\s+)?function\s+#{m}\b/} end.to_h
Compiled once per verb — interpolated regex literals would otherwise
be rebuilt (full PCRE2 compile) for every method on every file.
EXTENSIONS = [".js", ".jsx", ".ts", ".tsx", ".mjs"]
FUNCTION_DEFINITION_LINE = /\bfunction\b|=>|=\s*(?:async\s*)?\(/
GUARD_CONDITIONAL = /\bif\b|\?|&&|\|\|/
GUARD_REJECTS = /\bthrow\b|\b4\d\d\b|\bMETHOD_NOT_ALLOWED\b|(?i:not allowed)/
What makes a consequent a rejection, and what makes it conditional
(a nested if, ternary or &&/|| ahead of the rejection).
HTTP_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]
LOCAL_CALL_RE = /(?<![\w$.])([A-Za-z_$][\w$]*)\s*\(/
METHOD_EQ = /\b(?:req|request)\.method\s*===?\s*['"]([A-Z]+)['"]/
METHOD_EQ_BARE = /(?:\b(?:req|request)\.|(?<![\w$.]))method\s*===?\s*['"]([A-Z]+)['"]/
METHOD_FROM_REQUEST = /(?<![\w$.])method\s*=\s*(?:req|request)\.method\b/
Pages Router method checks. The receiver is req.method /
request.method, or a bare method once the file binds it from the
request (const { method } = req, const method = req.method).
METHOD_GUARD = /\bif\s*\(((?:[^(){};]++|\([^()]*+\))*+)\)\s*(?:(throw)\b|(?=\{([^{}]*))|return\b([^{};\n]*))/
if (<cond>) followed by its consequent: an immediate throw, the
block up to its first brace (captured in a lookahead, so a guard
nested in that block is still scanned), or a return statement.
Every repetition is possessive or a single char class: grouped
repetition overflowed the PCRE2 JIT stack on long hostile input.
METHOD_INCLUDES = /\[\s*([^\]]+)\]\s*\.includes\s*\(\s*(?:req|request)\.method/
METHOD_INCLUDES_BARE = /\[\s*([^\]]+)\]\s*\.includes\s*\(\s*(?:(?:req|request)\.)?method\b/
METHOD_NE = /\b(?:req|request)\.method\s*!==?\s*['"]([A-Z]+)['"]/
METHOD_NE_BARE = /(?:\b(?:req|request)\.|(?<![\w$.]))method\s*!==?\s*['"]([A-Z]+)['"]/
METHOD_SWITCH = /switch\s*\(\s*(?:req|request)\.method\s*\)/
METHOD_SWITCH_BARE = /switch\s*\(\s*(?:(?:req|request)\.)?method\s*\)/
REEXPORT_DEFAULT = /export\s*\{\s*(?:([\w$]+)\s+as\s+)?default\s*\}\s*from\s*['"`]([^'"`]+)['"`]/
SPLIT_TOP_LEVEL_COMMAS_RULES =
Noir::TopLevelSplit::Rules.new(nest: ((
Noir::TopLevelSplit::Nest::Paren |
Noir::TopLevelSplit::Nest::Bracket) |
Noir::TopLevelSplit::Nest::Brace) |
Noir::TopLevelSplit::Nest::Angle, quotes: "", escape:
Noir::TopLevelSplit::Escape::None, strip: false, empties:
Noir::TopLevelSplit::Empties::Keep, per_kind: false, clamp: true)
Unlike every other JS/TS splitter this one has NO quote handling at all,
counts < > as nesting, and neither strips nor drops empty parts —
reproduced verbatim from the body it replaces.
The two callers explain the shape: exported_alias_for_method passes the
inside of an export { a, b as c } clause and
extract_server_action_params passes a TypeScript parameter list, so
generics have to nest ({ params }: { params: Promise<{ id: string }> })
but neither input can contain a string literal. Both strip each part and
skip the empties themselves.
VERB_MAP_KEY = /\A(?:async\s+)?["']?(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)["']?\s*(?::|\(|\z)/
WRAPPER_CALL = /\A\s*(?!(?:async|function|new)\b)[\w$.]+\s*(?:<[^>()]*>)?\s*\(/