0.9.6 • Published 8 years ago

primitive-enum v0.9.6

Weekly downloads
3
License
MIT
Repository
github
Last release
8 years ago

primitive-enum

version npm build status Coveralls deps status mit license

Primitive-enum is a a lightweight generator of immutable enums that aims to optimize convenience and utility without resorting to enumerated keys, values, or pairs wrapped in objects. This enum facility may be the best fit if you:

  • want convenient lookup for both properties and values
  • need full control over how values are generated for enumerated properties
  • want to maximize interoperability by keeping values primitive (string, int, float)
  • want the reliability of immutable enums
  • or just want to keep enum usage terse

Basic Usage

Create a new enum. Enjoy.

const Enum = require('primitive-enum');

const myEnum = Enum({a: 'x', c: 'z', b: 'y'});

// myEnum is identifiable
myEnum instanceof Enum; // => true
myEnum.name; // => 'PrimitiveEnum'

// myEnum provides immutable metadata
myEnum.keys; // => ['a', 'c', 'b'];
myEnum.values; // => ['x', 'z', 'y'];
myEnum.map; // => {a: 'x', c: 'z', b: 'y'}
myEnum.reverseMap; // => {x: 'a', z: 'c', y: 'b'}
myEnum.defaultKey; // => 'a'
myEnum.defaultValue; // => 'x'
myEnum.count; // => 3

// myEnum supports multiple forms of expression and lookup
myEnum.a; // => 'x'
myEnum['a']; // => 'x'
myEnum('a'); // => 'x'
myEnum.value('a') // => 'x'
myEnum.value('x') // => undefined

myEnum.x; // => 'a'
myEnum['x']; // => 'a'
myEnum('x'); // => 'a'
myEnum.key('x') // => 'a'
myEnum.key('a') // => undefined

// myEnum is iterable
var keys = [];
for(var key in myEnum) {
    keys.push(key);
}
keys; // => ['a', 'c', 'b']

In the Browser

Coming soon.

API

Construction

const myEnum = Enum(mapping, options);
  • mapping is either an object defining key => value enum pairs, or an array listing only keys.
  • options is either a configuration object or one of the properties accepted in one:
    • options.defaultKey is a string identifying the default key (and by extension default value). If unspecified, it will be the first key defined.
    • options.transform is a function of the form fn(value, key|idx) => enum-value used to transform or generate the enum values to pair with keys. Several built-in transform options are available, along with configurable default behavior. See Value Transforms.

Retrieval

Access enum keys and values, in original order.

Enum.keys
myEnum.keys; // => ['a', 'c', 'b']
Enum.values
myEnum.values; // => ['x', 'z', 'y']

Access forward and reverse mappings as immutable objects.

Enum.map
myEnum.map; // => {a: 'x', c: 'z', b: 'y'}
Enum.reverseMap
myEnum.reverseMap; // => {x: 'a', z: 'c', y: 'b'}

Lookup

Find any value or key by its corresponding property-like pair.

Enum.propname
myEnum.a; // => 'x'
myEnum.x; // => 'a'

For non-strings and strings that cannot be used as property names, use array or function access.

Enum'propname'
const uglyEnum = {'string with spaces': 12}

uglyEnum['string with spaces']; // => 12
uglyEnum[''+12]; // => 'string with spaces'

Note that array lookup must be by string keys or values cast to strings. The returned value for any key will however be in its original primitive form. Lookups by non-string primitive types can be performed using the following function-based lookup options.

Primitive-enum is not intended to support non-primitive keys or values.

Enum(prop)
uglyEnum('string with spaces'); // => 12
uglyEnum(12); // => 'string with spaces'

For explicit lookup among only keys or values, use one-way lookup methods.

Enum.key(value)
myEnum.key('x'); // => 'a'
myEnum.key('a'); // => undefined
Enum.value(key)
myEnum.value('a'); // => 'x'
myEnum.value('x'); // => undefined

Extras

PrimitiveEnums also specify a default key/value, which is initially the first pair defined.

Enum.defaultKey
myEnum.defaultKey; // => 'a'
myEnum.defaultKey = 'b'; // throws Error
Enum.defaultValue
myEnum.defaultValue; // => 'x'
myEnum.defaultValue = 'y'; // throws Error

PrimitiveEnum instances are string-comparable - so long as their enumerated values are comparable primitives - and serializable. The constructed results are preserved, but details of construction are discarded.

Enum.toString()
const
    enum1 = Enum(['a', 'b', 'c'], Enum.bitwise),
    enum2 = Enum({a: 1, b: 2, c: 4});

enum1.toString(); // => '[Function: PrimitiveEnum] a,b,c|1,2,4|0
''+enum1 == enum2; // => true
Enum.fromJSON(str|obj)
const jsonStr = JSON.stringify(myEnum);
const copiedEnum = Enum.fromJSON(jsonStr);
''+copiedEnum == myEnum; // => true

Value Transforms

When constructing an enum from an array, the array values are treated as enum keys. When constructing an enum from an object, the property names are treated as enum keys. In either case, the object/array keys/indices and values are passed through a transform function to determine the paired enum values. Several standard options are made available through the enum constructor, and as well as configuration properties to alter the default choices.

  • Enum.defaultArrayTransform Default transform to use on arrays. Initially Enum.sequence
  • Enum.defaultObjectTransform Default transform to use on objects. Initially unset (Enum.defaultTransform is used instead).
  • Enum.defaultTransform Default transform to use for arrays or objects if no input-type-specific transform is provided. Initially Enum.identity. Changing is supported but not advised.
Enum.identity
const identEnum = Enum(['a', 'b', 'c'], Enum.identity);
identEnum.map; // => {'a': 'a', 'b': 'b', 'c': 'c'}

const normalEnum = Enum({a: 'x', b: 'y', c: 'z'}, Enum.identity);
normalEnum.map; // => {a: 'x', b: 'y', c: 'z'}

Straightforward identity mapping: key === value. Final default option, supports objects and arrays.

Enum.sequence
const seqEnum = Enum(['a', 'b', 'c'], Enum.sequence);
seqEnum.map; // => {'a': 1, 'b': 2, 'c': 3};

Basic incrementing integer values for array inputs. Starts at 1 so that the enumeration contains no falsey values. For arrays only. Default option for arrays.

Enum.bitwise
const bitEnum = Enum(['a', 'b', 'c'], Enum.bitwise);
bitEnum.map; // => {'a': 1, 'b': 2, 'c': 4}

Sequence of incrementing powers of 2. While primitive-enum provides no support for bitwise comparisons or combinations (yet), this will play nicely with other tools that do. For arrays only.

Enum.idString
const colorEnum = Enum(['RED', 'BLUE', 'COUNTRY_ROSE'], Enum.idString);
colorEnum.map; // => {RED: 'red', BLUE: 'blue', COUNTRY_ROSE: 'country-rose'}

Provides conversion from SCREAMING_SNAKE to winding-river format, as an option for working with classic c-style constant naming conventions, where string values are also needed. For arrays only.

Example custom transforms

Arrays send value, idx as arguments. Objects send propvalue, propname as arguments.

// Generate values based on enum keys (from array or object)
const ucKeys = (propvalue, propname) => propname.toUpperCase();
const ucKeysEnum = Enum({a: 1, b: 2}, ucKeys);
ucKeysEnum.map; // => {a: 'A', b: 'B'}

const ucArr = (value, idx) => value.toUpperCase();
const ucArrEnum = Enum(['a', 'b'], ucArr);
ucArrEnum.map; // => {a: 'A', b: 'B'}

// Generate values based on array indices
const even = (value, idx) => (idx+1) * 2;
const evenEnum = Enum(['a', 'b'], even);
evenEnum.map; // => {a: 2, b: 4}

Limitations

By design, primitive-enum does not allow the same value to be used as two different keys nor as two different values. Additionally, no same value may be used as both enum key and enum value, except in the case of matching key-value pairs where key == value. This is partly to enforce good enum-defining conventions, but primarily to minimize limitations of using the most concise means of performing enum lookups - which map keys and values interchangeably.

Lastly, all enum keys and values are expected to be simple primitives, castable to strings. Instead supplying custom objects which cast to (unique) strings may also work, but is not explicitly supported.

Roadmap

The following features are planned for the 1.0 release:

  • Package for client-side use (include es5-compatible dist/primitive-enum.js with browser test coverage).

And for subsequent 1.x releases:

  • Add minified source dist/primitive-enum.min.js.
  • Add support for aliases (options.aliases probably as map of key => alternate keys).
0.9.6

8 years ago

0.9.5

8 years ago

0.9.4

8 years ago

0.9.3

8 years ago

0.9.2

8 years ago

0.9.1

8 years ago