mrkeyoor.com_
Wed 23 Sept 00:34 UTC
npmUtilsupdated 22 Sept 2026

@hey-api/json-schema-ref-parser review

@hey-api/json-schema-ref-parser 1.4.4 is Hey API's Node-only fork for reading JSON or YAML schemas and rewriting external `$ref` targets into one document with internal pointers. It accepts a path, URL, object, or supplied ArrayBuffer. Its extra `bundleMany()` operation merges several OpenAPI-shaped inputs, prefixes colliding components and operation IDs, and rewrites conflicting paths. Version 1.4.4 removes CommonJS files from the package and deletes `$ref` keywords the bundler cannot resolve. The published class exposes `parse()`, `bundle()`, and `bundleMany()`; the README's `dereference()` example does not match the shipped API.

Verdict

@hey-api/json-schema-ref-parser 1.4.4 installed in 2.3 seconds but produced 2 high audit findings, rejected `require()`, and failed our browser build; it fits trusted Node 22 ESM tooling that specifically needs Hey API's `bundleMany()`. General-purpose or user-facing schema services should prefer the upstream parser with explicit resolver controls.

We installed it

Lab card: what happened when we installed @hey-api/json-schema-ref-parserScreenshot of @hey-api/json-schema-ref-parser documentation
Install✓ · 2.3s5 packages on disk · 2 MB
Import½ESM import works · require() fails · ESM package with exports map
Browsern/acould not be bundled for the browser (Node-only code, most likely)
TypesTypeScript types bundled
Known vulns20 critical · 2 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does @hey-api/json-schema-ref-parser install cleanly?

Yes. In a fresh container with an empty cache, npm install @hey-api/json-schema-ref-parser finished in 2 seconds, leaving 5 packages and 2 MB on disk. npm audit reported 2 known vulnerabilities.

Can @hey-api/json-schema-ref-parser run in a browser?

Not directly: esbuild could not bundle it for the browser in our run, which normally means it depends on Node built-ins. Use it on the server, or find a browser-targeted alternative.

Does @hey-api/json-schema-ref-parser work with both ESM and CommonJS?

ESM only. import '@hey-api/json-schema-ref-parser' worked, require('@hey-api/json-schema-ref-parser') failed in our run, so CommonJS projects need a dynamic import or a build step.

Does @hey-api/json-schema-ref-parser include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

@hey-api/json-schema-ref-parser or @apidevtools/json-schema-ref-parser: which should you use?

@apidevtools/json-schema-ref-parser: Use the upstream parser for documented parse, resolve, bundle, and dereference operations plus configurable resolvers. @hey-api/json-schema-ref-parser 1.4.4 installed in 2.3 seconds but produced 2 high audit findings, rejected require(), and failed our browser build; it fits trusted Node 22 ESM tooling that specifically needs Hey API's bundleMany().

When should you not use @hey-api/json-schema-ref-parser?

You need resolve() or dereference(). Version 1.4.4's exported class has neither method, although the package README advertises both behaviors.

API stability2/5The package is at 1.4.4, and version 1.4.0 raised the Node floor as a breaking change. The published class differs from its upstream namesake through object-only arguments, `bundleMany()`, and the absence of public resolve, dereference, static helpers, and callbacks. Recent 1.4.x patches changed URL encoding, YAML parsing, source naming, sibling bundling, and the treatment of unresolved references, all of which can change emitted schemas.
Docs2/5The package README explains mixed JSON and YAML references, bundling, circular graphs, object input, `$id`, and the fork's multi-input merge with a concrete example. Its central dereference section is inaccurate for 1.4.4 because `$RefParser` exposes no public `dereference()` method. Browser compatibility is also claimed despite a Node 22.18.0 engine floor and a failed browser build in our check. Security boundaries around file and URL resolution are undocumented.
Maintenance5/5Version 1.4.4 was published on June 22, 2026, and the Hey API monorepo was pushed on August 24, 2026. The changelog records fixes for unsafe URL characters, YAML parsing, whole-file reference names, unresolved pointers, sibling schemas, and multi-input collisions. GitHub shows 5,311 stars and 591 open issues and pull requests across the full monorepo. Active code work is clear, though documentation has lagged behind the exported class.
Ecosystem3/5npm recorded 4,069,974 downloads from August 18 through August 24, 2026. The package benefits from Hey API's code-generation ecosystem and uses established JSON Pointer, JSON Reference, JSON Schema type, and YAML conventions. Independent interoperability is weaker than the familiar package name suggests: it requires Node 22 ESM, removes upstream methods, and concentrates its distinctive value in Hey API's opinionated OpenAPI merging path.

Use it if

  • A Hey API build needs the exact parser and bundling behavior used by the surrounding monorepo.
  • Several trusted OpenAPI files must be combined with `bundleMany()` and reviewed after its collision prefixing.
  • External JSON or YAML references should become internal pointers while recursive schemas remain serializable.
  • The process runs on Node 22.18.0 or newer and uses ESM throughout.
Skip it if

Setup reality

We installed @hey-api/json-schema-ref-parser 1.4.4 in a fresh Node 22 Bookworm sandbox in 2.3 seconds. The install left 5 packages and 2 MB on disk. npm audit found 2 known vulnerabilities, both high severity. The package has 3 direct dependencies, 0 peers, and a 496 KB unpacked size. Bundled TypeScript declarations are present. ESM import worked, while require() failed under Node 22.23.2.

The manifest requires Node 22.18.0 or newer and exports only dist/index.mjs plus package.json. There are no credentials or native build tools. Each public method takes one object argument rather than the positional signatures used by the upstream parser. parse() reads the root and returns { schema }; it leaves $ref strings unresolved. bundle() returns the schema itself after loading external targets and replacing them with internal pointers.

A local reference is read through the filesystem, and an HTTP reference uses global fetch. Request options supplied through fetch reach the root request, but version 1.4.4 does not carry those headers into every nested URL resolution path. The API has no resolver allowlist or offline flag. For untrusted input, call parse() first, reject every $ref that does not begin with #, or run bundling in a process that cannot reach sensitive files and networks.

bundleMany() applies OpenAPI-specific merge rules to info, servers, paths, tags, operation IDs, and components. A filename can become a prefix when names collide, so diff the generated contract before publishing it. Version 1.4.4 also removes an unresolvable $ref keyword during bundling; that can leave a sibling object with different meaning instead of a visible broken pointer. Our browser bundle attempt failed, so keep this parser in Node tooling. Inspect the 2 high audit findings in the resolved lockfile before CI adoption.

Patterns

Parse one local JSON or YAML document parse-local-file

import { $RefParser } from '@hey-api/json-schema-ref-parser'

const parser = new $RefParser()
const { schema } = await parser.parse({
  pathOrUrlOrSchema: './schemas/root.yaml'
})

`parse()` reads only the root document and returns `{ schema }`. It does not follow, bundle, or validate `$ref` targets.

Accept an in-memory schema parse-object

const input = {
  $schema: 'https://json-schema.org/draft/2020-12/schema',
  type: 'object',
  properties: { id: { type: 'string' } }
}

const { schema } = await new $RefParser().parse({
  pathOrUrlOrSchema: input
})

An object without `$id` causes no root I/O. The parser checks that the root is object-like, not that it follows the declared JSON Schema dialect.

Send headers for a remote root parse-private-url

const { schema } = await new $RefParser().parse({
  pathOrUrlOrSchema: 'https://api.example.com/openapi.yaml',
  fetch: { headers: { Authorization: `Bearer ${token}` } }
})

The RequestInit applies to the root fetch. Nested references reached by `bundle()` do not consistently inherit these headers in 1.4.4.

Convert external references to internal pointers bundle-external-refs

import { writeFile } from 'node:fs/promises'

const parser = new $RefParser()
const bundled = await parser.bundle({
  pathOrUrlOrSchema: './schemas/root.yaml'
})
await writeFile('dist/schema.json', JSON.stringify(bundled, null, 2))

`bundle()` can read arbitrary file and HTTP targets named by the schema. Restrict the process when the input is not fully trusted.

Reuse already fetched root bytes supply-root-bytes

const response = await fetch(rootUrl, {
  headers: { Authorization: `Bearer ${token}` }
})
if (!response.ok) throw new Error(`HTTP ${response.status}`)

const bundled = await new $RefParser().bundle({
  pathOrUrlOrSchema: rootUrl,
  arrayBuffer: await response.arrayBuffer()
})

The URL remains the base for relative pointers. Supplying root bytes does not prevent nested `$ref` values from causing more network requests.

List sources opened during bundling list-read-sources

const parser = new $RefParser()
await parser.bundle({ pathOrUrlOrSchema: './schemas/root.yaml' })

console.log(parser.$refs.paths())
console.log(parser.$refs.paths('file'))
console.log(parser.$refs.paths('http'))

`$refs.paths()` is useful for an audit after the run. It cannot block a file or URL before the parser reads it.

Inspect a resolved pointer read-reference-value

const parser = new $RefParser()
await parser.bundle({ pathOrUrlOrSchema: './schemas/root.yaml' })

if (parser.$refs.exists('#/components/schemas/User', parser.options)) {
  console.log(parser.$refs.get('#/components/schemas/User'))
}

The reference map belongs to the latest operation on that parser instance. A new parse resets `$refs`.

Serialize a recursive schema bundle-recursive-schema

const bundled = await new $RefParser().bundle({
  pathOrUrlOrSchema: './schemas/tree.yaml'
})

const json = JSON.stringify(bundled)

Bundling preserves internal `$ref` pointers, so recursion does not create a circular JavaScript object graph.

Merge several OpenAPI inputs merge-openapi-files

const merged = await new $RefParser().bundleMany({
  pathOrUrlOrSchemas: [
    './specs/catalog.yaml',
    './specs/billing.yaml',
    { openapi: '3.1.0', info: { title: 'Inline', version: '1' }, paths: {} }
  ]
})

`bundleMany()` may prefix components, operation IDs, and conflicting routes from source filenames. Review the merged paths before distribution.

Reject user-controlled external pointers reject-external-refs

function rejectExternalRefs(value) {
  if (!value || typeof value !== 'object') return
  if (typeof value.$ref === 'string' && !value.$ref.startsWith('#')) {
    throw new Error(`External $ref rejected: ${value.$ref}`)
  }
  for (const child of Object.values(value)) rejectExternalRefs(child)
}

const { schema } = await new $RefParser().parse({ pathOrUrlOrSchema: upload })
rejectExternalRefs(schema)

Version 1.4.4 has no public `external: false` option. Inspect after `parse()` and before any call to `bundle()`.

Report grouped parser errors handle-reference-errors

import { $RefParser, JSONParserErrorGroup, isHandledError } from '@hey-api/json-schema-ref-parser'

try {
  await new $RefParser().bundle({ pathOrUrlOrSchema: input })
} catch (error) {
  if (error instanceof JSONParserErrorGroup) {
    for (const item of error.errors) console.error(item.code, item.source)
  } else if (isHandledError(error)) {
    console.error(error.code, error.source)
  } else {
    throw error
  }
}

External resolution can group handled errors. Use the exported code and source fields instead of matching message text.

Limit syntax handling to JSON disable-non-json-parsers

const parser = new $RefParser()
parser.options.parse.yaml.canHandle = () => false
parser.options.parse.text.canHandle = () => false
parser.options.parse.binary.canHandle = () => false

const bundled = await parser.bundle({
  pathOrUrlOrSchema: './schemas/root.json'
})

Disabling syntax parsers does not restrict filesystem paths or remote hosts. JSON references can still trigger external reads.

Alternatives

PackageRegistryPick it when
@apidevtools/json-schema-ref-parsernpmUse the upstream parser for documented parse, resolve, bundle, and dereference operations plus configurable resolvers.
@apidevtools/swagger-parsernpmUse it when an OpenAPI or Swagger document also needs specification validation.
@stoplight/json-ref-resolvernpmUse it when custom authority handlers and explicit control over reference lookup are central requirements.
json-refsnpmUse it for lower-level JSON Reference discovery and resolution in an established CommonJS application.

More utils guides

lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.