Skip to content

feat(validator): add tree-shakeable ESM export, fix tests, add a standalone validator with zero dependencies#518

Open
maxkoryukov wants to merge 4 commits into
jsonresume:masterfrom
maxkoryukov:feat/standalone-validator-esm-cjs
Open

feat(validator): add tree-shakeable ESM export, fix tests, add a standalone validator with zero dependencies#518
maxkoryukov wants to merge 4 commits into
jsonresume:masterfrom
maxkoryukov:feat/standalone-validator-esm-cjs

Conversation

@maxkoryukov
Copy link
Copy Markdown

@maxkoryukov maxkoryukov commented May 16, 2026

Improve package export and add CJS/ESM versions of a standalone AJV validator for "resume schema" with 0 additional dependencies.

also, the new "export"-design of the package makes "tree shaking" easier with ESM, one only needs to use

import schema from '@jsonresume/schema/schemas/resume.json'  with { type: 'json' }

and only the JSON schema will be imported, so the bundler won't include "validate"-functionality in the final bundle (at least from this package). Though, for the "validate.mjs" - the approach is still not ideal. I think another "export" will be required - for "precompiled and standalone" function, and another function that "import ajv" and "import ajv-formats" - so bundler and the programmer can decide how they want to bundle things together.

in order to avoid conflicts - exported as @jsonresume/schema/all

the old export and validator - without changes

Summary by CodeRabbit

  • New Features

    • Added new package export entrypoints (./all, ./validate, ./schemas/resume.json, ./schemas/job.json) for improved modular imports.
  • Chores

    • Enhanced build pipeline with bundling for both ESM and CommonJS formats.
    • Updated CI/CD workflows to include build verification before tests.
    • Updated development dependencies (ajv, esbuild).
    • Updated .gitignore to exclude build artifacts.
  • Tests

    • Added comprehensive test coverage for package exports and schema validation across ESM and CommonJS environments.

Review Change Stack


i've tested like this:

import { validate }     from '@jsonresume/schema/all'

// load CV from YAML ...
const cvDataJsonObj = loadCV(12892)

validate(
	cvDataJsonObj,
	function (errs) {
		if (errs) {
			console.error(`CV [${params.id}] was invalid:`, errs)
			return
		}
		console.log(`CV [${params.id}] validated successfully:`)
	},
)

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 16, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This PR implements a build pipeline to compile JSON schemas into standalone Ajv validators and distribute them via package exports. The changes include vendored formats, build infrastructure using esbuild, package configuration updates, entrypoint re-exports, CI workflow integration, and comprehensive tests.

Changes

Build Pipeline and Package Exports

Layer / File(s) Summary
Micro-formats validation module
tools/ajv-formats-micro.mjs
Vendored minimal subset of ajv-formats containing URI and email validators for use by Ajv schema compilation.
Build pipeline script
tools/build.mjs
Compiles schema.json to Ajv standalone validator module, outputs to ./tmp, then bundles both ESM and CJS distributions to ./dist/ using esbuild.
Package configuration and dependencies
package.json
Adds exports map for root and subpaths (./all, ./validate, ./schemas/*); expands files whitelist; updates test scripts to cover .cjs and .mjs files; adds ajv and esbuild dev dependencies.
Entrypoints and runtime validate wrapper
index.mjs, validate.mjs, job-schema.json
index.mjs re-exports schema and jobSchema from JSON modules and validate from validate.mjs; validate.mjs wraps the compiled validator with a callback interface; minor formatting adjustment to job-schema.json closing brace.
CI integration and build output cleanup
.github/workflows/main.yml, .github/workflows/release.yml, .gitignore
CI workflows updated to run npm run build before tests; .gitignore updated to ignore dist/ and tmp/ directories.
Packaging and awards schema tests
test/0-package.spec.cjs, test/0-package.spec.mjs, test/awards-esm.spec.mjs
New ESM/CJS tests verify package exports (validate function, schema objects, subpath imports); extensive awards-schema test suite validates overall schema and individual field types (title, date formats, awarder, summary).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A build pipeline hops to life,
Ajv schemas bundled without strife,
ESM and CJS dance in dist—
Package exports: none are missed!
Tests validate the awards, schemas too,
Build before test—fresh and new! 🏗️

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: adding tree-shakeable ESM exports and a standalone validator with zero dependencies, which are the core objectives of this PR.

✏️ 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.

@maxkoryukov maxkoryukov marked this pull request as ready for review May 16, 2026 11:40
Copy link
Copy Markdown

@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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
.github/workflows/release.yml (2)

33-43: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Publish job does not build distributable artifacts before npm publish (Line 40).

dist/ is generated and gitignored, and this job runs on a fresh runner. Without npm ci && npm run build here (or artifact transfer), published package can miss files required by exports.

Suggested fix
   npm:
     runs-on: ubuntu-latest
     needs: check
     steps:
     - name: Checkout
       uses: actions/checkout@master
+    - name: Install
+      run: npm ci
+    - name: Build
+      run: npm run build
     - name: Publish
       run: |
         echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_AUTH_TOKEN }}" > ~/.npmrc
         npm publish --access public
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 33 - 43, The Publish step in the
"npm" job runs npm publish on a fresh runner without building the distributable,
so the gitignored dist/ folder will be missing; modify the Publish step (the
step named "Publish" under job "npm") to install dependencies and build before
publishing—e.g., run "npm ci" and "npm run build" (or restore artifacts if you
upload from a prior job) before the existing npm publish command—and ensure the
build output expected by package.json exports is generated and present on the
runner.

13-13: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Remove Node 18 from the release check matrix; package.json declares engines.node: ">=20".

The workflow matrix at lines 13 and 31 tests Node 18, which violates the declared minimum version requirement in package.json. Align the matrix with supported engines to ensure CI tests against compatible versions.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml at line 13, Update the GitHub Actions release
matrix to stop testing Node 18: find the matrix entry that sets "node: [18, 20]"
(and any duplicate matrix entries with "node: 18") and remove 18 so the array
matches package.json's engines (e.g., "node: [20]" or include only supported
versions >=20); ensure both occurrences of the node matrix are updated so CI
only runs against Node 20+.
.github/workflows/main.yml (1)

9-9: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Build step will fail on Node 18 in the current CI matrix (Line 9).

The build script uses import ... with { type: 'json' } syntax (line 8 of tools/build.mjs), which requires Node.js 18.20.0 or later. However, the CI matrix specifies node: [18, 20] without pinning a minimum minor version, so it may install Node 18.0–18.19.x where this syntax is unsupported. This conflicts with package.json declaring engines: ">=20". Either remove Node 18 from the matrix to align with the declared minimum, or pin it to 18.20.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/main.yml at line 9, CI matrix entry "node: [18, 20]" is
unsafe because tools/build.mjs uses "import ... with { type: 'json' }" which
requires Node >=18.20 and package.json declares "engines: >=20"; fix by either
removing Node 18 from the matrix to match package.json (leave "node: [20]") or
pin the minor to a compatible 18 release ("node: [18.20, 20]"), and update
.github/workflows/main.yml accordingly so the matrix aligns with tools/build.mjs
and package.json.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@index.mjs`:
- Around line 6-10: The validate function always signals failure because both
branches call callback(..., false); update the success branch to call
callback(_v.errors, true) when _v(resumeObj) returns truthy so callers receive
true on valid input; locate this in the validate function where _v, _v.errors
and callback are used and change only the second callback's boolean to true.

In `@job-schema.json`:
- Around line 2-4: The schema declares "$schema":
"http://json-schema.org/draft-04/schema#" but uses the draft-06 keyword "$id";
replace the "$id" property with "id" to be draft-04 compatible (i.e., change the
identifier key named "$id" to id in the top-level object so the schema's
identifier uses the draft-04 "id" keyword while keeping the same identifier
value).

In `@package.json`:
- Around line 12-14: The "./ajv" package subpath's require field points to a
missing file ("./dist/index.js"); update the package.json exports for the
"./ajv" entry so the require target matches the published CJS artifact (e.g.,
change require from "./dist/index.js" to "./dist/index.cjs") or ensure the
missing "./dist/index.js" is produced; update the "./ajv" exports block
accordingly so CJS consumers can resolve the subpath.

In `@tools/build.mjs`:
- Around line 47-55: The CJS build produced by the esbuild.build call is not
bundled (the bundle option is commented out), so the generated dist/index.cjs
contains imports that resolve to invalid relative paths at runtime; fix this by
enabling bundling for the esbuild.build invocation (set bundle: true in the
options passed to esbuild.build) so the CJS artifact is self-contained and no
runtime import paths like './dist/resume-validator.mjs' remain unresolved.

---

Outside diff comments:
In @.github/workflows/main.yml:
- Line 9: CI matrix entry "node: [18, 20]" is unsafe because tools/build.mjs
uses "import ... with { type: 'json' }" which requires Node >=18.20 and
package.json declares "engines: >=20"; fix by either removing Node 18 from the
matrix to match package.json (leave "node: [20]") or pin the minor to a
compatible 18 release ("node: [18.20, 20]"), and update
.github/workflows/main.yml accordingly so the matrix aligns with tools/build.mjs
and package.json.

In @.github/workflows/release.yml:
- Around line 33-43: The Publish step in the "npm" job runs npm publish on a
fresh runner without building the distributable, so the gitignored dist/ folder
will be missing; modify the Publish step (the step named "Publish" under job
"npm") to install dependencies and build before publishing—e.g., run "npm ci"
and "npm run build" (or restore artifacts if you upload from a prior job) before
the existing npm publish command—and ensure the build output expected by
package.json exports is generated and present on the runner.
- Line 13: Update the GitHub Actions release matrix to stop testing Node 18:
find the matrix entry that sets "node: [18, 20]" (and any duplicate matrix
entries with "node: 18") and remove 18 so the array matches package.json's
engines (e.g., "node: [20]" or include only supported versions >=20); ensure
both occurrences of the node matrix are updated so CI only runs against Node
20+.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 06595f75-2d9b-4259-ab2b-ededb76270d4

📥 Commits

Reviewing files that changed from the base of the PR and between 50798e3 and b1def46.

📒 Files selected for processing (8)
  • .github/workflows/main.yml
  • .github/workflows/release.yml
  • .gitignore
  • index.mjs
  • job-schema.json
  • package.json
  • tools/ajv-formats-micro.mjs
  • tools/build.mjs

Comment thread index.mjs Outdated
Comment thread job-schema.json
Comment thread package.json Outdated
Comment thread tools/build.mjs
CJS and ESM versions of standalone AJV validator for "resume schema"
with 0 additional dependencies.

in order to avoid conflicts - exported as `@jsonresume/schema/ajv`

the old export and validator - without changes
`npm run build` is called:
- during testing
- before publishing
@maxkoryukov maxkoryukov force-pushed the feat/standalone-validator-esm-cjs branch from b1def46 to 0a75f35 Compare May 16, 2026 11:50
Copy link
Copy Markdown

@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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@package.json`:
- Around line 16-18: The package exports "./validate": "./validate.mjs" (and
indirectly via the "./all" re-export in index.mjs) but the package.json "files"
array does not include validate.mjs, causing consumers to fail to resolve it;
update the package.json "files" array to include "validate.mjs" (or
"./validate.mjs") so the exported entry "./validate" and the "./all" re-export
can be published and resolved correctly.

In `@tests/resume-awards.test.cjs`:
- Around line 31-34: The test file contains a focused test and a debug log:
change the test declaration in the 'awards[].title - invalid' case from
it.only(...) back to it(...) and remove the stray console.log(err) inside the
validate callback so the suite runs all tests and no debug output is committed;
locate the test by the string 'awards[].title - invalid' and the validate(...)
callback in tests/resume-awards.test.cjs to apply these edits.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 502a5752-ec5c-476f-9e46-8c162709b4c5

📥 Commits

Reviewing files that changed from the base of the PR and between 0a75f35 and 447a269.

📒 Files selected for processing (8)
  • index.mjs
  • package.json
  • test/0-package.spec.cjs
  • test/0-package.spec.mjs
  • test/awards-esm.spec.mjs
  • tests/resume-awards.test.cjs
  • tools/build.mjs
  • validate.mjs
✅ Files skipped from review due to trivial changes (2)
  • test/0-package.spec.cjs
  • test/0-package.spec.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • tools/build.mjs

Comment thread package.json
Comment thread tests/resume-awards.test.cjs Outdated
@maxkoryukov maxkoryukov force-pushed the feat/standalone-validator-esm-cjs branch 2 times, most recently from 4a6d002 to 0290455 Compare May 16, 2026 23:01
Copy link
Copy Markdown
Author

@maxkoryukov maxkoryukov left a comment

Choose a reason for hiding this comment

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

self review - DONE

…xported

in general: optimized and tested the "export"-design of the package

- the new export (ESM/CJS) implemented with node-conditional export
  is tested (see 0-package.spec - cjs and mjs files)
- fixed "coerceTypes" bug in AJV config
- copied "awards.spec" and the new "validate" (from ESM) used in the
  copied test
- 'index.mjs' converted to a barrel file, and 'validate.mjs' added - making
  the package "tree-shakeable" at least in the ESM mode (modern JS)
@maxkoryukov maxkoryukov force-pushed the feat/standalone-validator-esm-cjs branch from 0290455 to a830630 Compare May 17, 2026 01:24
@maxkoryukov
Copy link
Copy Markdown
Author

@thomasdavis hello, sorry for mentioning directly...

I would be glad to know, if changes in this PR align well with the purpose of the package. If yes - i would improve the PR/add more a few more like this

thanks

@maxkoryukov maxkoryukov changed the title feat(validator): standalone validator with zero dependencies feat(validator): ESM export, fix tests, add a standalone validator with zero dependencies May 18, 2026
@maxkoryukov maxkoryukov changed the title feat(validator): ESM export, fix tests, add a standalone validator with zero dependencies feat(validator): add tree-shakeable ESM export, fix tests, add a standalone validator with zero dependencies May 18, 2026
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.

1 participant