Contributing / PR Guide
June 2, 2026 · View on GitHub
Repository Setup
This repository uses git submodules. Clone with:
git clone --recursive https://github.com/zaggino/z-schema.git
cd z-schema
npm install
If already cloned without --recursive:
git submodule update --init --recursive
Commit Messages
All commits must follow Conventional Commits.
Format: <type>[optional scope]: <description>
Common types:
| Type | When to use |
|---|---|
feat | A new feature |
fix | A bug fix |
docs | Documentation-only changes |
refactor | Code change that neither fixes a bug nor adds a feature |
perf | Performance improvement |
test | Adding or updating tests |
chore | Build process, CI, tooling, dependency updates |
Examples:
feat: add maxRecursionDepth option
fix: prevent global_cache mutation in fromCache
refactor(schema-cache): cache global clone in instance cache
docs: add conventional commits guide
feat!: remove deprecated constructor (BREAKING CHANGE)
Append ! after the type/scope for breaking changes, or include a BREAKING CHANGE: footer in the commit body.
Branch & PR Workflow
- Create a feature branch from
main(the active development branch):git checkout -b feature/my-change main - Make your changes following the code conventions.
- Run the full check suite before pushing:
npm run check npm run build npm run build:tests npm test - Push and open a PR against the
mainbranch.
Making Changes
Adding a New Feature
- Implement the feature in the appropriate
src/file. - Export any new public types/values through
src/index.ts. - Write tests in
test/spec/using the correct suffix (.spec.tsfor both environments,.node-spec.tsfor node-only,.browser-spec.tsfor browser-only). - If the feature relates to a JSON Schema keyword from the test suite, remove the relevant entries from
excludedFiles/excludedTestsintest/spec/json-schema-test-suite.common.tsand confirm tests pass. - Update documentation in
docs/if the feature affects the public API.
Adding a New Error Code
- Add the error to the
Errorsobject insrc/errors.tsusingUPPER_SNAKE_CASEand template placeholders ({0},{1}). - Use
report.addError(code, params)in the relevant validation logic. - Add tests that verify the error code is produced.
Adding a New Format Validator
- Add the validator function in
src/format-validators.ts. - Register it in the
inbuiltValidatorsrecord. - Add tests in
test/spec/format-validators.spec.ts.
Adding a New Utility
- Create a new file in
src/utils/— each file should be single-purpose. - Import it where needed using
.jsextension (ESM convention). - Do not export utilities from
src/index.tsunless they are part of the public API.
Modifying Options
- Add the option to the
ZSchemaOptionsinterface insrc/z-schema-options.ts. - Add a default value to the
defaultOptionsobject in the same file. - If the option affects
strictMode, add it to thestrictModeblock innormalizeOptions. - Document the option in
docs/options.md. - Add tests.
Code Quality Checks
| Check | Command | Notes |
|---|---|---|
| Check | npm run check | ultracite check — oxlint (type-aware) + oxfmt format check |
| Fix | npm run fix | ultracite fix — oxlint --fix + oxfmt --write |
| Build | npm run build | tsdown bundling (ESM + CJS + UMD + types) |
| Test type-check | npm run build:tests | Type-check test files without running them |
| Tests (all) | npm test | Vitest — node + browser projects |
| Tests (node) | npm run test:node | Node-only tests with output |
| Tests (browser) | npm run test:browser | Browser tests (Chromium, Firefox, WebKit) |
| Coverage | npm run test:coverage | Istanbul coverage for src/ |
Pre-commit & Pre-push Hooks
Git hooks are managed by lefthook (lefthook.yml), installed automatically via the prepare npm script (lefthook install).
- Pre-commit: auto-runs oxlint
--fixon staged JS/TS files and oxfmt--writeon all staged files, re-staging any changes. - Pre-push: runs
npm run build && npm run build:teststo catch build/type errors.
File Organization Rules
- All public exports go through
src/index.ts. - Internal types (e.g.,
JsonSchemaInternal, compiler metadata) stay unexported. - Tests go in
test/spec/with appropriate suffix. - Test fixtures go in
test/fixtures/. - Pure utility functions go in
src/utils/(one file per concern). - Use
import typefor type-only imports. - Use
.jsextension insrc/imports (ESM),.tsextension intest/imports (enabled byallowImportingTsExtensions).
Common Pitfalls
- Never use
new ZSchema()— always useZSchema.create(). ValidateError.details(not.errors) is the array of error objects.- Default version is
draft2020-12. Specifyversion: 'draft-04','draft-06','draft-07','draft2019-09','draft2020-12'ornoneexplicitly if needed. - Import extensions:
src/uses.js,test/uses.ts. - Schemas in
src/schemas/are generated byscripts/copy-schemas.mtsat build time — do not edit them manually. json-schema-spec/is a git submodule — do not commit changes to it directly.
Coverage Artifact Auto-Updates in PRs
For pull requests, CI may auto-commit coverage artifacts (docs/test-coverage.md and README.md) when they change.
- Auto-commit runs only for same-repository pull requests.
- Auto-commit is skipped for fork pull requests.
- Auto-commit is skipped when the actor is
github-actions[bot]. - Only coverage artifact files are staged for this CI-authored commit.
- Coverage artifact update logic is serialized per PR branch with cancel-in-progress behavior to avoid commit races.