Introducing Quick-check

I recently released quick-check, a JS library to easily declare data schema and validate and convert data accordinly.

Why Yet Another Library?

I did not find anything that fits my need. I ended up writing some boiler-plate code, code to convert object trees (i.e., maps and lists) into home-grown classes, first while working on the CAMP project (Python), and then on my RPP project.

I did find though libraries to convert JSON files into home-grown classes, using annotations for instance, but in my case, I needed to accept both objects trees from multiple syntax files, say TOML and YAML for instance, which I parsed using different libraries.

Declaring Schemas

Using quick-check, I can declare data schemas directly in the code, in a way that serves as documentation, and that cannot go out of date. For instance, in the following, I declare a schema to represent a tree of teams (where teams are made of either persons or other teams).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
export const teamSchema = new Grammar();
teamSchema.define("team")
    .as(anObject()
        .with(aProperty("name").ofType("string"))
        .with(aProperty("members")
              .ofType(anArrayOf(eitherOf("person", "team")))));

teamSchema.define("person")
    .as(anObject()
        .with(aProperty("firstname").ofType("string"))
        .with(aProperty("lastname").ofType("string"))

Parsing Data

Given this schema—which I can directly refer to as documentation—I can now parse my data file using:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
const fileContent = fs.readFileSync('./data.yaml', 'utf8');
const data = yaml.safeLoad(fileContents);

try {
    const team = schema.read(data).as("team");

} catch (errors) {
    console.log(errors);

}

Converting Data

By constrast, my custom classes looks like the following UML class diagram:

UML classdiagram

To ease the convertion, I can attach a convertion function to each type my schema has, as follows:

1
2
3
4
5
teamSchema.on("team")
    .apply( (data) => {
        return new Team(data.name, data.members);
    }
);

This allows me to quickly validate the data I read from files and to directly instantiates my custom classes.

Share Comments
comments powered by Disqus