diff --git a/README.md b/README.md index 551f884..b97bf42 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,30 @@ output = { } ``` +Specifying a format: +```js +ms.string({format: 'email'}) + +output = { + type: 'string', + format: 'email' +} +``` +Note: Check which formats are available with your JSON Schema +implementation before using this. + + +Specifying min and max length: +```js +ms.string({minLength: 3, maxLength: 50}) + +output = { + type: 'string', + minLength: 3, + maxLength: 50 +} +``` + Setting the required flag (only possible within an object): ```js ms.obj({ @@ -180,6 +204,22 @@ output = { } ``` +Add title and description: +```js +ms.obj({ + displayName: 'string', +}, {title: 'Title', description: 'Desc.'}) +``` + +Add dependencies: +```js +ms.obj({ + creditCard: 'string', + address: 'string' +}, {dependencies: {creditCard: 'address'}}) +``` + + ## Arrays ```js @@ -191,6 +231,18 @@ output = { } ``` +You can use these additional modifiers: +```js +ms.arrayOf(ms.string(), {minItems: 1, maxItems: 3, uniqueItems: true}) + +output = { + type: 'array', + items: {type: 'string'}, + minItems: 1, + maxItems: 3, + uniqueItems: true +} +``` ## Enumerations @@ -203,3 +255,16 @@ output = { enum: ['foo', 'bar'] } ``` + +## Constant Value + +```js +ms.const('foo') + +// The output is the same as ms.enum('foo') as there is no equivalent +// to value in JSON schema. +output = { + type: 'string', + const: 'foo' +} +``` diff --git a/index.js b/index.js index 3e7883f..5ed37d5 100644 --- a/index.js +++ b/index.js @@ -33,13 +33,16 @@ module.exports = { // Methods // ------- - obj (microschema = {}, {strict, required} = {}) { + obj (microschema = {}, {strict, required, title, description, dependencies} = {}) { const jsonSchema = { type: 'object', properties: {} } + if (title) jsonSchema.title = title + if (description) jsonSchema.description = description if (strict) jsonSchema.additionalProperties = false + if (dependencies) setDependencies(jsonSchema, dependencies) if (required) { if (!Array.isArray(required)) throw new Error("'required' must be an array") @@ -87,22 +90,35 @@ module.exports = { }) }, + + const (value) { + return this.decorate({ + type: getJsonType(value), + const: value + }) + }, + // @param schemaOrType // Pass in either a string or an object: // 1. {String} A json schema type. E.g. 'string' // Example: microschema.arrayOf('string') // 2. {Object} JSON Schema // Example: microschema.arrayOf({type: 'object', properties: {...}}) - arrayOf (schemaOrType) { + arrayOf (schemaOrType, {minItems, maxItems, uniqueItems} = {}) { const items = isString(schemaOrType) ? {type: schemaOrType} : schemaOrType - - return this.decorate({ + const s = this.decorate({ type: 'array', items: items }) + + if (minItems) s.minItems = minItems + if (maxItems) s.maxItems = maxItems + if (uniqueItems) s.uniqueItems = uniqueItems + + return s }, - string ({pattern} = {}) { + string ({pattern, format, minLength, maxLength} = {}) { const s = {type: 'string'} if (pattern) { if (pattern instanceof RegExp) { @@ -114,6 +130,11 @@ module.exports = { s.pattern = pattern } } + + if (format) s.format = format + if (minLength) s.minLength = minLength + if (maxLength) s.maxLength = maxLength + return this.decorate(s) }, @@ -178,3 +199,12 @@ function isString (str) { function isNumber (nr) { return typeof nr === 'number' } + +function setDependencies (jsonSchema, dependencies) { + const formattedDeps = {} + for (const prop in dependencies) { + const value = dependencies[prop] + formattedDeps[prop] = isString(value) ? [value] : value + } + jsonSchema.dependencies = formattedDeps +} diff --git a/test.js b/test.js index 421fc6c..f8813ed 100644 --- a/test.js +++ b/test.js @@ -2,6 +2,44 @@ const ms = require('./index') const test = require('ava').test const assert = require('assert') +test('obj() creates an object with title and description', function (t) { + const schema = ms.obj({ + displayName: 'string' + }, { + title: 'Title', + description: 'Desc.' + }) + + assert.deepEqual(schema, { + type: 'object', + properties: { + displayName: {type: 'string'} + }, + title: 'Title', + description: 'Desc.' + }) +}) + +test('obj() creates an object with dependencies', function (t) { + const schema = ms.obj({ + name: 'string', + displayName: 'string' + }, { + dependencies: {name: 'displayName'} + }) + + assert.deepEqual(schema, { + type: 'object', + properties: { + name: {type: 'string'}, + displayName: {type: 'string'} + }, + dependencies: { + name: ['displayName'] + } + }) +}) + test('strictObj() creates an object with a single property', function (t) { const schema = ms.strictObj({foo: 'string'}) @@ -60,6 +98,14 @@ test('enum() creates an enum from an array', function (t) { }) }) +test('const() creates a const value', function (t) { + const schema = ms.const('foo') + assert.deepEqual(schema, { + type: 'string', + const: 'foo' + }) +}) + test('arrayOf() creates an array with a type of its items', function (t) { const schema = ms.arrayOf('integer') @@ -69,6 +115,23 @@ test('arrayOf() creates an array with a type of its items', function (t) { }) }) + +test('arrayOf() creates an array with additional properties', function (t) { + const schema = ms.arrayOf(ms.string(), { + minItems: 1, + maxItems: 3, + uniqueItems: true + }) + + assert.deepEqual(schema, { + type: 'array', + items: {type: 'string'}, + minItems: 1, + maxItems: 3, + uniqueItems: true + }) +}) + test('string() creates a type string', function (t) { const schema = ms.string() assert.deepEqual(schema, {type: 'string'}) @@ -124,6 +187,26 @@ test('string({pattern}) does not accept a javascript regex with flags', function }) }) + +test('string({format}) adds a format', function (t) { + const schema = ms.string({format: 'email'}) + + assert.deepEqual(schema, { + type: 'string', + format: 'email' + }) +}) + +test('string({minLength, maxLength}) adds these properties', function (t) { + const schema = ms.string({minLength: 3, maxLength: 50}) + + assert.deepEqual(schema, { + type: 'string', + minLength: 3, + maxLength: 50 + }) +}) + test('number() creates a type number', function (t) { const schema = ms.number() assert.deepEqual(schema, {type: 'number'})