Repository navigation
fix: alphanumeric ISPB lookup, and bound getAddressInfoByCep - #596
Conversation
… and IBGE codes
getBankByCode, getBankByIspb, getAreaCodeInfo, getStateByIbgeCode, getMunicipalityByCode
and getMunicipality stripped every non-digit before the lookup, so a value that is not a
code at all found a real entry: getBankByIspb("0000000A") was Banco do Brasil,
getBankByCode("1e0") was 010, getAreaCodeInfo("1e1") and "DDD 11" were 11,
getStateByIbgeCode("x11") was Rondônia and getMunicipalityByCode("11abc00015") was Alta
Floresta D'Oeste.
A string may now carry whitespace and hyphens, and getAreaCodeInfo still takes the DDD
wrapped in parentheses; any other character, a dot included since "1.0" reads as a decimal,
returns null instead of being stripped.
getBankByIspb also reads the ISPB as 8 letters and digits, since Resolução BCB nº 585/2026
art. 2º III makes it alphanumeric, the same rule isValidIban already follows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLkm9YrtAifc6XCLFVEsdH
… and signal
The CEP is now read under the rules of isValidCep: whitespace, dots and hyphens are
ignored and any other character rejects it, where every non-digit used to be stripped
("abc01310100" was looked up as 01310-100). A number is still left padded to 8 digits,
but only from 1000000 (01000-000, the lowest CEP the Correios assign) up, so 123 is
rejected instead of being looked up as 00000-123.
BrasilAPI answers 404 both for an unknown CEP and when the services behind it are down,
so its 404 now only counts as "not found" when no other provider failed to answer; next
to a network failure the call rejects with GetAddressInfoByCepServiceError instead of
reporting an outage as an unknown CEP.
No request had a time limit, so a provider that never answered left the promise pending.
The new timeoutMs option bounds the whole lookup, retries included, and rejects with
GetAddressInfoByCepServiceError; the new signal option cancels it and rejects with
signal.reason, the same as fetch. Both default to the previous behavior.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLkm9YrtAifc6XCLFVEsdH
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
commit: |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## claude/bundle-size #596 +/- ##
====================================================
Coverage 100.00% 100.00%
====================================================
Files 223 224 +1
Lines 2303 2341 +38
Branches 697 703 +6
====================================================
+ Hits 2303 2341 +38
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Tree-shaking report✅ No size regression. 7 grew, 1 shrank out of 185 exports.
What changed (8)
All exports (185)
How this is measuredEvery export is imported alone into an esbuild consumer bundle (minified, tree-shaken) built from the head and from the base of this pull request; the sizes are the resulting bundles, gzip is their gzipped size. 🔴 marks a regression: a pre-existing export that grew more than 20% and more than 256 B, or the bundle importing every pre-existing export growing more than 5%. 🟡 is growth under the threshold, 🟢 a decrease, ⚪ no change, 🆕 an export that does not exist on the base (never a regression), 🗑️ an export that was removed. An intentional increase is accepted with the |
…on tests The Deno test shim has no rejects.toBe, so the two cancellation tests left the rejection unhandled; they now use rejects.toThrow, which every runtime supports. Stryker found mutants that survived the new code. The tests now check that every provider gets the signal, that the time limit and the forwarded signal are released once the lookup settles, that no time limit is set without timeoutMs, and that getAreaCodeInfo only unwraps parentheses around the whole trimmed value. The redundant checks behind the rest are gone: getBankByIspb matches the table exactly, so it only needs to turn down an empty value before padding; readTimeout relies on Number.isFinite, which never coerces; and a provider failure is now either a service failure or a "not found", so the ambiguous flag is no longer needed. The null guards in front of the table lookups stay, with a note on why the lookup would miss anyway. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RLkm9YrtAifc6XCLFVEsdH
… says
getAreaCodeInfo, getStateByIbgeCode, getMunicipalityByCode, getMunicipality, getBankByCode and
getAddressInfoByCep documented (and did) in 2.4.0 that a string code has any non-digit character
stripped, so "0xx11", "35/SP", "3550308 SP" and "CEP 01310-100" were found. This PR had narrowed
them to whitespace and hyphens, which broke those inputs; readLookupDigits and readCep now strip
every non-digit character again. getBankByIspb drops every character that is neither a letter
nor a digit ("00.000.000"), keeping the letters an alphanumeric ISPB (Resolução BCB nº 585/2026)
carries. A negative or fractional number is still rejected, as no code can be one.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLkm9YrtAifc6XCLFVEsdH
…etMunicipalityByCode do Follows #596 restoring the 2.4.0 contract of the lookups it builds on: a string code has any non-digit character stripped, so the tests and docs no longer expect "1e1" or "355030a8" to be rejected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RLkm9YrtAifc6XCLFVEsdH
Ported from #595 so every PR of the stack gets the retry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RLkm9YrtAifc6XCLFVEsdH
One retry was not enough: Chrome lost an iframe on both attempts in #600 and #604. The retries now run with --no-file-parallelism, since the iframes are lost when many files load at once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RLkm9YrtAifc6XCLFVEsdH
What does this PR do?
Stacks on #594. It fixes bugs that already exist in 2.4.0; none of them came from the stack.
1. Lookups keep the 2.4.0 reading, with the alphanumeric ISPB (
fix(lookups))An earlier version of this PR made
getBankByCode,getAreaCodeInfo,getStateByIbgeCode,getMunicipalityByCodeandgetMunicipalityreject any character other than whitespace and hyphens. 2.4.0 documented the opposite, "stripping any non-digit characters before matching", and official notations depend on it: Anatel writes a DDD as0xx11, and an ISPB is printed as a CNPJ root (00.000.000). d179683 restores the 2.4.0 reading. The internalreadLookupDigitshelper now strips every non-digit from a string, so"(0xx11)","35/SP","3550308 SP"and"0x1"resolve as they did in 2.4.0.What this PR still changes:
getBankByIspbkeeps letters. Resolução BCB nº 585/2026 art. 2º III makes the ISPB alphanumeric, so a letter is part of the code and is never stripped:"0000000A"is no longer read as Banco do Brasil. Every character that is neither a letter nor a digit is dropped, as in 2.4.0, so"00.000.000"still finds Banco do Brasil.isValidIbanalready reads the ISPB this way.isLookupCode).2.
getAddressInfoByCep(fix(get-address-info-by-cep))"CEP 01310-100"is 01310-100), and the digits that are left have to be the 8 of a CEP.1000000are rejected. A number is still padded with zeros to 8 digits, but only from1000000up, which is01000-000, the lowest CEP the Correios assign. Before,123was sent to the providers as00000-123.GetAddressInfoByCepServiceErrorinstead ofGetAddressInfoByCepNotFoundError. A lone BrasilAPI 404, or a 404 alongside a ViaCEPerro: true, is still "not found".timeoutMsandsignaloptions. No request had a time limit, so the promise stayed pending when a provider never answered.timeoutMsbounds the whole lookup, retries included, and rejects withGetAddressInfoByCepServiceError.signalcancels the lookup and rejects withsignal.reason, the same asfetch.3. Tests (
test(lookups))rejects.toThrow, which the Deno test shim supports.The docs in both languages and the JSDoc were updated.
Checklist
docs/utilities.mdanddocs/pt-br/utilities.md.npm run checkpasses locally. Also passing:vp test run --coverage(7718 tests, 100%), Deno, Bun,check:unused,check:duplication,check:api, and Stryker on the changed files (100%).npm run build:llms.check:apiholds against 2.4.0, and every string 2.4.0 resolved still resolves.Additional context
service_error.🤖 Generated with Claude Code
https://claude.ai/code/session_01RLkm9YrtAifc6XCLFVEsdH