Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
c9cb205
feat: add toStandardSchema, a Standard Schema wrapper for the validators
hyanmandian Sep 19, 2026
c9bee75
test: draw valid documents from fast-check arbitraries instead of gen…
hyanmandian Sep 19, 2026
31c1e83
ci(datasets): describe what changed in the dataset refresh pull request
hyanmandian Sep 19, 2026
e0c5346
ci(preview): publish every pull request's build to pkg.pr.new
hyanmandian Sep 19, 2026
b8d68e5
ci(jsr): publish the package to JSR, from its TypeScript sources
hyanmandian Sep 19, 2026
ab6c6ad
docs(site): add a playground that runs the published package in the b…
hyanmandian Sep 19, 2026
f06445f
ci(docs): deploy a preview of the documentation site for every pull r…
hyanmandian Sep 19, 2026
3722d3d
chore(context7): tell agents about toStandardSchema, keep the playgro…
hyanmandian Sep 19, 2026
a791bd0
docs(contributing): document the datasets, the test arbitraries, JSR …
hyanmandian Sep 19, 2026
0f88a09
chore: ignore the lockfile Deno writes next to jsr.json
hyanmandian Sep 19, 2026
ab98e0f
ci(release): name the npm job publish-npm and always publish to JSR
hyanmandian Sep 19, 2026
ff59701
ci(preview): publish the pull request preview without an opt-in variable
hyanmandian Sep 19, 2026
8e8d326
fix(docs): skip the Vercel preview only when docs are unchanged since…
hyanmandian Sep 19, 2026
d7f4ee7
docs: replace the playground with a CPF field example in React, Vue, …
hyanmandian Sep 19, 2026
42c7fde
docs(examples): one file per example, shared by both languages, live …
hyanmandian Sep 19, 2026
888ebc2
docs(examples): framework tabs with live demos and a caret-aware CPF …
hyanmandian Sep 19, 2026
5b4adf6
docs(site): move the site's styles into one stylesheet shared by ever…
hyanmandian Sep 19, 2026
55e068e
docs(examples): give the demos the site's own theme, fix the tab unde…
hyanmandian Sep 19, 2026
ec7ba05
fix(docs): load Angular's compiler before the Angular demo and its pa…
hyanmandian Sep 19, 2026
f6e64b9
docs: rewrite the getting started, README and migration pages in plai…
hyanmandian Sep 19, 2026
11ecabf
docs: restructure the utilities reference into short sections
hyanmandian Sep 19, 2026
d899102
docs(contributing): describe the new shape of a utilities section
hyanmandian Sep 19, 2026
dbfe432
docs: trim the utilities reference to what a caller needs
hyanmandian Sep 19, 2026
608dce5
docs(utilities): reshape the toStandardSchema section and move it to …
hyanmandian Sep 19, 2026
74c1316
docs(examples): follow each framework's current conventions
hyanmandian Sep 19, 2026
057d039
docs(examples): hand the CPF to the parent component in each framework
hyanmandian Sep 19, 2026
0e1325f
docs(examples): each field the way its framework expects
hyanmandian Sep 19, 2026
c6114ae
fix(docs): build the Vercel preview when the last deployed commit is …
hyanmandian Sep 19, 2026
2de274a
docs(examples): show each field in the form library most projects use
hyanmandian Sep 19, 2026
23f93dd
docs(examples): move what is specific to each framework into its tab
hyanmandian Sep 19, 2026
e6ac552
docs(examples): one example page per task, starting with a generic do…
hyanmandian Sep 20, 2026
b3bd350
docs(examples): one focused example per document instead of a generic…
hyanmandian Sep 20, 2026
0775c1b
docs(examples): size each live demo to its content
hyanmandian Sep 20, 2026
1fb8ce6
docs(examples): tie each message to its field and add a schema tab
hyanmandian Sep 20, 2026
fadeb57
fix(docs): declare the autocomplete column of the examples table
hyanmandian Sep 20, 2026
c37d679
docs(examples): fix the accessibility of the fields and show the file…
hyanmandian Sep 20, 2026
63985cf
docs(examples): let the field mask and the form validate
hyanmandian Sep 20, 2026
be91fe9
docs(examples): give each field an errorMessage prop and each framewo…
hyanmandian Sep 20, 2026
df1a101
fix(docs): point the Angular examples at the folder they live in
hyanmandian Sep 20, 2026
fab6408
fix(docs): show every file of an example, and hand React a ref
hyanmandian Sep 20, 2026
26b1da5
docs(examples): mask inside React's own event, which is what works ei…
hyanmandian Sep 20, 2026
966295b
docs(examples): write the mask where each framework puts it
hyanmandian Sep 20, 2026
b872bf9
build(docs): generate the site at deploy instead of keeping it in the…
hyanmandian Sep 20, 2026
0e97da4
docs(examples): let the React hook own the input, value and all
hyanmandian Sep 21, 2026
ccb6000
docs(examples): report both values from the React hook
hyanmandian Sep 21, 2026
de9168f
docs(examples): report both values from the Vue and Angular masks too
hyanmandian Sep 21, 2026
0a64243
docs(examples): show the Standard Schema in a form library that takes it
hyanmandian Sep 21, 2026
1194f35
docs(examples): show the Standard Schema in four libraries that take it
hyanmandian Sep 21, 2026
d222a3a
docs(guides): a form that fills an address from a CEP
hyanmandian Sep 21, 2026
16f152c
docs(guides): a state picker that loads its cities on demand
hyanmandian Sep 21, 2026
115348f
docs(guides): do the asking properly, and lay a demo out like a form
hyanmandian Sep 21, 2026
c7f008a
docs(guides): ask by value, and borrow the field the other guide builds
hyanmandian Sep 21, 2026
27e1305
docs(guides): build a field once and dress it up per document
hyanmandian Sep 21, 2026
d5918c9
docs(guides): a document field is a component, not an attribute on an…
hyanmandian Sep 21, 2026
c4774b0
docs(guides): the Angular address form holds its fields the way the o…
hyanmandian Sep 21, 2026
f94463d
fix(build): keep the documentation out of the library's type-check
hyanmandian Sep 21, 2026
18024ed
test: keep every arbitrary in one file
hyanmandian Sep 22, 2026
d715484
docs(guides): give the schemas a guide of their own
hyanmandian Sep 22, 2026
a304d71
docs(guides): each framework keeps its templates in a folder of its own
hyanmandian Sep 22, 2026
48ff536
docs(guides): the document picker leads the strip of tabs
hyanmandian Sep 22, 2026
9223ff1
docs(guides): the Angular examples lay out like the ones beside them
hyanmandian Sep 22, 2026
02ee925
docs(guides): the document sits at the end of the strip of tabs
hyanmandian Sep 22, 2026
5e77e09
docs(guides): the demo comes after what the page says about it
hyanmandian Sep 22, 2026
787f2ac
docs(guides): a submit shows the values it would send
hyanmandian Sep 22, 2026
1c97835
docs(guides): the guide asks which document in words
hyanmandian Sep 22, 2026
d2090d3
docs(guides): the vanilla address form fills its fields by name
hyanmandian Sep 22, 2026
e9ad292
fix(docs): a CEP that no service knows stops the Angular form from lo…
hyanmandian Sep 22, 2026
d66d8b6
docs(guides): the schema guide is about schema libraries
hyanmandian Sep 22, 2026
cd48e25
docs(guides): the state and city lists load when their select is opened
hyanmandian Sep 22, 2026
d9f8e92
docs(guides): the state and city guide drops a table it no longer wants
hyanmandian Sep 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,13 @@ jobs:
- name: Check llms.txt/llms-full.txt are up to date
run: npm run build:llms && git diff --exit-code -- docs/llms.txt docs/llms-full.txt

- name: Check the docs site shells and sitemap are up to date
# --intent-to-add makes a shell written for a new page show up in the diff as well.
run: npm run build:site && git add --intent-to-add docs && git diff --exit-code -- docs/sitemap.xml 'docs/*.html' 'docs/pt-br/*.html'
- name: Check the JSR exports are up to date
run: npm run build:jsr && git diff --exit-code -- jsr.json

- name: Build the documentation site
# The site is generated at deploy time (the Docs workflow), so nothing here can be stale;
# this only has to fail when a generator does.
run: npm run build:docs

- name: Check the VEX statements against the suppressed advisories
run: npm run check:vex
Expand Down
15 changes: 9 additions & 6 deletions .github/workflows/datasets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ permissions:

jobs:
update-datasets:
name: Update IBGE/CONCLA datasets
name: Update the embedded datasets
runs-on: ubuntu-latest
# Only this job pushes the dataset branch and opens the pull request.
permissions:
Expand Down Expand Up @@ -43,14 +43,17 @@ jobs:
echo "changed=true" >> "$GITHUB_OUTPUT"
fi

# Written outside the workspace, so the pull request does not pick the file up as a change.
- name: Summarize what changed
if: steps.diff.outputs.changed == 'true'
run: node scripts/data-summary.ts "$RUNNER_TEMP/dataset-summary.md"

- name: Open pull request
if: steps.diff.outputs.changed == 'true'
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7.0.11
with:
commit-message: "chore(data): update IBGE/CONCLA datasets"
commit-message: "chore(data): update the embedded datasets"
branch: chore/update-datasets
base: ${{ github.event.repository.default_branch }}
title: "chore(data): update IBGE/CONCLA datasets"
body: |
Automated weekly refresh of the cities, states and legal-natures
datasets sourced from IBGE/CONCLA.
title: "chore(data): update the embedded datasets"
body-path: ${{ runner.temp }}/dataset-summary.md
63 changes: 63 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Builds the documentation site and publishes it to GitHub Pages. Everything the site needs that a
# script can write - the per-page shells, the sitemap, llms.txt, llms-full.txt and the examples of
# the document field page - is written here rather than kept in the repository, so a page and what
# it is generated from can never disagree.
#
# This needs Pages set to "GitHub Actions" (Settings -> Pages -> Build and deployment -> Source);
# serving the branch directly would publish `docs/` without these files.
name: Docs

on:
push:
branches: [main]
paths:
- docs/**
- scripts/**
- package.json
- .github/workflows/docs.yml
workflow_dispatch:

concurrency:
group: pages
cancel-in-progress: false

permissions:
contents: read

jobs:
deploy:
name: Build and deploy
runs-on: ubuntu-latest
timeout-minutes: 15

permissions:
pages: write
id-token: write

environment:
name: github-pages
url: ${{ steps.deploy.outputs.page_url }}

steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Setup
uses: ./.github/actions/setup

- name: Build the site
run: npm run build:docs

- name: Configure Pages
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0

- name: Upload the site
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
with:
path: docs

- name: Deploy to Pages
id: deploy
uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1
38 changes: 38 additions & 0 deletions .github/workflows/preview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Publishes every pull request's build to pkg.pr.new, so a change can be installed and tried before
# it is merged: `npm i https://pkg.pr.new/@brazilian-utils/brazilian-utils@<pr-number>`. The
# pkg.pr.new GitHub App (https://github.com/apps/pkg-pr-new), installed on this repository, posts
# the install command as a comment; the job itself needs no token and no write permission, which is
# why it can run for pull requests from forks.
name: Preview

on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true

permissions:
contents: read

jobs:
preview:
name: Publish a preview to pkg.pr.new
runs-on: ubuntu-latest
timeout-minutes: 15

steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Setup
uses: ./.github/actions/setup

- name: Run build
run: vp run build

- name: Publish the preview
run: npx --yes pkg-pr-new@0.0.88 publish --compact --comment=update
41 changes: 39 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# published yet. A maintainer reviews and merges that PR: that merge is confirmation #1.
# 2. Merging the release PR makes release-please tag the release commit and create a GitHub
# Release, which triggers this same workflow again. This time `release_created` is `true`,
# so the `publish` job builds, validates and STAGES the package on npm
# so the `publish-npm` job builds, validates and STAGES the package on npm
# (`npm stage publish --provenance`). A staged version is not installable until a
# maintainer approves it with 2FA, on npmjs.com (package -> Staged versions) or with
# `npm stage approve <stage-id>`. That approval is confirmation #2 (npm's
Expand All @@ -26,6 +26,12 @@
# 4. Save. No NPM_TOKEN secret is needed: npm exchanges the workflow's OIDC token for a
# short-lived token automatically.
#
# One-time JSR setup (done by a package maintainer, not by CI):
# 1. Sign in at jsr.io with GitHub and create the scope `brazilian-utils` and the package
# `brazilian-utils` in it.
# 2. Package Settings -> GitHub Actions -> link `brazilian-utils/javascript`. JSR then trusts
# this repository's OIDC token; no JSR token is stored anywhere.
#
# One-time GitHub Environment setup (done by a package maintainer, not by CI):
# Repository Settings -> Environments -> New environment -> name it `npm`. No protection rules
# are needed: the environment only exists so the npm trusted publisher can be bound to it.
Expand Down Expand Up @@ -64,7 +70,7 @@ jobs:
config-file: release-please-config.json
manifest-file: .release-please-manifest.json

publish:
publish-npm:
name: Publish to npm
needs: release-please
if: ${{ needs.release-please.outputs.release_created == 'true' }}
Expand Down Expand Up @@ -120,6 +126,37 @@ jobs:
- name: Stage on npm
run: npm stage publish --provenance --access public

publish-jsr:
name: Publish to JSR
needs: release-please
# JSR publishes through OIDC as well: no token is stored. It needs the one-time JSR setup
# described at the top of this file; until that is done this job fails, and the npm job, which
# does not depend on it, still publishes.
if: ${{ needs.release-please.outputs.release_created == 'true' }}
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
id-token: write

steps:
- name: Checkout the release tag
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ needs.release-please.outputs.tag_name }}
persist-credentials: false

- name: Setup
uses: ./.github/actions/setup

- name: Setup Deno
uses: denoland/setup-deno@22d081ff2d3a40755e97629de92e3bcbfa7cf2ed # v2.0.5
with:
deno-version: v2.x

- name: Publish to JSR
run: deno publish

sbom:
name: Record the SBOM of the release
needs: release-please
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ jobs:
- name: Run tests
run: deno test --unstable-sloppy-imports --allow-net --allow-env src

# What JSR would reject at release time fails here instead: slow types in the public API,
# an export of jsr.json that does not resolve, a file outside the publish list.
- name: Dry-run the JSR publication
run: deno publish --dry-run

test-browsers:
name: Test on Browsers (${{ matrix.browser }})
runs-on: ubuntu-latest
Expand Down
2 changes: 2 additions & 0 deletions .github/zizmor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ rules:
ignore:
- build.yml
- check.yml
- docs.yml
- datasets.yml
- live-tests.yml
- mutation.yml
- preview.yml
- release.yml
- tests.yml
20 changes: 20 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,23 @@ reports/*
!reports/api/
reports/api/*
!reports/api/brazilian-utils.api.md
# Deno writes a lockfile next to jsr.json on every `deno test`/`deno publish`; the npm lockfile is
# the one that pins this project's dependencies.
deno.lock

# The documentation site is generated by `npm run build:docs` and published by the Docs workflow:
# only what a person writes is kept here.
docs/*.html
!docs/index.html
docs/pt-br/*.html
docs/guides/*.html
docs/pt-br/guides/*.html
docs/sitemap.xml
docs/llms.txt
docs/llms-full.txt
docs/snippets/document-field/generated/
docs/snippets/address-form/*/cep-field.*
docs/snippets/address-form/*/field.*
docs/snippets/address-form/react/use-mask.ts
docs/snippets/address-form/vue/mask.ts
docs/snippets/address-form/angular/mask.directive.ts
Loading
Loading