UNPKG

@onesy/subscription

Version:
506 lines (457 loc) 21 kB
/** @license Subscription v1.0.0 * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Subscription = factory()); })(this, (function () { 'use strict'; 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; } var global$1 = (typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}); function getDefaultExportFromCjs (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } var is$1 = {exports: {}}; (function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); const optionsDefault = {}; const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined'; const isNodejs = !!(typeof global$1 !== 'undefined' && 'object' !== 'undefined' && module.exports); // Multiple is methods instead of one, // so it's lighter for tree shaking usability reasons function is(type, value, options_ = {}) { var _a; const options = Object.assign(Object.assign({}, optionsDefault), options_); const { variant } = options; const prototype = value && typeof value === 'object' && Object.getPrototypeOf(value); switch (type) { case 'string': return typeof value === 'string'; case 'number': return typeof value === 'number' && !Number.isNaN(value); case 'boolean': return typeof value === 'boolean'; case 'array': return Array.isArray(value); case 'object': const isObject = typeof value === 'object' && !!value && value.constructor === Object; return isObject; // Map, null, WeakMap, Date, etc. case 'object-like': return typeof value === 'object' && (value === null || value.constructor !== Object); case 'class': return ((typeof value === 'object' || typeof value === 'function') && (/class/gi.test(String(value)) || /class/gi.test(String(value === null || value === void 0 ? void 0 : value.constructor)))); case 'function': return !!(value && value instanceof Function); case 'async': // If it's browser avoid calling the method // to see if it's async func or not, // where as in nodejs we have no other choice // that i know of when using transpilation // And also it might not be always correct, as // a method that returns a promise is also async // but we can't know that until the method is called and // we inspect the method's return value return !!(is('function', value) && (isBrowser ? value.constructor.name === 'AsyncFunction' : value() instanceof Promise)); case 'map': return !!(prototype === Map.prototype); case 'weakmap': return !!(prototype === WeakMap.prototype); case 'set': return !!(prototype === Set.prototype); case 'weakset': return !!(prototype === WeakSet.prototype); case 'promise': return !!(prototype === Promise.prototype); case 'int8array': return !!(prototype === Int8Array.prototype); case 'uint8array': return !!(prototype === Uint8Array.prototype); case 'uint8clampedarray': return !!(prototype === Uint8ClampedArray.prototype); case 'int16array': return !!(prototype === Int16Array.prototype); case 'uint16array': return !!(prototype === Uint16Array.prototype); case 'int32array': return !!(prototype === Int32Array.prototype); case 'uint32array': return !!(prototype === Uint32Array.prototype); case 'float32array': return !!(prototype === Float32Array.prototype); case 'float64array': return !!(prototype === Float64Array.prototype); case 'bigint64array': return !!(prototype === BigInt64Array.prototype); case 'biguint64array': return !!(prototype === BigUint64Array.prototype); case 'typedarray': return is('int8array', value) || is('uint8array', value) || is('uint8clampedarray', value) || is('int16array', value) || is('uint16array', value) || is('int32array', value) || is('uint32array', value) || is('float32array', value) || is('float64array', value) || is('bigint64array', value) || is('biguint64array', value); case 'dataview': return !!(prototype === DataView.prototype); case 'arraybuffer': return !!(prototype === ArrayBuffer.prototype); case 'sharedarraybuffer': return typeof SharedArrayBuffer !== 'undefined' && !!(prototype === SharedArrayBuffer.prototype); case 'symbol': return !!(typeof value === 'symbol'); case 'error': return !!(value && value instanceof Error); case 'date': return !!(value && value instanceof Date); case 'regexp': return !!(value && value instanceof RegExp); case 'arguments': return !!(value && value.toString() === '[object Arguments]'); case 'null': return value === null; case 'undefined': return value === undefined; case 'blob': return isBrowser && value instanceof Blob; case 'buffer': return !!(isNodejs && typeof ((_a = value === null || value === void 0 ? void 0 : value.constructor) === null || _a === void 0 ? void 0 : _a.isBuffer) === 'function' && value.constructor.isBuffer(value)); case 'element': if (value) { switch (variant) { case undefined: case 'html': case 'element': return isBrowser && (typeof HTMLElement === 'object' ? value instanceof HTMLElement : value && typeof value === 'object' && value !== null && value.nodeType === 1 && typeof value.nodeName === 'string'); case 'node': return isBrowser && (typeof Node === 'object' ? value instanceof Node : value && typeof value === 'object' && value !== null && typeof value.nodeType === 'number' && typeof value.nodeName === 'string'); case 'react': return value.elementType || value.hasOwnProperty('$$typeof'); default: return false; } } return false; case 'simple': return (is('string', value, options) || is('number', value, options) || is('boolean', value, options) || is('undefined', value, options) || is('null', value, options)); case 'not-array-object': return !is('array', value, options) && !is('object', value, options); default: return false; } } exports.default = is; }(is$1, is$1.exports)); var is = /*@__PURE__*/getDefaultExportFromCjs(is$1.exports); var copy$1 = {}; Object.defineProperty(copy$1, "__esModule", { value: true }); const isArray = value => Array.isArray(value); const isObject = value => typeof value === 'object' && !!value && value.constructor === Object; // It keeps the references of the methods and classes, // unlike JSON.stringify usually used for deep simple copy const copy = (value, values_) => { const values = !values_ ? new WeakSet() : values_; // Ref circular value if (values.has(value)) return value; if (isObject(value) || isArray(value)) values.add(value); if (isArray(value)) return value.map(item => copy(item, values)); if (isObject(value)) { const newValue = {}; Object.keys(value).forEach(key => newValue[key] = copy(value[key], values)); return newValue; } return value; }; var _default$1 = copy$1.default = copy; var _try = {}; var getEnvironment$1 = {}; Object.defineProperty(getEnvironment$1, "__esModule", { value: true }); const getEnvironment = () => { if (typeof self !== 'undefined') return self; if (typeof window !== 'undefined') return window; if (typeof global$1 !== 'undefined') return global$1; }; getEnvironment$1.default = getEnvironment; var setObjectValue$1 = {}; var cleanValue = {}; var capitalize$1 = {}; var __importDefault$3 = (undefined && undefined.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(capitalize$1, "__esModule", { value: true }); const is_1$3 = __importDefault$3(is$1.exports); const capitalize = (value) => { if ((0, is_1$3.default)('string', value)) return `${value.charAt(0).toUpperCase()}${value.slice(1)}`; return value; }; capitalize$1.default = capitalize; (function (exports) { var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.optionsDefault = void 0; const is_1 = __importDefault(is$1.exports); const capitalize_1 = __importDefault(capitalize$1); exports.optionsDefault = { filters: [',', '.', '-', '_', '\s+'], replaceWith: ' ', trim: true, }; const cleanValue = (value_, options_ = {}) => { try { const options = Object.assign(Object.assign({}, exports.optionsDefault), options_); // Few predefined options // for className cammel case to regular // css property names convert if (options.className) { options.replaceWith = '-'; options.cammelCaseTransform = true; options.lowercase = true; } if ((0, is_1.default)('string', value_)) { let value = value_; if (options.url) { const parts = value.split('?').filter(Boolean); let path = parts[0]; const query = parts[1]; if (path.slice(-1) === '/') path = path.slice(0, -1); value = query ? [path, query].join('?') : path; return value; } if (options.cammelCaseTransform) value = value.split(/(?=[A-Z])/g).join(options.replaceWith || ' '); options.filters.forEach(filter => { const expression = `\\${filter}`; const regexp = new RegExp(expression, 'g'); value = value.replace(regexp, options.replaceWith || ' '); }); if (options.trim) value = value.trim(); if (options.capitalize) value = (0, capitalize_1.default)(value); if (options.lowercase) value = value.toLocaleLowerCase(); return value; } return value_; } catch (error) { } return value_; }; exports.default = cleanValue; }(cleanValue)); var castParam$1 = {}; var __importDefault$2 = (undefined && undefined.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(castParam$1, "__esModule", { value: true }); const is_1$2 = __importDefault$2(is$1.exports); const optionsDefault$3 = { decode: false, decodeMethod: decodeURIComponent, }; const castParam = (value, options_ = {}) => { const options = Object.assign(Object.assign({}, optionsDefault$3), options_); let newValue = value; try { if ((0, is_1$2.default)('string', value) && options.decode && (0, is_1$2.default)('function', options.decodeMethod)) newValue = options.decodeMethod(value); } catch (error) { } try { if ((0, is_1$2.default)('string', newValue)) { if ('undefined' === newValue) return undefined; if ('NaN' === newValue) return NaN; return JSON.parse(newValue); } return newValue; } catch (error) { } return newValue; }; castParam$1.default = castParam; var __importDefault$1 = (undefined && undefined.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(setObjectValue$1, "__esModule", { value: true }); const is_1$1 = __importDefault$1(is$1.exports); const cleanValue_1 = __importDefault$1(cleanValue); const castParam_1 = __importDefault$1(castParam$1); const optionsDefault$2 = { valueOverride: false }; const setObjectValue = (object, keys = '', value = undefined, options_ = {}) => { const options = Object.assign(Object.assign({}, optionsDefault$2), options_); if (!(object || keys)) return object; if ((0, is_1$1.default)('string', keys)) { const keys_ = keys.split('.').filter(Boolean).map(key => (0, castParam_1.default)(key)); return setObjectValue(object, keys_, value, options); } if ((0, is_1$1.default)('array', keys)) { const key = keys[0]; const keyClean = (0, cleanValue_1.default)(String(key), { filters: ['.', ','], replaceWith: '' }); if (keys.length === 1) { if (((0, is_1$1.default)('array', object) && (0, is_1$1.default)('number', key)) || (0, is_1$1.default)('object', object)) { // Add array or object as a value of the key, if that key doesn't exist atm if (!(object === null || object === void 0 ? void 0 : object.hasOwnProperty(key)) || options.valueOverride) object[keyClean] = (0, is_1$1.default)('number', keys[1]) ? [] : {}; object[(0, is_1$1.default)('string', key) ? keyClean : key] = value; } } else { if (((0, is_1$1.default)('array', object) && (0, is_1$1.default)('number', key)) || (0, is_1$1.default)('object', object)) { // Add array or object as a value of the key, if that key doesn't exist atm if (!(object === null || object === void 0 ? void 0 : object.hasOwnProperty(key)) || options.valueOverride) object[keyClean] = (0, is_1$1.default)('number', keys[1]) ? [] : {}; } const value_ = object[keyClean]; // If we are trying to set a deeply nested value on a // simple value type, meaning if it's not an array or an object, // To override existing value use valueOverride: true option if (!((0, is_1$1.default)('object', value_) || (0, is_1$1.default)('array', value_))) return object; return setObjectValue(object[key], keys.slice(1), value, options); } } return object; }; setObjectValue$1.default = setObjectValue; var __importDefault = (undefined && undefined.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(_try, "__esModule", { value: true }); const is_1 = __importDefault(is$1.exports); const getEnvironment_1 = __importDefault(getEnvironment$1); const setObjectValue_1 = __importDefault(setObjectValue$1); const optionsDefault$1 = {}; const Try = (value, options_ = {}) => { var _a, _b, _c, _d; const options = Object.assign(Object.assign({}, optionsDefault$1), options_); try { return (0, is_1.default)('function', value) ? value() : undefined; } catch (error) { if (options.log) { console.error('Try: ', error); const env = (0, getEnvironment_1.default)(); if (((_a = env.AMAUI) === null || _a === void 0 ? void 0 : _a.env) === 'test') { if (!((_d = (_c = (_b = env.AMAUI) === null || _b === void 0 ? void 0 : _b.test) === null || _c === void 0 ? void 0 : _c.Try) === null || _d === void 0 ? void 0 : _d.logs)) (0, setObjectValue_1.default)(env, 'AMAUI.test.Try.logs', []); env.AMAUI.test.Try.logs.push(error); } } } }; var _default = _try.default = Try; const optionsDefault = { emit: { priorValue: true, copy: false, pre: {}, post: {} } }; class OnesySubscription { constructor(value) { let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; _defineProperty(this, "methods", []); _defineProperty(this, "push", this.emit); this.value = value; this.options = options; this.options = { ...optionsDefault, ...this.options }; } get length() { return this.methods.length; } emit(value) { var _this$options$emit, _this$options$emit$pr, _this$options$emit$po; for (var _len = arguments.length, other = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { other[_key - 1] = arguments[_key]; } const values = [value, ...other]; // Important for use cases, // to be available pre emit, // Save value as last emitted value as a previous state optionally if ((_this$options$emit = this.options.emit) !== null && _this$options$emit !== void 0 && _this$options$emit.priorValue) this.value = values.length === 1 ? values[0] : values; // Pre // Value might be of simple type so we have to assign a new value to the value if (is('function', (_this$options$emit$pr = this.options.emit.pre) === null || _this$options$emit$pr === void 0 ? void 0 : _this$options$emit$pr.method)) this.options.emit.pre.method(...values); // Whether to send a copied value version or not, // it might be useful since if value is of reference type, // methods in the beginning might update the value, // and other following methods wouldn't get the // same value as it was sent to the first method. const methodValue = this.options.emit.copy ? _default$1(values) : values; const methods = this.methods.filter(method => is('function', method)); // Emit to methods for (const method of methods) _default(() => method(...methodValue)); // Post // Value might be of simple type so we have to assign a new value to the value if (is('function', (_this$options$emit$po = this.options.emit.post) === null || _this$options$emit$po === void 0 ? void 0 : _this$options$emit$po.method)) this.options.emit.post.method(...values); } // alias forEach() { for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } this.methods.forEach(method => _default(() => method(...args))); } map(value_) { if (!this.methods.length) return; let value = value_; for (const method of this.methods) value = _default(() => method(value)); return value; } subscribe(method) { if (is('function', method) && this.methods.indexOf(method) === -1) this.methods.push(method); const instance = this; return { unsubscribe: () => { instance.unsubscribe(method); } }; } unsubscribe(method) { if (is('function', method) && this.methods.indexOf(method) > -1) { const index = this.methods.findIndex(method_ => method_ === method); if (index > -1) this.methods.splice(index, 1); } } } var OnesySubscription$1 = OnesySubscription; return OnesySubscription$1; }));