Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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).toBeUndefined();
expect(postSchema.type).toBe("object");
expect(postSchema.properties.bar.type).toBe("string");

// Both schemas should be identical objects
expect(postSchema).toEqual(getSchema);
});
});
46 changes: 46 additions & 0 deletions lib/__tests__/spec/openapi-paths-ref.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"openapi": "3.1.0",
"info": {
"title": "Sample API",
"version": "1.0.0"
},
"paths": {
"/foo": {
"get": {
"summary": "Get foo",
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"bar": {
"type": "string"
}
}
}
}
}
}
}
},
"post": {
"summary": "Create foo",
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/paths/~1foo/get/responses/200/content/application~1json/schema"
}
}
}
}
}
}
}
}
}
2 changes: 1 addition & 1 deletion lib/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ function remap(inventory: InventoryEntry[]) {
for (const entry of inventory) {
// console.log('Re-mapping $ref pointer "%s" at %s', entry.$ref.$ref, entry.pathFromRoot);

if (!entry.external) {
if (!entry.external && !entry.hash?.startsWith("#/paths/")) {
// This $ref already resolves to the main JSON Schema file
entry.$ref.$ref = entry.hash;
} else if (entry.file === file && entry.hash === hash) {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
],
"scripts": {
"build": "rimraf dist && tsc",
"dev": "rimraf dist && tsc --watch",
"lint": "eslint lib",
"prepublishOnly": "yarn build",
"prettier": "prettier --write \"**/*.+(js|jsx|ts|tsx|har||json|css|md)\"",
Expand Down
Loading