Summary
surf lint cannot resolve a symbol declared as export const NAME = <callExpr>(...). In modern TS / React Server Component code this is extremely common — query and mutation helpers are routinely wrapped, e.g. export const getX = cache(unstable_cache(async () => { ... })).
By contrast, export function / export async function declarations and export type aliases resolve fine, so the limitation appears specific to const declarations with (call-expression) initializers.
Environment
surf 0.1.0, prebuilt binary surf-aarch64-apple-darwin (curl installer)
- macOS (Apple Silicon, arm64)
- Target: TypeScript (tree-sitter TS grammar)
Repro
- Anchor a wrapped const-bound function:
- claim: "..."
at: "src/lib/queries.ts > getOffsideResults"
where the source is:
export const getOffsideResults = cache(
unstable_cache(async (/* ... */) => { /* ... */ }),
);
- Run
surf lint.
Actual
error: ... > getOffsideResults
`getOffsideResults` not found (claim has no stored hash to match against)
surf lint: 1 error(s), 0 warning(s).
Expected
The anchor resolves to the const's initializer (the arrow function), the same way a function declaration resolves.
Notes / suggested fix
Index lexical_declaration → variable_declarator names. When the initializer is a call expression, resolve the span either to the function passed as an argument or to the whole initializer.
Worth deciding the documented contract: does the stored hash cover just the inner function body, or the entire initializer (so that swapping the cache(...) wrapper also trips)?
Impact
This pattern covers the entire data-access layer of a typical Next.js App Router codebase (cached server queries, server actions, Zod schemas via export const X = z.object(...)), so today those symbols can't be anchored at all.
Found while dogfooding surface on a real TypeScript codebase (OffsideFPL).
Summary
surf lintcannot resolve a symbol declared asexport const NAME = <callExpr>(...). In modern TS / React Server Component code this is extremely common — query and mutation helpers are routinely wrapped, e.g.export const getX = cache(unstable_cache(async () => { ... })).By contrast,
export function/export async functiondeclarations andexport typealiases resolve fine, so the limitation appears specific toconstdeclarations with (call-expression) initializers.Environment
surf 0.1.0, prebuilt binarysurf-aarch64-apple-darwin(curl installer)Repro
surf lint.Actual
Expected
The anchor resolves to the
const's initializer (the arrow function), the same way afunctiondeclaration resolves.Notes / suggested fix
Index
lexical_declaration→variable_declaratornames. When the initializer is a call expression, resolve the span either to the function passed as an argument or to the whole initializer.Worth deciding the documented contract: does the stored hash cover just the inner function body, or the entire initializer (so that swapping the
cache(...)wrapper also trips)?Impact
This pattern covers the entire data-access layer of a typical Next.js App Router codebase (cached server queries, server actions, Zod schemas via
export const X = z.object(...)), so today those symbols can't be anchored at all.Found while dogfooding surface on a real TypeScript codebase (OffsideFPL).