Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
8369d91
refactor: simplify the code to serve Hey API requirements
mrlubos Dec 23, 2024
ab68509
0.0.0
mrlubos Dec 25, 2024
c667923
0.0.1
mrlubos Dec 25, 2024
7a54120
Merge pull request #1 from hey-api/feat/download-resolve
mrlubos Dec 25, 2024
8f5531c
chore: update package.json
mrlubos Dec 25, 2024
c9f9b09
Merge pull request #2 from hey-api/chore/package-json
mrlubos Dec 25, 2024
25ba4b3
fix: do not use buffer type as generic
mrlubos Dec 25, 2024
1754059
0.0.2
mrlubos Dec 25, 2024
4743034
Merge pull request #3 from hey-api/fix/buffer-type
mrlubos Dec 25, 2024
b790294
fix: allow passing timeout value to sendRequest
mrlubos Feb 3, 2025
e5c19c0
0.0.3
mrlubos Feb 3, 2025
1a3f1c0
Merge pull request #4 from hey-api/fix/request-timeout
mrlubos Feb 3, 2025
f153d25
chore: sync package.json version with npm
mrlubos Feb 3, 2025
6860977
Merge pull request #5 from hey-api/chore/package-json-version
mrlubos Feb 3, 2025
6eb665e
fix: correctly resolve json input
mrlubos Mar 14, 2025
a92ca73
1.0.3
mrlubos Mar 14, 2025
92dbaac
Merge pull request #6 from hey-api/fix/resolve-json
mrlubos Mar 14, 2025
5e5ccf1
fix: allow passing fetch options to request
mrlubos Mar 31, 2025
dbde5d1
Merge pull request #7 from hey-api/fix/fetch-options
mrlubos Mar 31, 2025
f0a4310
fix: extended equality check
mrlubos Apr 23, 2025
9ba4565
Merge pull request #8 from hey-api/fix/extended-ref-equality
mrlubos Apr 23, 2025
9e09d3b
fix: parsing of schema resolved from URL when HTTP status is 200
mblumenstingl-n11 May 5, 2025
7b37bdf
Merge pull request #9 from mblumenstingl-n11/fix/parsing-of-schema-re…
mrlubos May 13, 2025
4e36205
fix: improve inventory check for pointers and add tests for multiple …
carson2222 Aug 27, 2025
f05ba07
Merge pull request #10 from hey-api/fix/improve-ref-pointer-inventory…
carson2222 Aug 27, 2025
50c6ee3
fix: inline internal JSON Pointer refs under #/paths/ for OpenAPI bun…
carson2222 Aug 29, 2025
5fb8e24
chore: add test case
carson2222 Aug 29, 2025
a549ba5
chore: code cleanup
carson2222 Sep 1, 2025
d6f8438
chore: code cleanup
carson2222 Sep 1, 2025
5a801bf
Merge pull request #11 from hey-api/fix/internal-json-pointer-bundling
carson2222 Sep 1, 2025
b3ba1d9
feat: enhance performance tracking in JSON reference bundling
max-scopp Sep 2, 2025
9eea073
chore: disable debug logging for bundling process
max-scopp Sep 2, 2025
9937043
fix: enhance bundling and dereferencing logic for external $ref
carson2222 Sep 2, 2025
d4ec386
Merge branch 'main' into fix--update-external-ref-handling
carson2222 Sep 2, 2025
cbf25e7
Merge commit 'refs/pull/12/head' of https://github.com/hey-api/json-s…
carson2222 Sep 3, 2025
0f7f409
Merge pull request #13 from hey-api/fix--update-external-ref-handling
carson2222 Sep 3, 2025
4674566
feat: implement bundling of multiple schemas with enhanced prefix han…
carson2222 Sep 8, 2025
46315f8
chore: enhance schema merging logic to prioritize OpenAPI and Swagger…
carson2222 Sep 8, 2025
e97ef5c
chore: update version to 1.2.0 in package.json
carson2222 Sep 10, 2025
f5f2c67
docs: update README to reflect package name change and new features i…
carson2222 Sep 10, 2025
e043602
Merge pull request #14 from hey-api/feat--multiple-input-support
carson2222 Sep 10, 2025
e58322a
fix: do not overwrite in circular self references
mrlubos Oct 22, 2025
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
github: philsturgeon
github:
- mrlubos
- hey-api
63 changes: 34 additions & 29 deletions .github/workflows/CI-CD.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,16 @@ jobs:
- name: Run linter
run: yarn lint

- name: Run Node tests
run: yarn test:node
# disabled after refactoring
# - name: Run Node tests
# run: yarn test:node

- name: Send code coverage results to Coveralls
uses: coverallsapp/github-action@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel: true
# disabled after refactoring
# - name: Send code coverage results to Coveralls
# uses: coverallsapp/github-action@v2
# with:
# github-token: ${{ secrets.GITHUB_TOKEN }}
# parallel: true

browser_tests:
name: Browser Tests
Expand All @@ -76,28 +78,31 @@ jobs:
- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Run tests
run: yarn test:browser

- name: Send code coverage results to Coveralls
uses: coverallsapp/github-action@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel: true

coverage:
name: Code Coverage
runs-on: ubuntu-latest
timeout-minutes: 5
needs:
- node_tests
- browser_tests
steps:
- name: Let Coveralls know that all tests have finished
uses: coverallsapp/github-action@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel-finished: true
# disabled after refactoring
# - name: Run tests
# run: yarn test:browser

# disabled after refactoring
# - name: Send code coverage results to Coveralls
# uses: coverallsapp/github-action@v2
# with:
# github-token: ${{ secrets.GITHUB_TOKEN }}
# parallel: true

# disabled after refactoring
# coverage:
# name: Code Coverage
# runs-on: ubuntu-latest
# timeout-minutes: 5
# needs:
# - node_tests
# - browser_tests
# steps:
# - name: Let Coveralls know that all tests have finished
# uses: coverallsapp/github-action@v2
# with:
# github-token: ${{ secrets.GITHUB_TOKEN }}
# parallel-finished: true

release:
name: Release
Expand Down
894 changes: 0 additions & 894 deletions .yarn/releases/yarn-4.2.2.cjs

This file was deleted.

934 changes: 934 additions & 0 deletions .yarn/releases/yarn-4.5.3.cjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
nodeLinker: node-modules

yarnPath: .yarn/releases/yarn-4.2.2.cjs
yarnPath: .yarn/releases/yarn-4.5.3.cjs
12 changes: 6 additions & 6 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)
MIT License

Copyright (c) 2015 James Messinger
Copyright (c) Hey API

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -9,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
110 changes: 60 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
> This is a modified fork to serve Hey API needs

# JSON Schema $Ref Parser

#### Parse, Resolve, and Dereference JSON Schema $ref pointers

[![Build Status](https://github.com/APIDevTools/json-schema-ref-parser/workflows/CI-CD/badge.svg?branch=master)](https://github.com/APIDevTools/json-schema-ref-parser/actions)
[![Coverage Status](https://coveralls.io/repos/github/APIDevTools/json-schema-ref-parser/badge.svg?branch=master)](https://coveralls.io/github/APIDevTools/json-schema-ref-parser)
<!-- [![Build Status](https://github.com/APIDevTools/json-schema-ref-parser/workflows/CI-CD/badge.svg?branch=master)](https://github.com/APIDevTools/json-schema-ref-parser/actions)
[![Coverage Status](https://coveralls.io/repos/github/APIDevTools/json-schema-ref-parser/badge.svg?branch=master)](https://coveralls.io/github/APIDevTools/json-schema-ref-parser) -->

[![npm](https://img.shields.io/npm/v/@apidevtools/json-schema-ref-parser.svg)](https://www.npmjs.com/package/@apidevtools/json-schema-ref-parser)
[![License](https://img.shields.io/npm/l/@apidevtools/json-schema-ref-parser.svg)](LICENSE)
[![Buy us a tree](https://img.shields.io/badge/Treeware-%F0%9F%8C%B3-lightgreen)](https://plant.treeware.earth/APIDevTools/json-schema-ref-parser)
<!-- [![npm](https://img.shields.io/npm/v/@apidevtools/json-schema-ref-parser.svg)](https://www.npmjs.com/package/@apidevtools/json-schema-ref-parser)
[![License](https://img.shields.io/npm/l/@apidevtools/json-schema-ref-parser.svg)](LICENSE) -->

## Installation

Install using [npm](https://docs.npmjs.com/about-npm/):

```bash
npm install @apidevtools/json-schema-ref-parser
yarn add @apidevtools/json-schema-ref-parser
bun add @apidevtools/json-schema-ref-parser
npm install @hey-api/json-schema-ref-parser
yarn add @hey-api/json-schema-ref-parser
bun add @hey-api/json-schema-ref-parser
```

## The Problem:
Expand Down Expand Up @@ -56,13 +57,10 @@ complex [JSON Schemas](http://json-schema.org/latest/json-schema-core.html) and
JavaScript objects.

- Use **JSON** or **YAML** schemas &mdash; or even a mix of both!
- Supports `$ref` pointers to external files and URLs, as well
as [custom sources](https://apitools.dev/json-schema-ref-parser/docs/plugins/resolvers.html) such as databases
- Can [bundle](https://apitools.dev/json-schema-ref-parser/docs/ref-parser.html#bundlepath-options-callback) multiple
files into a single schema that only has _internal_ `$ref` pointers
- Can [dereference](https://apitools.dev/json-schema-ref-parser/docs/ref-parser.html#dereferencepath-options-callback)
your schema, producing a plain-old JavaScript object that's easy to work with
- Supports [circular references](https://apitools.dev/json-schema-ref-parser/docs/#circular-refs), nested references,
- Supports `$ref` pointers to external files and URLs, as well as custom sources such as databases
- Can bundle multiple files into a single schema that only has _internal_ `$ref` pointers
- Can dereference your schema, producing a plain-old JavaScript object that's easy to work with
- Supports circular references, nested references,
back-references, and cross-references between files
- Maintains object reference equality &mdash; `$ref` pointers to the same value always resolve to the same object
instance
Expand All @@ -71,22 +69,60 @@ JavaScript objects.
## Example

```javascript
import $RefParser from "@apidevtools/json-schema-ref-parser";
import { $RefParser } from "@hey-api/json-schema-ref-parser";

try {
await $RefParser.dereference(mySchema);
// note - by default, mySchema is modified in place, and the returned value is a reference to the same object
console.log(mySchema.definitions.person.properties.firstName);

// if you want to avoid modifying the original schema, you can disable the `mutateInputSchema` option
let clonedSchema = await $RefParser.dereference(mySchema, { mutateInputSchema: false });
console.log(clonedSchema.definitions.person.properties.firstName);
const parser = new $RefParser();
await parser.dereference({ pathOrUrlOrSchema: mySchema });
console.log(parser.schema.definitions.person.properties.firstName);
} catch (err) {
console.error(err);
}
```

For more detailed examples, please see the [API Documentation](https://apitools.dev/json-schema-ref-parser/docs/)
### New in this fork (@hey-api)

- **Multiple inputs with `bundleMany`**: Merge and bundle several OpenAPI/JSON Schema inputs (files, URLs, or raw objects) into a single schema. Components are prefixed to avoid name collisions, paths are namespaced on conflict, and `$ref`s are rewritten accordingly.

```javascript
import { $RefParser } from "@hey-api/json-schema-ref-parser";

const parser = new $RefParser();
const merged = await parser.bundleMany({
pathOrUrlOrSchemas: [
"./specs/a.yaml",
"https://example.com/b.yaml",
{ openapi: "3.1.0", info: { title: "Inline" }, paths: {} },
],
});

// merged.components.* will contain prefixed names like a_<name>, b_<name>, etc.
```

- **Dereference hooks**: Fine-tune dereferencing with `excludedPathMatcher(path) => boolean` to skip subpaths and `onDereference(path, value, parent, parentPropName)` to observe replacements.

```javascript
const parser = new $RefParser();
parser.options.dereference.excludedPathMatcher = (p) => p.includes("/example/");
parser.options.dereference.onDereference = (p, v) => {
// inspect p / v as needed
};
await parser.dereference({ pathOrUrlOrSchema: "./openapi.yaml" });
```

- **Smart input resolution**: You can pass a file path, URL, or raw schema object. If a raw schema includes `$id`, it is used as the base URL for resolving relative `$ref`s.

```javascript
await new $RefParser().bundle({
pathOrUrlOrSchema: {
$id: "https://api.example.com/openapi.json",
openapi: "3.1.0",
paths: {
"/ping": { get: { responses: { 200: { description: "ok" } } } },
},
},
});
```

## Polyfills

Expand Down Expand Up @@ -128,16 +164,6 @@ config.plugins.push(
);
```

## API Documentation

Full API documentation is available [right here](https://apitools.dev/json-schema-ref-parser/docs/)

## Contributing

I welcome any contributions, enhancements, and
bug-fixes. [Open an issue](https://github.com/APIDevTools/json-schema-ref-parser/issues) on GitHub
and [submit a pull request](https://github.com/APIDevTools/json-schema-ref-parser/pulls).

#### Building/Testing

To build/test the project locally on your computer:
Expand All @@ -150,19 +176,3 @@ To build/test the project locally on your computer:

3. **Run the tests**<br>
`yarn test`

## License

JSON Schema $Ref Parser is 100% free and open-source, under the [MIT license](LICENSE). Use it however you want.

This package is [Treeware](http://treeware.earth). If you use it in production, then we ask that you [**buy the world a
tree**](https://plant.treeware.earth/APIDevTools/json-schema-ref-parser) to thank us for our work. By contributing to
the Treeware forest you’ll be creating employment for local families and restoring wildlife habitats.

## Big Thanks To

Thanks to these awesome companies for their support of Open Source developers ❤

[![Stoplight](https://svgshare.com/i/TK5.svg)](https://stoplight.io/?utm_source=github&utm_medium=readme&utm_campaign=json_schema_ref_parser)
[![SauceLabs](https://jstools.dev/img/badges/sauce-labs.svg)](https://saucelabs.com)
[![Coveralls](https://jstools.dev/img/badges/coveralls.svg)](https://coveralls.io)
52 changes: 52 additions & 0 deletions lib/__tests__/bundle.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import path from "path";

import { describe, expect, it } from "vitest";

import { $RefParser } from "..";

describe("bundle", () => {
it("handles circular reference with description", async () => {
const refParser = new $RefParser();
const pathOrUrlOrSchema = path.resolve("lib", "__tests__", "spec", "circular-ref-with-description.json");
const schema = await refParser.bundle({ pathOrUrlOrSchema });
expect(schema).toEqual({
schemas: {
Bar: {
$ref: '#/schemas/Foo',
description: 'ok',
},
Foo: {
$ref: '#/schemas/Bar',
},
},
});
});

it("bundles multiple references to the same file correctly", async () => {
const refParser = new $RefParser();
const pathOrUrlOrSchema = path.resolve("lib", "__tests__", "spec", "multiple-refs.json");
const schema = (await refParser.bundle({ pathOrUrlOrSchema })) as any;

// Both parameters should now be $ref to the same internal definition
const firstParam = schema.paths["/test1/{pathId}"].get.parameters[0];
const secondParam = schema.paths["/test2/{pathId}"].get.parameters[0];

// The $ref should match the output structure in file_context_0
expect(firstParam.$ref).toBe("#/components/parameters/path-parameter_pathId");
expect(secondParam.$ref).toBe("#/components/parameters/path-parameter_pathId");

// The referenced parameter should exist and match the expected structure
expect(schema.components).toBeDefined();
expect(schema.components.parameters).toBeDefined();
expect(schema.components.parameters["path-parameter_pathId"]).toEqual({
name: "pathId",
in: "path",
required: true,
schema: {
type: "string",
format: "uuid",
description: "Unique identifier for the path",
},
});
});
});
45 changes: 45 additions & 0 deletions lib/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import path from "node:path";

import { describe, expect, it } from "vitest";

import { getResolvedInput } from "../index";

describe("getResolvedInput", () => {
it("handles url", async () => {
const pathOrUrlOrSchema = "https://foo.com";
const resolvedInput = await getResolvedInput({ pathOrUrlOrSchema });
expect(resolvedInput.type).toBe("url");
expect(resolvedInput.schema).toBeUndefined();
expect(resolvedInput.path).toBe("https://foo.com/");
});

it("handles file", async () => {
const pathOrUrlOrSchema = "./path/to/openapi.json";
const resolvedInput = await getResolvedInput({ pathOrUrlOrSchema });
expect(resolvedInput.type).toBe("file");
expect(resolvedInput.schema).toBeUndefined();
expect(path.normalize(resolvedInput.path).toLowerCase()).toBe(
path.normalize(path.resolve("./path/to/openapi.json")).toLowerCase(),
);
});

it("handles raw spec", async () => {
const pathOrUrlOrSchema = {
info: {
version: "1.0.0",
},
openapi: "3.1.0",
paths: {},
};
const resolvedInput = await getResolvedInput({ pathOrUrlOrSchema });
expect(resolvedInput.type).toBe("json");
expect(resolvedInput.schema).toEqual({
info: {
version: "1.0.0",
},
openapi: "3.1.0",
paths: {},
});
expect(resolvedInput.path).toBe("");
});
});
26 changes: 26 additions & 0 deletions lib/__tests__/pointer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { describe, expect, it } from "vitest";
import { $RefParser } from "..";
import path from "path";

describe("pointer", () => {
it("inlines internal JSON Pointer refs under #/paths/ for OpenAPI bundling", async () => {
const refParser = new $RefParser();
const pathOrUrlOrSchema = path.resolve("lib", "__tests__", "spec", "openapi-paths-ref.json");
const schema = (await refParser.bundle({ pathOrUrlOrSchema })) as any;

// The GET endpoint should have its schema defined inline
const getSchema = schema.paths["/foo"].get.responses["200"].content["application/json"].schema;
expect(getSchema.$ref).toBeUndefined();
expect(getSchema.type).toBe("object");
expect(getSchema.properties.bar.type).toBe("string");

// The POST endpoint should have its schema inlined (copied) instead of a $ref
const postSchema = schema.paths["/foo"].post.responses["200"].content["application/json"].schema;
expect(postSchema.$ref).toBe("#/paths/~1foo/get/responses/200/content/application~1json/schema");
expect(postSchema.type).toBeUndefined();
expect(postSchema.properties?.bar?.type).toBeUndefined();

// Both schemas should be identical objects
expect(postSchema).not.toBe(getSchema);
});
});
Loading