npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

schemagic

v6.2.1

Published

JSON validation with schemas, and schema tools

Downloads

373

Readme

schemagic Build Status

npm package

JSON validation with schemagic, and schema tools

Put your json-schemas in a directory called schemas in your root folder.

Each schema will be loaded with require. This is an example of a schema in the file schemas/login.js

//JSON Schemas defined according to the standard json-schema http://json-schema.org/latest/json-schema-core.html
var regexpPatternUtil = require("./util/regexpPatternUtil");
module.exports = {
	"description":"Login",
	"required":true,
	"type":"object",
	"properties":{
		"email":{
			"description":"Email of the user",
			"required":true,
			"type":"string",
			"format":"email",
			"pattern": regexpPatternUtil.emailPattern.source,
			"example": "[email protected]"
		},
		"password":{
			"description":"Password of the user",
			"required":true,
			"type":"string",
			"example": "*********"
		}
	}
};

When you require schemagic

var schemagic = require("schemagic");

You will find the following things on schemagic.login

NOTE: if you do:

Object.keys(schmagic)

You will ONLY get schemas. Anything not a schema on schemagic is non-enumerable

additionalProperties, default false

Instead of as in the spec where the default for the schema is to allow additionalProperties. Schmagic will insert additionalProperties:false if you have not specified a additionalPropertiesvalue. We have done this to avoid programmer mistakes of forgetting additionalProperties:false in schemas.

NOTE: Schemagic 2.0 does not support removing properties with the values null, empty string or undefined. Take a look at the node module groom, for this functionality.

Build-in formats

Schmagic has these build in formats:

  • currency. Use this for numbers that are currency. Will allow maximum 2 decimals after the decimal point.
  • currency-rate Positive number. Minimum 0.000001, maximum 999,999,999. Will allow maximum 6 decimals after the decimal point.
  • date. Is verified to be a date of the format YYYY-MM-DD
  • date-time. Is verified to be a valid date and time in the format YYYY-MM-DDThh:mm:ssZ
  • rate. Positive number, between zero and 100. Will allow maximum 2 decimals after the decimal point
  • rate-negative. Negative number, between zero and -100. Will allow maximum 2 decimals after the decimal point
  • url. A http:// or https:// URL

schemagic.login.validate(object, options[, callback])

You will be able to validate a JavaScript object against the schema definition with the validate function. This is just a proxy for the is-my-json-valid validate function.

Options can be passed to the validate function:

{
	removeReadOnlyFields: true, // remove readonly fields from the object, default: true
	filter: false  // filter away any properties not in schema (if additionalProperties:false), default: false
	foreignKeys: false //check MongoDB foreign keys (callback is required), default: false
	mongo: [tenantmongo-object] // this is just passed to the functions in schemas/foreignKeys.js
}

It will return this kind of response if there is an error:

{
	valid: false,
	errors: [
		{
    		"property":"a",
    		"message":"string value found, but a number is required"
    	}
	]
}

It will return this response if there is no error:

{
	valid: true,
	errors: []
}

schemagic.login.exampleJson

This property wil contain a string, with pretty-printed JSON-ish and comments about what is required, read only and so on. This example-JSON is generated directly from the schema definition, using the example properties, if available (not required). Example:

//Signup and login
{
     //Email of the user
    //Required
    email:"[email protected]",
    //Password of the user
    //Required
    password:"*********"
}

schemagic.login.example

This property wil contain the parsed version of the exampleJson property. The exampleJson can not be parsed trivially because it's not valid JSON. It contains comments and property names are not quoted.

schemagic.login.exampleMinimalJson

The same as schemagic.login.exampleJson, except this example only includes required properties and properties that have minimal: true, all other properties have been omitted

schemagic.login.exampleMinimal

The same as schemagic.login.example, except this example only includes required properties and properties that have minimal: true, all other properties have been omitted

schemagic.login.exampleNoReadOnlyJson

The same as schemagic.login.exampleJson, except this example excludes properties that have readonly: true.

schemagic.login.exampleNoReadOnly

The same as schemagic.login.example, except this example excludes properties that have readonly: true.

schemagic.login.schema

This property wil contain the result of require("schemagic/login.js"), the raw schema as it was required from disk.

schemagic.login.array

This property wil contain a schemagic schema like login except it accepts an array of the documents specified in login. The root array is required.

- schemagic.login.array.validate
- schemagic.login.array.exampleJson
- schemagic.login.array.example
- schemagic.login.array.exampleMinimalJson
- schemagic.login.array.exampleMinimal
- schemagic.login.array.exampleNoReadOnlyJson
- schemagic.login.array.exampleNoReadOnly
- schemagic.login.array.schema

schemagic.login.patch

This property wil contain a schemagic schema like login except ALL required properties are now optional and all properties allow null values. This schema is intended for validation of JSON-PATCH. It has the properties:

- schemagic.login.patch.validate
- schemagic.login.patch.exampleJson
- schemagic.login.patch.example
- schemagic.login.patch.exampleMinimalJson (this will be empty object, as nothing is required on PATCH)
- schemagic.login.patch.exampleMinimal (this will be empty object, as nothing is required on PATCH)
- schemagic.login.patch.exampleNoReadOnlyJson
- schemagic.login.patch.exampleNoReadOnly
- schemagic.login.patch.array (with sub properties like schemagic.login.array)
- schemagic.login.patch.schema

Foreign key constraints (schemas/foreignKeys.js)

In the file schemas/foreignKeys.js you can specify foreign key constraints for MongoDB and in-memory lookups like this:

function getForeignKeyChecker(collectionName, propertyName) {
	return function (documentIds, options, callback) {
		var ids = [], formatErrors = [], anyFormatError = false;
		documentIds.forEach(function (invoiceId) {
			var id;
			try {
				id = new options.mongo.ObjectID(invoiceId);
				formatErrors.push(true);
			} catch (ex) {
				formatErrors.push(false);
				anyFormatError = true;
			}
			ids.push(id);
		});
		if(anyFormatError){
			return callback(null, formatErrors);
		}
		var query = {};
		query[propertyName] = {$in: ids};
		var fields = {};
		fields[propertyName] = 1;
		return options.mongo(collectionName).find(query, fields, getArray);

		function getArray(err, cursor) {
			if (err) {
				return callback(err);
			}
			return cursor.toArray(checkResults);
		}

		function checkResults(err, documentsInDb) {
			var result;
			if (err) {
				return callback(err);
			}
			if (documentsInDb.length === documentIds.length) {
				//Array of length = invoiceIds.length, with values all TRUE
				result = documentsInDb.map(Boolean); //truthy values become TRUE
				return callback(null, result); //result array must have same order as array passed in documentIds param
			}
			var idsInDb = documentsInDb.map(function (invoice) {
				return traverse(invoice).get(propertyName.split(".")).toString();
			});
			result = documentIds.map(function (id) {
				return idsInDb.indexOf(id) !== -1;
			});
			return callback(null, result); //result array must have same order as array passed in documentIds param
		}
	};
}

module.exports = {
	invoiceId: getForeignKeyChecker("invoices", "_id"),
	unitId: function(unitIds, options, callback){
		//unitIds === [1,9999,2]
		//lookup in memory: result = [true, false, true]; array must have same order as array passed in unitIds param
		return callback(null, result);
	}
};

Foreign keys are specified by convention. Meaning that with the above specification, ANY property with the name invoiceId or unitId will be subject to a foreign key check in ALL schemas.

Use dot notation if you want to apply the check for a specific schema:

module.exports = {
	"expense.categoryId": function(){..},
	"income.categoryId": function(){..},
}

If you want to use foreignKey checks you will have to pass mongo (and anything else used by your foreign key checkers) in options when you call validate like this:

schemagic.invoice.validate(doc, {foreignKey:true, mongo: mongo}, callback);

schemagic.parseExampleJson() (non-enumerable)

(NOTE: on root schemagic object)

This function tries to pares a text as though it was an exampleJson created by schemagic. It will throw if there is an error.

===================================== EXPERIMENTAL (NOTE: on root schemagic object)

When getSchemaFromObject is called with a JavaScript object, it will return a suggested schema for that object. It's far from perfect, but it gives you a starting point if you are creating a schema for a large object.