Skip to content

fix(vnda): optimize /api/v2/tags/:name calls to prevent rate limiting#1563

Open
pandeiro7 wants to merge 1 commit intodeco-cx:mainfrom
tec4udigital:fix/loader/vnda
Open

fix(vnda): optimize /api/v2/tags/:name calls to prevent rate limiting#1563
pandeiro7 wants to merge 1 commit intodeco-cx:mainfrom
tec4udigital:fix/loader/vnda

Conversation

@pandeiro7
Copy link
Copy Markdown
Contributor

@pandeiro7 pandeiro7 commented Mar 26, 2026

Contexto

O loader productListingPage.ts disparava um número excessivo de chamadas à API /api/v2/tags/:name da VNDA por page load, resultando em erros HTTP 429 (Rate Limit) bloqueados pelo Cloudflare (Error 1015 — You are being rate limited) em páginas de categoria com filtros ativos.

O erro era intermitente em produção e se tornava consistente em momentos de tráfego elevado ou em URLs com muitos filtros aplicados simultaneamente.

Log de erro original:
HttpError 429 em searchLoaderapi.vnda.com.br bloqueado pelo Cloudflare
Ray ID: 9e26b7badb7eed832026-03-26 14:06:44 UTC


Diagnóstico

Causa raiz #1 — coleta indiscriminada de query params

// ANTES: capturava TODOS os valores da URL como possíveis nomes de tag
const categoryTagNames = Array.from(url.searchParams.values());

Para a URL real que gerou o 429:
/feminino/tenis-para-corrida/amortecimento/busca/hoka_one_one?dir=asc&order=position&type_tags[Peso do tênis (g)][]=esp-peso-tenis-281&type_tags[Finalidade][]=finalidade-corrida&type_tags[Tipo de Pisada][]=esp-pisada-neutra-tipo&type_tags[Tipo de Pisada][]=esp-pisada-supinada-severa-tipo&type_tags[Artigo][]=artigo-tenis&type_tags[property1][]=38

O código original disparava 15 chamadas à /api/v2/tags/:name:

Valor Origem Era necessário?
asc dir=asc ❌ nunca é uma tag
position order=position ❌ nunca é uma tag
38 type_tags[property1][]=38 ❌ atributo de tamanho, não é tag
esp-peso-tenis-281 type_tags[...][] ✅ tag válida
feminino, tenis-para-corrida, ... pathname ✅ tags válidas

Causa raiz #2 — sem deduplicação

O mesmo slug podia aparecer tanto em categoryTagNames quanto em categoryTagName, gerando chamadas duplicadas para o mesmo recurso sem nenhum mecanismo de cache entre elas.

Causa raiz #3typeTagExtractor dependia de chamadas desnecessárias

A função typeTagExtractor(url, filteredTags) recebia objetos Tag resolvidos dos params type_tags[X][]=value para mapear os filtros da URL no products/search. Porém, a URL já contém todas as informações necessárias:

  • Chave: type_tags[Finalidade][]
  • Valor: finalidade-corrida
  • É property: derivado de type_tags[property1][]

A chamada à API servia apenas como validação, não como enriquecimento de dados.


Solução

1. Substituição de typeTagExtractor por parseTypeTagsFromUrl

A nova função extrai typeTags e cleanUrl diretamente da URL, sem nenhuma chamada à API:

const parseTypeTagsFromUrl = (url: URL): { typeTags: TypeTag[]; cleanUrl: URL } => {
  const TYPE_TAG_PATTERN = /^type_tags\[(.+)\]\[\]$/;

  const typeTags = [...url.searchParams.entries()]
    .filter(([key]) => TYPE_TAG_PATTERN.test(key))
    .map(([key, value]) => {
      const keyName = key.match(TYPE_TAG_PATTERN)?. ?? "";[1]
      return {
        key,
        value,
        isProperty: /^property\d+$/.test(keyName),
      };
    });

  const cleanUrl = new URL(url.href);
  [...cleanUrl.searchParams.keys()]
    .filter((k) => k.startsWith("type_tags"))
    .forEach((k) => cleanUrl.searchParams.delete(k));

  return { typeTags, cleanUrl };
};

Por que é seguro: a URL type_tags[Finalidade][]=finalidade-corrida já encoda explicitamente chave e valor. O único comportamento que typeTagExtractor adicionava era rejeitar slugs inválidos — slugs inválidos na URL simplesmente não retornam produtos no products/search, sem impacto funcional.

2. Fetches de tags restritos ao pathname

// ANTES: buscava params + pathname (até 15 chamadas)
const categoryTagNames = Array.from(url.searchParams.values());
const tags = await Promise.all([
  ...categoryTagNames,
  ...categoryTagName,
].map((name) => api["GET /api/v2/tags/:name"]({ name }, STALE)...));

// DEPOIS: busca APENAS os segmentos do pathname (máximo = nº de segmentos)
const uniquePathNames = [...new Set(
  categoryTagName.filter((item): item is string => typeof item === "string"),
)];
const tagByName = new Map(
  await Promise.all(
    uniquePathNames.map(async (name) => [name, await fetchTag(api, name)] as const),
  ),
);

3. Deduplicação via Set

new Set() antes do Promise.all garante que slugs repetidos no pathname sejam resolvidos apenas uma vez.


Quando /api/v2/tags/:name ainda é chamada

A API de tags continua sendo utilizada, mas agora apenas onde o objeto Tag completo é estritamente necessário: os segmentos do pathname da URL.
URL: /feminino/tenis-para-corrida?type_tags[Marca][]=nike&dir=asc&page=2

/api/v2/tags/:name chamada para:
✅ "feminino" → tag.title usado no breadcrumb e SEO
✅ "tenis-para-corrida" → tag.title usado no breadcrumb e SEO

/api/v2/tags/:name NÃO chamada para:
❌ "nike" (type_tags[Marca][]) → parseTypeTagsFromUrl extrai direto da URL
❌ "asc" (dir=asc) → parâmetro de sistema, nunca é tag
❌ "2" (page=2) → parâmetro de sistema, nunca é tag

O motivo pelo qual o pathname ainda precisa da API é que tag.title — o nome legível da categoria — não pode ser derivado do slug:

Slug (URL) tag.title (API) Usado em
tenis-para-corrida "Tênis para Corrida" Breadcrumb, SEO
feminino "Feminino" Breadcrumb, SEO
amortecimento "Amortecimento" Breadcrumb, SEO

Para os filtros (type_tags[X][]=value), a URL já é a fonte da verdade: chave, valor e flag isProperty são todos deriváveis da estrutura do parâmetro, sem necessidade de consultar a API.


Impacto em chamadas à API

URL Antes Depois Redução
/feminino/.../hoka_one_one?dir=asc&order=position&[7 filtros] 15 5 −67%
/acessorios/meia-cano-curto/...?utm_source=vurdere-ai&[4 filtros] 9 3 −67%
/tenis-de-corrida?type_tags[Categoria][]=...&type_tags[Marca][]=... 3 1 −67%
/feminino (sem filtros) 1 1 0%
/busca?q=hoka 1 0 −100%

Testes realizados localmente

Os testes foram realizados localmente comparando produção (velocita.com.br) e ambiente de desenvolvimento via JSON-LD ProductListingPage embutido no HTML, não fazem parte deste PR.

Unitários — parseTypeTagsFromUrl — ✅ 8/8 passando

  • Extração de type_tags simples e com múltiplos valores no mesmo filtro
  • isProperty: true identificado corretamente para property1/2/3
  • Params de sistema (dir, order, utm_source, sort, page) não entram em typeTags
  • cleanUrl remove apenas params type_tags, preservando todos os demais
  • Conversão correta para params do products/search (incluindo agrupamento por chave)
  • Validação com a URL exata do log de erro 429

E2E de regressão — ✅ 7/7 passando

ID URL prod local Breadcrumb
TC-01 /tenis-de-corrida com 2 filtros type_tags 4 4
TC-02 Pathname aninhado + utm_source + property1 24 24
TC-03 Categoria aninhada sem filtros 24 24
TC-04 Página de busca (/busca?q=hoka) 24 24
TC-05 Categoria simples (/feminino) 24 24
TC-06 URL original do log de erro 429 2 2
TC-07 Mesmo type_tag com múltiplos valores 24 24

Arquivos alterados

vnda/loaders/productListingPage.ts ← único arquivo modificado


Breaking changes

Nenhum. A interface pública do loader (Props, tipos de retorno, cache, cacheKey) permanece idêntica. O comportamento observável — produtos, breadcrumb, filtros, SEO e paginação — foi validado como equivalente à versão de produção em todos os cenários de teste.


Referências


Summary by cubic

Reduce VNDA tag API calls in the PLP loader to stop Cloudflare 429s on filtered category pages. We now parse type_tags from the URL and only fetch tag details for pathname segments.

  • Bug Fixes
    • Replaced typeTagExtractor with parseTypeTagsFromUrl to extract filters without API calls, returning typeTags and cleanUrl.
    • Fetch tags only for pathname segments via fetchTag, deduplicated with Set and cached in a map.
    • Kept breadcrumb/SEO by resolving pathname tags; no changes to the loader’s public interface or cache behavior.
    • Impact: ~67% fewer /api/v2/tags/:name calls on filtered URLs; zero calls on search pages when possible.

Written for commit 99b4ec3. Summary will update on new commits.

Summary by CodeRabbit

  • Refactor
    • Optimized product listing page performance through refined tag and category processing, ensuring more consistent and reliable product filtering.
    • Enhanced product search request handling for improved efficiency.
    • Improved URL parameter parsing to better extract and process product filtering criteria.

@github-actions
Copy link
Copy Markdown
Contributor

Tagging Options

Should a new tag be published when this PR is merged?

  • 👍 for Patch 0.142.2 update
  • 🎉 for Minor 0.143.0 update
  • 🚀 for Major 1.0.0 update

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 26, 2026

📝 Walkthrough

Walkthrough

Replaced typeTagExtractor with parseTypeTagsFromUrl to extract type_tags query parameters directly from URLs. Introduced fetchTag helper for retrieving tag metadata with caching and error suppression. Refactored tag-processing pipeline to deduplicate tag names, fetch metadata, and reconstruct categories. Optimized products/search request handling and applied minor formatting adjustments.

Changes

Cohort / File(s) Summary
Tag Extraction & Fetching Refactor
vnda/loaders/productListingPage.ts
Replaced typeTagExtractor with parseTypeTagsFromUrl for query parameter extraction; added fetchTag helper with STALE caching; updated tag deduplication and mapping logic to build categories from fetched metadata; removed unnecessary await from products/search request; applied control-flow compression and formatting edits.

Sequence Diagram

sequenceDiagram
    participant PageLoader as Page Loader
    participant URLParser as URL Parser
    participant TagCache as Tag Cache/API
    participant CategoryBuilder as Category Builder

    PageLoader->>URLParser: Parse URL for type_tags params
    URLParser-->>PageLoader: Extract {key, value, isProperty} array + cleanUrl
    
    PageLoader->>PageLoader: Deduplicate tag names from path
    
    loop For each unique tag name
        PageLoader->>TagCache: fetchTag(name)
        alt Cache hit or API success
            TagCache-->>PageLoader: Tag metadata
        else Error/Missing
            TagCache-->>PageLoader: undefined
        end
    end
    
    PageLoader->>CategoryBuilder: Map original path order to fetched tags
    CategoryBuilder->>CategoryBuilder: Filter out undefined entries
    CategoryBuilder-->>PageLoader: Built categories array
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 In the warren of tags, a new path appears,
URL parsing whispers what once caused peers.
Cache holds the answers, no errors to fear,
Categories bloom fresh, the refactor is clear!
Hop forward, clean code leads us here. 🌿✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description is comprehensive and well-structured, but does not follow the required template sections (What is this Contribution About, Issue Link, Loom Video, Demonstration Link). Reorganize the description to follow the template structure: add a concise summary in 'What is this Contribution About', include Issue Link section, and consider adding Loom Video and Demonstration Link sections for clarity.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: optimizing /api/v2/tags API calls to prevent rate limiting, which is the primary objective of the fix.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@vnda/loaders/productListingPage.ts`:
- Around line 103-105: CI is failing due to formatting issues in this file
(e.g., the parseTypeTagsFromUrl function block and other nearby ranges); run the
code formatter and apply its changes—execute `deno fmt` (or your project's
formatter) on vnda/loaders/productListingPage.ts and commit the resulting
formatting changes so the parseTypeTagsFromUrl function signature, surrounding
blocks, and the other affected ranges are formatted correctly.
- Around line 117-123: cleanUrl currently retains the page query param which
causes stale pagination after filter changes; in the function that builds
cleanUrl (the block creating new URL(url.href) and before returning { typeTags,
cleanUrl }), remove the "page" search param (e.g.,
cleanUrl.searchParams.delete("page")) so that the cleanUrl passed into
toFilters(...) has pagination reset and filter navigation behaves correctly.
- Around line 153-163: The code currently builds categoryTagName from props.term
(a free-text search) and url.pathname, causing incorrect tag lookups and
unnecessary API calls; change the logic that computes
categoryTagName/uniquePathNames to use only the URL path segments (e.g.,
url.pathname.slice(1).split("/")), remove any empty segments (filter(Boolean) or
item => item !== ""), and use those filtered segments (optionally
decodeURIComponent) when calling the tags endpoint so lookups use the slug/path
rather than props.term; update occurrences of categoryTagName and
uniquePathNames to reflect this filtered-path-only source.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1a573ad4-9742-4fb7-b42c-ded65fb7d123

📥 Commits

Reviewing files that changed from the base of the PR and between 0b95d39 and 99b4ec3.

📒 Files selected for processing (1)
  • vnda/loaders/productListingPage.ts

Comment on lines +103 to +105
const parseTypeTagsFromUrl = (url: URL): { typeTags: TypeTag[]; cleanUrl: URL } => {
const TYPE_TAG_PATTERN = /^type_tags\[(.+)\]\[\]$/;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

deno fmt --check is failing for this file.

CI is red due to formatting diffs in these changed ranges. Please run formatter before merge.

Also applies to: 153-157, 161-167, 333-333

🧰 Tools
🪛 GitHub Actions: ci

[error] 103-167: deno fmt --check failed for this file. Deno reported formatting diffs near lines 103-105, 153-157, and 161-167 (e.g., function signature/arguments and split .split("/" )/filter formatting).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@vnda/loaders/productListingPage.ts` around lines 103 - 105, CI is failing due
to formatting issues in this file (e.g., the parseTypeTagsFromUrl function block
and other nearby ranges); run the code formatter and apply its changes—execute
`deno fmt` (or your project's formatter) on vnda/loaders/productListingPage.ts
and commit the resulting formatting changes so the parseTypeTagsFromUrl function
signature, surrounding blocks, and the other affected ranges are formatted
correctly.

Comment on lines +117 to +123
const cleanUrl = new URL(url.href);
[...cleanUrl.searchParams.keys()]
.filter((k) => k.startsWith("type_tags"))
.forEach((k) => cleanUrl.searchParams.delete(k));

return { typeTags, cleanUrl };
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Reset page in cleanUrl to preserve filter navigation behavior.

cleanUrl is passed to toFilters(...), but this parser no longer removes page. That can keep users on stale page numbers after toggling filters.

Suggested fix
 const cleanUrl = new URL(url.href);
 [...cleanUrl.searchParams.keys()]
   .filter((k) => k.startsWith("type_tags"))
   .forEach((k) => cleanUrl.searchParams.delete(k));
+cleanUrl.searchParams.delete("page");

 return { typeTags, cleanUrl };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const cleanUrl = new URL(url.href);
[...cleanUrl.searchParams.keys()]
.filter((k) => k.startsWith("type_tags"))
.forEach((k) => cleanUrl.searchParams.delete(k));
return { typeTags, cleanUrl };
};
const cleanUrl = new URL(url.href);
[...cleanUrl.searchParams.keys()]
.filter((k) => k.startsWith("type_tags"))
.forEach((k) => cleanUrl.searchParams.delete(k));
cleanUrl.searchParams.delete("page");
return { typeTags, cleanUrl };
};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@vnda/loaders/productListingPage.ts` around lines 117 - 123, cleanUrl
currently retains the page query param which causes stale pagination after
filter changes; in the function that builds cleanUrl (the block creating new
URL(url.href) and before returning { typeTags, cleanUrl }), remove the "page"
search param (e.g., cleanUrl.searchParams.delete("page")) so that the cleanUrl
passed into toFilters(...) has pagination reset and filter navigation behaves
correctly.

Comment on lines +153 to +163
const categoryTagName = (props.term || url.pathname.slice(1) || "").split("/");

const properties1 = url.searchParams.getAll("type_tags[property1][]");
const properties2 = url.searchParams.getAll("type_tags[property2][]");
const properties3 = url.searchParams.getAll("type_tags[property3][]");

const categoryTagNames = Array.from(url.searchParams.values());
const uniquePathNames = [
...new Set(
categoryTagName.filter((item): item is string => typeof item === "string"),
),
];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Use slug/path for category tag lookup, not props.term, and drop empty segments.

This segment currently derives tag names from props.term, which can be a free-text search term and trigger unnecessary /api/v2/tags/:name calls. Also, empty segments are not filtered before fetch.

Suggested fix
-const categoryTagName = (props.term || url.pathname.slice(1) || "").split("/");
+const categoryTagName = (props.slug || url.pathname.slice(1) || "").split("/");

 const uniquePathNames = [
   ...new Set(
-    categoryTagName.filter((item): item is string => typeof item === "string"),
+    categoryTagName.filter(
+      (item): item is string => typeof item === "string" && item.trim().length > 0,
+    ),
   ),
 ];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const categoryTagName = (props.term || url.pathname.slice(1) || "").split("/");
const properties1 = url.searchParams.getAll("type_tags[property1][]");
const properties2 = url.searchParams.getAll("type_tags[property2][]");
const properties3 = url.searchParams.getAll("type_tags[property3][]");
const categoryTagNames = Array.from(url.searchParams.values());
const uniquePathNames = [
...new Set(
categoryTagName.filter((item): item is string => typeof item === "string"),
),
];
const categoryTagName = (props.slug || url.pathname.slice(1) || "").split("/");
const properties1 = url.searchParams.getAll("type_tags[property1][]");
const properties2 = url.searchParams.getAll("type_tags[property2][]");
const properties3 = url.searchParams.getAll("type_tags[property3][]");
const uniquePathNames = [
...new Set(
categoryTagName.filter(
(item): item is string => typeof item === "string" && item.trim().length > 0,
),
),
];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@vnda/loaders/productListingPage.ts` around lines 153 - 163, The code
currently builds categoryTagName from props.term (a free-text search) and
url.pathname, causing incorrect tag lookups and unnecessary API calls; change
the logic that computes categoryTagName/uniquePathNames to use only the URL path
segments (e.g., url.pathname.slice(1).split("/")), remove any empty segments
(filter(Boolean) or item => item !== ""), and use those filtered segments
(optionally decodeURIComponent) when calling the tags endpoint so lookups use
the slug/path rather than props.term; update occurrences of categoryTagName and
uniquePathNames to reflect this filtered-path-only source.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 1 file

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="vnda/loaders/productListingPage.ts">

<violation number="1" location="vnda/loaders/productListingPage.ts:117">
P2: `cleanUrl` only strips `type_tags` params but retains `page`. When passed to `toFilters(...)`, the generated filter toggle URLs will carry a stale page number, so toggling a filter may land the user on page N instead of page 1. Consider also deleting `page` from `cleanUrl`.</violation>

<violation number="2" location="vnda/loaders/productListingPage.ts:161">
P2: The filter `typeof item === "string"` does not exclude empty strings. A trailing slash in the pathname (e.g., `/feminino/`) produces an empty segment that passes through and triggers a wasted `fetchTag(api, "")` call. Filter with `item.length > 0` as well.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Add one-off context when rerunning by tagging @cubic-dev-ai with guidance or docs links (including llms.txt)
  • Ask questions if you need clarification on any suggestion

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

};
});

const cleanUrl = new URL(url.href);
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: cleanUrl only strips type_tags params but retains page. When passed to toFilters(...), the generated filter toggle URLs will carry a stale page number, so toggling a filter may land the user on page N instead of page 1. Consider also deleting page from cleanUrl.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At vnda/loaders/productListingPage.ts, line 117:

<comment>`cleanUrl` only strips `type_tags` params but retains `page`. When passed to `toFilters(...)`, the generated filter toggle URLs will carry a stale page number, so toggling a filter may land the user on page N instead of page 1. Consider also deleting `page` from `cleanUrl`.</comment>

<file context>
@@ -87,6 +86,42 @@ const handleOperator = (
+      };
+    });
+
+  const cleanUrl = new URL(url.href);
+  [...cleanUrl.searchParams.keys()]
+    .filter((k) => k.startsWith("type_tags"))
</file context>
Fix with Cubic

const categoryTagNames = Array.from(url.searchParams.values());
const uniquePathNames = [
...new Set(
categoryTagName.filter((item): item is string => typeof item === "string"),
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The filter typeof item === "string" does not exclude empty strings. A trailing slash in the pathname (e.g., /feminino/) produces an empty segment that passes through and triggers a wasted fetchTag(api, "") call. Filter with item.length > 0 as well.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At vnda/loaders/productListingPage.ts, line 161:

<comment>The filter `typeof item === "string"` does not exclude empty strings. A trailing slash in the pathname (e.g., `/feminino/`) produces an empty segment that passes through and triggers a wasted `fetchTag(api, "")` call. Filter with `item.length > 0` as well.</comment>

<file context>
@@ -108,44 +143,40 @@ const searchLoader = async (
-  const categoryTagNames = Array.from(url.searchParams.values());
+  const uniquePathNames = [
+    ...new Set(
+      categoryTagName.filter((item): item is string => typeof item === "string"),
+    ),
+  ];
</file context>
Suggested change
categoryTagName.filter((item): item is string => typeof item === "string"),
categoryTagName.filter((item): item is string => typeof item === "string" && item.length > 0),
Fix with Cubic

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants