UNPKG

es6-class-privates

Version:

Provides a method of converting underscored pseudo-private class members into truly private class members

128 lines (101 loc) 3.99 kB
'use strict'; 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; }; var config = { privatePrefix: '_', protectedPrefix: '$', dropPrefix: true }; var findConfigErrors = function findConfigErrors(newConfig) { var validPrefixTypes = ['string', 'undefined']; var validDropPrefixTypes = ['boolean', 'undefined']; var prefixProps = ['privatePrefix', 'protectedPrefix']; var errors = []; // Config must be a valid object if ((typeof newConfig === 'undefined' ? 'undefined' : _typeof(newConfig)) !== 'object') { errors.push('Configuration must be an object'); return errors; } prefixProps.forEach(function (prop) { // Check prefix types if (!validPrefixTypes.includes(_typeof(newConfig[prop]))) { errors.push(prop + ' must be a string if provided'); } // Prefixes may not be blank strings if (newConfig[prop] === '') { errors.push('Invalid prefix for ' + prop + ': Prefix may not be a blank string'); } }); // Prefixes may not be the same var priv = newConfig.privatePrefix; var prot = newConfig.protectedPrefix; if (priv && prot && priv === prot) { errors.push('Invalid prefixes: Prefixes may not be the same'); } if (priv && !prot && priv === config.protectedPrefix) { errors.push('Invalid prefixes: Prefixes may not be the same'); } if (prot && !priv && prot === config.privatedPrefix) { errors.push('Invalid prefixes: Prefixes may not be the same'); } // Drop prefix flag must be boolean or undefined if (!validDropPrefixTypes.includes(_typeof(newConfig.dropPrefix))) { errors.push('Invalid dropPrefix flag: Must be boolean or undefined'); } return errors; }; var formatErrors = function formatErrors(errors) { return 'Invalid configuration - ' + errors.join('; ') + '.'; }; var makeMine = function makeMine() { var newConfig = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var errors = findConfigErrors(newConfig); if (errors.length > 0) throw new Error(formatErrors(errors)); var localConfig = Object.assign({}, config, newConfig); var restrictTo = function restrictTo(accessor) { return function (constructor) { var propNames = Object.getOwnPropertyNames(constructor.prototype); propNames.forEach(function (name) { var prop = constructor.prototype[name]; // Skip non-methods and constructor if (!(prop instanceof Function) || prop === constructor) return; // Handle private methods if (name.indexOf(localConfig.privatePrefix) === 0) { var newName = localConfig.dropPrefix ? name.substr(1) : name; accessor(constructor)[newName] = prop; delete constructor.prototype[name]; } }); return constructor; }; }; var bindAllTo = function bindAllTo(accessor) { return function (instance) { var constructor = Object.getPrototypeOf(instance).constructor; var propMap = accessor(constructor); Object.keys(propMap).forEach(function (name) { var prop = propMap[name]; // Skip non-methods if (!(prop instanceof Function)) return; accessor(instance)[name] = prop.bind(instance); }); return instance; }; }; var map = new WeakMap(); var accessor = function accessor(object) { if (!map.has(object)) map.set(object, {}); return map.get(object); }; accessor.restrict = restrictTo(accessor); accessor.bindAllTo = bindAllTo(accessor); return accessor; }; var configure = function configure(newConfig) { var errors = findConfigErrors(newConfig); if (errors.length > 0) throw new Error(errors); config = Object.assign({}, config, newConfig); }; module.exports = { makeMine: makeMine, configure: configure };