graphql-2-json-schema
Advanced tools
Comparing version 0.3.1-0 to 0.3.1
@@ -5,2 +5,4 @@ # Changelog | ||
### [0.3.1](https://github.com/wittydeveloper/graphql-to-json-schema/compare/v0.3.1-0...v0.3.1) (2021-01-21) | ||
### [0.3.1-0](https://github.com/wittydeveloper/graphql-to-json-schema/compare/v0.3.0...v0.3.1-0) (2021-01-19) | ||
@@ -7,0 +9,0 @@ |
@@ -13,2 +13,3 @@ "use strict"; | ||
if (rootMutationType) { | ||
; | ||
introspection.__schema.types.Mutation = rootMutationType; | ||
@@ -21,2 +22,3 @@ introspection.__schema.types.Mutation.name = 'Mutation'; | ||
if (rootQueryType) { | ||
; | ||
introspection.__schema.types.Query = rootQueryType; | ||
@@ -26,3 +28,6 @@ introspection.__schema.types.Query.name = 'Query'; | ||
} | ||
var _b = lodash_1.partition(introspection.__schema.types, function (type) { return typeGuards_1.isIntrospectionObjectType(type) && lodash_1.includes(['Query', 'Mutation'], type.name); }), properties = _b[0], definitions = _b[1]; | ||
var _b = lodash_1.partition(introspection.__schema.types, function (type) { | ||
return typeGuards_1.isIntrospectionObjectType(type) && | ||
lodash_1.includes(['Query', 'Mutation'], type.name); | ||
}), properties = _b[0], definitions = _b[1]; | ||
return { | ||
@@ -29,0 +34,0 @@ $schema: 'http://json-schema.org/draft-06/schema#', |
@@ -7,18 +7,20 @@ "use strict"; | ||
var typesMapping_1 = require("./typesMapping"); | ||
var getRequiredFields = function (fields) { return lodash_1.map(lodash_1.filter(fields, function (f) { | ||
return typeGuards_1.isIntrospectionListTypeRef(f.type) ? | ||
typeGuards_1.isNonNullIntrospectionType(f.type.ofType) : | ||
typeGuards_1.isNonNullIntrospectionType(f.type); | ||
}), function (f) { return f.name; }); }; | ||
var getRequiredFields = function (fields) { | ||
return lodash_1.map(lodash_1.filter(fields, function (f) { | ||
return typeGuards_1.isIntrospectionListTypeRef(f.type) | ||
? typeGuards_1.isNonNullIntrospectionType(f.type.ofType) | ||
: typeGuards_1.isNonNullIntrospectionType(f.type); | ||
}), function (f) { return f.name; }); | ||
}; | ||
exports.getRequiredFields = getRequiredFields; | ||
var propertiesIntrospectionFieldReducer = function (acc, curr) { | ||
if (typeGuards_1.isIntrospectionField(curr)) { | ||
var returnType = typeGuards_1.isNonNullIntrospectionType(curr.type) ? | ||
typesMapping_1.graphqlToJSONType(curr.type.ofType) : | ||
typesMapping_1.graphqlToJSONType(curr.type); | ||
var returnType = typeGuards_1.isNonNullIntrospectionType(curr.type) | ||
? typesMapping_1.graphqlToJSONType(curr.type.ofType) | ||
: typesMapping_1.graphqlToJSONType(curr.type); | ||
acc[curr.name] = { | ||
type: 'object', | ||
properties: { | ||
'return': returnType, | ||
'arguments': { | ||
"return": returnType, | ||
arguments: { | ||
type: 'object', | ||
@@ -33,5 +35,5 @@ properties: lodash_1.reduce(curr.args, exports.propertiesIntrospectionFieldReducer, {}), | ||
else if (typeGuards_1.isIntrospectionInputValue(curr)) { | ||
var returnType = typeGuards_1.isNonNullIntrospectionType(curr.type) ? | ||
typesMapping_1.graphqlToJSONType(curr.type.ofType) : | ||
typesMapping_1.graphqlToJSONType(curr.type); | ||
var returnType = typeGuards_1.isNonNullIntrospectionType(curr.type) | ||
? typesMapping_1.graphqlToJSONType(curr.type.ofType) | ||
: typesMapping_1.graphqlToJSONType(curr.type); | ||
acc[curr.name] = returnType; | ||
@@ -48,11 +50,11 @@ if (curr.defaultValue) { | ||
if (typeGuards_1.isIntrospectionField(curr)) { | ||
var returnType = typeGuards_1.isNonNullIntrospectionType(curr.type) ? | ||
typesMapping_1.graphqlToJSONType(curr.type.ofType) : | ||
typesMapping_1.graphqlToJSONType(curr.type); | ||
var returnType = typeGuards_1.isNonNullIntrospectionType(curr.type) | ||
? typesMapping_1.graphqlToJSONType(curr.type.ofType) | ||
: typesMapping_1.graphqlToJSONType(curr.type); | ||
acc[curr.name] = returnType; | ||
} | ||
else if (typeGuards_1.isIntrospectionInputValue(curr)) { | ||
var returnType = typeGuards_1.isNonNullIntrospectionType(curr.type) ? | ||
typesMapping_1.graphqlToJSONType(curr.type.ofType) : | ||
typesMapping_1.graphqlToJSONType(curr.type); | ||
var returnType = typeGuards_1.isNonNullIntrospectionType(curr.type) | ||
? typesMapping_1.graphqlToJSONType(curr.type.ofType) | ||
: typesMapping_1.graphqlToJSONType(curr.type); | ||
acc[curr.name] = returnType; | ||
@@ -68,11 +70,11 @@ if (curr.defaultValue) { | ||
var resolveDefaultValue = function (curr) { | ||
return typeGuards_1.isIntrospectionEnumType(curr.type) ? | ||
curr.defaultValue : | ||
JSON.parse(curr.defaultValue); | ||
return typeGuards_1.isIntrospectionEnumType(curr.type) | ||
? curr.defaultValue | ||
: JSON.parse(curr.defaultValue); | ||
}; | ||
exports.resolveDefaultValue = resolveDefaultValue; | ||
var introspectionTypeReducer = function (type) { return function (acc, curr) { | ||
var fieldReducer = type === 'definitions' ? | ||
exports.definitionsIntrospectionFieldReducer : | ||
exports.propertiesIntrospectionFieldReducer; | ||
var fieldReducer = type === 'definitions' | ||
? exports.definitionsIntrospectionFieldReducer | ||
: exports.propertiesIntrospectionFieldReducer; | ||
if (typeGuards_1.isIntrospectionObjectType(curr)) { | ||
@@ -97,5 +99,3 @@ acc[curr.name] = { | ||
return { | ||
"enum": [ | ||
item.name, | ||
], | ||
"enum": [item.name], | ||
title: item.description || item.name, | ||
@@ -102,0 +102,0 @@ description: item.description || undefined |
@@ -5,32 +5,33 @@ "use strict"; | ||
var lodash_1 = require("lodash"); | ||
var isIntrospectionField = function (type) { | ||
return lodash_1.has(type, 'args'); | ||
}; | ||
var isIntrospectionField = function (type) { return lodash_1.has(type, 'args'); }; | ||
exports.isIntrospectionField = isIntrospectionField; | ||
var isIntrospectionInputValue = function (type) { | ||
return lodash_1.has(type, 'defaultValue'); | ||
}; | ||
var isIntrospectionInputValue = function (type) { return lodash_1.has(type, 'defaultValue'); }; | ||
exports.isIntrospectionInputValue = isIntrospectionInputValue; | ||
var isIntrospectionListTypeRef = function (type) { return (type.kind === 'LIST'); }; | ||
var isIntrospectionListTypeRef = function (type) { return type.kind === 'LIST'; }; | ||
exports.isIntrospectionListTypeRef = isIntrospectionListTypeRef; | ||
var isIntrospectionObjectType = function (type) { return (type.kind === 'OBJECT'); }; | ||
var isIntrospectionObjectType = function (type) { return type.kind === 'OBJECT'; }; | ||
exports.isIntrospectionObjectType = isIntrospectionObjectType; | ||
var isIntrospectionInputObjectType = function (type) { return (type.kind === 'INPUT_OBJECT'); }; | ||
var isIntrospectionInputObjectType = function (type) { return type.kind === 'INPUT_OBJECT'; }; | ||
exports.isIntrospectionInputObjectType = isIntrospectionInputObjectType; | ||
var isIntrospectionEnumType = function (type) { return (type.kind === 'ENUM'); }; | ||
var isIntrospectionEnumType = function (type) { return type.kind === 'ENUM'; }; | ||
exports.isIntrospectionEnumType = isIntrospectionEnumType; | ||
var isNonNullIntrospectionType = function (type) { return (type.kind === 'NON_NULL'); }; | ||
var isNonNullIntrospectionType = function (type) { return type.kind === 'NON_NULL'; }; | ||
exports.isNonNullIntrospectionType = isNonNullIntrospectionType; | ||
var isIntrospectionScalarType = function (type) { return (type.kind === 'SCALAR'); }; | ||
var isIntrospectionScalarType = function (type) { return type.kind === 'SCALAR'; }; | ||
exports.isIntrospectionScalarType = isIntrospectionScalarType; | ||
var isIntrospectionDefaultScalarType = function (type) { return (type.kind === 'SCALAR' && lodash_1.includes(['Boolean', 'String', 'Int', 'Float'], type.name)); }; | ||
var isIntrospectionDefaultScalarType = function (type) { | ||
return type.kind === 'SCALAR' && | ||
lodash_1.includes(['Boolean', 'String', 'Int', 'Float'], type.name); | ||
}; | ||
exports.isIntrospectionDefaultScalarType = isIntrospectionDefaultScalarType; | ||
var filterDefinitionsTypes = function (types, opts) { | ||
var ignoreInternals = opts && opts.ignoreInternals; | ||
return lodash_1.filter(types, function (type) { return ((exports.isIntrospectionObjectType(type) && !!type.fields) || | ||
(exports.isIntrospectionInputObjectType(type) && !!type.inputFields) || | ||
(exports.isIntrospectionEnumType(type) && !!type.enumValues) || | ||
(exports.isIntrospectionScalarType(type) && !!type.name)) && | ||
(!ignoreInternals || (ignoreInternals && !lodash_1.startsWith(type.name, '__'))); }); | ||
return lodash_1.filter(types, function (type) { | ||
return ((exports.isIntrospectionObjectType(type) && !!type.fields) || | ||
(exports.isIntrospectionInputObjectType(type) && !!type.inputFields) || | ||
(exports.isIntrospectionEnumType(type) && !!type.enumValues) || | ||
(exports.isIntrospectionScalarType(type) && !!type.name)) && | ||
(!ignoreInternals || (ignoreInternals && !lodash_1.startsWith(type.name, '__'))); | ||
}); | ||
}; | ||
exports.filterDefinitionsTypes = filterDefinitionsTypes; |
@@ -7,6 +7,6 @@ "use strict"; | ||
exports.typesMapping = { | ||
'Boolean': 'boolean', | ||
'String': 'string', | ||
'Int': 'number', | ||
'Float': 'number' | ||
Boolean: 'boolean', | ||
String: 'string', | ||
Int: 'number', | ||
Float: 'number' | ||
}; | ||
@@ -25,11 +25,10 @@ var graphqlToJSONType = function (k) { | ||
var name_1 = k.name; | ||
return lodash_1.includes(['OBJECT', 'INPUT_OBJECT', 'ENUM', 'SCALAR'], k.kind) ? | ||
lodash_1.includes(['OBJECT', 'INPUT_OBJECT', 'ENUM'], k.kind) ? | ||
{ $ref: "#/definitions/" + name_1 } : | ||
{ $ref: "#/definitions/" + name_1, | ||
type: exports.typesMapping[name_1] | ||
} : | ||
{ type: exports.typesMapping[name_1] }; | ||
return lodash_1.includes(['OBJECT', 'INPUT_OBJECT', 'ENUM', 'SCALAR'], k.kind) | ||
? lodash_1.includes(['OBJECT', 'INPUT_OBJECT', 'ENUM'], k.kind) | ||
? { $ref: "#/definitions/" + name_1 } | ||
: | ||
{ $ref: "#/definitions/" + name_1, type: exports.typesMapping[name_1] } | ||
: { type: exports.typesMapping[name_1] }; | ||
} | ||
}; | ||
exports.graphqlToJSONType = graphqlToJSONType; |
@@ -26,3 +26,3 @@ "use strict"; | ||
properties: { | ||
id: { type: 'string', description: "todo identifier" }, | ||
id: { type: 'string', description: 'todo identifier' }, | ||
isCompleted: { type: 'boolean', "default": false } | ||
@@ -96,7 +96,7 @@ }, | ||
definitions: { | ||
'Todo': { | ||
Todo: { | ||
type: 'object', | ||
description: "A ToDo Object", | ||
description: 'A ToDo Object', | ||
properties: { | ||
id: { type: 'string', description: "A unique identifier" }, | ||
id: { type: 'string', description: 'A unique identifier' }, | ||
name: { type: 'string' }, | ||
@@ -106,3 +106,3 @@ completed: { type: 'boolean' }, | ||
colors: { | ||
description: "A list containing colors that cannot contain nulls", | ||
description: 'A list containing colors that cannot contain nulls', | ||
type: 'array', | ||
@@ -114,3 +114,3 @@ items: { $ref: '#/definitions/Color' } | ||
}, | ||
'Color': { | ||
Color: { | ||
type: 'string', | ||
@@ -127,6 +127,6 @@ anyOf: [ | ||
description: 'Green color' | ||
} | ||
}, | ||
] | ||
}, | ||
'TodoInputType': { | ||
TodoInputType: { | ||
type: 'object', | ||
@@ -133,0 +133,0 @@ description: 'A type that describes ToDoInputType. Its description might not\nfit within the bounds of 80 width and so you want MULTILINE', |
@@ -1,2 +0,2 @@ | ||
export * from './lib/fromIntrospectionQuery'; | ||
export * from './lib/fromIntrospectionQuery' | ||
// export * from './fromGraphQLSchema'; |
@@ -1,7 +0,7 @@ | ||
import { GraphQLSchema } from 'graphql'; | ||
import { JSONSchema6 } from 'json-schema'; | ||
import { GraphQLSchema } from 'graphql' | ||
import { JSONSchema6 } from 'json-schema' | ||
export const fromIntrospectionQuery = (schema: GraphQLSchema): JSONSchema6 => { | ||
// TODO: implement. | ||
return {}; | ||
}; | ||
// TODO: implement. | ||
return {} | ||
} |
@@ -1,58 +0,68 @@ | ||
import { IntrospectionQuery, IntrospectionType } from 'graphql'; | ||
import { JSONSchema6 } from 'json-schema'; | ||
import { includes, partition, reduce } from 'lodash'; | ||
import { introspectionTypeReducer, JSONSchema6Acc } from './reducer'; | ||
import { filterDefinitionsTypes, isIntrospectionObjectType } from './typeGuards'; | ||
import { IntrospectionQuery, IntrospectionType } from 'graphql' | ||
import { JSONSchema6 } from 'json-schema' | ||
import { includes, partition, reduce } from 'lodash' | ||
import { introspectionTypeReducer, JSONSchema6Acc } from './reducer' | ||
import { filterDefinitionsTypes, isIntrospectionObjectType } from './typeGuards' | ||
// FIXME: finish this type | ||
export interface GraphQLJSONSchema6 extends JSONSchema6 { | ||
properties: { | ||
Query: JSONSchema6Acc; | ||
Mutation: JSONSchema6Acc; | ||
}; | ||
definitions: JSONSchema6Acc; | ||
properties: { | ||
Query: JSONSchema6Acc | ||
Mutation: JSONSchema6Acc | ||
} | ||
definitions: JSONSchema6Acc | ||
} | ||
export interface FromIntrospectionQueryOptions { | ||
ignoreInternals?: boolean; // true by default | ||
ignoreInternals?: boolean // true by default | ||
} | ||
export const fromIntrospectionQuery = ( | ||
introspection: IntrospectionQuery, | ||
opts?: FromIntrospectionQueryOptions | ||
introspection: IntrospectionQuery, | ||
opts?: FromIntrospectionQueryOptions | ||
): JSONSchema6 => { | ||
const options = opts || { ignoreInternals: true }; | ||
const { queryType, mutationType } = introspection.__schema; | ||
const options = opts || { ignoreInternals: true } | ||
const { queryType, mutationType } = introspection.__schema | ||
if (mutationType) { | ||
const rootMutationType = (introspection.__schema.types as any).find( (t: any) => t.name == mutationType.name); | ||
if (rootMutationType) { | ||
(introspection.__schema.types as any).Mutation = rootMutationType; | ||
(introspection.__schema.types as any).Mutation.name = 'Mutation'; | ||
} | ||
if (mutationType) { | ||
const rootMutationType = (introspection.__schema.types as any).find( | ||
(t: any) => t.name == mutationType.name | ||
) | ||
if (rootMutationType) { | ||
;(introspection.__schema.types as any).Mutation = rootMutationType | ||
;(introspection.__schema.types as any).Mutation.name = 'Mutation' | ||
} | ||
} | ||
if (queryType) { | ||
const rootQueryType = (introspection.__schema.types as any).find( (t: any) => t.name == queryType.name); | ||
if (rootQueryType) { | ||
(introspection.__schema.types as any).Query = rootQueryType; | ||
(introspection.__schema.types as any).Query.name = 'Query'; | ||
} | ||
if (queryType) { | ||
const rootQueryType = (introspection.__schema.types as any).find( | ||
(t: any) => t.name == queryType.name | ||
) | ||
if (rootQueryType) { | ||
;(introspection.__schema.types as any).Query = rootQueryType | ||
;(introspection.__schema.types as any).Query.name = 'Query' | ||
} | ||
////////////////////////////////////////////////////////////////////// | ||
//// Query and Mutation are properties, custom Types are definitions | ||
////////////////////////////////////////////////////////////////////// | ||
const [properties, definitions] = partition( | ||
introspection.__schema.types, | ||
type => isIntrospectionObjectType(type) && includes(['Query', 'Mutation'], type.name) | ||
); | ||
} | ||
////////////////////////////////////////////////////////////////////// | ||
//// Query and Mutation are properties, custom Types are definitions | ||
////////////////////////////////////////////////////////////////////// | ||
const [properties, definitions] = partition( | ||
introspection.__schema.types, | ||
(type) => | ||
isIntrospectionObjectType(type) && | ||
includes(['Query', 'Mutation'], type.name) | ||
) | ||
return { | ||
$schema: 'http://json-schema.org/draft-06/schema#', | ||
properties: reduce<IntrospectionType, JSONSchema6Acc>( | ||
properties, introspectionTypeReducer('properties'), {} | ||
), | ||
definitions: reduce<IntrospectionType, JSONSchema6Acc>( | ||
filterDefinitionsTypes(definitions, options), introspectionTypeReducer('definitions'), {} | ||
) | ||
}; | ||
}; | ||
return { | ||
$schema: 'http://json-schema.org/draft-06/schema#', | ||
properties: reduce<IntrospectionType, JSONSchema6Acc>( | ||
properties, | ||
introspectionTypeReducer('properties'), | ||
{} | ||
), | ||
definitions: reduce<IntrospectionType, JSONSchema6Acc>( | ||
filterDefinitionsTypes(definitions, options), | ||
introspectionTypeReducer('definitions'), | ||
{} | ||
), | ||
} | ||
} |
@@ -1,103 +0,115 @@ | ||
import { IntrospectionField, IntrospectionInputValue, IntrospectionScalarType, IntrospectionType } from 'graphql'; | ||
import { JSONSchema6 } from 'json-schema'; | ||
import { filter, map, MemoListIterator, reduce } from 'lodash'; | ||
import { | ||
isIntrospectionEnumType, | ||
isIntrospectionField, | ||
isIntrospectionInputObjectType, | ||
isIntrospectionInputValue, | ||
isIntrospectionListTypeRef, | ||
isIntrospectionObjectType, | ||
isNonNullIntrospectionType, | ||
isIntrospectionScalarType, | ||
isIntrospectionDefaultScalarType | ||
} from './typeGuards'; | ||
import { graphqlToJSONType, typesMapping } from './typesMapping'; | ||
IntrospectionField, | ||
IntrospectionInputValue, | ||
IntrospectionScalarType, | ||
IntrospectionType, | ||
} from 'graphql' | ||
import { JSONSchema6 } from 'json-schema' | ||
import { filter, map, MemoListIterator, reduce } from 'lodash' | ||
import { | ||
isIntrospectionEnumType, | ||
isIntrospectionField, | ||
isIntrospectionInputObjectType, | ||
isIntrospectionInputValue, | ||
isIntrospectionListTypeRef, | ||
isIntrospectionObjectType, | ||
isNonNullIntrospectionType, | ||
isIntrospectionScalarType, | ||
isIntrospectionDefaultScalarType, | ||
} from './typeGuards' | ||
import { graphqlToJSONType, typesMapping } from './typesMapping' | ||
export type JSONSchema6Acc = { | ||
[k: string]: JSONSchema6; | ||
}; | ||
[k: string]: JSONSchema6 | ||
} | ||
type GetRequiredFieldsType = ReadonlyArray<IntrospectionInputValue | IntrospectionField>; | ||
type GetRequiredFieldsType = ReadonlyArray< | ||
IntrospectionInputValue | IntrospectionField | ||
> | ||
// Extract GraphQL no-nullable types | ||
export const getRequiredFields = (fields: GetRequiredFieldsType) => map( | ||
filter( | ||
fields, | ||
f => { | ||
// Not 100% sure if the GraphQL spec requires that NON_NULL should be | ||
// the parent of LIST if it's both a NON_NULL and LIST field, but this | ||
// should handle either case/implementation | ||
return isIntrospectionListTypeRef(f.type) ? | ||
isNonNullIntrospectionType(f.type.ofType) : | ||
isNonNullIntrospectionType(f.type); | ||
} | ||
), | ||
f => f.name | ||
); | ||
export const getRequiredFields = (fields: GetRequiredFieldsType) => | ||
map( | ||
filter(fields, (f) => { | ||
// Not 100% sure if the GraphQL spec requires that NON_NULL should be | ||
// the parent of LIST if it's both a NON_NULL and LIST field, but this | ||
// should handle either case/implementation | ||
return isIntrospectionListTypeRef(f.type) | ||
? isNonNullIntrospectionType(f.type.ofType) | ||
: isNonNullIntrospectionType(f.type) | ||
}), | ||
(f) => f.name | ||
) | ||
export type IntrospectionFieldReducerItem = IntrospectionField | IntrospectionInputValue; | ||
export type IntrospectionFieldReducerItem = | ||
| IntrospectionField | ||
| IntrospectionInputValue | ||
// reducer for a queries/mutations | ||
export const propertiesIntrospectionFieldReducer: | ||
MemoListIterator<IntrospectionFieldReducerItem, JSONSchema6Acc, ReadonlyArray<IntrospectionFieldReducerItem>> = | ||
(acc, curr: IntrospectionFieldReducerItem): JSONSchema6Acc => { | ||
if (isIntrospectionField(curr)) { | ||
const returnType = isNonNullIntrospectionType(curr.type) ? | ||
graphqlToJSONType(curr.type.ofType) : | ||
graphqlToJSONType(curr.type); | ||
export const propertiesIntrospectionFieldReducer: MemoListIterator< | ||
IntrospectionFieldReducerItem, | ||
JSONSchema6Acc, | ||
ReadonlyArray<IntrospectionFieldReducerItem> | ||
> = (acc, curr: IntrospectionFieldReducerItem): JSONSchema6Acc => { | ||
if (isIntrospectionField(curr)) { | ||
const returnType = isNonNullIntrospectionType(curr.type) | ||
? graphqlToJSONType(curr.type.ofType) | ||
: graphqlToJSONType(curr.type) | ||
acc[curr.name] = { | ||
type: 'object', | ||
properties: { | ||
'return': returnType, | ||
'arguments': { | ||
type: 'object', | ||
properties: reduce<IntrospectionFieldReducerItem, JSONSchema6Acc>( | ||
curr.args as IntrospectionFieldReducerItem[], propertiesIntrospectionFieldReducer, {} | ||
), | ||
required: getRequiredFields(curr.args) | ||
}, | ||
}, | ||
required: [] | ||
}; | ||
} else if (isIntrospectionInputValue(curr)) { | ||
const returnType = isNonNullIntrospectionType(curr.type) ? | ||
graphqlToJSONType(curr.type.ofType) : | ||
graphqlToJSONType(curr.type); | ||
acc[curr.name] = { | ||
type: 'object', | ||
properties: { | ||
return: returnType, | ||
arguments: { | ||
type: 'object', | ||
properties: reduce<IntrospectionFieldReducerItem, JSONSchema6Acc>( | ||
curr.args as IntrospectionFieldReducerItem[], | ||
propertiesIntrospectionFieldReducer, | ||
{} | ||
), | ||
required: getRequiredFields(curr.args), | ||
}, | ||
}, | ||
required: [], | ||
} | ||
} else if (isIntrospectionInputValue(curr)) { | ||
const returnType = isNonNullIntrospectionType(curr.type) | ||
? graphqlToJSONType(curr.type.ofType) | ||
: graphqlToJSONType(curr.type) | ||
acc[curr.name] = returnType; | ||
if (curr.defaultValue) { | ||
acc[curr.name].default = resolveDefaultValue(curr) | ||
} | ||
} | ||
acc[curr.name] = returnType | ||
if (curr.defaultValue) { | ||
acc[curr.name].default = resolveDefaultValue(curr) | ||
} | ||
} | ||
acc[curr.name].description = curr.description || undefined; | ||
return acc; | ||
}; | ||
acc[curr.name].description = curr.description || undefined | ||
return acc | ||
} | ||
// reducer for a custom types | ||
export const definitionsIntrospectionFieldReducer: | ||
MemoListIterator<IntrospectionFieldReducerItem, JSONSchema6Acc, ReadonlyArray<IntrospectionFieldReducerItem>> = | ||
(acc, curr: IntrospectionFieldReducerItem): JSONSchema6Acc => { | ||
if (isIntrospectionField(curr)) { | ||
const returnType = isNonNullIntrospectionType(curr.type) ? | ||
graphqlToJSONType(curr.type.ofType) : | ||
graphqlToJSONType(curr.type); | ||
export const definitionsIntrospectionFieldReducer: MemoListIterator< | ||
IntrospectionFieldReducerItem, | ||
JSONSchema6Acc, | ||
ReadonlyArray<IntrospectionFieldReducerItem> | ||
> = (acc, curr: IntrospectionFieldReducerItem): JSONSchema6Acc => { | ||
if (isIntrospectionField(curr)) { | ||
const returnType = isNonNullIntrospectionType(curr.type) | ||
? graphqlToJSONType(curr.type.ofType) | ||
: graphqlToJSONType(curr.type) | ||
acc[curr.name] = returnType; | ||
} else if (isIntrospectionInputValue(curr)) { | ||
const returnType = isNonNullIntrospectionType(curr.type) ? | ||
graphqlToJSONType(curr.type.ofType) : | ||
graphqlToJSONType(curr.type); | ||
acc[curr.name] = returnType | ||
} else if (isIntrospectionInputValue(curr)) { | ||
const returnType = isNonNullIntrospectionType(curr.type) | ||
? graphqlToJSONType(curr.type.ofType) | ||
: graphqlToJSONType(curr.type) | ||
acc[curr.name] = returnType; | ||
if (curr.defaultValue) { | ||
acc[curr.name].default = resolveDefaultValue(curr) | ||
} | ||
} | ||
acc[curr.name] = returnType | ||
if (curr.defaultValue) { | ||
acc[curr.name].default = resolveDefaultValue(curr) | ||
} | ||
} | ||
acc[curr.name].description = curr.description || undefined; | ||
return acc; | ||
}; | ||
acc[curr.name].description = curr.description || undefined | ||
return acc | ||
} | ||
@@ -108,60 +120,66 @@ // ENUM type defaults will not JSON.parse correctly, so if it is an ENUM then don't | ||
export const resolveDefaultValue = (curr: any) => { | ||
return isIntrospectionEnumType(curr.type) ? | ||
curr.defaultValue : | ||
JSON.parse(curr.defaultValue); | ||
return isIntrospectionEnumType(curr.type) | ||
? curr.defaultValue | ||
: JSON.parse(curr.defaultValue) | ||
} | ||
// Reducer for each type exposed by the GraphQL Schema | ||
export const introspectionTypeReducer: | ||
(type: 'definitions' | 'properties') => MemoListIterator<IntrospectionType, JSONSchema6Acc, IntrospectionType[]> = | ||
type => (acc, curr: IntrospectionType): JSONSchema6Acc => { | ||
const fieldReducer = type === 'definitions' ? | ||
definitionsIntrospectionFieldReducer : | ||
propertiesIntrospectionFieldReducer; | ||
export const introspectionTypeReducer: ( | ||
type: 'definitions' | 'properties' | ||
) => MemoListIterator< | ||
IntrospectionType, | ||
JSONSchema6Acc, | ||
IntrospectionType[] | ||
> = (type) => (acc, curr: IntrospectionType): JSONSchema6Acc => { | ||
const fieldReducer = | ||
type === 'definitions' | ||
? definitionsIntrospectionFieldReducer | ||
: propertiesIntrospectionFieldReducer | ||
if (isIntrospectionObjectType(curr)) { | ||
acc[curr.name] = { | ||
type: 'object', | ||
properties: reduce<IntrospectionFieldReducerItem, JSONSchema6Acc>( | ||
curr.fields as IntrospectionFieldReducerItem[], fieldReducer, {} | ||
), | ||
// ignore required for Mutations/Queries | ||
required: type === 'definitions' ? getRequiredFields(curr.fields) : [] | ||
}; | ||
} else if (isIntrospectionInputObjectType(curr)) { | ||
acc[curr.name] = { | ||
type: 'object', | ||
properties: reduce<IntrospectionFieldReducerItem, JSONSchema6Acc>( | ||
curr.inputFields as IntrospectionFieldReducerItem[], fieldReducer, {} | ||
), | ||
required: getRequiredFields(curr.inputFields) | ||
}; | ||
} else if (isIntrospectionEnumType(curr)) { | ||
acc[curr.name] = { | ||
type: 'string', | ||
anyOf: curr.enumValues.map((item) => { | ||
return { | ||
enum: [ | ||
item.name, | ||
], | ||
title: item.description || item.name, | ||
description: item.description || undefined | ||
}; | ||
}), | ||
}; | ||
} else if(isIntrospectionDefaultScalarType(curr)){ | ||
acc[curr.name] = { | ||
type: (typesMapping as any)[curr.name], | ||
title: curr.name | ||
} | ||
if (isIntrospectionObjectType(curr)) { | ||
acc[curr.name] = { | ||
type: 'object', | ||
properties: reduce<IntrospectionFieldReducerItem, JSONSchema6Acc>( | ||
curr.fields as IntrospectionFieldReducerItem[], | ||
fieldReducer, | ||
{} | ||
), | ||
// ignore required for Mutations/Queries | ||
required: type === 'definitions' ? getRequiredFields(curr.fields) : [], | ||
} | ||
} else if (isIntrospectionInputObjectType(curr)) { | ||
acc[curr.name] = { | ||
type: 'object', | ||
properties: reduce<IntrospectionFieldReducerItem, JSONSchema6Acc>( | ||
curr.inputFields as IntrospectionFieldReducerItem[], | ||
fieldReducer, | ||
{} | ||
), | ||
required: getRequiredFields(curr.inputFields), | ||
} | ||
} else if (isIntrospectionEnumType(curr)) { | ||
acc[curr.name] = { | ||
type: 'string', | ||
anyOf: curr.enumValues.map((item) => { | ||
return { | ||
enum: [item.name], | ||
title: item.description || item.name, | ||
description: item.description || undefined, | ||
} | ||
else if (isIntrospectionScalarType(curr)){ | ||
acc[(curr as IntrospectionScalarType).name] = { | ||
type: 'object', | ||
title: (curr as IntrospectionScalarType).name | ||
}; | ||
} | ||
}), | ||
} | ||
} else if (isIntrospectionDefaultScalarType(curr)) { | ||
acc[curr.name] = { | ||
type: (typesMapping as any)[curr.name], | ||
title: curr.name, | ||
} | ||
} else if (isIntrospectionScalarType(curr)) { | ||
acc[(curr as IntrospectionScalarType).name] = { | ||
type: 'object', | ||
title: (curr as IntrospectionScalarType).name, | ||
} | ||
} | ||
acc[curr.name].description = curr.description || undefined; | ||
return acc; | ||
}; | ||
acc[curr.name].description = curr.description || undefined | ||
return acc | ||
} |
import { | ||
IntrospectionEnumType, | ||
IntrospectionField, | ||
IntrospectionInputObjectType, | ||
IntrospectionInputTypeRef, | ||
IntrospectionInputValue, | ||
IntrospectionListTypeRef, | ||
IntrospectionNamedTypeRef, | ||
IntrospectionNonNullTypeRef, | ||
IntrospectionObjectType, | ||
IntrospectionOutputTypeRef, | ||
IntrospectionSchema, | ||
IntrospectionType, | ||
IntrospectionTypeRef, | ||
IntrospectionScalarType | ||
} from 'graphql'; | ||
import { filter, has, startsWith, includes } from 'lodash'; | ||
IntrospectionEnumType, | ||
IntrospectionField, | ||
IntrospectionInputObjectType, | ||
IntrospectionInputTypeRef, | ||
IntrospectionInputValue, | ||
IntrospectionListTypeRef, | ||
IntrospectionNamedTypeRef, | ||
IntrospectionNonNullTypeRef, | ||
IntrospectionObjectType, | ||
IntrospectionOutputTypeRef, | ||
IntrospectionSchema, | ||
IntrospectionType, | ||
IntrospectionTypeRef, | ||
IntrospectionScalarType, | ||
} from 'graphql' | ||
import { filter, has, startsWith, includes } from 'lodash' | ||
@@ -23,56 +23,63 @@ /////////////////// | ||
export const isIntrospectionField = (type: IntrospectionField | IntrospectionInputValue): type is IntrospectionField => | ||
has(type, 'args'); | ||
export const isIntrospectionField = ( | ||
type: IntrospectionField | IntrospectionInputValue | ||
): type is IntrospectionField => has(type, 'args') | ||
export const isIntrospectionInputValue = | ||
(type: IntrospectionField | IntrospectionInputValue): type is IntrospectionInputValue => | ||
has(type, 'defaultValue'); | ||
export const isIntrospectionInputValue = ( | ||
type: IntrospectionField | IntrospectionInputValue | ||
): type is IntrospectionInputValue => has(type, 'defaultValue') | ||
// @ts-ignore | ||
export const isIntrospectionListTypeRef = | ||
(type: IntrospectionTypeRef | IntrospectionInputTypeRef | IntrospectionOutputTypeRef): | ||
type is IntrospectionListTypeRef => ( | ||
type.kind === 'LIST' | ||
); | ||
export const isIntrospectionListTypeRef = ( | ||
type: | ||
| IntrospectionTypeRef | ||
| IntrospectionInputTypeRef | ||
| IntrospectionOutputTypeRef | ||
): type is IntrospectionListTypeRef => type.kind === 'LIST' | ||
export const isIntrospectionObjectType = (type: IntrospectionSchema['types'][0]): type is IntrospectionObjectType => ( | ||
type.kind === 'OBJECT' | ||
); | ||
export const isIntrospectionObjectType = ( | ||
type: IntrospectionSchema['types'][0] | ||
): type is IntrospectionObjectType => type.kind === 'OBJECT' | ||
export const isIntrospectionInputObjectType = | ||
(type: IntrospectionSchema['types'][0]): type is IntrospectionInputObjectType => ( | ||
type.kind === 'INPUT_OBJECT' | ||
); | ||
export const isIntrospectionInputObjectType = ( | ||
type: IntrospectionSchema['types'][0] | ||
): type is IntrospectionInputObjectType => type.kind === 'INPUT_OBJECT' | ||
export const isIntrospectionEnumType = (type: IntrospectionSchema['types'][0]): type is IntrospectionEnumType => ( | ||
type.kind === 'ENUM' | ||
); | ||
export const isIntrospectionEnumType = ( | ||
type: IntrospectionSchema['types'][0] | ||
): type is IntrospectionEnumType => type.kind === 'ENUM' | ||
export const isNonNullIntrospectionType = | ||
(type: IntrospectionTypeRef): type is IntrospectionNonNullTypeRef<IntrospectionNamedTypeRef<IntrospectionType>> => ( | ||
type.kind === 'NON_NULL' | ||
); | ||
export const isIntrospectionScalarType = (type: IntrospectionSchema['types'][0]): type is IntrospectionScalarType => ( | ||
type.kind === 'SCALAR' | ||
); | ||
export const isNonNullIntrospectionType = ( | ||
type: IntrospectionTypeRef | ||
): type is IntrospectionNonNullTypeRef< | ||
IntrospectionNamedTypeRef<IntrospectionType> | ||
> => type.kind === 'NON_NULL' | ||
export const isIntrospectionScalarType = ( | ||
type: IntrospectionSchema['types'][0] | ||
): type is IntrospectionScalarType => type.kind === 'SCALAR' | ||
export const isIntrospectionDefaultScalarType = (type: IntrospectionSchema['types'][0]): type is IntrospectionScalarType => ( | ||
type.kind === 'SCALAR' && includes(['Boolean', 'String', 'Int', 'Float'], type.name) | ||
); | ||
export const isIntrospectionDefaultScalarType = ( | ||
type: IntrospectionSchema['types'][0] | ||
): type is IntrospectionScalarType => | ||
type.kind === 'SCALAR' && | ||
includes(['Boolean', 'String', 'Int', 'Float'], type.name) | ||
// Ignore all GraphQL native Scalars, directives, etc... | ||
export interface FilterDefinitionsTypesOptions { ignoreInternals?: boolean; } | ||
export const filterDefinitionsTypes = | ||
(types: IntrospectionType[], opts?: FilterDefinitionsTypesOptions): IntrospectionType[] => { | ||
const ignoreInternals = opts && opts.ignoreInternals; | ||
return filter( | ||
types, | ||
type => ( | ||
(isIntrospectionObjectType(type) && !!type.fields) || | ||
(isIntrospectionInputObjectType(type) && !!type.inputFields) || | ||
(isIntrospectionEnumType(type) && !!type.enumValues) || | ||
(isIntrospectionScalarType(type) && !! type.name) | ||
) && | ||
(!ignoreInternals || (ignoreInternals && !startsWith(type.name, '__'))) | ||
); | ||
}; | ||
export interface FilterDefinitionsTypesOptions { | ||
ignoreInternals?: boolean | ||
} | ||
export const filterDefinitionsTypes = ( | ||
types: IntrospectionType[], | ||
opts?: FilterDefinitionsTypesOptions | ||
): IntrospectionType[] => { | ||
const ignoreInternals = opts && opts.ignoreInternals | ||
return filter( | ||
types, | ||
(type) => | ||
((isIntrospectionObjectType(type) && !!type.fields) || | ||
(isIntrospectionInputObjectType(type) && !!type.inputFields) || | ||
(isIntrospectionEnumType(type) && !!type.enumValues) || | ||
(isIntrospectionScalarType(type) && !!type.name)) && | ||
(!ignoreInternals || (ignoreInternals && !startsWith(type.name, '__'))) | ||
) | ||
} |
import { | ||
IntrospectionInputType, | ||
IntrospectionInputTypeRef, | ||
IntrospectionNamedTypeRef, | ||
IntrospectionOutputType, | ||
IntrospectionOutputTypeRef, | ||
IntrospectionTypeRef, | ||
} from 'graphql'; | ||
IntrospectionInputType, | ||
IntrospectionInputTypeRef, | ||
IntrospectionNamedTypeRef, | ||
IntrospectionOutputType, | ||
IntrospectionOutputTypeRef, | ||
IntrospectionTypeRef, | ||
} from 'graphql' | ||
import { JSONSchema6, JSONSchema6TypeName } from 'json-schema' | ||
import { includes } from 'lodash' | ||
import { | ||
JSONSchema6, | ||
JSONSchema6TypeName | ||
} from 'json-schema'; | ||
import { includes } from 'lodash'; | ||
import { isIntrospectionListTypeRef, isNonNullIntrospectionType } from './typeGuards'; | ||
isIntrospectionListTypeRef, | ||
isNonNullIntrospectionType, | ||
} from './typeGuards' | ||
export type GraphQLTypeNames = 'String' | 'Int' | 'Float' | 'Boolean'; | ||
export type GraphQLTypeNames = 'String' | 'Int' | 'Float' | 'Boolean' | ||
export const typesMapping: { [k in GraphQLTypeNames]: JSONSchema6TypeName } = { | ||
'Boolean': 'boolean', | ||
'String': 'string', | ||
'Int': 'number', | ||
'Float': 'number' | ||
}; | ||
Boolean: 'boolean', | ||
String: 'string', | ||
Int: 'number', | ||
Float: 'number', | ||
} | ||
// Convert a GraphQL Type to a valid JSON Schema type | ||
export type GraphqlToJSONTypeArg = IntrospectionTypeRef | IntrospectionInputTypeRef | IntrospectionOutputTypeRef; | ||
export type GraphqlToJSONTypeArg = | ||
| IntrospectionTypeRef | ||
| IntrospectionInputTypeRef | ||
| IntrospectionOutputTypeRef | ||
export const graphqlToJSONType = (k: GraphqlToJSONTypeArg): JSONSchema6 => { | ||
if (isIntrospectionListTypeRef(k)) { | ||
return { | ||
type: 'array', | ||
items: graphqlToJSONType(k.ofType) | ||
}; | ||
} else if (isNonNullIntrospectionType(k)) { | ||
return graphqlToJSONType(k.ofType); | ||
} else { | ||
const name = (k as IntrospectionNamedTypeRef<IntrospectionInputType | IntrospectionOutputType>).name; | ||
return includes(['OBJECT', 'INPUT_OBJECT', 'ENUM', 'SCALAR'], k.kind) ? | ||
includes(['OBJECT', 'INPUT_OBJECT', 'ENUM'], k.kind) ? | ||
{ $ref: `#/definitions/${name}` } : | ||
// tslint:disable-next-line:no-any | ||
{ $ref: `#/definitions/${name}`, | ||
type: (typesMapping as any)[name] | ||
} : | ||
{ type: (typesMapping as any)[name]} | ||
; | ||
if (isIntrospectionListTypeRef(k)) { | ||
return { | ||
type: 'array', | ||
items: graphqlToJSONType(k.ofType), | ||
} | ||
}; | ||
} else if (isNonNullIntrospectionType(k)) { | ||
return graphqlToJSONType(k.ofType) | ||
} else { | ||
const name = (k as IntrospectionNamedTypeRef< | ||
IntrospectionInputType | IntrospectionOutputType | ||
>).name | ||
return includes(['OBJECT', 'INPUT_OBJECT', 'ENUM', 'SCALAR'], k.kind) | ||
? includes(['OBJECT', 'INPUT_OBJECT', 'ENUM'], k.kind) | ||
? { $ref: `#/definitions/${name}` } | ||
: // tslint:disable-next-line:no-any | ||
{ $ref: `#/definitions/${name}`, type: (typesMapping as any)[name] } | ||
: { type: (typesMapping as any)[name] } | ||
} | ||
} |
{ | ||
"name": "graphql-2-json-schema", | ||
"version": "0.3.1-0", | ||
"version": "0.3.1", | ||
"main": "dist/index.js", | ||
@@ -15,3 +15,5 @@ "repository": "git@github.com:wittydeveloper/graphql-to-json-schema.git", | ||
"scripts": { | ||
"test": "jest" | ||
"test": "jest", | ||
"prettier:check": "prettier -c \"**/*.ts\"", | ||
"prettier:format": "prettier -w \"**/*.ts\"" | ||
}, | ||
@@ -27,2 +29,3 @@ "devDependencies": { | ||
"jest": "^26.6.3", | ||
"prettier": "^2.2.1", | ||
"standard-version": "^9.1.0", | ||
@@ -29,0 +32,0 @@ "ts-jest": "^26.4.4", |
import { | ||
buildSchema, | ||
GraphQLSchema, | ||
graphqlSync, | ||
IntrospectionQuery, | ||
getIntrospectionQuery | ||
} from 'graphql'; | ||
import { JSONSchema6 } from 'json-schema'; | ||
buildSchema, | ||
GraphQLSchema, | ||
graphqlSync, | ||
IntrospectionQuery, | ||
getIntrospectionQuery, | ||
} from 'graphql' | ||
import { JSONSchema6 } from 'json-schema' | ||
type GetTodoSchemaIntrospectionResult = { | ||
schema: GraphQLSchema; | ||
introspection: IntrospectionQuery; | ||
}; | ||
schema: GraphQLSchema | ||
introspection: IntrospectionQuery | ||
} | ||
export const getTodoSchemaIntrospection = (): GetTodoSchemaIntrospectionResult => { | ||
const schema = buildSchema(` | ||
const schema = buildSchema(` | ||
"A ToDo Object" | ||
@@ -57,134 +57,135 @@ type Todo { | ||
} | ||
`); | ||
`) | ||
const result = graphqlSync(schema, getIntrospectionQuery()); | ||
return { | ||
introspection: (result.data as IntrospectionQuery), | ||
schema | ||
}; | ||
}; | ||
const result = graphqlSync(schema, getIntrospectionQuery()) | ||
return { | ||
introspection: result.data as IntrospectionQuery, | ||
schema, | ||
} | ||
} | ||
export const todoSchemaAsJsonSchema: JSONSchema6 = { | ||
$schema: 'http://json-schema.org/draft-06/schema#', | ||
properties: { | ||
Query: { | ||
type: 'object', | ||
properties: { | ||
todo: { | ||
type: 'object', | ||
properties: { | ||
arguments: { | ||
type: 'object', | ||
properties: { | ||
id: { type: 'string', description: "todo identifier" }, | ||
isCompleted: { type: 'boolean', default: false } | ||
}, | ||
required: ['id'] | ||
}, | ||
return: { | ||
$ref: '#/definitions/Todo' | ||
} | ||
}, | ||
required: [] | ||
}, | ||
todos: { | ||
type: 'object', | ||
properties: { | ||
arguments: { | ||
type: 'object', | ||
properties: {}, | ||
required: [] | ||
}, | ||
return: { | ||
type: 'array', | ||
items: { $ref: '#/definitions/Todo' } | ||
} | ||
}, | ||
required: [] | ||
} | ||
$schema: 'http://json-schema.org/draft-06/schema#', | ||
properties: { | ||
Query: { | ||
type: 'object', | ||
properties: { | ||
todo: { | ||
type: 'object', | ||
properties: { | ||
arguments: { | ||
type: 'object', | ||
properties: { | ||
id: { type: 'string', description: 'todo identifier' }, | ||
isCompleted: { type: 'boolean', default: false }, | ||
}, | ||
required: ['id'], | ||
}, | ||
required: [] | ||
return: { | ||
$ref: '#/definitions/Todo', | ||
}, | ||
}, | ||
required: [], | ||
}, | ||
Mutation: { | ||
type: 'object', | ||
properties: { | ||
update_todo: { | ||
type: 'object', | ||
properties: { | ||
arguments: { | ||
type: 'object', | ||
properties: { | ||
id: { type: 'string' }, | ||
todo: { $ref: '#/definitions/TodoInputType' } | ||
}, | ||
required: ['id', 'todo'] | ||
}, | ||
return: { | ||
$ref: '#/definitions/Todo' | ||
} | ||
}, | ||
required: [] | ||
}, | ||
create_todo: { | ||
type: 'object', | ||
properties: { | ||
arguments: { | ||
type: 'object', | ||
properties: { | ||
todo: { $ref: '#/definitions/TodoInputType' } | ||
}, | ||
required: ['todo'] | ||
}, | ||
return: { | ||
$ref: '#/definitions/Todo' | ||
} | ||
}, | ||
required: [] | ||
} | ||
} | ||
todos: { | ||
type: 'object', | ||
properties: { | ||
arguments: { | ||
type: 'object', | ||
properties: {}, | ||
required: [], | ||
}, | ||
return: { | ||
type: 'array', | ||
items: { $ref: '#/definitions/Todo' }, | ||
}, | ||
}, | ||
required: [], | ||
}, | ||
}, | ||
required: [], | ||
}, | ||
definitions: { | ||
'Todo': { | ||
type: 'object', | ||
description: "A ToDo Object", | ||
properties: { | ||
id: { type: 'string', description: "A unique identifier" }, | ||
name: { type: 'string' }, | ||
completed: { type: 'boolean' }, | ||
color: { $ref: '#/definitions/Color' }, | ||
colors: { | ||
description: "A list containing colors that cannot contain nulls", | ||
type: 'array', | ||
items: { $ref: '#/definitions/Color' } | ||
}, | ||
Mutation: { | ||
type: 'object', | ||
properties: { | ||
update_todo: { | ||
type: 'object', | ||
properties: { | ||
arguments: { | ||
type: 'object', | ||
properties: { | ||
id: { type: 'string' }, | ||
todo: { $ref: '#/definitions/TodoInputType' }, | ||
}, | ||
required: ['id', 'todo'], | ||
}, | ||
required: ['id', 'name', 'colors'] | ||
return: { | ||
$ref: '#/definitions/Todo', | ||
}, | ||
}, | ||
required: [], | ||
}, | ||
'Color': { | ||
type: 'string', | ||
anyOf: [ | ||
{ | ||
enum: ['RED'], | ||
title: 'Red color', | ||
description: 'Red color' | ||
}, | ||
{ | ||
enum: ['GREEN'], | ||
title: 'Green color', | ||
description: 'Green color' | ||
} | ||
] | ||
create_todo: { | ||
type: 'object', | ||
properties: { | ||
arguments: { | ||
type: 'object', | ||
properties: { | ||
todo: { $ref: '#/definitions/TodoInputType' }, | ||
}, | ||
required: ['todo'], | ||
}, | ||
return: { | ||
$ref: '#/definitions/Todo', | ||
}, | ||
}, | ||
required: [], | ||
}, | ||
'TodoInputType': { | ||
type: 'object', | ||
description: 'A type that describes ToDoInputType. Its description might not\nfit within the bounds of 80 width and so you want MULTILINE', | ||
properties: { | ||
name: { type: 'string' }, | ||
completed: { type: 'boolean' }, | ||
color: { default: 'RED', $ref: '#/definitions/Color' }, | ||
}, | ||
required: ['name'] | ||
} | ||
} | ||
}; | ||
}, | ||
}, | ||
}, | ||
definitions: { | ||
Todo: { | ||
type: 'object', | ||
description: 'A ToDo Object', | ||
properties: { | ||
id: { type: 'string', description: 'A unique identifier' }, | ||
name: { type: 'string' }, | ||
completed: { type: 'boolean' }, | ||
color: { $ref: '#/definitions/Color' }, | ||
colors: { | ||
description: 'A list containing colors that cannot contain nulls', | ||
type: 'array', | ||
items: { $ref: '#/definitions/Color' }, | ||
}, | ||
}, | ||
required: ['id', 'name', 'colors'], | ||
}, | ||
Color: { | ||
type: 'string', | ||
anyOf: [ | ||
{ | ||
enum: ['RED'], | ||
title: 'Red color', | ||
description: 'Red color', | ||
}, | ||
{ | ||
enum: ['GREEN'], | ||
title: 'Green color', | ||
description: 'Green color', | ||
}, | ||
], | ||
}, | ||
TodoInputType: { | ||
type: 'object', | ||
description: | ||
'A type that describes ToDoInputType. Its description might not\nfit within the bounds of 80 width and so you want MULTILINE', | ||
properties: { | ||
name: { type: 'string' }, | ||
completed: { type: 'boolean' }, | ||
color: { default: 'RED', $ref: '#/definitions/Color' }, | ||
}, | ||
required: ['name'], | ||
}, | ||
}, | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1004
49234
13