Skip to content

Commit 12aa721

Browse files
authored
Fix js-yaml $ref (#1146)
* Fix js-yaml $refs * Add changeset
1 parent 1af2194 commit 12aa721

File tree

4 files changed

+47
-19
lines changed

4 files changed

+47
-19
lines changed

.changeset/gold-berries-kick.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"openapi-typescript": patch
3+
---
4+
5+
Fix js-yaml $refs

packages/openapi-typescript/src/utils.ts

+25-9
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,31 @@ export function comment(text: string, indentLv?: number): string {
106106
/** handle any valid $ref */
107107
export function parseRef(ref: string): { filename: string; path: string[] } {
108108
if (typeof ref !== "string") return { filename: ".", path: [] };
109-
if (!ref.includes("#")) return { filename: ref, path: [] };
110-
const [filename, path] = ref.split("#");
111-
return {
112-
filename: filename || ".",
113-
path: path
114-
.split("/") // split by special character
115-
.filter((p) => !!p && p !== "properties") // remove empty parts and "properties" (gets flattened by TS)
116-
.map(decodeRef), // decode encoded chars
117-
};
109+
110+
// OpenAPI $ref
111+
if (ref.includes("#/")) {
112+
const [filename, pathStr] = ref.split("#");
113+
const parts = pathStr.split("/");
114+
const path: string[] = [];
115+
for (const part of parts) {
116+
if (!part || part === "properties") continue; // remove empty parts and "properties" (gets flattened by TS)
117+
path.push(decodeRef(part));
118+
}
119+
return { filename: filename || ".", path };
120+
}
121+
// js-yaml $ref
122+
else if (ref.includes('["')) {
123+
const parts = ref.split('["');
124+
const path: string[] = [];
125+
for (const part of parts) {
126+
const sanitized = part.replace('"]', "").trim();
127+
if (!sanitized || sanitized === "properties") continue;
128+
path.push(sanitized);
129+
}
130+
return { filename: ".", path };
131+
}
132+
// remote $ref
133+
return { filename: ref, path: [] };
118134
}
119135

120136
/** Parse TS index */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { bench } from "vitest";
2+
import { parseRef } from "../src/utils.js";
3+
4+
bench("parseRef", () => {
5+
parseRef("#/test/schema-object");
6+
});

packages/openapi-typescript/test/utils.test.ts

+11-10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { bench } from "vitest";
12
import { parseRef, tsIntersectionOf, tsUnionOf } from "../src/utils.js";
23

34
describe("utils", () => {
@@ -48,11 +49,7 @@ describe("utils", () => {
4849
["identity for unknown type", ["unknown"], "unknown"],
4950
["unknown for no types passed", [], "unknown"],
5051
["parentheses around types with union", ["4", `string | number`], "4 & (string | number)"],
51-
[
52-
"parentheses around types with intersection",
53-
["{ red: string }", "{ blue: string } & { green: string }"],
54-
"{ red: string } & ({ blue: string } & { green: string })",
55-
],
52+
["parentheses around types with intersection", ["{ red: string }", "{ blue: string } & { green: string }"], "{ red: string } & ({ blue: string } & { green: string })"],
5653
];
5754

5855
tests.forEach(([name, input, output]) => {
@@ -64,19 +61,23 @@ describe("utils", () => {
6461

6562
describe("parseRef", () => {
6663
it("basic", () => {
67-
expect(parseRef("#/test/schema-object")).toStrictEqual({ filename: ".", path: [ "test", "schema-object" ] });
64+
expect(parseRef("#/test/schema-object")).toStrictEqual({ filename: ".", path: ["test", "schema-object"] });
6865
});
6966

7067
it("double quote", () => {
71-
expect(parseRef("#/test/\"")).toStrictEqual({ filename: ".", path: [ "test", '\\\"' ] });
68+
expect(parseRef('#/test/"')).toStrictEqual({ filename: ".", path: ["test", '\\"'] });
7269
});
7370

7471
it("escaped double quote", () => {
75-
expect(parseRef("#/test/\\\"")).toStrictEqual({ filename: ".", path: [ "test", '\\\"' ] });
72+
expect(parseRef('#/test/\\"')).toStrictEqual({ filename: ".", path: ["test", '\\"'] });
7673
});
7774

7875
it("tilde escapes", () => {
79-
expect(parseRef("#/test/~1~0")).toStrictEqual({ filename: ".", path: [ "test", "/~" ] });
76+
expect(parseRef("#/test/~1~0")).toStrictEqual({ filename: ".", path: ["test", "/~"] });
77+
});
78+
79+
it("js-yaml $ref", () => {
80+
expect(parseRef('components["schemas"]["SchemaObject"]')).toStrictEqual({ filename: ".", path: ["components", "schemas", "SchemaObject"] });
8081
});
8182
});
82-
});
83+
});

0 commit comments

Comments
 (0)