New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

shapeshifter

Package Overview
Dependencies
Maintainers
1
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

shapeshifter - npm Package Compare versions

Comparing version 2.3.0 to 3.0.0

lib/DefinitionFactory.js

22

bin/shapeshifter.js

@@ -26,3 +26,3 @@ #! /usr/bin/env node

alias: 'n',
description: 'Mark attributes as nullable by default (flow). Default false.',
description: 'Mark attributes as nullable by default (recommended). Defaults to false.',
type: Boolean,

@@ -32,11 +32,4 @@ defaultValue: false,

{
name: 'required',
alias: 'r',
description: 'Mark attributes as required by default (react, typescript). Default false.',
type: Boolean,
defaultValue: false,
},
{
name: 'indent',
description: 'The indentation characters to use. Default 2 space indent.',
description: 'The indentation characters to use. Defaults to 2 space indent.',
typeLabel: '[underline]{char}',

@@ -48,3 +41,3 @@ type: String,

name: 'format',
description: 'The format to generate. Accepts react, flow, or typescript. Default react.',
description: 'The format to generate. Accepts react, flow, or typescript. Defaults to react.',
typeLabel: '[underline]{name}',

@@ -56,3 +49,3 @@ type: String,

name: 'schemas',
description: 'Include schema class exports in the output. Default false.',
description: 'Include schema class exports in the output. Defaults to false.',
type: Boolean,

@@ -63,3 +56,3 @@ defaultValue: false,

name: 'attributes',
description: 'Include an attribute list in the schema class export. Default false.',
description: 'Include an attribute list in the schema class export. Defaults to false.',
type: Boolean,

@@ -70,3 +63,3 @@ defaultValue: false,

name: 'types',
description: 'Include type definition exports in the output. Default false.',
description: 'Include type definition exports in the output. Defaults to false.',
type: Boolean,

@@ -109,4 +102,3 @@ defaultValue: false,

new Transpiler({
defaultNull: options.nullable,
defaultRequired: options.required,
defaultNullable: options.nullable,
includeSchemas: options.schemas,

@@ -113,0 +105,0 @@ includeAttributes: options.attributes,

@@ -0,1 +1,12 @@

# 3.0.0
* Added GraphQL support through the use of `.gql` files to read from (instead of JSON).
* Updated TypeScript requirement to v2.0 and Flowtype to v0.30.
* Replaced Mocha + Chai with Jest and increased code coverage to 100%.
* Merged `null` and `required` flags into a single `nullable` field used by all formats.
* Removed `function` type definition support.
* Removed `nullable` support from TypeScript; use TypeScript's `--strictNullChecks` instead.
* Renamed `SchemaReader` to `Schematic` and all instances of the word reader (like variables).
* Renamed and split `Factory` into `DefinitionFactory` and `RendererFactory`.
* Fixed an issue in which nullable flags could not be passed to enum value types.
# 2.3.0

@@ -6,3 +17,3 @@ * Added a new shape reference feature, which allows for local reusable shapes in a JSON schema.

# 2.2.2
* Added flowtype definitions to the `libs/` output folder.
* Added Flowtype definitions to the `libs/` output folder.
* Updated develop dependency TypeScript to v2.0.

@@ -32,3 +43,3 @@

* React type suffix is now `Shape`.
* Flow type suffix is now `Type`.
* Flowtype type suffix is now `Type`.
* TypeScript type suffix is now `Interface`.

@@ -35,0 +46,0 @@ * Removed global `config.js` object file. Configuration options are now

@@ -13,3 +13,3 @@ 'use strict';

var PRIMITIVE_TYPES /*: string[]*/ = exports.PRIMITIVE_TYPES = ['boolean', 'number', 'string'];
var COMPOUND_TYPES /*: string[]*/ = exports.COMPOUND_TYPES = ['array', 'enum', 'instance', 'object', 'shape', 'union', 'function', 'reference'];
var COMPOUND_TYPES /*: string[]*/ = exports.COMPOUND_TYPES = ['array', 'enum', 'instance', 'object', 'shape', 'union', 'reference'];
var TYPES /*: string[]*/ = exports.TYPES = PRIMITIVE_TYPES.concat(COMPOUND_TYPES);

@@ -45,4 +45,3 @@ 'use strict';

this.config = (0, _extends3.default)({
null: options.defaultNull,
required: options.defaultRequired
nullable: options.defaultNullable
}, config);

@@ -63,18 +62,6 @@

value: function isNullable() /*: boolean*/ {
return this.config.null;
return this.config.nullable;
}
/**
* Returns true if the attribute is required.
*
* @returns {Boolean}
*/
}, {
key: 'isRequired',
value: function isRequired() /*: boolean*/ {
return this.config.required;
}
/**
* Validate the definition configuration.

@@ -88,9 +75,5 @@ */

if (typeof config.null !== 'boolean') {
throw new TypeError('Invalid type detected, "null" property must be a boolean.');
if (typeof config.nullable !== 'boolean') {
throw new TypeError('Invalid type detected, "nullable" property must be a boolean.');
}
if (typeof config.required !== 'boolean') {
throw new TypeError('Invalid type detected, "required" property must be a boolean.');
}
}

@@ -97,0 +80,0 @@ }]);

@@ -35,5 +35,5 @@ 'use strict';

var _Factory = require('../Factory');
var _DefinitionFactory = require('../DefinitionFactory');
var _Factory2 = _interopRequireDefault(_Factory);
var _DefinitionFactory2 = _interopRequireDefault(_DefinitionFactory);

@@ -75,3 +75,3 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

this.valueType = _Factory2.default.definition(this.options, this.attribute, valueType);
this.valueType = _DefinitionFactory2.default.factory(this.options, this.attribute, valueType);
}

@@ -78,0 +78,0 @@ }]);

@@ -89,2 +89,3 @@ 'use strict';

})) {
/* istanbul ignore next This is tested but Istanbul won't pick up */
throw new TypeError('Enum values do not match the defined value type.');

@@ -104,11 +105,4 @@ }

value: function validateValue(value /*: mixed*/) /*: boolean*/ {
var valueType = (0, _normalizeType2.default)(this.config.valueType);
// Function names are defined as strings within the schema
if (valueType === 'function') {
valueType = 'string';
}
// eslint-disable-next-line valid-typeof
return (typeof value === 'undefined' ? 'undefined' : (0, _typeof3.default)(value)) === valueType;
return (typeof value === 'undefined' ? 'undefined' : (0, _typeof3.default)(value)) === (0, _normalizeType2.default)(this.config.valueType);
}

@@ -115,0 +109,0 @@ }]);

@@ -39,5 +39,5 @@ 'use strict';

var _Factory = require('../Factory');
var _DefinitionFactory = require('../DefinitionFactory');
var _Factory2 = _interopRequireDefault(_Factory);
var _DefinitionFactory2 = _interopRequireDefault(_DefinitionFactory);

@@ -90,4 +90,10 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

this.keyType = _Factory2.default.definition(this.options, this.attribute + '_key', keyType);
this.valueType = _Factory2.default.definition(this.options, this.attribute + '_value', valueType);
// Object keys should never be null
this.keyType = _DefinitionFactory2.default.factory(this.options, this.attribute + '_key', {
type: keyType,
nullable: false
});
// Values can be anything
this.valueType = _DefinitionFactory2.default.factory(this.options, this.attribute + '_value', valueType);
}

@@ -94,0 +100,0 @@ }]);

@@ -39,5 +39,5 @@ 'use strict';

var _Factory = require('../Factory');
var _DefinitionFactory = require('../DefinitionFactory');
var _Factory2 = _interopRequireDefault(_Factory);
var _DefinitionFactory2 = _interopRequireDefault(_DefinitionFactory);

@@ -91,3 +91,3 @@ var _isObject = require('../helpers/isObject');

this.attributes = (0, _keys2.default)(attributes).map(function (attribute) {
return _Factory2.default.definition(_this2.options, attribute, attributes[attribute]);
return _DefinitionFactory2.default.factory(_this2.options, attribute, attributes[attribute]);
});

@@ -94,0 +94,0 @@ } else {

@@ -35,5 +35,5 @@ 'use strict';

var _Factory = require('../Factory');
var _DefinitionFactory = require('../DefinitionFactory');
var _Factory2 = _interopRequireDefault(_Factory);
var _DefinitionFactory2 = _interopRequireDefault(_DefinitionFactory);

@@ -78,3 +78,3 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

this.valueTypes = valueTypes.map(function (type, i) {
return _Factory2.default.definition(_this2.options, _this2.attribute + '_' + i, type);
return _DefinitionFactory2.default.factory(_this2.options, _this2.attribute + '_' + i, type);
});

@@ -81,0 +81,0 @@ }

@@ -7,8 +7,9 @@ 'use strict';

exports.default = normalizeType;
/**
* @copyright 2016, Miles Johnson
* @license https://opensource.org/licenses/MIT
* @flow
*/
var _isObject = require('./isObject');
var _isObject2 = _interopRequireDefault(_isObject);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// Use a hash map for faster lookups

@@ -18,3 +19,2 @@ var ALIAS_MAP = {

bool: 'boolean',
func: 'function',
inst: 'instance',

@@ -40,3 +40,14 @@ int: 'number',

*/
/**
* @copyright 2016, Miles Johnson
* @license https://opensource.org/licenses/MIT
* @flow
*/
function normalizeType(type /*: mixed*/) /*: string*/ {
if ((0, _isObject2.default)(type)) {
// $FlowIssue We know its an object
type = type.type;
}
type = String(type).toLowerCase();

@@ -43,0 +54,0 @@

@@ -11,2 +11,10 @@ 'use strict';

var _from = require('babel-runtime/core-js/array/from');
var _from2 = _interopRequireDefault(_from);
var _set = require('babel-runtime/core-js/set');
var _set2 = _interopRequireDefault(_set);
var _extends2 = require('babel-runtime/helpers/extends');

@@ -32,6 +40,2 @@

var _Factory = require('./Factory');
var _Factory2 = _interopRequireDefault(_Factory);
var _Definition = require('./Definition');

@@ -41,2 +45,6 @@

var _DefinitionFactory = require('./DefinitionFactory');
var _DefinitionFactory2 = _interopRequireDefault(_DefinitionFactory);
var _Schema = require('./Schema');

@@ -46,5 +54,5 @@

var _SchemaReader = require('./SchemaReader');
var _Schematic = require('./Schematic');
var _SchemaReader2 = _interopRequireDefault(_SchemaReader);
var _Schematic2 = _interopRequireDefault(_Schematic);

@@ -63,6 +71,2 @@ var _Array = require('./definitions/Array');

var _Func = require('./definitions/Func');
var _Func2 = _interopRequireDefault(_Func);
var _Instance = require('./definitions/Instance');

@@ -110,8 +114,2 @@

/**
* @copyright 2016, Miles Johnson
* @license https://opensource.org/licenses/MIT
* @flow
*/
/*:: import type {

@@ -124,11 +122,16 @@ Options,

ImportStructure,
} from './types';*/
} from './types';*/ /**
* @copyright 2016, Miles Johnson
* @license https://opensource.org/licenses/MIT
* @flow
*/
/*:: type TemplateList = string[];*/
var Renderer = function () {
function Renderer(options /*: Options*/, reader /*: SchemaReader*/) {
function Renderer(options /*: Options*/, schematic /*: Schematic*/) {
(0, _classCallCheck3.default)(this, Renderer);
this.options = options;
this.reader = reader;
this.schematic = schematic;
this.suffix = '';

@@ -141,3 +144,2 @@ this.imports = [];

this.relations = [];
this.referencePaths = [];
}

@@ -280,14 +282,2 @@

/**
* Return a list of all relative reference paths.
*
* @returns {String[]}
*/
}, {
key: 'getReferences',
value: function getReferences() /*: TemplateList*/ {
return this.referencePaths;
}
/**
* Return the export name to be used as the prop type or type alias name.

@@ -371,3 +361,3 @@ *

var constants = this.reader.constants;
var constants = this.schematic.constants;

@@ -389,3 +379,3 @@

this.reader.imports.forEach(function (statement /*: ImportStructure*/) {
this.schematic.imports.forEach(function (statement /*: ImportStructure*/) {
_this2.imports.push(_this2.renderImport(statement));

@@ -401,10 +391,4 @@ });

key: 'parseReferences',
value: function parseReferences() {
var _this3 = this;
value: function parseReferences() {}
(0, _keys2.default)(this.reader.references).forEach(function (key /*: string*/) {
_this3.referencePaths.push(_this3.reader.references[key]);
});
}
/**

@@ -421,6 +405,6 @@ * Parse out all schemas.

var _reader = this.reader,
attributes = _reader.attributes,
name = _reader.name,
metadata = _reader.metadata;
var _schematic = this.schematic,
attributes = _schematic.attributes,
name = _schematic.name,
metadata = _schematic.metadata;

@@ -443,3 +427,3 @@

value: function parseSets() {
var _this4 = this;
var _this3 = this;

@@ -450,7 +434,7 @@ if (!this.options.includeTypes) {

var baseAttributes = this.reader.data.attributes;
var _reader2 = this.reader,
attributes = _reader2.attributes,
subsets = _reader2.subsets,
name = _reader2.name;
var baseAttributes = this.schematic.data.attributes;
var _schematic2 = this.schematic,
attributes = _schematic2.attributes,
subsets = _schematic2.subsets,
name = _schematic2.name;

@@ -467,4 +451,3 @@ // Subsets

var nullable = subset.null || {};
var required = subset.required || {};
var nullable = subset.nullable || {};

@@ -474,2 +457,3 @@ subset.attributes.forEach(function (attribute /*: string*/) {

/* istanbul ignore next Hard to test */
if (!setConfig) {

@@ -486,13 +470,9 @@ throw new SyntaxError('Attribute ' + attribute + ' does not exist in the base schema.');

if (attribute in nullable) {
setConfig.null = nullable[attribute];
setConfig.nullable = nullable[attribute];
}
if (attribute in required) {
setConfig.required = required[attribute];
}
setAttributes.push(_Factory2.default.definition(_this4.options, attribute, setConfig));
setAttributes.push(_DefinitionFactory2.default.factory(_this3.options, attribute, setConfig));
});
_this4.sets.push(_this4.render(_this4.getObjectName(name, setName, _this4.suffix), setAttributes));
_this3.sets.push(_this3.render(_this3.getObjectName(name, setName, _this3.suffix), setAttributes));
});

@@ -511,7 +491,7 @@

value: function parseShapes() {
var _this5 = this;
var _this4 = this;
var _reader3 = this.reader,
name = _reader3.name,
shapes = _reader3.shapes;
var _schematic3 = this.schematic,
name = _schematic3.name,
shapes = _schematic3.shapes;

@@ -521,6 +501,6 @@

var attributes = (0, _keys2.default)(shapes[key]).map(function (attribute) {
return _Factory2.default.definition(_this5.options, attribute, shapes[key][attribute]);
return _DefinitionFactory2.default.factory(_this4.options, attribute, shapes[key][attribute]);
});
_this5.sets.push(_this5.render(_this5.getObjectName(name, key, _this5.suffix), attributes));
_this4.sets.push(_this4.render(_this4.getObjectName(name, key, _this4.suffix), attributes));
});

@@ -560,4 +540,2 @@ }

return this.renderEnum(definition, depth);
} else if (definition instanceof _Func2.default) {
return this.renderFunc(definition, depth);
} else if (definition instanceof _Instance2.default) {

@@ -604,3 +582,3 @@ return this.renderInstance(definition, depth);

value: function renderArrayItems(items /*: PrimitiveType[]*/) /*: string[]*/ {
var _this6 = this;
var _this5 = this;

@@ -611,3 +589,3 @@ var depth /*: number*/ = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;

return items.map(function (item) {
return _this6.wrapItem(_this6.formatValue(item, valueType), depth);
return _this5.wrapItem(_this5.formatValue(item, valueType), depth);
});

@@ -627,9 +605,11 @@ }

value: function renderArrayDefinitions(items /*: Definition[]*/) /*: string[]*/ {
var _this7 = this;
var _this6 = this;
var depth /*: number*/ = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
return items.map(function (item) {
return _this7.wrapItem(_this7.renderAttribute(item, depth), depth);
});
var set = new _set2.default(items.map(function (item) {
return _this6.wrapItem(_this6.renderAttribute(item, depth), depth);
}));
return (0, _from2.default)(set.values());
}

@@ -658,7 +638,7 @@

value: function renderConstant(name /*: string*/, value /*: PrimitiveType | PrimitiveType[]*/) /*: string*/ {
var _this8 = this;
var _this7 = this;
if (Array.isArray(value)) {
value = this.formatArray(value.map(function (v) {
return _this8.formatValue(v);
return _this7.formatValue(v);
}), 0, ', ', '');

@@ -683,12 +663,2 @@ } else {

/**
* Render a function definition.
*/
}, {
key: 'renderFunc',
value: function renderFunc(definition /*: FuncDefinition*/, depth /*: number*/) /*: string*/ {
return this.unsupported('function');
}
/**
* Render an import statement.

@@ -774,3 +744,3 @@ *

value: function renderObjectProps(props /*: Definition[]*/) /*: string[]*/ {
var _this9 = this;
var _this8 = this;

@@ -781,3 +751,3 @@ var depth /*: number*/ = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;

return props.map(function (prop) {
return _this9.wrapProperty(_this9.wrapPropertyName(prop), _this9.renderAttribute(prop, depth), depth, sep);
return _this8.wrapProperty(_this8.wrapPropertyName(prop), _this8.renderAttribute(prop, depth), depth, sep);
});

@@ -819,13 +789,13 @@ }

var refReader = self ? this.reader : this.reader.referenceReaders[reference];
var refSchema = self ? this.schematic : this.schematic.referenceSchematics[reference];
if (!refReader) {
throw new SyntaxError('The reference "' + reference + '" does not exist in the "' + this.reader.name + '" schema.');
if (!refSchema) {
throw new SyntaxError('The reference "' + reference + '" does not exist in the "' + this.schematic.name + '" schema.');
}
if (subset && !refReader.subsets[subset]) {
if (subset && !refSchema.subsets[subset]) {
throw new SyntaxError('The reference "' + reference + '" does not contain a subset named "' + subset + '".');
}
return this.getObjectName(refReader.name, subset, this.suffix);
return this.getObjectName(refSchema.name, subset, this.suffix);
}

@@ -846,3 +816,3 @@

var _relations,
_this10 = this;
_this9 = this;

@@ -855,3 +825,3 @@ var attributes /*: Definition[]*/ = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];

var references = this.reader.referenceReaders;
var references = this.schematic.referenceSchematics;
var fields = [];

@@ -871,3 +841,3 @@ var relations /*: { [key: string]: string[] }*/ = (_relations = {}, (0, _defineProperty3.default)(_relations, _Schema2.default.HAS_ONE, []), (0, _defineProperty3.default)(_relations, _Schema2.default.HAS_MANY, []), (0, _defineProperty3.default)(_relations, _Schema2.default.BELONGS_TO, []), (0, _defineProperty3.default)(_relations, _Schema2.default.BELONGS_TO_MANY, []), _relations);

if (includeAttributes) {
fields.push(_this10.wrapItem(_this10.formatValue(definition.attribute, 'string'), 1));
fields.push(_this9.wrapItem(_this9.formatValue(definition.attribute, 'string'), 1));
}

@@ -889,2 +859,3 @@

if (relationDefinition) {
/* istanbul ignore next Hard to test */
if (typeof relations[relationType] === 'undefined') {

@@ -900,5 +871,5 @@ throw new Error('Invalid relation type for reference attribute "' + definition.attribute + '".');

var relationName = relationConfig.self ? _this10.reader.name : references[relationConfig.reference].name;
var relationName = relationConfig.self ? _this9.schematic.name : references[relationConfig.reference].name;
relations[relationConfig.relation || relationType].push(_this10.wrapProperty(relationDefinition.attribute, _this10.getObjectName(relationName, 'Schema'), 1));
relations[relationConfig.relation || relationType].push(_this9.wrapProperty(relationDefinition.attribute, _this9.getObjectName(relationName, 'Schema'), 1));
}

@@ -924,3 +895,3 @@ });

if (relations[relation].length) {
relationTemplate += '.' + relation + '(' + _this10.formatObject(relations[relation], 0) + ')';
relationTemplate += '.' + relation + '(' + _this9.formatObject(relations[relation], 0) + ')';
}

@@ -963,3 +934,3 @@ });

return this.getObjectName(this.reader.name, reference, this.suffix);
return this.getObjectName(this.schematic.name, reference, this.suffix);
}

@@ -966,0 +937,0 @@

@@ -7,2 +7,10 @@ 'use strict';

var _from = require('babel-runtime/core-js/array/from');
var _from2 = _interopRequireDefault(_from);
var _set = require('babel-runtime/core-js/set');
var _set2 = _interopRequireDefault(_set);
var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');

@@ -36,5 +44,5 @@

var _SchemaReader = require('../SchemaReader');
var _Schematic = require('../Schematic');
var _SchemaReader2 = _interopRequireDefault(_SchemaReader);
var _Schematic2 = _interopRequireDefault(_Schematic);

@@ -57,6 +65,2 @@ var _Definition = require('../Definition');

var _Func = require('../definitions/Func');
var _Func2 = _interopRequireDefault(_Func);
var _Instance = require('../definitions/Instance');

@@ -90,6 +94,2 @@

var _isPrimitive = require('../helpers/isPrimitive');
var _isPrimitive2 = _interopRequireDefault(_isPrimitive);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

@@ -106,6 +106,6 @@

function FlowRenderer(options /*: Options*/, reader /*: SchemaReader*/) {
function FlowRenderer(options /*: Options*/, schematic /*: Schematic*/) {
(0, _classCallCheck3.default)(this, FlowRenderer);
var _this = (0, _possibleConstructorReturn3.default)(this, (FlowRenderer.__proto__ || (0, _getPrototypeOf2.default)(FlowRenderer)).call(this, options, reader));
var _this = (0, _possibleConstructorReturn3.default)(this, (FlowRenderer.__proto__ || (0, _getPrototypeOf2.default)(FlowRenderer)).call(this, options, schematic));

@@ -148,12 +148,3 @@ _this.suffix = 'Type';

value: function renderArray(definition /*: ArrayDefinition*/, depth /*: number*/) /*: string*/ {
var configType = definition.valueType.config.type;
var template = this.renderAttribute(definition.valueType, depth);
if ((0, _isPrimitive2.default)(configType) || configType === 'instance') {
template += '[]';
} else {
template = this.wrapGenerics('Array', template);
}
return this.wrapNullable(definition, template);
return this.wrapNullable(definition, this.wrapGenerics('Array', this.renderAttribute(definition.valueType, depth)));
}

@@ -195,18 +186,2 @@

}, {
key: 'renderFunc',
value: function renderFunc(definition /*: FuncDefinition*/, depth /*: number*/) /*: string*/ {
var returnType = definition.returnType ? this.renderAttribute(definition.returnType, depth + 1) : 'void';
var argTypes = definition.argTypes
// eslint-disable-next-line newline-per-chained-call
? this.renderObjectProps(definition.argTypes).join(' ').trim().replace(/,$/, '') : '';
return this.wrapNullable(definition, '(' + argTypes + ') => ' + returnType);
}
/**
* {@inheritDoc}
*/
}, {
key: 'renderInstance',

@@ -279,5 +254,7 @@ value: function renderInstance(definition /*: InstanceDefinition*/) /*: string*/ {

return definition.valueTypes.map(function (item) {
var set = new _set2.default(definition.valueTypes.map(function (item) {
return _this3.renderAttribute(item, depth);
}).join(' | ');
}));
return (0, _from2.default)(set.values()).join(' | ');
}

@@ -284,0 +261,0 @@

@@ -35,5 +35,5 @@ 'use strict';

var _SchemaReader = require('../SchemaReader');
var _Schematic = require('../Schematic');
var _SchemaReader2 = _interopRequireDefault(_SchemaReader);
var _Schematic2 = _interopRequireDefault(_Schematic);

@@ -56,6 +56,2 @@ var _Definition = require('../Definition');

var _Func = require('../definitions/Func');
var _Func2 = _interopRequireDefault(_Func);
var _Instance = require('../definitions/Instance');

@@ -91,17 +87,15 @@

/**
* @copyright 2016, Miles Johnson
* @license https://opensource.org/licenses/MIT
* @flow
*/
/*:: import type { Options } from '../types';*/ /**
* @copyright 2016, Miles Johnson
* @license https://opensource.org/licenses/MIT
* @flow
*/
/*:: import type { Options } from '../types';*/
var ReactRenderer = function (_Renderer) {
(0, _inherits3.default)(ReactRenderer, _Renderer);
function ReactRenderer(options /*: Options*/, reader /*: SchemaReader*/) {
function ReactRenderer(options /*: Options*/, schematic /*: Schematic*/) {
(0, _classCallCheck3.default)(this, ReactRenderer);
var _this = (0, _possibleConstructorReturn3.default)(this, (ReactRenderer.__proto__ || (0, _getPrototypeOf2.default)(ReactRenderer)).call(this, options, reader));
var _this = (0, _possibleConstructorReturn3.default)(this, (ReactRenderer.__proto__ || (0, _getPrototypeOf2.default)(ReactRenderer)).call(this, options, schematic));

@@ -177,12 +171,2 @@ _this.suffix = 'Shape';

}, {
key: 'renderFunc',
value: function renderFunc(definition /*: FuncDefinition*/, depth /*: number*/) /*: string*/ {
return this.wrapPropType(definition, 'func');
}
/**
* {@inheritDoc}
*/
}, {
key: 'renderInstance',

@@ -231,6 +215,6 @@ value: function renderInstance(definition /*: InstanceDefinition*/) /*: string*/ {

if (self && !subset) {
return '(...args) => ' + this.wrapRequired(definition, reference + '(...args)');
return '(...args) => ' + this.wrapNullable(definition, reference + '(...args)');
}
return this.wrapRequired(definition, reference);
return this.wrapNullable(definition, reference);
}

@@ -248,3 +232,3 @@

if (reference) {
return this.wrapRequired(definition, reference);
return this.wrapNullable(definition, reference);
}

@@ -286,3 +270,3 @@

value: function wrapPropType(definition /*: Definition*/, template /*: string*/) /*: string*/ {
return this.wrapRequired(definition, 'PropTypes.' + template);
return this.wrapNullable(definition, 'PropTypes.' + template);
}

@@ -299,5 +283,5 @@

}, {
key: 'wrapRequired',
value: function wrapRequired(definition /*: Definition*/, template /*: string*/) /*: string*/ {
if (definition.isRequired && definition.isRequired()) {
key: 'wrapNullable',
value: function wrapNullable(definition /*: Definition*/, template /*: string*/) /*: string*/ {
if (definition.isNullable && !definition.isNullable()) {
return template + '.isRequired';

@@ -304,0 +288,0 @@ }

@@ -7,2 +7,10 @@ 'use strict';

var _from = require('babel-runtime/core-js/array/from');
var _from2 = _interopRequireDefault(_from);
var _set = require('babel-runtime/core-js/set');
var _set2 = _interopRequireDefault(_set);
var _fromCodePoint = require('babel-runtime/core-js/string/from-code-point');

@@ -36,5 +44,5 @@

var _SchemaReader = require('../SchemaReader');
var _Schematic = require('../Schematic');
var _SchemaReader2 = _interopRequireDefault(_SchemaReader);
var _Schematic2 = _interopRequireDefault(_Schematic);

@@ -57,6 +65,2 @@ var _Definition = require('../Definition');

var _Func = require('../definitions/Func');
var _Func2 = _interopRequireDefault(_Func);
var _Instance = require('../definitions/Instance');

@@ -100,17 +104,15 @@

/**
* @copyright 2016, Miles Johnson
* @license https://opensource.org/licenses/MIT
* @flow
*/
/*:: import type { Options, PrimitiveType } from '../types';*/ /**
* @copyright 2016, Miles Johnson
* @license https://opensource.org/licenses/MIT
* @flow
*/
/*:: import type { Options, PrimitiveType } from '../types';*/
var TypeScriptRenderer = function (_Renderer) {
(0, _inherits3.default)(TypeScriptRenderer, _Renderer);
function TypeScriptRenderer(options /*: Options*/, reader /*: SchemaReader*/) {
function TypeScriptRenderer(options /*: Options*/, schematic /*: Schematic*/) {
(0, _classCallCheck3.default)(this, TypeScriptRenderer);
var _this = (0, _possibleConstructorReturn3.default)(this, (TypeScriptRenderer.__proto__ || (0, _getPrototypeOf2.default)(TypeScriptRenderer)).call(this, options, reader));
var _this = (0, _possibleConstructorReturn3.default)(this, (TypeScriptRenderer.__proto__ || (0, _getPrototypeOf2.default)(TypeScriptRenderer)).call(this, options, schematic));

@@ -178,4 +180,3 @@ _this.suffix = 'Interface';

var members = [];
var enumName = this.getObjectName(this.reader.name, definition.attribute, 'Enum');
var enumName = this.getObjectName(this.schematic.name, definition.attribute, 'Enum');
var currentIndex = 0;

@@ -187,2 +188,3 @@ var currentChar = 65;

// Assign values incrementally starting from 0
default:
case 'string':

@@ -204,5 +206,2 @@ values.forEach(function (value /*: PrimitiveType*/) {

break;
default:
break;
}

@@ -220,18 +219,2 @@

}, {
key: 'renderFunc',
value: function renderFunc(definition /*: FuncDefinition*/, depth /*: number*/) /*: string*/ {
var returnType = definition.returnType ? this.renderAttribute(definition.returnType, depth + 1) : 'void';
var argTypes = definition.argTypes
// eslint-disable-next-line newline-per-chained-call
? this.renderObjectProps(definition.argTypes).join(' ').replace(/,$/, '') : '';
return '(' + argTypes + ') => ' + returnType;
}
/**
* {@inheritDoc}
*/
}, {
key: 'renderInstance',

@@ -294,28 +277,8 @@ value: function renderInstance(definition /*: InstanceDefinition*/) /*: string*/ {

return definition.valueTypes.map(function (item /*: Definition*/) {
var value = _this2.renderAttribute(item, depth);
var set = new _set2.default(definition.valueTypes.map(function (item) {
return _this2.renderAttribute(item, depth);
}));
// Functions need to be wrapped in parenthesis when used in unions
return item instanceof _Func2.default ? '(' + value + ')' : value;
}).join(' | ');
return (0, _from2.default)(set.values()).join(' | ');
}
/**
* Mark as optional.
*
* @param {Definition} definition
* @returns {String}
*/
}, {
key: 'wrapPropertyName',
value: function wrapPropertyName(definition /*: Definition*/) /*: string*/ {
var template = definition.attribute;
if (!definition.isRequired()) {
return template + '?';
}
return template;
}
}]);

@@ -322,0 +285,0 @@ return TypeScriptRenderer;

@@ -47,10 +47,18 @@ 'use strict';

var _Factory = require('./Factory');
var _RendererFactory = require('./RendererFactory');
var _Factory2 = _interopRequireDefault(_Factory);
var _RendererFactory2 = _interopRequireDefault(_RendererFactory);
var _SchemaReader = require('./SchemaReader');
var _Schematic = require('./Schematic');
var _SchemaReader2 = _interopRequireDefault(_SchemaReader);
var _Schematic2 = _interopRequireDefault(_Schematic);
var _node = require('./readers/node');
var _node2 = _interopRequireDefault(_node);
var _graphql = require('./readers/graphql');
var _graphql2 = _interopRequireDefault(_graphql);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

@@ -67,3 +75,3 @@

/*:: type ResolveList = {
parentReader?: SchemaReader,
parentSchematic?: Schematic,
refKey?: string,

@@ -81,6 +89,7 @@ resolvePath: string,

/**
* Output the rendered reader to stdout.
* Output the rendered schema to stdout.
*
* @param {String} value
*/
/* istanbul ignore next */

@@ -93,3 +102,3 @@

/**
* Transpile either a file or a folder by rendering each reader file.
* Transpile either a file or a folder by rendering each schematic file.
*

@@ -99,2 +108,3 @@ * @param {String} target

*/
/* istanbul ignore next */
value: function transpile(target /*: string*/) /*: Promise<string>*/ {

@@ -138,15 +148,13 @@ var _this = this;

var filePaths = _fs2.default.readdirSync(folderPath);
var readers = [];
var schematics = [];
filePaths.forEach(function (filePath /*: string*/) {
if (filePath.match(/\.(js|json)$/)) {
readers = [].concat((0, _toConsumableArray3.default)(readers), (0, _toConsumableArray3.default)(_this2.extractReaders(_path2.default.join(folderPath, filePath))));
}
schematics = [].concat((0, _toConsumableArray3.default)(schematics), (0, _toConsumableArray3.default)(_this2.extractSchematics(_path2.default.join(folderPath, filePath))));
});
return this.generateOutput(readers);
return this.generateOutput(schematics);
}
/**
* Transpile a file by rendering the reader at the defined path.
* Transpile a file by rendering the schematic at the defined path.
*

@@ -160,15 +168,15 @@ * @param {String} file

value: function transpileFile(file /*: string*/) /*: string*/ {
return this.generateOutput(this.extractReaders(file));
return this.generateOutput(this.extractSchematics(file));
}
/**
* Extract a list of file paths based on references defined within the reader.
* Extract a list of file paths based on references defined within the schematic.
*
* @param {String} filePath
* @returns {SchemaReader[]}
* @returns {Schematic[]}
*/
}, {
key: 'extractReaders',
value: function extractReaders(filePath /*: string*/) /*: SchemaReader[]*/ {
key: 'extractSchematics',
value: function extractSchematics(filePath /*: string*/) /*: Schematic[]*/ {
var _this3 = this;

@@ -178,3 +186,3 @@

var toResolve /*: ResolveList[]*/ = [{ resolvePath: filePath }];
var readers = [];
var schematics = [];

@@ -186,9 +194,14 @@ // Use `require()` as it handles JSON and JS files easily

resolvePath = _toResolve$shift.resolvePath,
parentReader = _toResolve$shift.parentReader,
parentSchematic = _toResolve$shift.parentSchematic,
refKey = _toResolve$shift.refKey;
// Only support JS and JSON
var pathExt = _path2.default.extname(resolvePath);
var data = null;
if (!resolvePath.match(/\.(js|json)$/)) {
/* istanbul ignore else */
if (pathExt === '.js' || pathExt === '.json') {
data = (0, _node2.default)(resolvePath);
} else if (pathExt === '.gql' || pathExt === '.graphql') {
data = (0, _graphql2.default)(resolvePath);
} else {
// eslint-disable-next-line no-continue

@@ -198,19 +211,16 @@ return 'continue';

/* eslint-disable */
// $FlowIssue `resolvePath` cannot be a literal string
var reader = new _SchemaReader2.default(resolvePath, require(resolvePath), _this3.options);
/* eslint-enable */
var schematic = new _Schematic2.default(resolvePath, data, _this3.options);
readers.unshift(reader);
schematics.unshift(schematic);
// Assign to parent
if (parentReader && refKey) {
parentReader.referenceReaders[refKey] = reader;
if (parentSchematic && refKey) {
parentSchematic.referenceSchematics[refKey] = schematic;
}
// Extract child references
(0, _keys2.default)(reader.references).forEach(function (ref /*: string*/) {
(0, _keys2.default)(schematic.references).forEach(function (ref /*: string*/) {
toResolve.push({
resolvePath: _path2.default.normalize(_path2.default.join(basePath, reader.references[ref])),
parentReader: reader,
resolvePath: _path2.default.normalize(_path2.default.join(basePath, schematic.references[ref])),
parentSchematic: schematic,
refKey: ref

@@ -227,9 +237,9 @@ });

return readers;
return schematics;
}
/**
* Generate the output by combining all readers into a single output.
* Generate the output by combining all schematics into a single output.
*
* @param {SchemaReader[]} readers
* @param {Schematic[]} schematics
* @returns {String}

@@ -240,3 +250,3 @@ */

key: 'generateOutput',
value: function generateOutput(readers /*: SchemaReader[]*/) /*: string*/ {
value: function generateOutput(schematics /*: Schematic[]*/) /*: string*/ {
var _this4 = this;

@@ -253,8 +263,8 @@

// Wrap in a set to remove duplicates
readers.forEach(function (reader /*: SchemaReader*/) {
if (rendered.has(reader.path)) {
schematics.forEach(function (schematic /*: Schematic*/) {
if (rendered.has(schematic.path)) {
return;
}
var renderer = _Factory2.default.renderer(_this4.options, reader);
var renderer = _RendererFactory2.default.factory(_this4.options, schematic);

@@ -275,3 +285,3 @@ renderer.parse();

rendered.add(reader.path);
rendered.add(schematic.path);
});

@@ -305,2 +315,3 @@

*/
/* istanbul ignore next */

@@ -307,0 +318,0 @@ }, {

@@ -12,4 +12,3 @@ "use strict";

/*:: export type Options = {
defaultNull: boolean,
defaultRequired: boolean,
defaultNullable: boolean,
includeAttributes: boolean,

@@ -27,9 +26,7 @@ includeSchemas: boolean,

/*:: export type BaseConfig = {
null?: boolean,
required?: boolean,
nullable?: boolean,
type: string,
};*/
/*:: export type ArrayConfig = {
null?: boolean,
required?: boolean,
nullable?: boolean,
type: string,

@@ -39,9 +36,7 @@ valueType: TypeDefinition,

/*:: export type BoolConfig = {
null?: boolean,
required?: boolean,
nullable?: boolean,
type: string,
};*/
/*:: export type EnumConfig = {
null?: boolean,
required?: boolean,
nullable?: boolean,
type: string,

@@ -51,18 +46,9 @@ values: PrimitiveType[],

};*/
/*:: export type FuncConfig = {
argTypes?: TypeDefinition[],
null?: boolean,
required?: boolean,
returnType?: TypeDefinition,
type: string,
};*/
/*:: export type InstanceConfig = {
contract: string,
null?: boolean,
required?: boolean,
nullable?: boolean,
type: string,
};*/
/*:: export type NumberConfig = {
null?: boolean,
required?: boolean,
nullable?: boolean,
type: string,

@@ -72,4 +58,3 @@ };*/

keyType: TypeDefinition,
null?: boolean,
required?: boolean,
nullable?: boolean,
type: string,

@@ -80,6 +65,5 @@ valueType: TypeDefinition,

export?: boolean,
null?: boolean,
nullable?: boolean,
reference: string,
relation?: string,
required?: boolean,
self: boolean,

@@ -91,15 +75,12 @@ subset?: string,

attributes: { [key: string]: TypeDefinition },
null?: boolean,
nullable?: boolean,
reference?: string,
required?: boolean,
type: string,
};*/
/*:: export type StringConfig = {
null?: boolean,
required?: boolean,
nullable?: boolean,
type: string,
};*/
/*:: export type UnionConfig = {
null?: boolean,
required?: boolean,
nullable?: boolean,
type: string,

@@ -113,3 +94,3 @@ valueTypes: TypeDefinition[],

/*:: export type TypeDefinition = string |
ArrayConfig | BoolConfig | EnumConfig | FuncConfig | InstanceConfig | NumberConfig |
ArrayConfig | BoolConfig | EnumConfig | InstanceConfig | NumberConfig |
ObjectConfig | ReferenceConfig | ShapeConfig | StringConfig | UnionConfig;*/

@@ -134,4 +115,3 @@ /*:: export type MetadataField = {

attributes: string[],
null?: { [key: string]: boolean },
required?: { [key: string]: boolean },
nullable?: { [key: string]: boolean },
};*/

@@ -138,0 +118,0 @@ /*:: export type SubsetsField = { [key: string]: string[] | SubsetStructure };*/

{
"name": "shapeshifter",
"version": "2.3.0",
"description": "Generate relational schemas, React prop types, Flow type aliases, or TypeScript interfaces from JSON schema files.",
"version": "3.0.0",
"description": "Generate relational schemas, React prop types, Flow type aliases, or TypeScript interfaces from JSON or GraphQL schematic files.",
"keywords": [
"generate",
"schema",
"schematic",
"react",

@@ -21,3 +22,4 @@ "prop",

"transpile",
"entity"
"entity",
"graphql"
],

@@ -33,14 +35,13 @@ "main": "./lib/index.js",

"clean": "rimraf ./lib",
"build": "babel ./src -d ./lib && yarn run build:flow",
"build:flow": "cp ./flow/shapeshifter.js.flow ./lib",
"watch": "babel --watch ./src -d ./lib",
"build": "babel ./src -d ./lib && cp ./flow/shapeshifter.js.flow ./lib",
"lint": "eslint ./src ./tests",
"check": "yarn run check:flow && yarn run check:typescript",
"check:flow": "flow check",
"check:typescript": "tsc --noEmit --allowJs ./tests/expected/typescript/*",
"mocha": "mocha --opts ./mocha.opts './tests/**/*.test.js'",
"pretest": "yarn run clean && yarn run build",
"test": "yarn run mocha",
"posttest": "yarn run lint && yarn run check",
"preversion": "yarn test"
"check:typescript": "tsc --noEmit --allowJs ./tests/expected/gql/typescript/* ./tests/expected/node/typescript/*",
"jest": "jest --config ./jest.json",
"coverage": "yarn run jest -- --coverage",
"pretest": "yarn run lint",
"test": "yarn run jest",
"posttest": "yarn run check",
"preversion": "yarn test && yarn run clean && yarn run build"
},

@@ -69,21 +70,21 @@ "repository": {

"babel-eslint": "^7.1.1",
"babel-jest": "^18.0.0",
"babel-plugin-transform-flow-comments": "^6.17.0",
"babel-plugin-transform-runtime": "^6.15.0",
"babel-preset-es2015": "^6.18.0",
"babel-preset-latest": "^6.16.0",
"babel-preset-stage-2": "^6.18.0",
"babel-register": "^6.18.0",
"chai": "^3.5.0",
"chai-files": "^1.4.0",
"eslint": "^3.12.1",
"eslint-config-airbnb": "^13.0.0",
"eslint-plugin-flowtype": "^2.25.0",
"eslint": "^3.13.1",
"eslint-config-airbnb": "^14.0.0",
"eslint-plugin-flowtype": "^2.29.2",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-jsx-a11y": "^2.2.3",
"eslint-plugin-react": "^6.7.1",
"flow-bin": "^0.37.0",
"mocha": "^3.1.2",
"react": "^15.4.0",
"eslint-plugin-jsx-a11y": "^3.0.2",
"eslint-plugin-react": "^6.9.0",
"flow-bin": "^0.37.4",
"graphql": "^0.8.2",
"jest": "^18.1.0",
"react": "^15.4.2",
"rimraf": "^2.5.4",
"typescript": "^2.1.4"
"typescript": "^2.1.5"
}
}

@@ -1,2 +0,2 @@

# Shapeshifter v2.3.0
# Shapeshifter v3.0.0
[![Build Status](https://travis-ci.org/milesj/shapeshifter.svg?branch=master)](https://travis-ci.org/milesj/shapeshifter)

@@ -6,7 +6,7 @@

files that export React prop types, Flow type aliases, or TypeScript
interfaces, as well as relation schema classes from JSON schema files.
Schemas can represent database tables, API endpoints, data structures,
resources, internal shapes, and more.
interfaces, as well as relation schema classes from JSON or GraphQL
schematic files. Schematics can represent database tables, API endpoints,
data structures, resources, internal shapes, and more.
Take this user schema for example.
Take this user schematic for example.

@@ -21,3 +21,3 @@ ```json

"type": "string",
"required": true
"nullable": true
},

@@ -41,9 +41,9 @@ "location": {

export const UserShape = PropTypes.shape({
id: PropTypes.number,
username: PropTypes.string,
email: PropTypes.string.isRequired,
id: PropTypes.number.isRequired,
username: PropTypes.string.isRequired,
email: PropTypes.string,
location: PropTypes.shape({
lat: PropTypes.number,
long: PropTypes.number,
}),
lat: PropTypes.number.isRequired,
long: PropTypes.number.isRequired,
}).isRequired,
});

@@ -60,3 +60,3 @@ ```

username: string,
email: string,
email: ?string,
location: {

@@ -73,8 +73,8 @@ lat: number,

export interface UserInterface {
id?: number;
username?: string;
id: number;
username: string;
email: string;
location?: {
lat?: number;
long?: number;
location: {
lat: number;
long: number;
};

@@ -94,3 +94,3 @@ }

* Node 4+
* React 0.14+ / Flow 0.20+ / TypeScript 1.6+
* React 0.14+ / Flow 0.30+ / TypeScript 2.0+

@@ -108,4 +108,3 @@ ## Installation

If you're generating schema classes, it will need to be a normal
dependency.
If you're generating schema classes, it will need to be a normal dependency.

@@ -126,4 +125,4 @@ ```

The binary input accepts either a single schema file or a directory of
schema files. If a directory is provided, they will be combined into
The binary input accepts either a single schematic file or a directory of
schematic files. If a directory is provided, they will be combined into
a single output.

@@ -138,27 +137,18 @@

* `--help`, `-h` - Displays a help menu.
* `--nullable`, `-n` - Marks all attributes as nullable by default.
Defaults to false. (Flow only)
* `--required`, `-r` - Marks all attributes as required by default.
Defaults to false. (React and TypeScript only)
Not applicable to GraphQL. Defaults to false.
* `--indent` - Defines the indentation characters to use in the
generated output. Defaults to 2 spaces.
generated output. Defaults to 2 spaces.
* `--format` - The format to output to. Accepts "react", "flow", or
"typescript". Defaults to "react".
"typescript". Defaults to "react".
* `--schemas` - Include schema class exports in the output. Defaults to
"false".
"false".
* `--attributes` - Include an attribute list in the schema class export.
Defaults to "false".
Defaults to "false".
* `--types` - Include type definition exports in the output. Defaults to
"false".
"false".
## Documentation
* [JSON Structure](#json-structure)
* [Schematic Structure](#schematic-structure)
* [Attributes](#attributes)

@@ -169,2 +159,3 @@ * [Metadata](#metadata)

* [Subsets](#subsets)
* [GraphQL Support](#graphql-support)
* [Attribute Types](#attribute-types)

@@ -187,23 +178,35 @@ * [Primitives](#primitives)

### JSON Structure
### Schematic Structure
A schema can either be a JSON file, or a JavaScript file
that exports an object (Node.js compatible). JSON is preferred
as it's a consumable format across many languages.
Shapeshifter is powered by files known as schematics, which can
be a JSON (`.json`), JavaScript (`.js`), or GraphQL file (`.gql`).
Schematics must define a name, used to denote the name of the
ES2015 export, and set of attributes, used as as fields in which
the schematic is defining.
Every schema requires a `name` and `attributes` property.
The name denotes the name of the export prefix found in the
ES2015 transpiled output file, while the attributes denotes the
available fields in the current schema.
```json
{
"name": "Users",
"attributes": {}
"name": "User",
"attributes": {
"id": "number"
}
}
```
```javascript
module.exports = {
name: 'User',
attributes: {
id: 'number'
}
};
```
```graphql
type User {
id: ID
}
```
Furthermore, a schema supports the following optional properties:
`meta`, `imports`, `constants`, `references`, and `subsets`. Continue
reading for more information on all the supported schema properties.
> GraphQL has limited functionality compared to JSON or JavaScript.
> Jump to the section on [GraphQL](#graphql-support), and read the
> documentation thoroughly, for more information.

@@ -234,21 +237,28 @@ #### Attributes

##### Modifiers
> For GraphQL, attributes are analogous to [fields](https://facebook.github.io/graphql/#sec-Language.Fields).
All attribute type definitions support two modifier properties,
`required` and `null`. Both of these values accept a boolean value.
##### Nullable
When `required` is used by React, it will append `isRequired` to all
prop types. When used by TypeScript, it will omit `?` on every
property name. Required attributes are not supported by Flow,
instead it supports `null`. Nullable fields will prepend `?` to
every type alias.
All attribute type definitions support the `nullable` modifier,
which accepts a boolean value, and triggers the following:
* React: Non-nullable fields will append `isRequired` to the prop type.
* Flowtype: Nullable fields will prepend `?` to each type alias.
* TypeScript: Does nothing, please use `--strictNullChecks` provided
by TypeScript.
```json
"field": {
"type": "string",
"required": true,
"null": false
"nullable": false
}
```
If using GraphQL, all attributes are nullable by default. To mark a field
as non-nullable, append an exclamation mark (`!`) to the type.
```graphql
field: String!
```
#### Metadata

@@ -271,2 +281,10 @@

If using GraphQL, the `ID` type can be used to denote a primary key.
```graphql
type User {
id: ID
}
```
#### Imports

@@ -290,2 +308,4 @@

> Imports are not supported by GraphQL.
#### Constants

@@ -310,2 +330,4 @@

> Constants are not supported by GraphQL.
#### Subsets

@@ -317,7 +339,6 @@

property can either be an array of [attribute names](#attributes),
or an object of `attributes`, `required` (optional), and `null`
(optional) properties.
or an object of `attributes` and `nullable` (optional) properties.
Unlike `required` and `null` properties found on type definitions,
these properties represent a mapping of attributes in the current
Unlike `nullable` properties found on type definitions,
this property represents a mapping of attributes in the current
subset to boolean values, which enable or disable the modifier.

@@ -329,13 +350,6 @@

"SetB": {
"attributes": ["foo", "qux"],
"null": {
"attributes": ["foo", "baz"],
"nullable": {
"foo": true
}
},
"SetC": {
"attributes": ["bar", "baz"],
"required": {
"bar": true,
"baz": false
}
}

@@ -348,7 +362,3 @@ },

"type": "string",
"required": true
},
"qux": {
"type": "string",
"null": true
"nullable": true
}

@@ -358,5 +368,23 @@ }

> Subsets are not supported by GraphQL.
### GraphQL Support
Shapeshifter supports reading from GraphQL (`.gql`) type files -- if you
prefer GraphQL over JavaScript/JSON. However, since GraphQL is a rather strict
and direct representation of a data model, only a small subset of Shapeshifter
functionality is available.
When defining a GraphQL schematic, multiple definitions (`type`, `enum`, `union`, etc)
can exist in a single schematic, with the last `type` definition being
used as the schematic representation. All prior definitions will be used
as internal shapes, references, enums, and unions.
For more guidance, [take a look at our test cases.](./tests/schemas/gql/)
> Introspection support being looked into!
### Attribute Types
For every attribute defined in a JSON schema, a type definition is required.
For every attribute defined in a schematic, a type definition is required.
Types will be generated when the `--types` CLI option is passed. The

@@ -376,2 +404,7 @@ following types are supported.

```
```graphql
name: String
status: Int
active: Boolean
```

@@ -406,5 +439,5 @@ As well as the expanded standard notation.

// TypeScript
name?: string;
status?: number;
active?: boolean;
name: string;
status: number;
active: boolean;
```

@@ -427,2 +460,5 @@

```
```graphql
messages: [String]
```

@@ -439,3 +475,3 @@ This transpiles down to:

// TypeScript
messages?: string[];
messages: string[];
```

@@ -473,3 +509,3 @@

// TypeScript
costs?: { [key: string]: number };
costs: { [key: string]: number };
```

@@ -479,2 +515,4 @@

> Objects are not supported by GraphQL. Use shapes instead.
#### Enums

@@ -493,3 +531,12 @@

```
```graphql
enum WordsEnum {
FOO
BAR
BAZ
}
words: WordsEnum
```
This transpiles down to:

@@ -511,5 +558,7 @@

words?: SchemaWordsEnum;
words: SchemaWordsEnum;
```
> Transpilation output slightly differs when using GraphQL.
#### Shapes

@@ -520,3 +569,3 @@

type for all keys and values, while a shape defines individual
attributes. This provides nested structures within a schema.
attributes. This provides nested structures within a schematic.

@@ -533,3 +582,3 @@ A shape is similar to a struct found in the C language.

"type": "string",
"required": true
"nullable": true
}

@@ -539,3 +588,12 @@ }

```
```graphql
type LocationStruct {
lat: Number
long: Number
name: String!
}
location: LocationStruct
```
This transpiles to:

@@ -546,5 +604,5 @@

location: PropTypes.shape({
lat: PropTypes.number,
long: PropTypes.number,
name: PropTypes.string.isRequired,
lat: PropTypes.number.isRequired,
long: PropTypes.number.isRequired,
name: PropTypes.string,
}),

@@ -556,9 +614,9 @@

long: number,
name: string,
name: ?string,
},
// TypeScript
location?: {
lat?: number,
long?: number,
location: {
lat: number,
long: number,
name: string,

@@ -573,3 +631,3 @@ },

Shapes are powerful at defining nested attributes, while
[references](#references) are great at reusing external schemas.
[references](#references) are great at reusing external schematics.
Shape references are a combination of both of these patterns --

@@ -619,2 +677,5 @@ it permits a local shape definition to be used throughout

> If an additional `type` definition exists within a GraphQL schematic,
> it will be treated as a shape reference, otherwise, a normal reference.
#### Unions

@@ -639,3 +700,8 @@

```
```graphql
union PrimitiveUnion = String | Int
error: PrimitiveUnion
```
This transpiles to:

@@ -655,3 +721,3 @@

// TypeScript
error?: string | number | Error;
error: string | number | Error;
```

@@ -662,15 +728,15 @@

The final type, `reference`, is the most powerful and versatile type.
A reference provides a link to an external schema file, permitting
easy re-use and extensibility, while avoiding schema structure
A reference provides a link to an external schematic file, permitting
easy re-use and extensibility, while avoiding schematic structure
duplication across files.
To make use of references, a `references` map must be defined in
the root of the schema. Each value in the map is a relative path to
an external schema file.
the root of the schematic. Each value in the map is a relative path to
an external schematic file.
```json
{
"name": "Users",
"name": "User",
"references": {
"Profile": "./profile.json"
"Profile": "./Profile.json"
},

@@ -684,3 +750,3 @@ "attributes": {}

the references map. An optional `subset` property can be defined
that points to a subset found in the reference schema file.
that points to a subset found in the reference schematic file.

@@ -694,2 +760,5 @@ ```json

```
```graphql
profile: Profile
```

@@ -706,3 +775,3 @@ This transpiles to:

// TypeScript
profile?: ProfileInterface;
profile: ProfileInterface;
```

@@ -712,6 +781,10 @@

> If a `type` definition does not exist in a GraphQL schematic,
> Shapeshifter will assume it to be a reference to a relative file of the same name.
> For example, using the code block mentioned previously, `./Profile.gql`.
##### Self References
It's possible to create recursive structures using the `self`
property, which refers to the current schema in which it was defined.
property, which refers to the current schematic in which it was defined.
When using self, the `reference` property and the `references` map

@@ -726,2 +799,7 @@ is not required.

```
```graphql
type Schema {
node: Schema
}
```

@@ -731,3 +809,3 @@ ##### Exported Schemas

When generating schema classes using the `--schemas` CLI option,
all references defined in a schema are considered a relation (ORM style),
all references defined in a schematic are considered a relation (ORM style),
and in turn, will generate schemas as well. To disable this export

@@ -744,2 +822,4 @@ from occurring, set `export` to false.

> Disabling exports are not supported by GraphQL.
##### Relation Type

@@ -763,2 +843,4 @@

> Customizing the relation type is not supported by GraphQL.
#### Instance Ofs

@@ -807,4 +889,6 @@

#### Schema Classes
> Instance Ofs are not supported by GraphQL.
### Schema Classes
Schema classes are ES2015 based classes that are generated and included

@@ -826,7 +910,7 @@ in the output when `--schemas` is passed to the command line. These

the first argument to the constructor. This field is based on
`meta.resourceName` in the JSON schema file.
`meta.resourceName` in the schematic file.
* `primaryKey` (string) - The name of the primary key in the current
schema, passed as the second argument to the constructor. This field
is based on `meta.primaryKey` in the JSON schema file. Defaults to "id".
is based on `meta.primaryKey` in the JSON schematic file. Defaults to "id".

@@ -852,4 +936,6 @@ * `attributes` (string[]) - List of attribute names in the current schema.

##### Including Attributes
> Schemas are not supported by GraphQL.
#### Including Attributes
By default, attributes are excluded from the output unless the

@@ -868,3 +954,3 @@ `--attributes` CLI option is passed. Once passed, they are defined

##### Including Relations
#### Including Relations

@@ -915,5 +1001,1 @@ Unlike attributes, relations are always included in the output, as

map to database tables or data structures very well, if at all.
The same could be said for `func` -- however, that is supported.
I've simply opted out in mentioning it in the documentation, as I'm
not too sure on its use case. Kind of a hidden feature really.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc