Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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"
}
}
}
}
}
}
}
}
}
20 changes: 19 additions & 1 deletion lib/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,24 @@ export interface InventoryEntry {
value: any;
}

/**
* Determines whether an internal $ref should be inlined (copied) rather than left as a $ref.
* Currently inlines OpenAPI path items ("#/paths/..."), while keeping components/definitions/declarations as refs.
*/
const shouldInlineInternal = (entry: InventoryEntry) => {
if (entry.external) {
return false;
}
const h = entry.hash as string | undefined;
if (!h || h === "#") {
return false;
}
if (h.startsWith("#/components/schemas") || h.indexOf("/definitions") !== -1 || h.startsWith("#/declarations")) {
Copy link
Member

Choose a reason for hiding this comment

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

Why do you

  • use indexOf for definitions but startsWith for the rest?
  • write it as /definitions and not #/definitions (with pound sign) like the rest
  • mention #/declarations? Where do those come from? It's not an OpenAPI 2.0/3.0/3.1 concept as far as I know

Copy link
Member Author

Choose a reason for hiding this comment

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

You're right, I mush have used some weird website to base it on lol
I cleaned it up

return false;
}
return h.startsWith("#/paths/");
};

/**
* TODO
*/
Expand Down Expand Up @@ -300,7 +318,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 && !shouldInlineInternal(entry)) {
// 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