Skip to content

Commit 03a5413

Browse files
authored
Merge pull request #24 from json-schema-tools/feat/hash-pointer
feat: handle hash fragment of json pointers
2 parents b0adca5 + 84da5c8 commit 03a5413

File tree

2 files changed

+80
-3
lines changed

2 files changed

+80
-3
lines changed

src/index.test.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,48 @@ describe("referenceResolver", () => {
8787
}
8888
});
8989
});
90+
91+
92+
describe("refs with hash fragment / internal reference component", () => {
93+
describe("files", () => {
94+
it("works in simple case", async () => {
95+
expect(await referenceResolver("./src/test-obj.json#/type", {})).toBe("string");
96+
});
97+
98+
it("errors when the json pointer is invalid", async () => {
99+
expect.assertions(1);
100+
try {
101+
await referenceResolver("./src/test-obj.json#balony", {});
102+
} catch (e) {
103+
expect(e).toBeInstanceOf(InvalidJsonPointerRefError);
104+
}
105+
});
106+
});
107+
108+
describe("urls", () => {
109+
it("works with forward slashes surrounding the hash", async () => {
110+
expect(await referenceResolver("https://meta.open-rpc.org/#/type", {})).toBe("object");
111+
});
112+
it("works without slash infront of hash, but with one after", async () => {
113+
expect(await referenceResolver("https://meta.open-rpc.org#/type", {})).toBe("object");
114+
});
115+
116+
it("errors when the json pointer is invalid", async () => {
117+
expect.assertions(1);
118+
try {
119+
await referenceResolver("https://meta.open-rpc.org/#type", {});
120+
} catch (e) {
121+
expect(e).toBeInstanceOf(InvalidJsonPointerRefError);
122+
}
123+
});
124+
125+
it("errors when you have 2 hash fragments in 1 ref", async () => {
126+
expect.assertions(1);
127+
try {
128+
await referenceResolver("https://meta.open-rpc.org/#properties/#openrpc", {});
129+
} catch (e) {
130+
expect(e).toBeInstanceOf(InvalidJsonPointerRefError);
131+
}
132+
});
133+
});
134+
});

src/reference-resolver.ts

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,25 +136,57 @@ export default (fetch: any, fs: any) => {
136136
}
137137
}
138138

139-
if (await fileExistsAndReadable(ref) === true) {
140-
const fileContents = await readFile(ref);
139+
const hashFragmentSplit = ref.split("#");
140+
let hashFragment;
141+
if (hashFragmentSplit.length > 1) {
142+
hashFragment = hashFragmentSplit[hashFragmentSplit.length - 1];
143+
}
144+
145+
let hashlessRef = ref;
146+
if (hashFragment) {
147+
hashlessRef = ref.replace(`#${hashFragment}`, "");
148+
}
149+
150+
if (await fileExistsAndReadable(hashlessRef) === true) {
151+
const fileContents = await readFile(hashlessRef);
141152
let reffedSchema;
142153
try {
143154
reffedSchema = JSON.parse(fileContents);
144155
} catch (e) {
145156
throw new NonJsonRefError({ $ref: ref }, fileContents);
146157
}
147158

159+
if (hashFragment) {
160+
try {
161+
const pointer = Ptr.parse(hashFragment);
162+
return Promise.resolve(pointer.eval(reffedSchema));
163+
} catch (e) {
164+
throw new InvalidJsonPointerRefError({ $ref: ref });
165+
}
166+
}
167+
148168
return reffedSchema;
149169
} else if (isUrlLike(ref) === false) {
150170
throw new InvalidFileSystemPathError(ref);
151171
}
152172

173+
let result;
153174
try {
154-
return await fetch(ref).then((r: any) => r.json());
175+
result = await fetch(ref).then((r: any) => r.json());
155176
} catch (e) {
156177
throw new InvalidRemoteURLError(ref);
157178
}
179+
180+
if (hashFragment) {
181+
try {
182+
const pointer = Ptr.parse(hashFragment);
183+
return Promise.resolve(pointer.eval(result));
184+
} catch (e) {
185+
throw new InvalidJsonPointerRefError({ $ref: ref });
186+
}
187+
}
188+
189+
return result;
158190
};
159191

160192
return resolveReference;

0 commit comments

Comments
 (0)