Add to-json-schema types (#40959)

This commit is contained in:
Emily Marigold Klassen
2019-12-19 22:52:37 -08:00
committed by Daniel Rosenwasser
parent 9ed34fd14f
commit 8be221da22
4 changed files with 493 additions and 0 deletions

223
types/to-json-schema/index.d.ts vendored Normal file
View File

@@ -0,0 +1,223 @@
// Type definitions for to-json-schema 0.2
// Project: https://github.com/ruzicka/to-json-schema#readme
// Definitions by: Emily Marigold Klassen <https://github.com/forivall>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
import { JSONSchema4, JSONSchema4TypeName } from 'json-schema';
export = toJsonSchema;
/**
* `to-json-schema` exports function that converts most javascript values to
* JSON schema. Such a schema can be used to further validation of similar
* objects/values
*
* @param value Any javascript value
* @param options optional options object
*/
declare function toJsonSchema(
value: any,
options?: toJsonSchema.Options
): toJsonSchema.JSONSchema3or4;
declare namespace toJsonSchema {
interface JSONSchema3or4 {
id?: JSONSchema4['id'];
$ref?: JSONSchema4['$ref'];
$schema?: JSONSchema4['$schema'];
title?: JSONSchema4['title'];
description?: JSONSchema4['description'];
default?: JSONSchema4['default'];
multipleOf?: JSONSchema4['multipleOf'];
/** JSON Schema 3 uses `divisibleBy` instead of `multipleOf`. */
divisibleBy?: JSONSchema4['multipleOf'];
maximum?: JSONSchema4['maximum'];
exclusiveMaximum?: JSONSchema4['exclusiveMaximum'];
minimum?: JSONSchema4['minimum'];
exclusiveMinimum?: JSONSchema4['exclusiveMinimum'];
maxLength?: JSONSchema4['maxLength'];
minLength?: JSONSchema4['minLength'];
pattern?: JSONSchema4['pattern'];
additionalItems?: boolean | JSONSchema3or4;
items?: JSONSchema3or4 | JSONSchema3or4[];
maxItems?: JSONSchema4['maxItems'];
minItems?: JSONSchema4['minItems'];
uniqueItems?: JSONSchema4['uniqueItems'];
maxProperties?: JSONSchema4['maxProperties'];
minProperties?: JSONSchema4['minProperties'];
required?: boolean | JSONSchema4['required'];
additionalProperties?: boolean | JSONSchema3or4;
definitions?: JSONSchema4['definitions'];
properties?: {
[k: string]: JSONSchema3or4
};
patternProperties?: {
[k: string]: JSONSchema3or4
};
dependencies?: {
[k: string]: JSONSchema3or4 | string | string[]
};
enum?: JSONSchema4['enum'];
type?: JSONSchema4['type'];
allOf?: JSONSchema4['allOf'];
anyOf?: JSONSchema4['anyOf'];
oneOf?: JSONSchema4['oneOf'];
not?: JSONSchema4['not'];
/** JSON Schema 3 only */
disallow?: string | Array<string | JSONSchema3or4>;
extends?: JSONSchema3or4 | JSONSchema3or4[];
[k: string]: any;
format?: string;
}
interface Options {
/**
* specify `true` to make all properties required.
*
* @default false
* @example
* const schema = toJsonSchema(33, {required: false});
* // { type: "integer" }
* const schema = toJsonSchema(33, {required: true});
* // { type: "integer", "required": true }
*/
required?: boolean;
/**
* By providing `postProcessFnc`, you can modify or replace generated
* schema. This function will be called recursively for all the properties
* and sub-properties and array items from leaves to the root. If you want
* to preserve default functionality, don't forget to call defaultFunc
* which is currently responsible for setting `required` for the schema
* items if there is common option `required` set to true.
*
* @param type JSON schema type of the `value`
* @param schema Generated JSON schema
* @param value - input value
* @param defaultFunc standard function that is used to post-process
* generated schema. Takes the `type`, `schema`,
* `value` params.
*/
postProcessFnc?(
type: JSONSchema4TypeName,
schema: JSONSchema3or4,
value: any,
defaultFunc: (
type: JSONSchema4TypeName,
schema: JSONSchema3or4,
value: any
) => JSONSchema3or4
): JSONSchema3or4;
arrays?: {
/**
* * `all` option causes parser to go through all array items, finding
* the most compatible yet most descriptive schema possible. If
* multiple types are found, the type is omitted so it can be
* validated.
* * `first` option takes only first item in the array into account. If
* performance is a concern, you may consider this option.
* * `uniform` option requires all items in array to have same structure
* (to convert to the same schema). If not, error is thrown.
* * `tuple` option generates a
* [tuple array](https://json-schema.org/understanding-json-schema/reference/array.html#tuple-validation)
* (array of objects) from arrays.
*
* @default 'all'
*/
mode?: 'all' | 'first' | 'uniform' | 'tuple';
};
objects?: {
/**
* By providing custom function you will be able to modify any object
* value (including nested ones) and pre-process it before it gets
* converted into schema or modify generated schema or do the schema
* conversion entirely by yourself.
*
* @param obj input object value that is supposed to be converted into
* JSON schema
* @param defaultFunc standard function that is used to generate schema
* from object. Takes just the `obj` param.
*/
preProcessFnc?(
obj: any,
defaultFunc: (obj: any) => JSONSchema3or4
): JSONSchema3or4;
/**
* By providing `postProcessFnc`, you can modify or replace generated
* schema. This function will be called recursively for all the
* properties and sub-properties and array items from leaves to the root
* of the `obj` object.
*
* @param schema Generated JSON schema
* @param obj input value
* @param defaultFunc standard function that is used to post-process
* generated schema. Takes the `schema`, `obj`
* params.
*/
postProcessFnc?(
schema: JSONSchema3or4,
obj: any,
defaultFnc: (schema: JSONSchema3or4, obj: any) => JSONSchema3or4
): JSONSchema3or4;
/**
* if set to `false`, all object schemas will include JSON schema
* property `additionalProperties: false` which makes generated schema
* to perevent any extra properties.
*
* @default true
*/
additionalProperties?: boolean;
};
strings?: {
/**
* By providing custom function you will be able to modify any string
* value (including nested ones) and pre-process it before it gets
* converted to schema, modify generated schema or do the schema
* conversion entirely by yourself.
*
* @param value `string` to be converted into JSON schema
* @param defaultFnc default function that normally generates the
* schema. This function receives only `string` to be
* converted to JSON schema
*/
preProcessFnc?(
value: string,
defaultFnc: (value: string) => JSONSchema3or4
): JSONSchema3or4;
/**
* When set to true format of the strings values may be detected based
* on it's content.
*
* These JSON schema string formats can be detected:
*
* * date-time
* * date
* * time
* * utc-millisec
* * color
* * style
* * phone
* * uri
* * email
* * ip-address
* * ipv6
*
* @default true
*/
detectFormat?: boolean;
};
}
}

View File

@@ -0,0 +1,246 @@
import toJsonSchema = require('to-json-schema');
{
const objToBeConverted = {
name: 'David',
rank: 7,
born: '1990-04-05T15:09:56.704Z',
luckyNumbers: [7, 77, 5],
};
// $ExpectType JSONSchema3or4
toJsonSchema(objToBeConverted);
}
{
// $ExpectType JSONSchema3or4
toJsonSchema(33, { required: false });
/*
{
"type": "integer"
}
*/
}
{
// $ExpectType JSONSchema3or4
toJsonSchema(33, { required: true });
/*
{
"type": "integer",
"required": true
}
*/
const options: toJsonSchema.Options = {
postProcessFnc: (type, schema, value, defaultFunc) =>
type === 'integer' ? { ...schema, required: true } : defaultFunc(type, schema, value),
};
const instance = {
a: 1,
b: 'str',
};
// $ExpectType JSONSchema3or4
toJsonSchema(instance, options);
/*
{
type: 'object',
properties: {
a: {type: 'integer', required: true},
b: {type: 'string'},
},
}
*/
}
{
const arr = [33, 44, 55];
// $ExpectType JSONSchema3or4
toJsonSchema(arr, { arrays: { mode: 'all' } });
/*
{
"type": "array",
"items": {
"type": "integer"
}
}
*/
}
{
const arr = [33, 'str', 55];
// $ExpectType JSONSchema3or4
toJsonSchema(arr, { arrays: { mode: 'all' } });
/*
{
"type": "array"
}
*/
}
{
const arr = [{ name: 'john', grades: [1, 2, 3] }, { name: 'david', grades: ['a', 'b', 'c'] }];
// $ExpectType JSONSchema3or4
toJsonSchema(arr, { arrays: { mode: 'all' } });
/*
{
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"grades": {
"type": "array" // due to incompatible array items' types, `items` field is omitted
}
}
}
*/
}
{
const arr = ['str', 11, 30];
// $ExpectType JSONSchema3or4
toJsonSchema(arr, { arrays: { mode: 'first' } });
/* Other than first array item is ignored
{
"type": "array",
"items": {
"type": "string"
}
}
}
*/
}
{
const arr = ['str', 11, 30];
// $ExpectType JSONSchema3or4
toJsonSchema(arr, { arrays: { mode: 'uniform' } });
/*
Above code will throw 'Error: Invalid schema, incompatible array items'
*/
}
{
const arr = ['str', 11, 30];
// $ExpectType JSONSchema3or4
toJsonSchema(arr, { arrays: { mode: 'tuple' } });
/*
{
"type": "array",
"items": [
{
"type": "string"
},
{
"type": "integer"
},
{
"type": "integer"
}
]
}
*/
}
{
const options: toJsonSchema.Options = {
objects: { additionalProperties: false },
};
const obj = {
a: {
c: 1,
d: 1,
},
b: 'str',
};
// $ExpectType JSONSchema3or4
toJsonSchema(obj, options);
/*
{
type: 'object',
properties: {
a: {
type: 'object',
properties: {
c: {type: 'integer'},
d: {type: 'integer'},
},
additionalProperties: false,
},
b: {type: 'string'},
},
additionalProperties: false,
}
*/
}
{
const options: toJsonSchema.Options = {
objects: {
preProcessFnc: (obj, defaultFnc) => defaultFnc({ a: obj.a, b: obj.b }),
},
};
const obj = { a: 1, b: 2, c: 3 };
// $ExpectType JSONSchema3or4
toJsonSchema(obj, options);
/*
{
"type": "object",
"properties": {
"a": {
"type": "integer"
},
"b": {
"type": "integer",
}
}
}
*/
}
{
const options: toJsonSchema.Options = {
objects: {
postProcessFnc: (schema, obj, defaultFnc) => ({
...defaultFnc(schema, obj),
required: Object.getOwnPropertyNames(obj),
}),
},
};
const obj = { a: 1, b: 'str' };
// $ExpectType JSONSchema3or4
toJsonSchema(obj, options);
/*
{
type: 'object',
properties: {
a: {type: 'integer'},
b: {type: 'string'},
}
required: ['a', 'b']
}
*/
}
{
const options: toJsonSchema.Options = {
strings: {
preProcessFnc: (value, defaultFnc) => {
const schema = defaultFnc(value);
if (value === 'date') {
schema.format = 'date';
}
return schema;
},
},
};
// $ExpectType JSONSchema3or4
toJsonSchema('date', options);
/*
{
"type": "string",
"format": "date"
}
*/
}
{
const obj = {
a: '2012-07-08T16:41:41.532Z',
b: '+31 42 123 4567',
c: 'http://www.google.com/',
d: 'obama@whitehouse.gov',
};
// $ExpectType JSONSchema3or4
toJsonSchema(obj, { strings: { detectFormat: true } });
}

View File

@@ -0,0 +1,23 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.d.ts",
"to-json-schema-tests.ts"
]
}

View File

@@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }