From 5c63542a169e0620b94b33e00fd2aa33f24fabb4 Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 5 Jul 2018 17:03:10 +0200 Subject: [PATCH 1/4] feat: add method ms.const() --- README.md | 13 +++++++++++++ index.js | 8 ++++++++ test.js | 8 ++++++++ 3 files changed, 29 insertions(+) diff --git a/README.md b/README.md index 551f884..6e60bda 100644 --- a/README.md +++ b/README.md @@ -203,3 +203,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..289c8d9 100644 --- a/index.js +++ b/index.js @@ -87,6 +87,14 @@ 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' diff --git a/test.js b/test.js index 421fc6c..7c7ce9f 100644 --- a/test.js +++ b/test.js @@ -60,6 +60,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') From dbb2f2f0aae787cec612be8b2ee33253041a93eb Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 5 Jul 2018 17:07:56 +0200 Subject: [PATCH 2/4] feat(arrayOf): allow to add additional properties --- README.md | 12 ++++++++++++ index.js | 11 ++++++++--- test.js | 17 +++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6e60bda..723c3e6 100644 --- a/README.md +++ b/README.md @@ -191,6 +191,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 diff --git a/index.js b/index.js index 289c8d9..4229a31 100644 --- a/index.js +++ b/index.js @@ -101,13 +101,18 @@ module.exports = { // 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} = {}) { diff --git a/test.js b/test.js index 7c7ce9f..7ad15b2 100644 --- a/test.js +++ b/test.js @@ -77,6 +77,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'}) From 97bd2e6b860bf0817ccb86137068988dabd4cd28 Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 5 Jul 2018 17:11:18 +0200 Subject: [PATCH 3/4] feat(string): allow to add additional properties --- README.md | 24 ++++++++++++++++++++++++ index.js | 7 ++++++- test.js | 20 ++++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 723c3e6..0fa283c 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({ diff --git a/index.js b/index.js index 4229a31..d639728 100644 --- a/index.js +++ b/index.js @@ -115,7 +115,7 @@ module.exports = { return s }, - string ({pattern} = {}) { + string ({pattern, format, minLength, maxLength} = {}) { const s = {type: 'string'} if (pattern) { if (pattern instanceof RegExp) { @@ -127,6 +127,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) }, diff --git a/test.js b/test.js index 7ad15b2..94a9ecd 100644 --- a/test.js +++ b/test.js @@ -149,6 +149,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'}) From 145e93109ea32cd143e1c1da274b1c7e8f9c4410 Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 5 Jul 2018 17:53:49 +0200 Subject: [PATCH 4/4] feat(obj): allow to add additional properties --- README.md | 16 ++++++++++++++++ index.js | 14 +++++++++++++- test.js | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0fa283c..b97bf42 100644 --- a/README.md +++ b/README.md @@ -204,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 diff --git a/index.js b/index.js index d639728..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") @@ -196,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 94a9ecd..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'})