diff --git a/.codeclimate.yml b/.codeclimate.yml new file mode 100644 index 0000000..6fc8b18 --- /dev/null +++ b/.codeclimate.yml @@ -0,0 +1,21 @@ +engines: + duplication: + enabled: true + config: + languages: + - javascript + eslint: + enabled: true + fixme: + enabled: true + nodesecurity: + enabled: false +ratings: + paths: + - "src/**" + - "configs/**" + - "./*.js" +exclude_paths: +- "dist/**/*" +- "build/**/*" +- "tests/**/*" diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..e8cc886 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +dist/** +build/** diff --git a/.gitignore b/.gitignore index e96610e..266c816 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ logs *.log node_modules bower_components +build diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..d3845ad --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v5.0.0 diff --git a/README.md b/README.md index b3f1369..3288ebf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ EnumJS ====== -A simple way to create an immutable list of enums in ES5. +A simple way to create an immutable enumerable list aka enum. Still a WIP use at your own risk [![Codacy Badge](https://www.codacy.com/project/badge/392d48a4b14f43f3853d534e34bbdd87)](https://www.codacy.com/public/RyanBogle/EnumJS) @@ -9,22 +9,90 @@ Still a WIP use at your own risk Usage ====== +ES6 +```javascript +import $enum { assign, assignTo } from 'enumjs'; + +var myEnum = $enum( 'a', 'b', 'c' ); +``` + NodeJS ```javascript -var Enum = require('Enum').Enum; +var $enum = require( 'enumjs' ); + +$enum +// { [Function: $enum] assign: [Function: assign], assignTo: [Function: assignTo] } + +var myEnum = $enum( 'one', 'two', 'three' ); +``` + +As a browser script +```javascript +// $enum will exist on the window object after the script is loaded +var myEnum = $enum(['one', 'two', 'three']); +``` -var myEnumFromAry = new Enum(['one', 'two', 'three']); -OR -var myEnumFromObj = new Enum({one:1, two:2, three:3}); +Constructor Patterns +====== +There are several ways to create an enum, as described below +```javascript +/** + * possible argument signatures + * $enum( ...names ) + * $enum([ names ]) + * $enum({ name:value }) + * $enum( startIndex, [ names ]) +**/ ``` -ES5 Compatible Browsers + +### As an argument list ### +#### `$enum( ...names );` #### + ```javascript -// Enum will exist on the window object after the script is loaded -var myEnumFromAry = new Enum(['one', 'two', 'three']); -OR -var myEnumFromObj = new Enum({one:1, two:2, three:3}); +var myEnum = $enum( 'zero', 'one', 'two' ); + +console.log( myEnum ); +// -> Enum { zero: 0, one: 1, two: 2 } ``` +### As an array ### +#### `$enum([ names ]);` #### + +```javascript +var myEnum = $enum([ 'zero', 'one', 'two' ]); + +console.log( myEnum ); +// -> Enum { zero: 0, one: 1, two: 2 } +``` + +### As an object of own keys ### +#### `$enum({ key:value });` #### + +```javascript +var myEnum = $enum({ + PLAY: 'play', + STOP: 'stop', + SKIP: 'next' +}); + +console.log( myEnum ); +// -> Enum { PLAY: 'play', STOP: 'stop', SKIP: 'next' } +``` + +### As a starting index and array of names ### +#### `$enum( startIndex, [ names ]);` #### + +```javascript +var myEnum = $enum( 1, [ 'one', 'two', 'three' ]); + +console.log( myEnum ); +// -> Enum Enum { one: 1, two: 2, three: 3 } +``` + +Assign Functions +====== +TODO + Come back for more updates! diff --git a/bower.json b/bower.json deleted file mode 100644 index c3f6e45..0000000 --- a/bower.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "enumJS", - "version": "0.0.0", - "homepage": "https://github.com/Ashwell/EnumJS", - "authors": [ - "Ryan Bogle " - ], - "moduleType": [ - "amd", - "globals", - "node" - ], - "license": "MIT", - "private": true, - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "test", - "tests" - ] -} diff --git a/configs/rollup.config.js b/configs/rollup.config.js new file mode 100644 index 0000000..6cb62fe --- /dev/null +++ b/configs/rollup.config.js @@ -0,0 +1,12 @@ + +import babel from 'rollup-plugin-babel'; + +export default { +// exports: 'auto', + moduleName: '$enum', + sourceMap: true, + plugins: [ + babel() + ] +}; + diff --git a/configs/rollup.es6.js b/configs/rollup.es6.js new file mode 100644 index 0000000..c40a4a6 --- /dev/null +++ b/configs/rollup.es6.js @@ -0,0 +1,8 @@ + +import config from './rollup.config'; + +config.entry = 'src/api.js'; +config.format = 'es6'; +config.dest = 'dist/enum.js'; + +export default config; diff --git a/configs/rollup.tests.js b/configs/rollup.tests.js new file mode 100644 index 0000000..160230f --- /dev/null +++ b/configs/rollup.tests.js @@ -0,0 +1,12 @@ + +import multiEntry, { entry } from 'rollup-plugin-multi-entry'; +import config from './rollup.config'; + +config.entry = entry; +config.format = 'cjs'; +config.dest = 'build/enum.tests.js'; +config.external = [ 'tape' ]; + +config.plugins.push( multiEntry( 'tests/**/*.js' )); + +export default config; diff --git a/configs/rollup.umd.js b/configs/rollup.umd.js new file mode 100644 index 0000000..23f1ef8 --- /dev/null +++ b/configs/rollup.umd.js @@ -0,0 +1,8 @@ + +import config from './rollup.config'; + +config.entry = 'src/api.es5.js'; +config.format = 'umd'; +config.dest = 'dist/enum.umd.js'; + +export default config; diff --git a/dist/enum.js b/dist/enum.js new file mode 100644 index 0000000..952e647 --- /dev/null +++ b/dist/enum.js @@ -0,0 +1,271 @@ +var babelHelpers_typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { + return typeof obj; +} : function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; +}; + +var babelHelpers_toConsumableArray = function (arr) { + if (Array.isArray(arr)) { + for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; + + return arr2; + } else { + return Array.from(arr); + } +}; + +var define; +var defaults = { + configurable: false, + enumerable: true, + writable: false +}; +define = function define(instance, name, value) { + var traits = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3]; + + traits = Object.assign({}, defaults, traits, { value: value }); + return Object.defineProperty(instance, name, traits); +}; + +var define$1 = define; + +/** + * possible argument signatures + * $enum( ...names ) + * $enum({ name: value }) + * $enum([ names ]) + * $enum( startIndex, [ names ]) + * + * names can be strings or Symbols, except for when single object of own keys + * + * transformed to [ keys, [values] ] +**/ +var intRange; +var symbolsOrRange; +var getKeyValueFromObject; +intRange = function intRange(first, last) { + var curr = typeof first === 'number' ? first : 0, + arr = [curr]; + + while (last > ++curr) { + arr.push(curr); + } + + return arr; +}; + +symbolsOrRange = function symbolsOrRange(list, first, last) { + return babelHelpers_typeof(list[0]) === 'symbol' ? list : intRange(first, last); +}; + +getKeyValueFromObject = function getKeyValueFromObject(object) { + var keys = [], + values = []; + + Object.keys(object).forEach(function (key) { + keys.push(key); + values.push(object[key]); + }); + + return [keys, values]; +}; + +/*eslint func-style:0*/ +function argParse() { + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + var first = args[0]; + + var second = args[1]; + var firstType = typeof first === 'undefined' ? 'undefined' : babelHelpers_typeof(first); + + // single argument, ( object | array | string | Symbol ) + if (args.length === 1) { + var isArray = Array.isArray(first); + + // single symbol + if (firstType === 'symbol') { + return [args, args]; + } + + // single string + if (firstType === 'string') { + return [args, [0]]; + } + + // single array + if (isArray) { + return [first, symbolsOrRange(first, 0, first.length)]; + } + + // I guess it's an object + return getKeyValueFromObject(first); + } + + // two arguments, ( startIndex, [ names ]) + if (args.length === 2 && firstType === 'number' && Array.isArray(second)) { + return [second, intRange(first, second.length + first)]; + } + + // "unlimited" args, ( ...names ); + return [args, symbolsOrRange(args, 0, args.length)]; +} + +var stringReduce; +var jsonReduce; +stringReduce = function stringReduce(str, key, index) { + return '' + (index === 0 ? str : str + ', ') + key + ':' + this.values[index]; +}; + +jsonReduce = function jsonReduce(obj, key, index) { + obj[key] = this.values[index]; + return obj; +}; + +/*eslint-disable func-style*/ +function createProto(keys, values, constructor) { + /*eslint-enable func-style*/ + var proto = {}; + + define$1(proto, 'length', keys.length); + define$1(proto, 'keys', keys, { enumerable: false }); + define$1(proto, 'values', values, { enumerable: false }); + + // toString + (function () { + var stringCache = null; + + define$1(proto, 'toString', function () { + if (stringCache == null) { + stringCache = this.keys.reduce(stringReduce.bind(this), '[ ') + ' ]'; + } + + return stringCache; + }); + })(); + + //toJSON + (function () { + var jsonCache = null; + + define$1(proto, 'toJSON', function () { + if (jsonCache == null) { + jsonCache = this.keys.reduce(jsonReduce.bind(this), {}); + } + + return jsonCache; + }); + })(); + + // Well known Symbols + if (Symbol.toStringTag) { + define$1(proto, Symbol.toStringTag, 'Enum'); + } + + if (Symbol.toPrimitive) { + define$1(proto, Symbol.toPrimitive, function (hint) { + switch (hint) { + case 'number': + return this.length; + case 'string': + return '[ ' + this.keys.join(', ') + ' ]'; + default: + return true; + } + }, { enumerable: false }); + } + + /* + TODO fix missing regeneratorRuntime + define( proto, Symbol.iterator, function*() { + for ( let i = 0 ; i < this.length ; i++ ) { + let + key = this.keys[ i ], + value = this.values[ i ]; + yield { key, value }; + } + }); + */ + + proto.constructor = constructor; + return Object.freeze(proto); +} + +/*eslint-disable func-style*/ +function stringifySymbol(symbol) { + var symStr = symbol.toString(); + return symStr.slice(7, symStr.length - 1); +} + +var factory; +var $enum; +factory = function factory(keys, values) { + var Enum; + // console.log( 'factory arguments: keys, values' ); + // console.log( keys ); + // console.log( values ); + keys = babelHelpers_typeof(keys[0]) === 'symbol' ? keys.map(stringifySymbol) : keys; + + Enum = function Enum() { + var _this = this; + + keys.forEach(function (key, index) { + return define$1(_this, key, values[index]); + }); + }; + + Enum.prototype = createProto(keys, values, Enum); + return Object.freeze(new Enum()); +}; + +$enum = function $enum() { + return factory.apply(undefined, babelHelpers_toConsumableArray(argParse.apply(undefined, arguments))); +}; + +var $enum$1 = $enum; + +var assign = function assign(enumInstance, assignTo) { + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = enumInstance[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var _step$value = _step.value; + var key = _step$value.key; + var value = _step$value.value; + + define$1(assignTo, key, value); + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } +}; + +var assignTo; + +assignTo = function assignTo(assignee) { + for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + assign($enum$1.apply(undefined, args), assignee); +}; + +var assignTo$1 = assignTo; + +export { assign, assignTo$1 as assignTo };export default $enum$1; +//# sourceMappingURL=enum.js.map \ No newline at end of file diff --git a/dist/enum.js.map b/dist/enum.js.map new file mode 100644 index 0000000..adcda45 --- /dev/null +++ b/dist/enum.js.map @@ -0,0 +1 @@ +{"version":3,"file":"enum.js","sources":["../src/define.js","../src/arg-parse.js","../src/create-proto.js","../src/stringify-symbol.js","../src/enum.js","../src/assign.js","../src/assign-to.js"],"sourcesContent":["\nvar\n define,\n defaults = {\n configurable: false,\n enumerable: true,\n writable: false\n };\n\ndefine = function( instance, name, value, traits = {}) {\n traits = Object.assign({}, defaults, traits, { value });\n return Object.defineProperty( instance, name, traits );\n};\n\nexport default define;\n","\n/**\n * possible argument signatures\n * $enum( ...names )\n * $enum({ name: value })\n * $enum([ names ])\n * $enum( startIndex, [ names ])\n *\n * names can be strings or Symbols, except for when single object of own keys\n *\n * transformed to [ keys, [values] ]\n**/\nvar\n intRange,\n symbolsOrRange,\n getKeyValueFromObject;\n\nintRange = function( first, last ) {\n var\n curr = typeof first === 'number' ? first : 0,\n arr = [ curr ];\n\n while ( last > ++curr ) {\n arr.push( curr );\n }\n\n return arr;\n};\n\nsymbolsOrRange = function( list, first, last ) {\n return typeof list[ 0 ] === 'symbol' ? list : intRange( first, last );\n};\n\ngetKeyValueFromObject = function( object ) {\n var\n keys = [],\n values = [];\n\n Object.keys( object ).forEach( key => {\n keys.push( key );\n values.push( object[ key ]);\n });\n\n return [ keys, values ];\n};\n\n/*eslint func-style:0*/\nexport default function argParse( ...args ) {\n var\n [ first, second ] = args,\n firstType = typeof first;\n\n // single argument, ( object | array | string | Symbol )\n if ( args.length === 1 ) {\n let isArray = Array.isArray( first );\n\n // single symbol\n if ( firstType === 'symbol' ) {\n return [ args, args ];\n }\n\n // single string\n if ( firstType === 'string' ) {\n return [ args, [ 0 ]];\n }\n\n // single array\n if ( isArray ) {\n return [ first, symbolsOrRange( first, 0, first.length ) ];\n }\n\n // I guess it's an object\n return getKeyValueFromObject( first );\n }\n\n // two arguments, ( startIndex, [ names ])\n if ( args.length === 2 && firstType === 'number' && Array.isArray( second )) {\n return [ second, intRange( first, second.length + first ) ];\n }\n\n // \"unlimited\" args, ( ...names );\n return [ args, symbolsOrRange( args, 0, args.length ) ];\n}\n","\nimport define from './define';\n\nvar\n stringReduce,\n jsonReduce;\n\nstringReduce = function( str, key, index ) {\n return `${index === 0 ? str : str + ', '}${key}:${this.values[ index ]}`;\n};\n\njsonReduce = function( obj, key, index ) {\n obj[ key ] = this.values[ index ];\n return obj;\n};\n\n/*eslint-disable func-style*/\nexport default function createProto( keys, values, constructor ) {\n /*eslint-enable func-style*/\n var proto = {};\n\n define( proto, 'length', keys.length );\n define( proto, 'keys', keys, { enumerable: false });\n define( proto, 'values', values, { enumerable: false });\n\n // toString\n ( function() {\n var stringCache = null;\n\n define( proto, 'toString', function() {\n if ( stringCache == null ) {\n stringCache = this.keys.reduce(\n stringReduce.bind( this ),\n '[ '\n ) + ' ]';\n }\n\n return stringCache;\n });\n })();\n\n //toJSON\n ( function() {\n var jsonCache = null;\n\n define( proto, 'toJSON', function() {\n if ( jsonCache == null ) {\n jsonCache = this.keys.reduce(\n jsonReduce.bind( this ),\n {}\n );\n }\n\n return jsonCache;\n });\n })();\n\n // Well known Symbols\n if ( Symbol.toStringTag ) {\n define( proto, Symbol.toStringTag, 'Enum' );\n }\n\n if ( Symbol.toPrimitive ) {\n define( proto, Symbol.toPrimitive, function( hint ) {\n switch ( hint ) {\n case 'number':\n return this.length;\n case 'string':\n return `[ ${this.keys.join( ', ' )} ]`;\n default:\n return true;\n }\n }, { enumerable: false });\n }\n\n /*\n TODO fix missing regeneratorRuntime\n define( proto, Symbol.iterator, function*() {\n for ( let i = 0 ; i < this.length ; i++ ) {\n let\n key = this.keys[ i ],\n value = this.values[ i ];\n\n yield { key, value };\n }\n });\n */\n\n proto.constructor = constructor;\n return Object.freeze( proto );\n}\n","/*eslint-disable func-style*/\nexport default function stringifySymbol( symbol ) {\n var symStr = symbol.toString();\n return symStr.slice( 7, symStr.length - 1 );\n}\n","\nimport define from './define';\nimport argParse from './arg-parse';\nimport createProto from './create-proto';\nimport stringifySymbol from './stringify-symbol';\n\nvar\n factory,\n $enum;\n\nfactory = function( keys, values ) {\n var Enum;\n// console.log( 'factory arguments: keys, values' );\n// console.log( keys );\n// console.log( values );\n keys = typeof keys[0] === 'symbol' ? keys.map( stringifySymbol ) : keys;\n\n Enum = function() {\n keys.forEach(( key, index ) => define( this, key, values[ index ]));\n };\n\n Enum.prototype = createProto( keys, values, Enum );\n return Object.freeze( new Enum());\n};\n\n$enum = function( ...args ) {\n return factory( ...argParse( ...args ));\n};\n\nexport default $enum;\n","/*eslint-disable no-unused-vars*/\nimport define from './define';\n\nvar assign = function( enumInstance, assignTo ) {\n for ( let { key, value } of enumInstance ) {\n define( assignTo, key, value );\n }\n};\n\nexport default assign;\n","/*eslint-disable no-unused-vars*/\nimport $enum from './enum';\nimport assign from './assign';\n\nvar assignTo;\n\nassignTo = function( assignee, ...args ) {\n assign( $enum( ...args ), assignee );\n};\n\nexport default assignTo;\n"],"names":["define","$enum"],"mappings":"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"} \ No newline at end of file diff --git a/dist/enum.umd.js b/dist/enum.umd.js new file mode 100644 index 0000000..db02f08 --- /dev/null +++ b/dist/enum.umd.js @@ -0,0 +1,282 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.$enum = factory()); +}(this, function () { 'use strict'; + + var babelHelpers_typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { + return typeof obj; + } : function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; + }; + + var babelHelpers_toConsumableArray = function (arr) { + if (Array.isArray(arr)) { + for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; + + return arr2; + } else { + return Array.from(arr); + } + }; + + var define; + var defaults = { + configurable: false, + enumerable: true, + writable: false + }; + define = function define(instance, name, value) { + var traits = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3]; + + traits = Object.assign({}, defaults, traits, { value: value }); + return Object.defineProperty(instance, name, traits); + }; + + var define$1 = define; + + var assign = function assign(enumInstance, assignTo) { + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = enumInstance[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var _step$value = _step.value; + var key = _step$value.key; + var value = _step$value.value; + + define$1(assignTo, key, value); + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + }; + + /** + * possible argument signatures + * $enum( ...names ) + * $enum({ name: value }) + * $enum([ names ]) + * $enum( startIndex, [ names ]) + * + * names can be strings or Symbols, except for when single object of own keys + * + * transformed to [ keys, [values] ] + **/ + var intRange; + var symbolsOrRange; + var getKeyValueFromObject; + intRange = function intRange(first, last) { + var curr = typeof first === 'number' ? first : 0, + arr = [curr]; + + while (last > ++curr) { + arr.push(curr); + } + + return arr; + }; + + symbolsOrRange = function symbolsOrRange(list, first, last) { + return babelHelpers_typeof(list[0]) === 'symbol' ? list : intRange(first, last); + }; + + getKeyValueFromObject = function getKeyValueFromObject(object) { + var keys = [], + values = []; + + Object.keys(object).forEach(function (key) { + keys.push(key); + values.push(object[key]); + }); + + return [keys, values]; + }; + + /*eslint func-style:0*/ + function argParse() { + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + var first = args[0]; + + var second = args[1]; + var firstType = typeof first === 'undefined' ? 'undefined' : babelHelpers_typeof(first); + + // single argument, ( object | array | string | Symbol ) + if (args.length === 1) { + var isArray = Array.isArray(first); + + // single symbol + if (firstType === 'symbol') { + return [args, args]; + } + + // single string + if (firstType === 'string') { + return [args, [0]]; + } + + // single array + if (isArray) { + return [first, symbolsOrRange(first, 0, first.length)]; + } + + // I guess it's an object + return getKeyValueFromObject(first); + } + + // two arguments, ( startIndex, [ names ]) + if (args.length === 2 && firstType === 'number' && Array.isArray(second)) { + return [second, intRange(first, second.length + first)]; + } + + // "unlimited" args, ( ...names ); + return [args, symbolsOrRange(args, 0, args.length)]; + } + + var stringReduce; + var jsonReduce; + stringReduce = function stringReduce(str, key, index) { + return '' + (index === 0 ? str : str + ', ') + key + ':' + this.values[index]; + }; + + jsonReduce = function jsonReduce(obj, key, index) { + obj[key] = this.values[index]; + return obj; + }; + + /*eslint-disable func-style*/ + function createProto(keys, values, constructor) { + /*eslint-enable func-style*/ + var proto = {}; + + define$1(proto, 'length', keys.length); + define$1(proto, 'keys', keys, { enumerable: false }); + define$1(proto, 'values', values, { enumerable: false }); + + // toString + (function () { + var stringCache = null; + + define$1(proto, 'toString', function () { + if (stringCache == null) { + stringCache = this.keys.reduce(stringReduce.bind(this), '[ ') + ' ]'; + } + + return stringCache; + }); + })(); + + //toJSON + (function () { + var jsonCache = null; + + define$1(proto, 'toJSON', function () { + if (jsonCache == null) { + jsonCache = this.keys.reduce(jsonReduce.bind(this), {}); + } + + return jsonCache; + }); + })(); + + // Well known Symbols + if (Symbol.toStringTag) { + define$1(proto, Symbol.toStringTag, 'Enum'); + } + + if (Symbol.toPrimitive) { + define$1(proto, Symbol.toPrimitive, function (hint) { + switch (hint) { + case 'number': + return this.length; + case 'string': + return '[ ' + this.keys.join(', ') + ' ]'; + default: + return true; + } + }, { enumerable: false }); + } + + /* + TODO fix missing regeneratorRuntime + define( proto, Symbol.iterator, function*() { + for ( let i = 0 ; i < this.length ; i++ ) { + let + key = this.keys[ i ], + value = this.values[ i ]; + yield { key, value }; + } + }); + */ + + proto.constructor = constructor; + return Object.freeze(proto); + } + + /*eslint-disable func-style*/ + function stringifySymbol(symbol) { + var symStr = symbol.toString(); + return symStr.slice(7, symStr.length - 1); + } + + var factory; + var $enum; + factory = function factory(keys, values) { + var Enum; + // console.log( 'factory arguments: keys, values' ); + // console.log( keys ); + // console.log( values ); + keys = babelHelpers_typeof(keys[0]) === 'symbol' ? keys.map(stringifySymbol) : keys; + + Enum = function Enum() { + var _this = this; + + keys.forEach(function (key, index) { + return define$1(_this, key, values[index]); + }); + }; + + Enum.prototype = createProto(keys, values, Enum); + return Object.freeze(new Enum()); + }; + + $enum = function $enum() { + return factory.apply(undefined, babelHelpers_toConsumableArray(argParse.apply(undefined, arguments))); + }; + + var $enum$1 = $enum; + + var assignTo; + + assignTo = function assignTo(assignee) { + for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + assign($enum$1.apply(undefined, args), assignee); + }; + + var assignTo$1 = assignTo; + + $enum$1.assign = assign; + $enum$1.assignTo = assignTo$1; + + return $enum$1; + +})); +//# sourceMappingURL=enum.umd.js.map \ No newline at end of file diff --git a/dist/enum.umd.js.map b/dist/enum.umd.js.map new file mode 100644 index 0000000..214ffd4 --- /dev/null +++ b/dist/enum.umd.js.map @@ -0,0 +1 @@ +{"version":3,"file":"enum.umd.js","sources":["../src/define.js","../src/assign.js","../src/arg-parse.js","../src/create-proto.js","../src/stringify-symbol.js","../src/enum.js","../src/assign-to.js","../src/api.es5.js"],"sourcesContent":["\nvar\n define,\n defaults = {\n configurable: false,\n enumerable: true,\n writable: false\n };\n\ndefine = function( instance, name, value, traits = {}) {\n traits = Object.assign({}, defaults, traits, { value });\n return Object.defineProperty( instance, name, traits );\n};\n\nexport default define;\n","/*eslint-disable no-unused-vars*/\nimport define from './define';\n\nvar assign = function( enumInstance, assignTo ) {\n for ( let { key, value } of enumInstance ) {\n define( assignTo, key, value );\n }\n};\n\nexport default assign;\n","\n/**\n * possible argument signatures\n * $enum( ...names )\n * $enum({ name: value })\n * $enum([ names ])\n * $enum( startIndex, [ names ])\n *\n * names can be strings or Symbols, except for when single object of own keys\n *\n * transformed to [ keys, [values] ]\n**/\nvar\n intRange,\n symbolsOrRange,\n getKeyValueFromObject;\n\nintRange = function( first, last ) {\n var\n curr = typeof first === 'number' ? first : 0,\n arr = [ curr ];\n\n while ( last > ++curr ) {\n arr.push( curr );\n }\n\n return arr;\n};\n\nsymbolsOrRange = function( list, first, last ) {\n return typeof list[ 0 ] === 'symbol' ? list : intRange( first, last );\n};\n\ngetKeyValueFromObject = function( object ) {\n var\n keys = [],\n values = [];\n\n Object.keys( object ).forEach( key => {\n keys.push( key );\n values.push( object[ key ]);\n });\n\n return [ keys, values ];\n};\n\n/*eslint func-style:0*/\nexport default function argParse( ...args ) {\n var\n [ first, second ] = args,\n firstType = typeof first;\n\n // single argument, ( object | array | string | Symbol )\n if ( args.length === 1 ) {\n let isArray = Array.isArray( first );\n\n // single symbol\n if ( firstType === 'symbol' ) {\n return [ args, args ];\n }\n\n // single string\n if ( firstType === 'string' ) {\n return [ args, [ 0 ]];\n }\n\n // single array\n if ( isArray ) {\n return [ first, symbolsOrRange( first, 0, first.length ) ];\n }\n\n // I guess it's an object\n return getKeyValueFromObject( first );\n }\n\n // two arguments, ( startIndex, [ names ])\n if ( args.length === 2 && firstType === 'number' && Array.isArray( second )) {\n return [ second, intRange( first, second.length + first ) ];\n }\n\n // \"unlimited\" args, ( ...names );\n return [ args, symbolsOrRange( args, 0, args.length ) ];\n}\n","\nimport define from './define';\n\nvar\n stringReduce,\n jsonReduce;\n\nstringReduce = function( str, key, index ) {\n return `${index === 0 ? str : str + ', '}${key}:${this.values[ index ]}`;\n};\n\njsonReduce = function( obj, key, index ) {\n obj[ key ] = this.values[ index ];\n return obj;\n};\n\n/*eslint-disable func-style*/\nexport default function createProto( keys, values, constructor ) {\n /*eslint-enable func-style*/\n var proto = {};\n\n define( proto, 'length', keys.length );\n define( proto, 'keys', keys, { enumerable: false });\n define( proto, 'values', values, { enumerable: false });\n\n // toString\n ( function() {\n var stringCache = null;\n\n define( proto, 'toString', function() {\n if ( stringCache == null ) {\n stringCache = this.keys.reduce(\n stringReduce.bind( this ),\n '[ '\n ) + ' ]';\n }\n\n return stringCache;\n });\n })();\n\n //toJSON\n ( function() {\n var jsonCache = null;\n\n define( proto, 'toJSON', function() {\n if ( jsonCache == null ) {\n jsonCache = this.keys.reduce(\n jsonReduce.bind( this ),\n {}\n );\n }\n\n return jsonCache;\n });\n })();\n\n // Well known Symbols\n if ( Symbol.toStringTag ) {\n define( proto, Symbol.toStringTag, 'Enum' );\n }\n\n if ( Symbol.toPrimitive ) {\n define( proto, Symbol.toPrimitive, function( hint ) {\n switch ( hint ) {\n case 'number':\n return this.length;\n case 'string':\n return `[ ${this.keys.join( ', ' )} ]`;\n default:\n return true;\n }\n }, { enumerable: false });\n }\n\n /*\n TODO fix missing regeneratorRuntime\n define( proto, Symbol.iterator, function*() {\n for ( let i = 0 ; i < this.length ; i++ ) {\n let\n key = this.keys[ i ],\n value = this.values[ i ];\n\n yield { key, value };\n }\n });\n */\n\n proto.constructor = constructor;\n return Object.freeze( proto );\n}\n","/*eslint-disable func-style*/\nexport default function stringifySymbol( symbol ) {\n var symStr = symbol.toString();\n return symStr.slice( 7, symStr.length - 1 );\n}\n","\nimport define from './define';\nimport argParse from './arg-parse';\nimport createProto from './create-proto';\nimport stringifySymbol from './stringify-symbol';\n\nvar\n factory,\n $enum;\n\nfactory = function( keys, values ) {\n var Enum;\n// console.log( 'factory arguments: keys, values' );\n// console.log( keys );\n// console.log( values );\n keys = typeof keys[0] === 'symbol' ? keys.map( stringifySymbol ) : keys;\n\n Enum = function() {\n keys.forEach(( key, index ) => define( this, key, values[ index ]));\n };\n\n Enum.prototype = createProto( keys, values, Enum );\n return Object.freeze( new Enum());\n};\n\n$enum = function( ...args ) {\n return factory( ...argParse( ...args ));\n};\n\nexport default $enum;\n","/*eslint-disable no-unused-vars*/\nimport $enum from './enum';\nimport assign from './assign';\n\nvar assignTo;\n\nassignTo = function( assignee, ...args ) {\n assign( $enum( ...args ), assignee );\n};\n\nexport default assignTo;\n","\nimport $enum from './enum';\nimport assign from './assign';\nimport assignTo from './assign-to';\n\n$enum.assign = assign;\n$enum.assignTo = assignTo;\n\nexport default $enum;\n\n"],"names":["define","$enum","assignTo"],"mappings":"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"} \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..52704ac --- /dev/null +++ b/index.js @@ -0,0 +1,2 @@ +'use strict'; +module.exports = require( './dist/enum.umd.js' ); diff --git a/package.json b/package.json index edc95fd..c9e9ef9 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,22 @@ { - "name": "enumJS", + "name": "enumjs", + "private": true, "version": "0.0.1", "description": "A class for making ENUMs in JavaScript ES5", - "main": "src/enum.js", - "private": true, + "main": "dist/enum.umd.js", + "jsnext:main": "dest/enum.js", + "files": [ + "dist", + "README.md" + ], + "directories": { + "doc": "docs", + "lib": "dist", + "test": "tests" + }, + "keywords": [], "license": "MIT", - "author": "Ryan Bogle ", + "author": "Ryan Bogle", "homepage": "https://github.com/Ashwell/EnumJS", "repository": { "type": "git", @@ -14,17 +25,50 @@ "bugs": { "url": "https://github.com/Ashwell/EnumJS/issues" }, - "directories": { - "test": "tests" + "babel": { + "presets": [ + "es2015-rollup" + ] + }, + "pre-commit": { + "run": [ + "lint", + "test" + ] }, "scripts": { - "test": "tape 'tests/**/*.js' | tap-spec", - "posttest": "eslint ." + "clean:dist": "trash 'dist/*'", + "clean:build": "trash 'build/*'", + "lint": "eslint .", + "rollup:es6": "rollup -c configs/rollup.es6.js", + "rollup:umd": "rollup -c configs/rollup.umd.js", + "rollup:tests": "rollup -c configs/rollup.tests.js", + "rollup": "npm-run-all -s 'rollup:*'", + "browserify:tests": "browserify -e build/enum.tests.js -o build/enum.browser.tests.js", + "prebuild": "npm-run-all -s 'clean:*'", + "build": "npm-run-all -s rollup:es6 rollup:umd", + "build:tests": "npm-run-all -s rollup:tests browserify:tests", + "pretest": "npm-run-all -s build build:tests", + "test:node": "node ./build/enum.tests.js | tap-spec", + "test:browser": "node -r shelljs/global -p \"cat('build/enum.browser.tests.js')\" | tap-closer | smokestack | tap-spec", + "test": "npm-run-all -s test:node test:browser", + "prepublish": "npm run build && npm test" }, "devDependencies": { "babel-eslint": "^5.0.0-beta6", + "babel-preset-es2015-rollup": "^1.0.0", + "browserify": "^12.0.2", "eslint": "^1.10.3", + "npm-run-all": "^1.4.0", + "pre-commit": "^1.1.2", + "rollup": "^0.24.0", + "rollup-plugin-babel": "^2.3.8", + "rollup-plugin-multi-entry": "^1.0.1", + "shelljs": "^0.5.3", + "smokestack": "^3.4.1", + "tap-closer": "^1.0.0", "tap-spec": "^4.1.1", - "tape": "^4.4.0" + "tape": "^4.4.0", + "trash-cli": "^1.2.0" } } diff --git a/src/api.es5.js b/src/api.es5.js new file mode 100644 index 0000000..aaca108 --- /dev/null +++ b/src/api.es5.js @@ -0,0 +1,10 @@ + +import $enum from './enum'; +import assign from './assign'; +import assignTo from './assign-to'; + +$enum.assign = assign; +$enum.assignTo = assignTo; + +export default $enum; + diff --git a/src/api.js b/src/api.js new file mode 100644 index 0000000..6460fa1 --- /dev/null +++ b/src/api.js @@ -0,0 +1,6 @@ + +import $enum from './enum'; +export default $enum; + +export { default as assign } from './assign'; +export { default as assignTo } from './assign-to'; diff --git a/src/arg-parse.js b/src/arg-parse.js new file mode 100644 index 0000000..b8c332f --- /dev/null +++ b/src/arg-parse.js @@ -0,0 +1,83 @@ + +/** + * possible argument signatures + * $enum( ...names ) + * $enum({ name: value }) + * $enum([ names ]) + * $enum( startIndex, [ names ]) + * + * names can be strings or Symbols, except for when single object of own keys + * + * transformed to [ keys, [values] ] +**/ +var + intRange, + symbolsOrRange, + getKeyValueFromObject; + +intRange = function( first, last ) { + var + curr = typeof first === 'number' ? first : 0, + arr = [ curr ]; + + while ( last > ++curr ) { + arr.push( curr ); + } + + return arr; +}; + +symbolsOrRange = function( list, first, last ) { + return typeof list[ 0 ] === 'symbol' ? list : intRange( first, last ); +}; + +getKeyValueFromObject = function( object ) { + var + keys = [], + values = []; + + Object.keys( object ).forEach( key => { + keys.push( key ); + values.push( object[ key ]); + }); + + return [ keys, values ]; +}; + +/*eslint func-style:0*/ +export default function argParse( ...args ) { + var + [ first, second ] = args, + firstType = typeof first; + + // single argument, ( object | array | string | Symbol ) + if ( args.length === 1 ) { + let isArray = Array.isArray( first ); + + // single symbol + if ( firstType === 'symbol' ) { + return [ args, args ]; + } + + // single string + if ( firstType === 'string' ) { + return [ args, [ 0 ]]; + } + + // single array + if ( isArray ) { + return [ first, symbolsOrRange( first, 0, first.length ) ]; + } + + // I guess it's an object + return getKeyValueFromObject( first ); + } + + // two arguments, ( startIndex, [ names ]) + if ( args.length === 2 && firstType === 'number' && Array.isArray( second )) { + return [ second, intRange( first, second.length + first ) ]; + } + + // "unlimited" args, ( ...names ); + return [ args, symbolsOrRange( args, 0, args.length ) ]; +} diff --git a/src/assign-to.js b/src/assign-to.js new file mode 100644 index 0000000..be73e29 --- /dev/null +++ b/src/assign-to.js @@ -0,0 +1,11 @@ +/*eslint-disable no-unused-vars*/ +import $enum from './enum'; +import assign from './assign'; + +var assignTo; + +assignTo = function( assignee, ...args ) { + assign( $enum( ...args ), assignee ); +}; + +export default assignTo; diff --git a/src/assign.js b/src/assign.js new file mode 100644 index 0000000..530e5f4 --- /dev/null +++ b/src/assign.js @@ -0,0 +1,10 @@ +/*eslint-disable no-unused-vars*/ +import define from './define'; + +var assign = function( enumInstance, assignTo ) { + for ( let { key, value } of enumInstance ) { + define( assignTo, key, value ); + } +}; + +export default assign; diff --git a/src/create-proto.js b/src/create-proto.js new file mode 100644 index 0000000..e017e96 --- /dev/null +++ b/src/create-proto.js @@ -0,0 +1,91 @@ + +import define from './define'; + +var + stringReduce, + jsonReduce; + +stringReduce = function( str, key, index ) { + return `${index === 0 ? str : str + ', '}${key}:${this.values[ index ]}`; +}; + +jsonReduce = function( obj, key, index ) { + obj[ key ] = this.values[ index ]; + return obj; +}; + +/*eslint-disable func-style*/ +export default function createProto( keys, values, constructor ) { + /*eslint-enable func-style*/ + var proto = {}; + + define( proto, 'length', keys.length ); + define( proto, 'keys', keys, { enumerable: false }); + define( proto, 'values', values, { enumerable: false }); + + // toString + ( function() { + var stringCache = null; + + define( proto, 'toString', function() { + if ( stringCache == null ) { + stringCache = this.keys.reduce( + stringReduce.bind( this ), + '[ ' + ) + ' ]'; + } + + return stringCache; + }); + })(); + + //toJSON + ( function() { + var jsonCache = null; + + define( proto, 'toJSON', function() { + if ( jsonCache == null ) { + jsonCache = this.keys.reduce( + jsonReduce.bind( this ), + {} + ); + } + + return jsonCache; + }); + })(); + + // Well known Symbols + if ( Symbol.toStringTag ) { + define( proto, Symbol.toStringTag, 'Enum' ); + } + + if ( Symbol.toPrimitive ) { + define( proto, Symbol.toPrimitive, function( hint ) { + switch ( hint ) { + case 'number': + return this.length; + case 'string': + return `[ ${this.keys.join( ', ' )} ]`; + default: + return true; + } + }, { enumerable: false }); + } + + /* + TODO fix missing regeneratorRuntime + define( proto, Symbol.iterator, function*() { + for ( let i = 0 ; i < this.length ; i++ ) { + let + key = this.keys[ i ], + value = this.values[ i ]; + + yield { key, value }; + } + }); + */ + + proto.constructor = constructor; + return Object.freeze( proto ); +} diff --git a/src/define.js b/src/define.js new file mode 100644 index 0000000..c2a1da2 --- /dev/null +++ b/src/define.js @@ -0,0 +1,15 @@ + +var + define, + defaults = { + configurable: false, + enumerable: true, + writable: false + }; + +define = function( instance, name, value, traits = {}) { + traits = Object.assign({}, defaults, traits, { value }); + return Object.defineProperty( instance, name, traits ); +}; + +export default define; diff --git a/src/enum.js b/src/enum.js index 060cd7d..d9fdb45 100644 --- a/src/enum.js +++ b/src/enum.js @@ -1,150 +1,30 @@ -/*globals module */ -!(function(){ - 'use strict'; - var exports; +import define from './define'; +import argParse from './arg-parse'; +import createProto from './create-proto'; +import stringifySymbol from './stringify-symbol'; - if( typeof window !== 'undefined'){ - exports = window; - } else if( typeof module !== 'undefined' ){ - exports = module.exports; - } else { - console.warn('I don\'t know where to export to....Enums.js'); - exports = {}; - } +var + factory, + $enum; -exports.Enum = (function () { - var Enum = function ( enums ) { - var i, - keys = [], - values = [], - length = 0; +factory = function( keys, values ) { + var Enum; +// console.log( 'factory arguments: keys, values' ); +// console.log( keys ); +// console.log( values ); + keys = typeof keys[0] === 'symbol' ? keys.map( stringifySymbol ) : keys; -// if(!(enums instanceof Array)){ -// throw new SyntaxError('Enum input must be an Array'); -// } - - if ( enums instanceof Array ) { - for ( i = 0 ; i < enums.length ; i++ ) { - try { - Object.defineProperty( - this, - enums[i], - { - configurable: false, - enumerable: true, - value: i, - writable: false - } - ); - ++length; - values.push(i); - keys.push(enums[i]); - } catch (e) { - throw new TypeError('Enum Constructor Failure, you must pass a set of unique keys.'); - } - } - } else if ( enums instanceof Object ) { - for ( i in enums ) { - if ( enums.hasOwnProperty(i) ) { - if ( values.lastIndexOf(enums[i]) !== -1 ) { - throw new TypeError('Enum Constructor Failure, you must pass a unique value for each key'); - } - try { - Object.defineProperty( - this, - i, - { - configurable: false, - enumerable: true, - value: enums[i], - writable: false - } - ); - ++length; - values.push(enums[i]); - keys.push(i); - } catch (e) { - throw new TypeError('Enum Constructor Failure.'); - } - } - } - } - - Object.defineProperty(this, 'length', { - configurable: false, - enumerable: false, - value: length, - writable: false - }); - -// Object.defineProperty(this, 'keys', { -// configurable: false, -// enumerable: false, -// value: keys, -// writable: false -// }); -// Object.defineProperty(this, 'values', { -// configurable: false, -// enumerable: false, -// value: values, -// writable: false -// }); - - return Object.freeze(this); + Enum = function() { + keys.forEach(( key, index ) => define( this, key, values[ index ])); }; - // Prototype Functions - Object.defineProperties(Enum.prototype, { - /*'length':{ - configurable: false, - enumerable: false, - get: function () { - var count = 0; - for ( var prop in this ){ - ++count; - } - return count; - //return this.keys.length; - } - },*/ - 'keys':{ - configurable: false, - enumerable: false, - get: function () { - var keys = []; - for ( var prop in this ){ - if ( this.hasOwnProperty(prop) ){ - keys.push(prop); - } - } - return keys; - } - }, - 'values':{ - configurable: false, - enumerable: false, - get: function () { - var values = []; - for ( var prop in this ){ - if ( this.hasOwnProperty(prop) ){ - values.push(this[prop]); - } - } - return values; - } - }, - 'toString':{ - configurable: false, - enumerable: false, - writable: false, - value: function(){return '[object Enum]';} - } - }); - - // Export - return Enum; + Enum.prototype = createProto( keys, values, Enum ); + return Object.freeze( new Enum()); +}; -})(); +$enum = function( ...args ) { + return factory( ...argParse( ...args )); +}; -})(); +export default $enum; diff --git a/src/stringify-symbol.js b/src/stringify-symbol.js new file mode 100644 index 0000000..5a63406 --- /dev/null +++ b/src/stringify-symbol.js @@ -0,0 +1,5 @@ +/*eslint-disable func-style*/ +export default function stringifySymbol( symbol ) { + var symStr = symbol.toString(); + return symStr.slice( 7, symStr.length - 1 ); +} diff --git a/tests/api.js b/tests/api.js new file mode 100644 index 0000000..5d0520f --- /dev/null +++ b/tests/api.js @@ -0,0 +1,11 @@ + +import test from 'tape'; +import $enum, { assign, assignTo } from '../src/api'; + +test( 'proper default and named exports', function( assert ) { + assert.equal( typeof $enum, 'function', '$enum is a function' ); + assert.equal( typeof assign, 'function', 'assign is a function and named export' ); + assert.equal( typeof assignTo, 'function', 'assignTo is a function and named export' ); + assert.end(); +}); + diff --git a/tests/assign-to.js b/tests/assign-to.js new file mode 100644 index 0000000..9fc270c --- /dev/null +++ b/tests/assign-to.js @@ -0,0 +1,21 @@ + +import test from 'tape'; +import { assignTo } from '../src/api'; + +var args = [ 'one', 'two', 'three' ]; + +test.skip( 'assignTo takes enum arguments', function( assert ) { + var assignee = {}; + + assignTo( assignee, args ); + + assert.deepEqual( + Object.keys( assignee ), + args, + 'own keys match arguments array' + ); + + + assert.end(); +}); + diff --git a/tests/assign.js b/tests/assign.js new file mode 100644 index 0000000..eaee969 --- /dev/null +++ b/tests/assign.js @@ -0,0 +1,21 @@ + +import test from 'tape'; +import $enum, { assign } from '../src/api'; + +var args = [ Symbol( 'one' ), Symbol( '2' ), Symbol( 'three' ) ]; + +test.skip( 'assign takes enum instance', function( assert ) { + var + assignee = {}, + myEnum = $enum( args ); + + assign( myEnum, assignee ); + + assert.deepEqual( + Reflect.ownKeys( assignee ), + args, + 'own keys of assignee match enum' + ); + + assert.end(); +}); diff --git a/tests/browser.html b/tests/browser.html new file mode 100644 index 0000000..396d1ee --- /dev/null +++ b/tests/browser.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/create.js b/tests/create.js index b59661e..4190433 100644 --- a/tests/create.js +++ b/tests/create.js @@ -1,39 +1,132 @@ -'use strict'; + +import test from 'tape'; +import $enum from '../src/api'; var - test = require( 'tape' ), - Enum = require( '../src/enum' ).Enum; + descriptor, + addValue; + +descriptor = { + configurable: false, + enumerable: true, + writable: false +}; -test( 'enums can be created from a list of strings', function( assert ) { +addValue = function( value ) { + return Object.assign( descriptor, { value }); +}; + +/* constructor tests */ +test( '$enum( ...names )', function( assert ) { var - args = [ 'one', 'two', 'three', 'four', 'five' ], - myEnum = new Enum( args ); + i = 0, + args = [ 'zero', 'one', 'two', 'three' ], + myEnum = $enum( ...args ); - args.forEach(function( propName ) { - assert.true( propName in myEnum, propName + ' is in enum' ); - }); + for ( let prop in myEnum ) { + if ( myEnum.hasOwnProperty( prop )) { + assert.deepEqual( + Object.getOwnPropertyDescriptor( myEnum, prop ), + addValue( i ), + `property ${ prop } has enum descriptor with value ${ i }` + ); + i++; + } + } + assert.equal( i, args.length, 'iterated properties count matches argument list length' ); assert.end(); }); -test( 'enums can be created from an object of name:value pairs', function( assert ) { +test( '$enum( { name: value })', function( assert ) { var - args = { - 1: 'one', - 2: 'two', - 3: 'three', - 4: 'four', - 5: 'five' + length = 0, + argument = { + 1: 'a', + 2: 'b', + 3: 'c', + 4: 'd', + 5: 'e' }, - myEnum = new Enum( args ); + myEnum = $enum( argument ); + + for ( let prop in argument ) { + if ( argument.hasOwnProperty( prop )) { + let value = argument[ prop ]; + assert.equals( + value, + myEnum[ prop ], + `enum value mirrors object based argument, ${ prop }:${ value }` + ); + length++; + } + } + + for ( let prop in myEnum ) { + if ( myEnum.hasOwnProperty( prop )) { + assert.deepEqual( + Object.getOwnPropertyDescriptor( myEnum, prop ), + addValue( argument[ prop ]), + `property ${ prop } has enum descriptor with value ${ myEnum[ prop ]}` + ); + length--; + } + } + + assert.equal( length, 0, 'iterated properties count matches for both argument and enum' ); + assert.end(); +}); + +test( '$enum([ names ])', function( assert ) { + var + i = 0, + args = [ 'zero', 'one', 'two' ], + myEnum = $enum( args ); + + for ( let prop in myEnum ) { + if ( myEnum.hasOwnProperty( prop )) { + assert.deepEqual( + Object.getOwnPropertyDescriptor( myEnum, prop ), + addValue( i ), + `property ${ prop } has enum descriptor with value ${ i }` + ); + i++; + } + } + + assert.equals( i, args.length, 'iterated properties count matches argument length' ); + assert.end(); +}); + +test( '$enum( startIndex, [ names ])', function( assert ) { + var + i = 0, + startIndex = 2, + enumValues, + enumList = [ 'two', 'three', 'four', 'five', '6' ], + myEnum = $enum( startIndex, enumList ); - Object.keys( args ).forEach(function( propName ) { - var value = args[ propName ]; + enumValues = { + two: 2, + three: 3, + four: 4, + five: 5, + 6: 6 + }; - assert.true( propName in myEnum, propName + ' is in enum' ); - assert.true( value === myEnum[ propName ], propName + ' maps to ' + value + ' in enum' ); - }); + for ( let prop in myEnum ) { + if ( myEnum.hasOwnProperty( prop )) { + let value = enumValues[ prop ]; + assert.deepEqual( + Object.getOwnPropertyDescriptor( myEnum, prop ), + addValue( value ), + `property ${ prop } has enum descriptor with value ${ value }` + ); + i++; + } + } + assert.equals( i, enumList.length, 'iterated properties count matches enum argument list' ); assert.end(); }); diff --git a/tests/proto.js b/tests/proto.js new file mode 100644 index 0000000..b395088 --- /dev/null +++ b/tests/proto.js @@ -0,0 +1,54 @@ + +import test from 'tape'; +import $enum from '../src/api'; + +// Properties +// length +test( 'has prototype property, length', function( assert ) { + // todo + assert.end(); +}); +// keys +test( 'has prototype property, keys', function( assert ) { + // todo + assert.end(); +}); +// values +test( 'has prototype property, values', function( assert ) { + // todo + assert.end(); +}); + +// Methods +// toString +test( 'has prototype function, toString', function( assert ) { + // todo + assert.end(); +}); +// toJSON +test( 'has prototype function, toJSON', function( assert ) { + // todo + assert.end(); +}); +test( 'toJSON is reflexive with object style constructor', function( assert ) { + var + myEnum = $enum( 1, [ 'one', 'two', 'three' ]), + fromJSON = $enum( JSON.parse( JSON.stringify( myEnum ))); + + assert.deepEqual( myEnum, fromJSON, 'created enum deeply equals original' ); + assert.end(); +}); + +// Symbols +// .toStringTag +test.skip( 'has prototype symbol, toStringTag', function( assert ) { + // todo +}); +// .toPrimitive +test.skip( 'has prototype symbol, toPrimitive', function( assert ) { + // todo +}); +// .iterator +test.skip( 'has prototype symbol, iterator', function( assert ) { + // todo +});