Skip to content

fix: flatten JS/TS template-literal URLs to {} placeholders#1008

Open
CharlesQueiroz wants to merge 1 commit into
DeusData:mainfrom
CharlesQueiroz:fix/template-string-urls
Open

fix: flatten JS/TS template-literal URLs to {} placeholders#1008
CharlesQueiroz wants to merge 1 commit into
DeusData:mainfrom
CharlesQueiroz:fix/template-string-urls

Conversation

@CharlesQueiroz

Copy link
Copy Markdown

Fixes #1006.

Root cause

Client-side URL extraction keyed on static string node kinds only (is_string_like / is_string_node); template_string was never included, so any URL built with a template literal was invisible:

fetch(`/api/v1/things/${id}`)          // no HTTP_CALLS, no Route
return `/api/v1/things/${id}/detail`   // no string_ref

Meanwhile the server side normalizes path params to {} (__route__GET__/api/v1/things/{}), so the join key existed on one side only and cross-repo route matching missed every parameterized endpoint.

Fix

New cbm_template_string_text() (helpers.c) flattens a template_string node: string_fragment children verbatim, each template_substitution becomes the canonical {} placeholder. Wired into the four extraction points that previously accepted only static strings:

  • extract_positional_url and extract_string_value (extract_calls.c): call-argument URLs, keyword and positional.
  • handle_string_refs (extract_unified.c): URL-shaped string refs from const/return positions.
  • handle_string_constants (extract_unified.c): module-level const lookup table.

Template literals now behave exactly like the equivalent static literal with {} in place of each interpolation; behavior for static strings is unchanged.

Validation

  • New regression test extract_ts_template_string_url_issue1006: fetch(/api/v1/things/${id}) yields first_string_arg == "/api/v1/things/{}", and the return-position template lands in string_refs as "/api/v1/things/{}/detail".
  • Full suite: 5986 passed, 1 skipped, 0 failures.
  • End-to-end fixture (TanStack-style hook, the failing shape from JS/TS: template-literal URLs in fetch/query hooks produce no HTTP_CALLS or Route nodes (static literals work) #1006) indexed with the patched binary now yields __route__ANY__/api/v1/things/{} and the queryFn -HTTP_CALLS-> /api/v1/things/{} edge.

…#1006)

Client-side URL extraction only recognized static string literals; any
template literal was silently skipped, so parameterized endpoints never
produced HTTP_CALLS edges or Route nodes and cross-repo route matching
missed them (the server side already normalizes path params to {}).

New cbm_template_string_text() flattens a template_string node: string
fragments verbatim, each ${...} substitution becomes {}. Wired into:
- extract_positional_url / extract_string_value (call-arg URLs)
- handle_string_refs (URL-shaped refs from const/return positions)
- handle_string_constants (module-level const lookups)

`/api/v1/things/${id}` now yields __route__ANY__/api/v1/things/{} and
the enclosing function gets the HTTP_CALLS edge, joining the canonical
placeholder shape of server-side routes.
@CharlesQueiroz CharlesQueiroz requested a review from DeusData as a code owner July 10, 2026 16:26
@DeusData DeusData added this to the 0.9.1-rc milestone Jul 10, 2026
@DeusData DeusData added bug Something isn't working parsing/quality Graph extraction bugs, false positives, missing edges ux/behavior Display bugs, docs, adoption UX priority/normal Standard review queue; useful PR with ordinary maintainer urgency. labels Jul 10, 2026
@DeusData

Copy link
Copy Markdown
Owner

Thanks for putting this together. I have triaged it into 0.9.1-rc as the fix candidate for #1006. Review focus will be template-literal flattening semantics, placeholder handling, and confirming that existing static-literal fetch/query extraction stays unchanged.

@DeusData

Copy link
Copy Markdown
Owner

Reviewed and verified locally — the approach is right, the flattening semantics match the server-side placeholder exactly, and static-literal behavior is unchanged. Three things before merge, two mechanical and one small hardening:

Verified working (your branch merged onto current main):

1. DCO (blocking): commit d2868cd lacks a Signed-off-by matching its author. git commit --amend -s (keeping author email = sign-off email) and force-push fixes it.

2. clang-format (blocking): two lines need wrapping — make lint-format locally, or apply:

// extract_unified.c:527
    char *value =
        flat_value ? (char *)flat_value : cbm_node_text(ctx->arena, value_node, ctx->source);
// extract_unified.c:578 (initializer wraps)
            .enclosing_func_qn =
                state->enclosing_func_qn ? state->enclosing_func_qn : ctx->module_qn,

3. Hardening (please include): in extract_positional_url, the flattened template text bypasses strip_and_validate_string_arg, which for quoted strings rejects control characters and over-long args. Template literals legally contain raw newlines (multiline SQL/HTML passed to a fetch-like callee would mint a junk route containing a newline). Routing the flat text through the same validator closes that — it's quote-agnostic, so it's a one-liner:

    if (strcmp(ak, "template_string") == 0) {
        const char *flat = cbm_template_string_text(ctx->arena, arg, ctx->source);
        if (flat) {
            return strip_and_validate_string_arg(ctx->arena, (char *)flat);
        }
    }

(Also noticed escape_sequence fragments inside templates are silently dropped by the flattener — fine for URLs, not worth complicating; just mentioning it's a known, accepted simplification.)

With those three in and CI green this is good to merge. Nice work on keying the placeholder to the server-side canonical form rather than inventing a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working parsing/quality Graph extraction bugs, false positives, missing edges priority/normal Standard review queue; useful PR with ordinary maintainer urgency. ux/behavior Display bugs, docs, adoption UX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

JS/TS: template-literal URLs in fetch/query hooks produce no HTTP_CALLS or Route nodes (static literals work)

2 participants