feat(get-cnpj-info): add getCnpjInfo to read the root, branch and check digits of a CNPJ - #560
hyanmandian wants to merge 4 commits into
Conversation
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (9)
Included review availability: Your plan provides up to 10 included reviews per hour; 7 remain after this review. 📝 WalkthroughWalkthroughAdds ChangesCNPJ information lookup
Priority: ⬇️ Low Estimated code review effort: 3 (Moderate) | ~20 minutes Change: Feature Sequence Diagram(s)sequenceDiagram
participant Caller
participant getCnpjInfo
participant isValidCnpj
Caller->>getCnpjInfo: Pass CNPJ and version
getCnpjInfo->>isValidCnpj: Validate input
isValidCnpj-->>getCnpjInfo: Return valid or invalid result
getCnpjInfo-->>Caller: Return CnpjInfo or null
Merge Risk: ⚪ Minimal · up to This change adds validated CNPJ parsing and public exports without a concrete remaining correctness, compatibility, security, or runtime risk requiring action before merge. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## claude/suframa #560 +/- ##
================================================
Coverage 100.00% 100.00%
================================================
Files 191 192 +1
Lines 2094 2101 +7
Branches 618 619 +1
================================================
+ Hits 2094 2101 +7
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. 2 grew, 1 new out of 162 exports.
What changed (3)
All exports (162)
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 |
|
@coderabbitai review |
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@coderabbitai review |
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
ea12037 to
e3a51ea
Compare
commit: |
|
@coderabbitai review |
✅ Action performedReview finished.
|
…k digits of a CNPJ A CNPJ encodes more than its validity: Anexo XV of IN RFB 2.119/2022, added by IN RFB 2.229/2024, lays the 14 positions out as 8 (root, the entity) + 4 (order, the establishment) + 2 (numeric check digits), for the numeric and for the alphanumeric format assigned from July 2026. getCnpjInfo returns those fields, the format the value is written in and whether the order is 0001, or null when isValidCnpj turns the same arguments down. The version option is the one of isValidCnpj (1 numeric only and the default, 2 both formats), so the CNPJ utils agree on what they read and nothing already exported changes. The 0001 flag is named isInitialHeadquarters because the Receita Federal Q&A (question 25) states that a branch can become the headquarters while keeping its order: the number only tells which establishment was the headquarters when the root was registered.
…jInfo Both modules asked the same question of a sanitized CNPJ, whether it carries a letter, with their own copy of /[A-Z]/. A constant used by two modules belongs in src/_internals/constants, next to CNPJ_LENGTH and the check digit weights, so it moves there as CNPJ_LETTER_REGEX. The docs of CnpjInfo.order also now say that those four positions are the ones generateCnpj takes as branch, so a reader moving between the two functions can tell the two names mean the same block.
Positions 9 to 12 of a CNPJ were exposed as CnpjInfo.order, after the "número de ordem" of the Receita Federal. The already released generateCnpj fills those same positions through its branch option, so reading them back under a different name would make the two utilities disagree about one concept. The key is now branch, and its JSDoc keeps the Receita Federal term so the mapping to the official layout stays visible.
The field only said whether the root or the branch carried a letter,
which the caller can read off root and branch it already has. Adding a
field to a returned object later is not a breaking change while removing
one is, so it stays out until someone asks for it, and CnpjFormat leaves
the public surface with it.
The version option is untouched: getCnpjInfo(value, { version }) still
decides which formats are read, and an alphanumeric CNPJ under version 1
is still null.
CNPJ_LETTER_REGEX stays in _internals/constants/cnpj.ts, next to
CNPJ_LENGTH which parse-cnpj is the only reader of, but its doc no
longer claims getCnpjInfo as a second user.
e3a51ea to
214ce29
Compare
|
@coderabbitai review |
|
What
Adds
getCnpjInfo(value, options?), in the style ofgetIbanInfo/getNfeKeyInfo/getBoletoInfo: for a valid CNPJ it returns the fields the number encodes, otherwisenull. Nothing already exported changes.API
Design notes:
versionis the option ofisValidCnpj, read the same way (1numeric only and the default,2both formats, anything else as1). The function delegates toisValidCnpj(value, options), so it returns a value exactly whenisValidCnpjreturnstruefor the same arguments (pinned by a property test), accepts the same masks and never throws.formatfield. An earlier revision returnedformat: "numeric" | "alphanumeric"with an exportedCnpjFormattype; the caller can read the same thing off therootandbranchit already has, and adding a field to a returned object later is not a breaking change while removing one is, so it stays out until someone asks for it. Theversionoption is untouched:getCnpjInfo(value, { version })still decides which formats are read, and an alphanumeric CNPJ under version1is stillnull.branchis the name of positions 9 to 12, the same one the already releasedgenerateCnpj({ branch })uses for them, so the package carries one name for one concept. The Receita Federal calls the block "número de ordem"; the JSDoc ofCnpjInfo.branchand both docs say so. A property test round-tripsgenerateCnpj({ branch })throughgetCnpjInfo(...).branch.isInitialHeadquarters, notisHeadquarters: the Receita Federal Q&A, question 25, says "o sufixo 0001 continuará indicando a matriz no momento da geração do CNPJ. No entanto, essa associação não será permanente. Com o tempo, uma filial pode se tornar a matriz [...] mesmo possuindo um número de ordem diferente de 0001". The number alone cannot tell the current headquarters, so the field only claims what the number proves.The letter test that tells an alphanumeric CNPJ from a numeric one lived twice, once in
isValidCnpjand once here, so it moved tosrc/_internals/constants/cnpj.tsasCNPJ_LETTER_REGEX, next toCNPJ_LENGTHand the check digit weights. Dropping theformatfield leftisValidCnpjas its only reader, asCNPJ_LENGTHalready is forparseCnpj; the constant stays where it is and its doc no longer claims a second user. Behaviour is unchanged andisValidCnpjkeeps the same bundle size.Sources
@see Based on:).branch) = 9th to 12th, either may be numeric or alphanumeric), question 25 (the branch0001and the matriz), and the examplesAA345678/000A-29and12.345.678/000A-08, used as test vectors.12.ABC.345/01DE-35, used as a test vector.The other test vectors are synthetic, with check digits computed by hand from the manual's algorithm.
Verification
Re-run on the rebased branch (base
claude/suframa), after dropping theformatfield:npm run check: passnpm run test:coverage: 192 files, 6309 tests, 100% statements, branches, functions and linesnpm run buildandnpm run check:api:update: pass, report committed (CnpjFormatandCnpjInfo.formatgone from the report)npm run check:unused,npm run check:duplication(0 clones),npm run check:commits: passnpm run test:mutation -- --mutate 'src/get-cnpj-info/get-cnpj-info.ts': 12 of 12 mutants killed, 100%npm run build:docsandnpm run build:jsr: run, output committed (jsr.jsongains./get-cnpj-info)check:tree-shaking(its CI job was broken on every branch rebased past feat: Standard Schema wrapper, JSR, pkg.pr.new, docs previews and a playground #556; fix(build): the document field templates stop breaking the package build #588, now at the bottom of this stack, fixes it, and the job is green here)Rebase onto #559
Rebased onto
claude/suframaafter #556 landed onmain. Conflicts resolved:docs/llms.txtanddocs/llms-full.txtare no longer tracked (they are generated now), so both weregit rm-ed.getCnpjInfosection ofdocs/utilities.mdanddocs/pt-br/utilities.mdwas ported into the new per-utility format: a short paragraph, a bullet list for the options and the returned fields, thejavascriptblock, and aSource:line at the end of the block.src/index.ts,src/index.test.tsandreports/api/brazilian-utils.api.mdkept strictly alphabetical next togetCpfInfo, which feat(get-cpf-info): add getCpfInfo #558 adds.jsr.json(new onmain) regenerated withnpm run build:jsr.Open points
AA345678/0003-29, does not pass the check digit algorithm of the Receita Federal's own manual (the digits forAA3456780003are86;29is the pair of the next example,AA345678/000A-29). It reads as a typo in the Q&A, so it is left out of the tests.branch, consistent withgenerateCnpj(wasorderin the first revision).isInitialHeadquarters. If a plainisHeadquartersname is preferred despite the Q&A, it is a one-line rename before release.Summary by CodeRabbit
New Features
getCnpjInfoto parse and validate numeric or alphanumeric CNPJs.null.Documentation