-
-
Notifications
You must be signed in to change notification settings - Fork 232
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
References to references resolve relative to self, not baseUrl #199
Comments
Just noticed this as well: Folder structure
Schemas// base.json
{
"type": "object",
"properties": {
"child": {
"allOf": [{ "$ref": "schemas/child.json" }],
// ...
}
}
}
// child.json
{
"type": "object",
"properties": {
"grandChild": {
"allOf": [{ "$ref": "schemas/grandchild.json" }],
// ...
}
}
}
// grandchild.json
{
"type": "object",
"properties": {
"firstName": {
"type": string
}
}
} Expected behavior is that calling {
"type": "object",
"properties": {
"child": {
"type": "object",
"properties": {
"grandChild": {
"type": "object",
"properties": {
"firstName": {
"type": "string"
}
}
}
}
}
} Actual behavior: calling {
stack: 'ResolverError: Error opening file "{rootDir}/schemas/schemas/grandchild.json" \n' +
"ENOENT: no such file or directory, open '{rootDir}/schemas/schemas/grandchild.json'\n" +
' at ReadFileContext.callback ({rootDir}/node_modules/@apidevtools/json-schema-ref-parser/lib/resolvers/file.js:52:20)\n' +
' at FSReqCallback.readFileAfterOpen [as oncomplete] (fs.js:265:13)',
code: 'ERESOLVER',
message: 'Error opening file "{rootDir}/schemas/schemas/grandchild.json" \n' +
"ENOENT: no such file or directory, open '{rootDir}/schemas/schemas/grandchild.json'",
source: '{rootDir}/schemas/schemas/grandchild.json',
path: null,
toJSON: [Function: toJSON],
ioErrorCode: 'ENOENT',
name: 'ResolverError',
toString: [Function: toString]
} |
I can confirm this. Here is a minimal example which shows this behavior. |
Was about to post a long comment about running into this as well, but @manuscriptmastr, seems to have covered it perfectly. |
FWIW, I ended up with the following workaround, defining a resolver which is tried in the event that the file parser fails:
and:
Such that it just calls "dereference" again, with the existing options, thus resolving from the original root directory. |
I will definitely try this as a workaround @evergreen-lee-campbell. It would solve a lot of issues for me. |
Will there be a fix to this or is this considered expected behaviour? |
@evergreen-lee-campbell when you say...
...do you mean you're calling it like In any case, my expectation would be for that to be used as the base URI for the top-level schema document and then for relative refs from that schema to result in different base URIs for the referenced schemas. Using @manuscriptmastr's example:
(Diagram courtesy of https://github.com/nfriend/tree-online) For purposes of simplification let's say the base is specified as an actual URI File:
File:
My expectation would not be for the initial base URI to be used to resolve all refs throughout the tree by default, though having an option to make it work like that would be fine. So resolution of that kind of relative path makes sense to me. What I would like though (and maybe a custom resolver is the solution -- haven't looked at that yet) is to be able to have root relative resolution such that refs like |
I can confirm this happens to grandchildren and older referenced files where the baseUrl is different to the currently referenced file; const rawSchema: JSONSchema | undefined = await readSchema(schemaWithRefPointingToAnotherSchemaWithRef);
const baseUrl: string = '/full/path/to/cwd/including/trailing/slash/';
const parsedSchema: JSONSchema = await $RefParser.dereference(baseUrl, rawSchema, {}); Luckily, I was actually looking for this functionality, since I am creating a library where the schema folder will not be inside the cwd, so thank you for pointing me in the right direction @jmm. In my case the bug replicates the behaviour I need. const rawSchema: JSONSchema | undefined = await readSchema(currentSchema);
const parsedSchema: JSONSchema = await $RefParser.dereference(currentSchema, rawSchema, {}); |
Also, it would be great if the eventual fix would add a parameter to the resolve options, as this library is used in a lot of other JSON Schema and OpenAPI libraries and they usually expose the options object of this library. Currently I have to create a complete dereferenced JSONSchema using the above logic and use that schema file for the rest of my API generation and validation toolchain as there is no way to declare what kind of $ref logic is desired via the options object. |
I also encountered the same issue when bundling some schemas located in the same folder. const fixedRootDirectoryResolver: ResolverOptions = {
order: 101,
canRead: true,
read(file) {
const fileUrl = [...new Set(file.url.split('/'))].join('/');
return readFileSync(fileUrl, 'utf-8');
},
};
const globalParserOptions: ParserOptions = {
continueOnError: true,
dereference: {
circular: true,
},
resolve: {
file: fixedRootDirectoryResolver,
},
}; That's bricolage, but it solved my problem! |
Given the schema,
mySchema.json
:{ "properties": { "thing": { "$ref": "./schemas/thing.json" } } }
Where
thing.json
is:{ "properties": { "inner_thing": { "$ref": "./schemas/inner_thing.json" } } }
Attempting to deference
mySchema.json
at baseUrljson/
, results in the dereference function observing the baseUrl formySchema.json
, but not forthing.json
, leading to trying to read the fileinner_thing.json
at:json/schemas/json/schemas/inner_thing.json
.As such, there is no way to resolve schema structure whereby there are schemas that reference either of
thing.json
orinner_thing.json
. Could a resolver option be included that says "always resolve relative to the supplied cwd"?The text was updated successfully, but these errors were encountered: