`ajv compile` command: add schemas before compiling them to allow refs between schemas
If you use ajv-cli to compile multiple schemas, it appears to process them in alphabetical order. If one of the earlier schemas references a later schema, the compilation will fail because the later schema has not yet been validated. You can work around that (appropriately) by adding the -r '**/*.json' flag so that all the referenced schemas are added to AJV first.
This seems non-intuitive (at least it tripped me up for an hour) because you can have some folders of schemas that work just fine, and then just by adding a reference to a schema that comes later in the alphabetical order, the schema resolution seems to stop working.
My suggestion would be that if a glob is passed to the compile step, that all schemas in the glob are first added to AJV, and then they are compiled after that, so that the order of them appearing in the glob does not matter, and users do not have to reference them again using the -r flag.
For example:
- Take the attached folder of schemas and untar it on your workstation.
- From the untarred schemas folder, run
ajv compile -s '**/*.json'. - You'll see that
auth-auth/token-with-nonce.jsonfailed because it couldn't resolve a schema it depended on (that came later in the glob). mv auth-auth zzzz- Run
ajv compile -s '**/*.json'again. Everything worked this time because the dependencies happened to be in the right order.
Here's the output of that exercise:
jrthomer@work:/tmp/foo/schemas$ ajv compile -s '**/*.json'
schema auth-auth/token-with-nonce.json is invalid
error: can't resolve reference ../core/jwt.json from id https://example.com/schemas/auth-auth/token-with-nonce.json#
schema core/jwt.json is valid
schema core/uuid.json is valid
jrthomer@work:/tmp/foo/schemas$ mv auth-auth zzzz
jrthomer@work:/tmp/foo/schemas$ ajv compile -s '**/*.json'
schema core/jwt.json is valid
schema core/uuid.json is valid
schema zzzz/token-with-nonce.json is valid
And if I had specified the glob twice, it would've worked (with the original folder structure):
jrthomer@work:/tmp/foo/schemas$ ajv compile -r '**/*.json' -s '**/*.json'
schema auth-auth/token-with-nonce.json is valid
schema core/jwt.json is valid
schema core/uuid.json is valid
If you don't agree with the proposed solution of always doing the addSchema step on all schemas before doing the compile step, perhaps at least the documentation could emphasize the need for the -r flag, which may be missed by newcomers (at least I missed it, and didn't realize it until I read the AJV code and made my own test case using AJV directly).
Thanks!
Forgot to attach the samples: schemas.tar.gz
@jthomerson thank you, that’s very detailed. I agree with the change.
To-do:
- [ ] correctly report errors (the schema can fail to validate during addSchema call or fail to compile).
- [ ] correctly handle the absence of $id/is on the top level of the schema file and do not add these schemas (but still attempt compiling them).
- [ ] probably, do not do it if -r option is present.
- [ ] docs for all that.
- [ ] tests for all these extra scenarios.
PR is welcome.
This seems to still be happening. Only difference is that when I add the -r command as @jthomerson commented, I get a ton of "already exist" errors and schemas are now invalid.