@brightcove/typed-immutable-extensions
Advanced tools
Comparing version
@@ -9,2 +9,16 @@ # Changelog | ||
## [0.1.2] - 2018-08-16 | ||
## Fixed | ||
- Fixed `Typed.typeName` specifiers for `Maybe`, `Enum` and `Discriminator` | ||
### Changed | ||
- Moved logic for `Maybe`, `Enum`, and `Discriminator` into separate classes which expose some typing information | ||
### Removed | ||
- jsdoc, we are now only using jsdoc-to-markdown | ||
## [0.1.1] - 2018-08-13 | ||
@@ -11,0 +25,0 @@ |
328
lib/index.js
'use strict'; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
@@ -11,3 +19,4 @@ | ||
typeOf = _require.typeOf, | ||
Any = _require.Any; | ||
Any = _require.Any, | ||
Type = _require.Type; | ||
@@ -42,3 +51,3 @@ /* istanbul ignore next */ | ||
*/ | ||
function extend(BaseRecord, descriptor, label) { | ||
module.exports.extend = function (BaseRecord, descriptor, label) { | ||
var _properties; | ||
@@ -107,5 +116,68 @@ | ||
return RecordType; | ||
} | ||
}; | ||
/** | ||
* Class for implementing Maybe | ||
* @private | ||
*/ | ||
var MaybeType = function (_Type) { | ||
_inherits(MaybeType, _Type); | ||
function MaybeType(type, defaultValue) { | ||
_classCallCheck(this, MaybeType); | ||
var _this = _possibleConstructorReturn(this, (MaybeType.__proto__ || Object.getPrototypeOf(MaybeType)).call(this)); | ||
_this[Typed.type] = typeOf(type); | ||
if (_this[Typed.type] === Any) { | ||
throw new TypeError(type + ' is not a valid type'); | ||
} | ||
if (defaultValue != null) { | ||
_this[Typed.defaultValue] = _this[Typed.type][Typed.read](defaultValue); | ||
if (_this[Typed.defaultValue] instanceof TypeError) { | ||
throw new TypeError(defaultValue + ' is not nully nor of ' + _this[Typed.type][Typed.typeName]() + ' type'); | ||
} | ||
} else { | ||
_this[Typed.defaultValue] = defaultValue; | ||
} | ||
if (typeof _this[Typed.defaultValue] === 'undefined' && typeof _this[Typed.type][Typed.defaultValue] !== 'undefined') { | ||
_this[Typed.defaultValue] = _this[Typed.type][Typed.defaultValue]; | ||
} | ||
return _this; | ||
} | ||
_createClass(MaybeType, [{ | ||
key: Typed.typeName, | ||
value: function value() { | ||
var typeName = this[Typed.type][Typed.typeName](); | ||
var defaultValue = this[Typed.defaultValue]; | ||
if (typeof defaultValue === 'undefined') { | ||
return 'Maybe(' + typeName + ')'; | ||
} | ||
return 'Maybe(' + typeName + ', ' + JSON.stringify(defaultValue) + ')'; | ||
} | ||
}, { | ||
key: Typed.read, | ||
value: function value() { | ||
var _value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this[Typed.defaultValue]; | ||
var result = void 0; | ||
if (_value == null) { | ||
result = _value; | ||
} else { | ||
result = this[Typed.type][Typed.read](_value); | ||
} | ||
if (result instanceof TypeError) { | ||
return TypeError('"' + _value + '" is not nully nor it is of ' + this[Typed.type][Typed.typeName]() + ' type'); | ||
} | ||
return result; | ||
} | ||
}]); | ||
return MaybeType; | ||
}(Type); | ||
/** | ||
* Defines an optional type, similar to typed-immutable's [Maybe]{@link https://github.com/typed-immutable/typed-immutable#maybe}, but provides extended options. | ||
@@ -137,32 +209,61 @@ * | ||
*/ | ||
function Maybe(Type, defaultValue) { | ||
var type = typeOf(Type); | ||
if (type === Any) { | ||
throw new TypeError(Type + ' is not a valid type'); | ||
} | ||
if (defaultValue != null) { | ||
defaultValue = type[Typed.read](defaultValue); | ||
if (defaultValue instanceof TypeError) { | ||
throw new TypeError(defaultValue + ' is not nully nor of ' + type[Typed.typeName]() + ' type'); | ||
module.exports.Maybe = function (Type, defaultValue) { | ||
return new MaybeType(Type, defaultValue); | ||
}; | ||
module.exports.Maybe.Type = MaybeType; | ||
/** | ||
* Class for implementing Enum | ||
* @private | ||
*/ | ||
var EnumType = function (_Type2) { | ||
_inherits(EnumType, _Type2); | ||
function EnumType(enumValues, defaultValue) { | ||
_classCallCheck(this, EnumType); | ||
var _this2 = _possibleConstructorReturn(this, (EnumType.__proto__ || Object.getPrototypeOf(EnumType)).call(this)); | ||
_this2[Typed.type] = enumValues; | ||
_this2[Typed.defaultValue] = defaultValue; | ||
if (!isArray(enumValues)) { | ||
throw new TypeError(enumValues + ' must be an array'); | ||
} | ||
if (!enumValues.length) { | ||
throw new TypeError(enumValues + ' must contain elements'); | ||
} | ||
if (typeof defaultValue !== 'undefined' && enumValues.indexOf(defaultValue) < 0) { | ||
throw new TypeError(defaultValue + ' is not in the set {' + enumValues.join(', ') + '}'); | ||
} | ||
return _this2; | ||
} | ||
if (typeof defaultValue === 'undefined' && typeof type[Typed.defaultValue] !== 'undefined') { | ||
defaultValue = type[Typed.defaultValue]; | ||
} | ||
return Typed('Maybe(' + type[Typed.typeName]() + ')', function (value) { | ||
var result = void 0; | ||
if (value == null) { | ||
result = value; | ||
} else { | ||
result = type[Typed.read](value); | ||
_createClass(EnumType, [{ | ||
key: Typed.typeName, | ||
value: function value() { | ||
var enumValues = JSON.stringify(this[Typed.type]); | ||
var defaultValue = this[Typed.defaultValue]; | ||
if (typeof defaultValue === 'undefined') { | ||
return 'Enum(' + enumValues + ')'; | ||
} | ||
return 'Enum(' + enumValues + ', ' + JSON.stringify(defaultValue) + ')'; | ||
} | ||
}, { | ||
key: Typed.read, | ||
value: function value() { | ||
var _value2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this[Typed.defaultValue]; | ||
if (result instanceof TypeError) { | ||
return TypeError('"' + value + '" is not nully nor it is of ' + type[Typed.typeName]() + ' type'); | ||
if (this[Typed.type].indexOf(_value2) < 0) { | ||
return new TypeError(_value2 + ' is not in the set {' + this[Typed.type].join(', ') + '}'); | ||
} | ||
return _value2; | ||
} | ||
return result; | ||
}, defaultValue); | ||
} | ||
}]); | ||
return EnumType; | ||
}(Type); | ||
/** | ||
@@ -182,21 +283,105 @@ * Restricts the values which can be set on a property. | ||
*/ | ||
function Enum(enumValues, defaultValue) { | ||
if (!isArray(enumValues)) { | ||
throw new TypeError(enumValues + ' must be an array'); | ||
module.exports.Enum = function (enumValues, defaultValue) { | ||
return new EnumType(enumValues, defaultValue); | ||
}; | ||
module.exports.Enum.Type = EnumType; | ||
/** | ||
* Class for implementing Discriminator | ||
* @private | ||
*/ | ||
var DiscriminatorType = function (_Type3) { | ||
_inherits(DiscriminatorType, _Type3); | ||
function DiscriminatorType(property, typeMap, defaultType) { | ||
_classCallCheck(this, DiscriminatorType); | ||
var _this3 = _possibleConstructorReturn(this, (DiscriminatorType.__proto__ || Object.getPrototypeOf(DiscriminatorType)).call(this)); | ||
_this3[Typed.type] = { | ||
property: property, | ||
typeMap: typeMap, | ||
defaultType: defaultType | ||
}; | ||
if (!property || typeof property !== 'string') { | ||
throw new TypeError(property + ' must be a string'); | ||
} | ||
if (!typeMap || (typeof typeMap === 'undefined' ? 'undefined' : _typeof(typeMap)) !== 'object') { | ||
throw new TypeError(typeMap + ' must be an object'); | ||
} | ||
var typeMapKeys = Object.keys(typeMap); | ||
if (!typeMapKeys.length) { | ||
throw new TypeError(typeMap + ' must contain at least one type mapping'); | ||
} | ||
typeMapKeys.forEach(function (key) { | ||
var type = typeMap[key]; | ||
if (!type || typeof type !== 'function' || !(type.prototype instanceof Record)) { | ||
throw new TypeError(key + ' type must be a record'); | ||
} | ||
if (!(property in type.prototype)) { | ||
throw new TypeError(key + ' type must have a ' + property + ' property'); | ||
} | ||
if (type.prototype[Typed.type][property] !== Typed.String.prototype) { | ||
throw new TypeError(key + '.' + property + ' must be a String type'); | ||
} | ||
}); | ||
if (typeof defaultType !== 'undefined') { | ||
if (!defaultType || typeof defaultType !== 'function' || !(defaultType.prototype instanceof Record)) { | ||
throw new TypeError('default type must be a record'); | ||
} | ||
if (!(property in defaultType.prototype)) { | ||
throw new TypeError('default type must have a ' + property + ' property'); | ||
} | ||
if (defaultType.prototype[Typed.type][property] !== Typed.String.prototype) { | ||
throw new TypeError('default.' + property + ' must be a String type'); | ||
} | ||
} | ||
return _this3; | ||
} | ||
if (!enumValues.length) { | ||
throw new TypeError(enumValues + ' must contain elements'); | ||
} | ||
var enumValueString = enumValues.join(', '); | ||
if (typeof defaultValue !== 'undefined' && enumValues.indexOf(defaultValue) < 0) { | ||
throw new TypeError(defaultValue + ' is not in the set {' + enumValueString + '}'); | ||
} | ||
return Typed('Enum(' + enumValueString + ')', function (value) { | ||
if (enumValues.indexOf(value) < 0) { | ||
return new TypeError(value + ' is not in the set {' + enumValueString + '}'); | ||
_createClass(DiscriminatorType, [{ | ||
key: Typed.typeName, | ||
value: function value() { | ||
var _Typed$type = this[Typed.type], | ||
property = _Typed$type.property, | ||
typeMap = _Typed$type.typeMap, | ||
defaultType = _Typed$type.defaultType; | ||
var typeMapString = JSON.stringify(Object.keys(typeMap).reduce(function (obj, key) { | ||
obj[key] = typeMap[key].prototype[Typed.typeName](); | ||
return obj; | ||
}, {})); | ||
if (typeof defaultType === 'undefined') { | ||
return 'Discriminator(' + JSON.stringify(property) + ', ' + typeMapString + ')'; | ||
} | ||
return 'Discriminator(' + JSON.stringify(property) + ', ' + typeMapString + ', ' + JSON.stringify(defaultType.prototype[Typed.typeName]()) + ')'; | ||
} | ||
return value; | ||
}, defaultValue); | ||
} | ||
}, { | ||
key: Typed.read, | ||
value: function value(_value3) { | ||
var _Typed$type2 = this[Typed.type], | ||
property = _Typed$type2.property, | ||
typeMap = _Typed$type2.typeMap, | ||
defaultType = _Typed$type2.defaultType; | ||
if (!_value3 || (typeof _value3 === 'undefined' ? 'undefined' : _typeof(_value3)) !== 'object') { | ||
return new TypeError(_value3 + ' is not an object'); | ||
} | ||
if (!(property in _value3)) { | ||
return new TypeError(_value3 + ' does not have a ' + property + ' property'); | ||
} | ||
var type = typeMap[_value3[property]] || defaultType; | ||
if (typeof type === 'undefined') { | ||
return new TypeError(_value3[property] + ' is not in the set {' + Object.keys(typeMap).join(', ') + '}'); | ||
} | ||
return _value3 instanceof type ? _value3 : new type(_value3); | ||
} | ||
}]); | ||
return DiscriminatorType; | ||
}(Type); | ||
/** | ||
@@ -238,56 +423,7 @@ * Chooses the type to use based on the value of a property. | ||
*/ | ||
function Discriminator(property, typeMap, defaultType) { | ||
if (!property || typeof property !== 'string') { | ||
throw new TypeError(property + ' must be a string'); | ||
} | ||
if (!typeMap || (typeof typeMap === 'undefined' ? 'undefined' : _typeof(typeMap)) !== 'object') { | ||
throw new TypeError(typeMap + ' must be an object'); | ||
} | ||
var typeMapKeys = Object.keys(typeMap); | ||
if (!typeMapKeys.length) { | ||
throw new TypeError(typeMap + ' must contain at least one type mapping'); | ||
} | ||
typeMapKeys.forEach(function (key) { | ||
var type = typeMap[key]; | ||
if (!type || typeof type !== 'function' || !(type.prototype instanceof Record)) { | ||
throw new TypeError(key + ' type must be a record'); | ||
} | ||
if (!(property in type.prototype)) { | ||
throw new TypeError(key + ' type must have a ' + property + ' property'); | ||
} | ||
if (type.prototype[Typed.type][property] !== Typed.String.prototype) { | ||
throw new TypeError(key + '.' + property + ' must be a String type'); | ||
} | ||
}); | ||
if (typeof defaultType !== 'undefined') { | ||
if (!defaultType || typeof defaultType !== 'function' || !(defaultType.prototype instanceof Record)) { | ||
throw new TypeError('default type must be a record'); | ||
} | ||
if (!(property in defaultType.prototype)) { | ||
throw new TypeError('default type must have a ' + property + ' property'); | ||
} | ||
if (defaultType.prototype[Typed.type][property] !== Typed.String.prototype) { | ||
throw new TypeError('default.' + property + ' must be a String type'); | ||
} | ||
} | ||
return Typed('Discriminator(' + property + ')', function (value) { | ||
if (!value || (typeof value === 'undefined' ? 'undefined' : _typeof(value)) !== 'object') { | ||
return new TypeError(value + ' is not an object'); | ||
} | ||
if (!(property in value)) { | ||
return new TypeError(value + ' does not have a ' + property + ' property'); | ||
} | ||
var type = typeMap[value[property]] || defaultType; | ||
if (typeof type === 'undefined') { | ||
return new TypeError(value[property] + ' is not in the set {' + Object.keys(typeMap).join(', ') + '}'); | ||
} | ||
return value instanceof type ? value : new type(value); | ||
}); | ||
} | ||
module.exports = { | ||
extend: extend, | ||
Maybe: Maybe, | ||
Enum: Enum, | ||
Discriminator: Discriminator | ||
}; | ||
module.exports.Discriminator = function (property, typeMap, defaultType) { | ||
return new DiscriminatorType(property, typeMap, defaultType); | ||
}; | ||
module.exports.Discriminator.Type = DiscriminatorType; |
{ | ||
"name": "@brightcove/typed-immutable-extensions", | ||
"version": "0.1.1", | ||
"version": "0.1.2", | ||
"description": "Extensions on top of typed-immutable to make it better", | ||
@@ -8,9 +8,8 @@ "main": "lib/index.js", | ||
"build": "babel src --out-dir lib", | ||
"build:all": "npm run build && npm run jsdoc:all", | ||
"build:all": "npm run build && npm run jsdoc", | ||
"pretest": "npm run lint", | ||
"test": "nyc --reporter html --reporter text mocha", | ||
"report": "nyc report --reporter=text-lcov > coverage.lcov", | ||
"lint": "eslint src test", | ||
"jsdoc": "jsdoc src -c jsdoc.conf.json --readme ./README.md", | ||
"jsdoc:md": "jsdoc2md --files src/index.js > docs/API.md", | ||
"jsdoc:all": "npm run jsdoc && npm run jsdoc:md", | ||
"jsdoc": "jsdoc2md --files src/index.js > docs/API.md", | ||
"prepublishOnly": "npm run build" | ||
@@ -30,7 +29,5 @@ }, | ||
"eslint": "^5.3.0", | ||
"jsdoc": "^3.5.5", | ||
"jsdoc-to-markdown": "^4.0.1", | ||
"mocha": "^5.2.0", | ||
"nyc": "^12.0.2", | ||
"tui-jsdoc-template": "^1.2.2", | ||
"typed-immutable": "^0.1.2" | ||
@@ -37,0 +34,0 @@ }, |
@@ -0,2 +1,6 @@ | ||
[](https://www.npmjs.com/package/@brightcove/typed-immutable-extensions) | ||
[](https://www.npmjs.com/package/@brightcove/typed-immutable-extensions) | ||
[](https://travis-ci.org/brightcove/typed-immutable-extensions) | ||
[](https://codecov.io/gh/brightcove/typed-immutable-extensions) | ||
[](https://greenkeeper.io/) | ||
@@ -27,3 +31,3 @@ # typed-immutable-extensions | ||
- Ted Janeczko - @tjaneczko | ||
- Ted Janeczko - [@tjaneczko](https://github.com/tjaneczko) | ||
@@ -30,0 +34,0 @@ ## Contributions |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
30307
25.93%8
-20%370
39.62%40
11.11%0
-100%