enum-plus
Version:
A drop-in replacement for native enum. Like native enum but much better!
378 lines (366 loc) • 17 kB
JavaScript
var _Symbol$hasInstance;
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
import { EnumItemClass } from "./enum-item.js";
import { IS_ENUM_ITEMS, KEYS, VALUES } from "./utils.js";
/**
* Enum items array, mostly are simple wrappers for EnumCollectionClass
*
* @template T Type of the initialization data of the enum collection
*
* @class EnumItemsArray
*
* @extends {EnumItemClass<T, K, V>[]}
*
* @implements {IEnumItems<T, K, V>}
*/
_Symbol$hasInstance = Symbol.hasInstance;
export var EnumItemsArray = /*#__PURE__*/function (_ref) {
_inherits(EnumItemsArray, _ref);
var _super = _createSuper(EnumItemsArray);
/**
* Instantiate an enum items array
*
* @memberof EnumItemsArray
*
* @param {T} raw Original initialization data object
* @param {EnumItemOptions<T[K], K, V, P> | undefined} options Enum item options
*/
function EnumItemsArray(raw, options) {
var _this;
_classCallCheck(this, EnumItemsArray);
_this = _super.call(this);
// Do not use class field here, because don't want print this field in Node.js
_defineProperty(_assertThisInitialized(_this), "__raw__", void 0);
_defineProperty(_assertThisInitialized(_this), KEYS, void 0);
_defineProperty(_assertThisInitialized(_this), VALUES, void 0);
_defineProperty(_assertThisInitialized(_this), "labels", void 0);
_defineProperty(_assertThisInitialized(_this), "named", void 0);
_defineProperty(_assertThisInitialized(_this), "meta", void 0);
_defineProperty(_assertThisInitialized(_this), "_runtimeError", void 0);
Object.defineProperty(_assertThisInitialized(_this), '__raw__', {
value: raw,
enumerable: false,
writable: false,
configurable: false
});
// Generate keys array
// exclude number keys with a "reverse mapping" value, it means those "reverse mapping" keys of number enums
var keys = parseKeys(raw);
var parsed = keys.map(function (key) {
return parseEnumItem(raw[key], key);
});
_this[KEYS] = keys;
Object.freeze(keys);
var items = [];
var meta = {};
_this.meta = meta;
var named = {};
_this.named = named;
keys.forEach(function (key, index) {
var _parsed$index = parsed[index],
value = _parsed$index.value,
label = _parsed$index.label;
var item = new EnumItemClass(key, value, label, raw[key], options);
items.push(item);
_this.push(item);
named[key] = item;
// Collect custom meta fields
var itemRaw = raw[key];
if (itemRaw && _typeof(itemRaw) === 'object') {
Object.keys(itemRaw).forEach(function (k) {
var metaKey = k;
if (metaKey !== 'key' && metaKey !== 'value' && metaKey !== 'label') {
if (meta[metaKey] == null) {
meta[metaKey] = [];
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var metaValue = itemRaw[metaKey];
if (metaValue != null) {
meta[metaKey].push(metaValue);
}
}
});
}
});
// Freeze meta arrays
Object.keys(meta).forEach(function (k) {
Object.freeze(meta[k]);
});
// Generate values array
var values = parsed.map(function (item) {
return item.value;
});
_this[VALUES] = values;
Object.freeze(values);
// Generate labels array
Object.defineProperty(_assertThisInitialized(_this), 'labels', {
get: function get() {
// Cannot save to static array because labels may be localized contents
// Should not use `items` in the closure because the getter function cannot be fully serialized
return Array.from(this).map(function (item) {
return item.label;
});
},
enumerable: true,
configurable: false
});
_this._runtimeError = undefined;
Object.defineProperty(_assertThisInitialized(_this), '_runtimeError', {
value: function value(name) {
return "The ".concat(name, " property of the enumeration is only allowed to be used to declare the ts type, and cannot be accessed at runtime! Please use the typeof operator in the ts type, for example: typeof Week.").concat(name);
},
writable: false,
enumerable: false,
configurable: false
});
return _this;
}
_createClass(EnumItemsArray, [{
key: IS_ENUM_ITEMS,
get:
/**
* - **EN:** A boolean value indicates that this is an enum items array.
* - **CN:** 布尔值,表示这是一个枚举项数组
*/
// Do not use readonly field here, because don't want print this field in Node.js
// eslint-disable-next-line @typescript-eslint/class-literal-property-style
function get() {
return true;
}
}, {
key: _Symbol$hasInstance,
value: function value(instance) {
// intentionally use == to support both number and string format value
return this.some(
// eslint-disable-next-line eqeqeq
function (i) {
return instance == i.value || instance === i.key;
});
}
}, {
key: "label",
value: function label(keyOrValue) {
var _ref2, _this$find;
// Find by value, then try key
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (_ref2 = (_this$find = this.find(function (i) {
return i.value === keyOrValue;
})) !== null && _this$find !== void 0 ? _this$find : this.find(function (i) {
return i.key === keyOrValue;
})) === null || _ref2 === void 0 ? void 0 : _ref2.label;
}
}, {
key: "key",
value: function key(value) {
var _this$find2;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (_this$find2 = this.find(function (i) {
return i.value === value;
})) === null || _this$find2 === void 0 ? void 0 : _this$find2.key;
}
}, {
key: "raw",
value: function raw(keyOrValue) {
if (keyOrValue == null) {
// Return the original initialization object
return this.__raw__;
} else {
// Find by key
if (Object.keys(this.__raw__).some(function (k) {
return k === keyOrValue;
})) {
return this.__raw__[keyOrValue];
}
// Find by value
var itemByValue = this.find(function (i) {
return i.value === keyOrValue;
});
if (itemByValue) {
return itemByValue.raw;
}
return undefined;
}
}
}, {
key: "has",
value: function has(keyOrValue) {
return this.some(function (i) {
return i.value === keyOrValue || i.key === keyOrValue;
});
}
}, {
key: "findBy",
value: function findBy(field, value) {
return this.find(function (item) {
if (field === 'key' || field === 'value') {
return item[field] === value;
} else if (field === 'label') {
var _item$raw;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return ((_item$raw = item.raw) === null || _item$raw === void 0 ? void 0 : _item$raw.label) === value || item.label === value;
} else {
var _item$raw2;
// For other fields, use the raw object to find
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return ((_item$raw2 = item.raw) === null || _item$raw2 === void 0 ? void 0 : _item$raw2[field]) === value;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
});
}
}, {
key: "toList",
value: function toList(config) {
var _ref3 = config !== null && config !== void 0 ? config : {},
_ref3$valueField = _ref3.valueField,
valueField = _ref3$valueField === void 0 ? 'value' : _ref3$valueField,
_ref3$labelField = _ref3.labelField,
labelField = _ref3$labelField === void 0 ? 'label' : _ref3$labelField,
extra = _ref3.extra;
return Array.from(this).map(function (item) {
var valueFieldName = typeof valueField === 'function' ? valueField(item) : valueField;
var labelFieldName = typeof labelField === 'function' ? labelField(item) : labelField;
var extraData = extra ? extra(item) : {};
var listItem = _objectSpread(_defineProperty(_defineProperty({}, valueFieldName, item.value), labelFieldName, item.label), extraData);
return listItem;
});
}
}, {
key: "toMap",
value: function toMap(config) {
if (!config) {
return this.reduce(function (prev, cur) {
prev[cur.value] = cur.label;
return prev;
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
{});
}
var _config$keySelector = config.keySelector,
keySelector = _config$keySelector === void 0 ? 'value' : _config$keySelector,
_config$valueSelector = config.valueSelector,
valueSelector = _config$valueSelector === void 0 ? 'label' : _config$valueSelector;
return this.reduce(function (prev, cur) {
var key;
if (typeof keySelector === 'function') {
key = keySelector(cur);
} else {
key = cur[keySelector];
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var value;
if (typeof valueSelector === 'function') {
value = valueSelector(cur);
} else {
value = cur[valueSelector];
}
prev[key] = value;
return prev;
}, {});
}
/** Stub method, only for typing usages, not for runtime calling */
}, {
key: "valueType",
get: function get() {
throw new Error(this._runtimeError('valueType'));
}
/** Stub method, only for typing usages, not for runtime calling */
}, {
key: "keyType",
get: function get() {
throw new Error(this._runtimeError('keyType'));
}
/** Stub method, only for typing usages, not for runtime calling */
}, {
key: "rawType",
get: function get() {
throw new Error(this._runtimeError('rawType'));
}
}]);
return EnumItemsArray;
}(Array);
/**
* - **EN:** Enum item collection interface, excluding members inherited from the array
* - **CN:** 枚举项集合接口,不包含从数组集成的成员
*
* @template T The type of enum initialization | 枚举初始化的类型
* @template K The type of enum keys | 枚举键的类型
* @template V The type of enum values | 枚举值的类型
*
* @interface IEnumItems
*/
// typeof IS_ENUM_ITEMS | typeof ITEMS | typeof KEYS | typeof VALUES | 'labels' | 'meta' | 'named'
/** More options for the options method */
export function parseKeys(raw) {
return Object.keys(raw).filter(function (k) {
var _raw;
return !(/^-?\d+$/.test(k) && k === "".concat((_raw = raw[raw[k]]) !== null && _raw !== void 0 ? _raw : ''));
});
}
function parseEnumItem(init, key) {
var value;
var label;
if (init != null) {
if (typeof init === 'number' || typeof init === 'string' || _typeof(init) === 'symbol') {
value = init;
label = key;
} else if (_typeof(init) === 'object') {
// Initialize using object
if (Object.prototype.toString.call(init) === '[object Object]') {
if ('value' in init && Object.keys(init).some(function (k) {
return k === 'value';
})) {
var _init$value;
// type of {value, label}
value = (_init$value = init.value) !== null && _init$value !== void 0 ? _init$value : key;
if ('label' in init && Object.keys(init).some(function (k) {
return k === 'label';
})) {
label = init.label;
} else {
label = key;
}
} else if ('label' in init && Object.keys(init).some(function (k) {
return k === 'label';
})) {
var _init$label;
// typeof {label}
value = key;
label = (_init$label = init.label) !== null && _init$label !== void 0 ? _init$label : key;
} else {
// {} empty object
value = key;
label = key;
}
} else {
// Probably Date, RegExp and other primitive types
value = init;
label = key;
}
} else {
throw new Error("Invalid enum item: ".concat(JSON.stringify(init)));
}
} else {
value = key;
label = key;
}
return {
value: value,
label: label
};
}
//# sourceMappingURL=enum-items.js.map