UNPKG

objecture

Version:

❂ Objecture ⏣ Object Watcher, Property Manager ⊚ Capture property changes for object, array mutator methods. ⊚ Schematize and validate object, array properties. ⊚ Browser, NodeJS compatible. ⁘ Uses Core-Plex - Event Listener Manage

1,481 lines (1,441 loc) 139 kB
const Primitives$2 = { 'string': String, 'number': Number, 'boolean': Boolean, 'bigint': BigInt, 'undefined': undefined, 'null': null, }; Object.values(Primitives$2); const Objects$2 = { 'object': Object, 'array': Array, }; Object.values(Objects$2); const Types$2 = Object.assign({}, Primitives$2, Objects$2); Object.values(Types$2); [ Primitives$2.String, Primitives$2.Number, Primitives$2.Boolean, Objects$2.Object, Objects$2.Array ]; var typeOf$2 = ($data) => Object .prototype .toString .call($data).slice(8, -1).toLowerCase(); const defaultAccessor$1 = ($target, $property) => { if($property === undefined) { return $target } else { return $target[$property] } }; var Accessors = { default: defaultAccessor$1}; const Options$2$1 = { depth: 0, maxDepth: 10, accessors: [Accessors.default], ancestors: [], }; function compandTree($object, $options) { const _compandTree = []; const options = Object.assign({}, Options$2$1, $options, { ancestors: [].concat($options.ancestors) }); options.depth++; if(options.depth > options.maxDepth) { return _compandTree } iterateAccessors: for(const $accessor of options.accessors) { const accessor = $accessor.bind($object); const object = accessor($object); if(!object) { continue iterateAccessors } if(!options.ancestors.includes(object)) { options.ancestors.unshift(object); } for(const [$key, $value] of Object.entries(object)) { if(!options.values) { _compandTree.push($key); } else if(options.values) { _compandTree.push([$key, $value]); } if( typeof $value === 'object' && $value !== null && !Object.is($value, object) && !options.ancestors.includes($value) ) { const subtargets = compandTree($value, options); if(!options.values) { for(const $subtarget of subtargets) { const path = [$key, $subtarget].join('.'); _compandTree.push(path); } } else if(options.values) { for(const [$subtargetKey, $subtarget] of subtargets) { const path = [$key, $subtargetKey].join('.'); _compandTree.push([path, $subtarget]); } } } } } return _compandTree } function assign$4($target, ...$sources) { if(!$target) { return $target} iterateSources: for(const $source of $sources) { if(!$source) continue iterateSources for(const [ $sourcePropertyKey, $sourcePropertyValue ] of Object.entries($source)) { const typeOfTargetPropertyValue = typeOf$2($target[$sourcePropertyKey]); const typeOfSourcePropertyValue = typeOf$2($sourcePropertyValue); if( typeOfTargetPropertyValue === 'object' && typeOfSourcePropertyValue === 'object' ) { $target[$sourcePropertyKey] = assign$4($target[$sourcePropertyKey], $sourcePropertyValue); } else { $target[$sourcePropertyKey] = $sourcePropertyValue; } } } return $target } function expandEvents($propEvents, $scopeKey = ':scope') { if( Array.isArray($propEvents) || $propEvents === undefined ) { return $propEvents } const propEvents = []; for(const [ $propEventSettings, $propEventListener ] of Object.entries($propEvents)) { const propEventSettings = $propEventSettings.trim().split(' '); let path, type, listener; if(propEventSettings.length === 1) { path = $scopeKey; type = propEventSettings[0]; } else if(propEventSettings.length > 1) { path = propEventSettings[0]; type = propEventSettings[1]; } if(Array.isArray($propEventListener)) { listener = $propEventListener[0]; $propEventListener[1]; } else { listener = $propEventListener; } const propEvent = { type, path, listener, enable: false, }; propEvents.push(propEvent); } return propEvents } const defaultAccessor = ($target, $property) => { if($property === undefined) { return $target } else { return $target[$property] } }; var accessors = { default: defaultAccessor}; var Settings$1 = ($settings = {}) => { const Settings = { events: {}, enableEvents: false, compandTree: { accessors: [accessors.default], scopeKey: ':scope', maxDepth: 10, }, propertyDefinitions: { getEvents: 'getEvents', addEvents: 'addEvents', removeEvents: 'removeEvents', enableEvents: 'enableEvents', disableEvents: 'disableEvents', reenableEvents: 'reenableEvents', emitEvents: 'emitEvents', }, }; for(const [$settingKey, $settingValue] of Object.entries($settings)) { switch($settingKey) { case 'propertyDefinitions': case 'compandTree': Settings[$settingKey] = Object.assign(Settings[$settingKey], $settingValue); break default: Settings[$settingKey] = $settingValue; break } } return Settings }; function handleNoCommaBraces(span) { if (span.length < 3) { return "{" + span + "}"; } var separatorI = -1; for (var i = 2; i < span.length; i++) { if (span[i] === '.' && span[i - 1] === '.' && (i < 2 || span[i - 2] !== '\\')) { if (separatorI > -1) { return "{" + span + "}"; } separatorI = i - 1; } } if (separatorI > -1) { var rangeStart = span.substr(0, separatorI); var rangeEnd = span.substr(separatorI + 2); if (rangeStart.length > 0 && rangeEnd.length > 0) { return "[" + span.substr(0, separatorI) + "-" + span.substr(separatorI + 2) + "]"; } } return "{" + span + "}"; } function expand(pattern) { if (typeof pattern !== 'string') { throw new TypeError("A pattern must be a string, but " + typeof pattern + " given"); } var scanning = false; var openingBraces = 0; var closingBraces = 0; var handledUntil = -1; var results = ['']; var alternatives = []; var span; for (var i = 0; i < pattern.length; i++) { var char = pattern[i]; if (char === '\\') { i++; continue; } if (char === '{') { if (scanning) { openingBraces++; } else if (i > handledUntil && !openingBraces) { span = pattern.substring(handledUntil + 1, i); for (var j = 0; j < results.length; j++) { results[j] += span; } alternatives = []; handledUntil = i; scanning = true; openingBraces++; } else { openingBraces--; } } else if (char === '}') { if (scanning) { closingBraces++; } else if (closingBraces === 1) { span = pattern.substring(handledUntil + 1, i); if (alternatives.length > 0) { var newResults = []; alternatives.push(expand(span)); for (var j = 0; j < results.length; j++) { for (var k = 0; k < alternatives.length; k++) { for (var l = 0; l < alternatives[k].length; l++) { newResults.push(results[j] + alternatives[k][l]); } } } results = newResults; } else { span = handleNoCommaBraces(span); for (var j = 0; j < results.length; j++) { results[j] += span; } } handledUntil = i; closingBraces--; } else { closingBraces--; } } else if (!scanning && char === ',' && closingBraces - openingBraces === 1) { span = pattern.substring(handledUntil + 1, i); alternatives.push(expand(span)); handledUntil = i; } if (scanning && (closingBraces === openingBraces || i === pattern.length - 1)) { scanning = false; i = handledUntil - 1; } } if (handledUntil === -1) { return [pattern]; } var unhandledFrom = pattern[handledUntil] === '{' ? handledUntil : handledUntil + 1; if (unhandledFrom < pattern.length) { span = pattern.substr(unhandledFrom); for (var j = 0; j < results.length; j++) { results[j] += span; } } return results; } function negate(pattern, options) { var supportNegation = options['!'] !== false; var supportParens = options['()'] !== false; var isNegated = false; var i; if (supportNegation) { for (i = 0; i < pattern.length && pattern[i] === '!'; i++) { if (supportParens && pattern[i + 1] === '(') { i--; break; } isNegated = !isNegated; } if (i > 0) { pattern = pattern.substr(i); } } return { pattern: pattern, isNegated: isNegated }; } function escapeRegExpChar(char) { if (char === '-' || char === '^' || char === '$' || char === '+' || char === '.' || char === '(' || char === ')' || char === '|' || char === '[' || char === ']' || char === '{' || char === '}' || char === '*' || char === '?' || char === '\\') { return "\\" + char; } else { return char; } } function escapeRegExpString(str) { var result = ''; for (var i = 0; i < str.length; i++) { result += escapeRegExpChar(str[i]); } return result; } function Pattern(source, options, excludeDot) { var separator = typeof options.separator === 'undefined' ? true : options.separator; var separatorSplitter = ''; var separatorMatcher = ''; var wildcard = '.'; if (separator === true) { separatorSplitter = '/'; separatorMatcher = '[/\\\\]'; wildcard = '[^/\\\\]'; } else if (separator) { separatorSplitter = separator; separatorMatcher = escapeRegExpString(separatorSplitter); if (separatorMatcher.length > 1) { separatorMatcher = "(?:" + separatorMatcher + ")"; wildcard = "((?!" + separatorMatcher + ").)"; } else { wildcard = "[^" + separatorMatcher + "]"; } } else { wildcard = '.'; } var requiredSeparator = separator ? separatorMatcher + "+?" : ''; var optionalSeparator = separator ? separatorMatcher + "*?" : ''; var segments = separator ? source.split(separatorSplitter) : [source]; var support = { qMark: options['?'] !== false, star: options['*'] !== false, globstar: separator && options['**'] !== false, brackets: options['[]'] !== false, extglobs: options['()'] !== false, excludeDot: excludeDot && options.excludeDot !== false, }; return { source: source, segments: segments, options: options, separator: separator, separatorSplitter: separatorSplitter, separatorMatcher: separatorMatcher, optionalSeparator: optionalSeparator, requiredSeparator: requiredSeparator, wildcard: wildcard, support: support, }; } function Segment(source, pattern, isFirst, isLast) { return { source: source, isFirst: isFirst, isLast: isLast, end: source.length - 1, }; } function Result() { return { match: '', unmatch: '', useUnmatch: false, }; } function State(pattern, segment, result) { return { pattern: pattern, segment: segment, result: result, openingBracket: segment.end + 1, closingBracket: -1, openingParens: 0, closingParens: 0, parensHandledUntil: -1, extglobModifiers: [], scanningForParens: false, escapeChar: false, addToMatch: true, addToUnmatch: pattern.support.extglobs, dotHandled: false, i: -1, char: '', nextChar: '', }; } var EXCLUDE_DOT_PATTERN = '(?!\\.)'; function add(state, addition, excludeDot) { if (state.addToUnmatch) { state.result.unmatch += addition; } if (state.addToMatch) { if (excludeDot && !state.dotHandled) { addition = EXCLUDE_DOT_PATTERN + addition; } state.dotHandled = true; state.result.match += addition; } return state.result; } function convertSegment(pattern, segment, result) { var support = pattern.support; var state = State(pattern, segment, result); var separatorMatcher = segment.isLast ? pattern.optionalSeparator : pattern.requiredSeparator; if (!support.excludeDot) { state.dotHandled = true; } if (segment.end === -1) { return segment.isLast && !segment.isFirst ? result : add(state, separatorMatcher); } if (support.globstar && segment.source === '**') { var prefix = !state.dotHandled ? EXCLUDE_DOT_PATTERN : ''; var globstarSegment = prefix + pattern.wildcard + "*?" + separatorMatcher; return add(state, "(?:" + globstarSegment + ")*?"); } while (++state.i <= segment.end) { state.char = state.segment.source[state.i]; state.nextChar = state.i < segment.end ? segment.source[state.i + 1] : ''; if (state.char === '\\') { if (state.i < state.segment.end) { state.escapeChar = true; continue; } else { state.char = ''; } } var pattern = state.pattern, segment = state.segment, char = state.char, i = state.i; if (pattern.support.brackets && !state.scanningForParens) { if (i > state.openingBracket && i <= state.closingBracket) { if (state.escapeChar) { add(state, escapeRegExpChar(char)); } else if (i === state.closingBracket) { add(state, ']'); state.openingBracket = segment.source.length; } else if (char === '-' && i === state.closingBracket - 1) { add(state, '\\-'); } else if (char === '!' && i === state.openingBracket + 1) { add(state, '^'); } else if (char === ']') { add(state, '\\]'); } else { add(state, char); } state.escapeChar = false; continue; } if (i > state.openingBracket) { if (char === ']' && !state.escapeChar && i > state.openingBracket + 1 && i > state.closingBracket) { state.closingBracket = i; state.i = state.openingBracket; if (pattern.separator) { add(state, "(?!" + pattern.separatorMatcher + ")[", true); } else { add(state, '[', true); } } else if (i === segment.end) { add(state, '\\['); state.i = state.openingBracket; state.openingBracket = segment.source.length; state.closingBracket = segment.source.length; } state.escapeChar = false; continue; } if (char === '[' && !state.escapeChar && i > state.closingBracket && i < segment.end) { state.openingBracket = i; state.escapeChar = false; continue; } } if (state.pattern.support.extglobs) { var extglobModifiers = state.extglobModifiers, char = state.char, nextChar = state.nextChar, i = state.i; if (nextChar === '(' && !state.escapeChar && (char === '@' || char === '?' || char === '*' || char === '+' || char === '!')) { if (state.scanningForParens) { state.openingParens++; } else if (i > state.parensHandledUntil && !state.closingParens) { state.parensHandledUntil = i; state.scanningForParens = true; state.openingParens++; } else if (state.closingParens >= state.openingParens) { if (char === '!') { state.addToMatch = true; state.addToUnmatch = false; add(state, state.pattern.wildcard + "*?", true); state.addToMatch = false; state.addToUnmatch = true; state.result.useUnmatch = true; } extglobModifiers.push(char); add(state, '(?:', true); state.openingParens--; state.i++; continue; } else { state.openingParens--; } } else if (char === ')' && !state.escapeChar) { if (state.scanningForParens) { state.closingParens++; } else if (extglobModifiers.length) { var modifier_1 = extglobModifiers.pop(); if (modifier_1 === '!' && extglobModifiers.indexOf('!') !== -1) { throw new Error("Nested negated extglobs aren't supported"); } modifier_1 = modifier_1 === '!' || modifier_1 === '@' ? '' : modifier_1; add(state, ")" + modifier_1); state.addToMatch = true; state.addToUnmatch = true; state.closingParens--; continue; } } else if (char === '|' && state.closingParens && !state.scanningForParens && !state.escapeChar) { add(state, '|'); continue; } if (state.scanningForParens) { if (state.closingParens === state.openingParens || i === state.segment.end) { state.scanningForParens = false; state.i = state.parensHandledUntil - 1; } state.escapeChar = false; continue; } } var pattern = state.pattern; var support = pattern.support; if (!state.escapeChar && support.star && state.char === '*') { if (state.i === state.segment.end || state.nextChar !== '*') { add(state, pattern.wildcard + "*?", true); } } else if (!state.escapeChar && support.qMark && state.char === '?') { add(state, pattern.wildcard, true); } else { add(state, escapeRegExpChar(state.char)); } state.escapeChar = false; } return add(state, separatorMatcher); } function convert(source, options, excludeDot) { var pattern = Pattern(source, options, excludeDot); var result = Result(); var segments = pattern.segments; for (var i = 0; i < segments.length; i++) { var segment = Segment(segments[i], pattern, i === 0, i === segments.length - 1); convertSegment(pattern, segment, result); } if (result.useUnmatch) { return "(?!^" + result.unmatch + "$)" + result.match; } else { return result.match; } } function flatMap(array, predicate) { var results = []; for (var i = 0; i < array.length; i++) { var mappedValue = predicate(array[i]); for (var j = 0; j < mappedValue.length; j++) { results.push(mappedValue[j]); } } return results; } function compile(patterns, options) { patterns = Array.isArray(patterns) ? patterns : [patterns]; if (options['{}'] !== false) { patterns = flatMap(patterns, expand); } var positiveResults = []; var negativeResults = []; var result = ''; for (var i = 0; i < patterns.length; i++) { var negatedPattern = negate(patterns[i], options); var convertedPattern = convert(negatedPattern.pattern, options, !negatedPattern.isNegated); if (negatedPattern.isNegated) { negativeResults.push(convertedPattern); } else { positiveResults.push(convertedPattern); } } if (negativeResults.length) { result = "(?!(?:" + negativeResults.join('|') + ")$)"; } if (positiveResults.length > 1) { result += "(?:" + positiveResults.join('|') + ")"; } else if (positiveResults.length === 1) { result += positiveResults[0]; } else if (result.length) { result += convert('**', options, true); } return "^" + result + "$"; } function isMatch(regexp, sample) { if (typeof sample !== 'string') { throw new TypeError("Sample must be a string, but " + typeof sample + " given"); } return regexp.test(sample); } /** * Compiles one or more glob patterns into a RegExp and returns an isMatch function. * The isMatch function takes a sample string as its only argument and returns true * if the string matches the pattern(s). * * ```js * outmatch('src/*.js')('src/index.js') //=> true * ``` * * ```js * const isMatch = outmatch('*.example.com', '.') * isMatch('foo.example.com') //=> true * isMatch('foo.bar.com') //=> false * ``` */ function outmatch(pattern, options) { if (typeof pattern !== 'string' && !Array.isArray(pattern)) { throw new TypeError("The first argument must be a single pattern string or an array of patterns, but " + typeof pattern + " given"); } if (typeof options === 'string' || typeof options === 'boolean') { options = { separator: options }; } if (arguments.length === 2 && !(typeof options === 'undefined' || (typeof options === 'object' && options !== null && !Array.isArray(options)))) { throw new TypeError("The second argument must be an options object or a string/boolean separator, but " + typeof options + " given"); } options = options || {}; if (options.separator === '\\') { throw new Error('\\ is not a valid separator'); } var regexpPattern = compile(pattern, options); var regexp = new RegExp(regexpPattern, options.flags); var fn = isMatch.bind(null, regexp); fn.options = options; fn.pattern = pattern; fn.regexp = regexp; return fn; } var Settings = ($settings = {}) => { const Settings = { enable: false, assign: 'addEventListener', deassign: 'removeEventListener', transsign: 'dispatchEvent', bindListener: true, errorLog: false, methods: { assign: { addEventListener: function addEventListener($eventDefinition, $target) { const { type, listener, settings } = $eventDefinition; const { options, useCapture } = settings; return $target['addEventListener'](type, listener, options || useCapture) }, on: function on($eventDefinition, $target) { const { type, listener } = $eventDefinition; return $target['on'](type, listener) }, once: function once($eventDefinition, $target) { const { type, listener } = $eventDefinition; return $target['once'](type, listener) }, }, deassign: { removeEventListener: function removeEventListener($eventDefinition, $target) { const { type, listener, settings } = $eventDefinition; const { options, useCapture } = settings; return $target['removeEventListener'](type, listener, options || useCapture) }, off: function off($eventDefinition, $target) { const { type, listener } = $eventDefinition; return $target['off'](type, listener) }, }, transsign: { dispatchEvent: function dispatchEvent($eventDefinition, $target, $event) { return $target['dispatchEvent']($event) }, emit: function emit($eventDefinition, $target, $type, ...$arguments) { return $target['emit']($type, ...$arguments) }, }, }, }; for(const [$settingKey, $settingValue] of Object.entries($settings)) { switch($settingKey) { case 'methods': Settings[$settingKey] = assign$4(Settings[$settingKey], $settingValue); break case 'enableEvents': break default: Settings[$settingKey] = $settingValue; break } } return Settings }; class EventDefinition { #context #enable = false #nontranssigned = [] #_targets = [] #_assign #_deassign #_transsign constructor($settings, $context) { if(!$settings || !$context) { return this } const settings = Settings($settings); const assigned = []; const deassigned = []; const transsigned = []; Object.defineProperties(this, { 'settings': { value: settings }, 'path': { value: settings.path }, 'type': { value: settings.type }, 'assigned': { value: assigned }, 'deassigned': { value: deassigned }, 'transsigned': { value: transsigned }, 'listener': { configurable: true, get() { const typeOfListener = typeOf$2(settings.listener); let listener; if(typeOfListener === 'string') { let listenerTarget = $context; iterateListenerPathKeys: for(const $pathKey of settings.listener.split('.')) { const value = listenerTarget[$pathKey]; if(value !== undefined) { listenerTarget = listenerTarget[$pathKey]; } else { break iterateListenerPathKeys } } if(typeOf$2(listenerTarget) === 'function') { listener = listenerTarget; } } else { listener = settings.listener; } if(settings.bindListener === true) { listener = listener.bind(this.#context); } Object.defineProperty(this, 'listener', { value: listener }); return listener } } }); this.#context = $context; this.enable = this.settings.enable; } get enable() { return this.#enable } set enable($enable) { const targets = this.#targets; const assigned = this.assigned; const deassigned = this.deassigned; assigned.length = 0; deassigned.length = 0; iterateTargetElements: for(const $targetElement of targets) { const { path, target, enable } = $targetElement; this.settings; if(enable === $enable) { continue iterateTargetElements } if($enable === true) { try { this.#assign(target); $targetElement.enable = $enable; assigned.push($targetElement); } catch($err) { if(this.settings.errorLog) { console.error($err); } } } else if($enable === false) { try { this.#deassign(target); $targetElement.enable = $enable; deassigned.push($targetElement); } catch($err) { if(this.settings.errorLog) { console.error($err); } } } } this.#enable = $enable; } get #target() { return this.settings.target } get #targets() { const pretargets = this.#_targets; const targets = []; if(this.#target) { for(const $target of [].concat(this.#target)) { const pretargetElement = pretargets.find( ($pretarget) => $pretarget?.path === this.path ); if(pretargetElement !== undefined) { targets.push(pretargetElement); } else if(pretargetElement === undefined) {ptargets.push({ path: this.path, target: $target, enable: false, }); } } } else if(typeOf$2(this.path) === 'string') { const targetPaths = []; if(this.path === this.#scopeKey) { const targetElement = { path: this.path, target: this.#context, enable: false, }; targets.push(targetElement); } else { if(this.settings.compandTree) { const compandTree = this.#compandTree; const propertyPathMatcher = outmatch(this.path, { separator: '.', }); for(const [$propertyPath, $propertyValue] of compandTree) { const propertyPathMatch = propertyPathMatcher($propertyPath); if(propertyPathMatch === true) { targetPaths.push([$propertyPath, $propertyValue]); } } if(this.path.charAt(0) === '*') { targetPaths.unshift([this.#scopeKey, this.#context]); } } else { targetPaths.push(this.path); } for(const [$targetPath, $targetValue] of targetPaths) { const pretargetElement = pretargets.find( ($pretarget) => $pretarget.path === $targetPath ); let target = $targetValue; let targetElement; if(target !== undefined) { if(target === pretargetElement?.target) { targetElement = pretargetElement; } else if(typeof target === 'object') { targetElement = { path: $targetPath, target: target, enable: false, }; } } if(targetElement !== undefined) { targets.push(targetElement); } } } } this.#_targets = targets; return this.#_targets } get #scopeKey() { return this.settings.compandTree.scopeKey } get #assign() { if(this.#_assign !== undefined) { return this.#_assign } this.#_assign = this.settings.methods.assign[this.settings.assign].bind(null, this); return this.#_assign } get #deassign() { if(this.#_deassign !== undefined) { return this.#_deassign } this.#_deassign = this.settings.methods.deassign[this.settings.deassign].bind(null, this); return this.#_deassign } get #transsign() { if(this.#_transsign !== undefined) { return this.#_transsign } this.#_transsign = this.settings.methods.transsign[this.settings.transsign].bind(null, this); return this.#_transsign } get #compandTree() { if(!this.settings.compandTree) { return null } const compandTreeSettings = Object.assign(this.settings.compandTree, { values: true }); return compandTree(this.#context, compandTreeSettings) } emit() { const targets = this.#targets; const transsigned = this.transsigned; const nontranssigned = this.#nontranssigned; transsigned.length = 0; nontranssigned.length = 0; for(const $targetElement of targets) { const { target } = $targetElement; try { this.#transsign(target, ...arguments); transsigned.push($targetElement); } catch($err) { nontranssigned.push($targetElement); } } return this } } class Core extends EventTarget { static implement = function ($target, $settings) { if(!$target || !$settings) { return undefined } const settings = Settings$1($settings); const events = []; Object.defineProperties($target, { [settings.propertyDefinitions.getEvents]: { enumerable: false, writable: false, value: function getEvents() { if(!arguments[0]) { return events } const getEvents = []; const $filterEvents = [].concat(arguments[0]); for(const $filterEvent of $filterEvents) { for(const $event of events) { let match; iterateEventFilterProperties: for(const [ $filterEventPropertyKey, $filterEventPropertyValue ] of Object.entries($filterEvent)) { let eventFilterMatch; if($filterEventPropertyKey === 'listener') { eventFilterMatch = ( $event.settings[$filterEventPropertyKey] === $filterEventPropertyValue ); } else { eventFilterMatch = ( $event[$filterEventPropertyKey] === $filterEventPropertyValue ); } if(match !== false) { match = eventFilterMatch; } else { break iterateEventFilterProperties } } if(match === true) { getEvents.push($event); } } } return getEvents } }, [settings.propertyDefinitions.addEvents]: { enumerable: false, writable: false, value: function addEvents() { if(!arguments.length) { return $target } let $addEvents = expandEvents(arguments[0], settings.compandTree.scopeKey); let $enableEvents = arguments[1] || false; for(let $addEvent of $addEvents) { const event = {}; for(const $settingKey of [ 'assign', 'deassign', 'transsign', 'compandTree', 'bindListener' ]) { const settingValue = settings[$settingKey]; if(settingValue !== undefined) { event[$settingKey] = settingValue; } } assign$4(event, $addEvent); const eventDefinition = new EventDefinition(event, $target); if($enableEvents) { eventDefinition.enable = true; } events.push(eventDefinition); } return $target }, }, [settings.propertyDefinitions.removeEvents]: { enumerable: false, writable: false, value: function removeEvents() { const $events = $target[settings.propertyDefinitions.getEvents](arguments[0]); if($events.length === 0) return $target let eventsIndex = events.length - 1; while(eventsIndex > -1) { const event = events[eventsIndex]; if($events.includes(event)) { event.enable = false; events.splice(eventsIndex, 1); } eventsIndex--; } return $target } }, [settings.propertyDefinitions.enableEvents]: { enumerable: false, writable: false, value: function enableEvents() { const $events = $target[settings.propertyDefinitions.getEvents](arguments[0]); if($events.length === 0) return $target for(const $event of $events) { $event.enable = true; } return $target }, }, [settings.propertyDefinitions.disableEvents]: { enumerable: false, writable: false, value: function disableEvents() { const $events = $target[settings.propertyDefinitions.getEvents](arguments[0]); if($events.length === 0) return $target for(const $event of $events) { $event.enable = false; } return $target }, }, [settings.propertyDefinitions.reenableEvents]: { enumerable: false, writable: false, value: function reenableEvents() { const $events = $target[settings.propertyDefinitions.getEvents](arguments[0]); for(const $event of $events) { $event.enable = false; $event.enable = true; } return $target }, }, [settings.propertyDefinitions.emitEvents]: { enumerable: false, writable: false, value: function emitEvents($filterEvents, ...$eventParameters) { const $events = $target[settings.propertyDefinitions.getEvents]($filterEvents); for(const $event of $events) { $event.emit(...$eventParameters); } return $target }, }, }); if(settings.events) { $target[settings.propertyDefinitions.addEvents](settings.events); } if(settings.enableEvents === true) { $target[settings.propertyDefinitions.enableEvents](); } return $target } constructor($settings = {}) { super(); return Core.implement(this, $settings) } } const Primitives$1 = { 'string': String, 'number': Number, 'boolean': Boolean, 'bigint': BigInt, 'undefined': undefined, 'null': null, }; const PrimitiveKeys = Object.keys(Primitives$1); const PrimitiveValues = Object.values(Primitives$1); const Objects$1 = { 'object': Object, 'array': Array, }; const ObjectKeys$1 = Object.keys(Objects$1); const ObjectValues = Object.values(Objects$1); const Types$1 = Object.assign({}, Primitives$1, Objects$1); const TypeKeys$1 = Object.keys(Types$1); const TypeValues = Object.values(Types$1); const TypeMethods = [ Primitives$1.String, Primitives$1.Number, Primitives$1.Boolean, Objects$1.Object, Objects$1.Array ]; var index = /*#__PURE__*/Object.freeze({ __proto__: null, ObjectKeys: ObjectKeys$1, ObjectValues: ObjectValues, Objects: Objects$1, PrimitiveKeys: PrimitiveKeys, PrimitiveValues: PrimitiveValues, Primitives: Primitives$1, TypeKeys: TypeKeys$1, TypeMethods: TypeMethods, TypeValues: TypeValues, Types: Types$1 }); var typeOf$1 = ($data) => Object .prototype .toString .call($data).slice(8, -1).toLowerCase(); function typedObjectLiteral$1($value) { let _typedObjectLiteral; const typeOfValue = typeOf$1($value); if(typeOfValue === 'string') { const value = $value.toLowerCase(); if(value === 'object') { _typedObjectLiteral = {}; } else if(value === 'array') { _typedObjectLiteral = []; } } else { if(typeOfValue === 'object') { _typedObjectLiteral = {}; } else if(typeOfValue === 'array') { _typedObjectLiteral = []; } } return _typedObjectLiteral } var regularExpressions = { quotationEscape: /\.(?=(?:[^"]*"[^"]*")*[^"]*$)/, }; function get($path, $source) { const subpaths = $path.split(new RegExp(regularExpressions.quotationEscape)); const key = subpaths.pop(); let subtarget = $source; for(const $subpath of subpaths) { subtarget = subtarget[$subpath]; } return subtarget[key] } function impandTree($source, $property) { const typeOfProperty = typeOf$1($property); const typeOfSource = typeOf$1($source); if( !['string', 'function'].includes(typeOfProperty) || !['array', 'object'].includes(typeOfSource) ) { return $source } let target = typedObjectLiteral$1($source); for(const [$sourceKey, $sourceValue] of Object.entries($source)) { if(typeOfProperty === 'string') { target[$sourceKey] = get($property, $sourceValue); } else if(typeOfProperty === 'function') { target[$sourceKey] = $property($sourceValue); } if(target[$sourceKey] && typeof target[$sourceKey] === 'object') { target[$sourceKey] = impandTree(target[$sourceKey], $property); } } return target } function assign$3($target, ...$sources) { if(!$target) { return $target} iterateSources: for(const $source of $sources) { if(!$source) continue iterateSources for(const [ $sourcePropertyKey, $sourcePropertyValue ] of Object.entries($source)) { const typeOfTargetPropertyValue = typeOf$1($target[$sourcePropertyKey]); const typeOfSourcePropertyValue = typeOf$1($sourcePropertyValue); if( typeOfTargetPropertyValue === 'object' && typeOfSourcePropertyValue === 'object' ) { $target[$sourcePropertyKey] = assign$3($target[$sourcePropertyKey], $sourcePropertyValue); } else { $target[$sourcePropertyKey] = $sourcePropertyValue; } } } return $target } const Primitives = { 'string': String, 'number': Number, 'boolean': Boolean, 'bigint': BigInt, 'undefined': undefined, 'null': null, }; Object.values(Primitives); const Objects = { 'object': Object, 'array': Array, }; Object.values(Objects); const Types = Object.assign({}, Primitives, Objects); Object.values(Types); [ Primitives.String, Primitives.Number, Primitives.Boolean, Objects.Object, Objects.Array ]; var typeOf = ($data) => Object .prototype .toString .call($data).slice(8, -1).toLowerCase(); function typedObjectLiteral($value) { let _typedObjectLiteral; const typeOfValue = typeOf($value); if(typeOfValue === 'string') { const value = $value.toLowerCase(); if(value === 'object') { _typedObjectLiteral = {}; } else if(value === 'array') { _typedObjectLiteral = []; } } else { if(typeOfValue === 'object') { _typedObjectLiteral = {}; } else if(typeOfValue === 'array') { _typedObjectLiteral = []; } } return _typedObjectLiteral } var isArrayLike = ($source) => { let isArrayLike; const typeOfSource = typeOf($source); if(typeOfSource === 'array') { isArrayLike = true; } else if( typeOfSource === 'object' && Number.isInteger($source.length) && $source.length >= 0 ) { iterateSourceKeys: for(const $sourceKey of Object.keys( Object.getOwnPropertyDescriptors($source) )) { if($sourceKey === 'length') { continue iterateSourceKeys } isArrayLike = !isNaN($sourceKey); if(!isArrayLike) { break iterateSourceKeys } } } else { isArrayLike = false; } return isArrayLike }; function assign$2($target, ...$sources) { if(!$target) { return $target} iterateSources: for(const $source of $sources) { if(!$source) continue iterateSources for(const [ $sourcePropertyKey, $sourcePropertyValue ] of Object.entries($source)) { const typeOfTargetPropertyValue = typeOf($target[$sourcePropertyKey]); const typeOfSourcePropertyValue = typeOf($sourcePropertyValue); if( typeOfTargetPropertyValue === 'object' && typeOfSourcePropertyValue === 'object' ) { $target[$sourcePropertyKey] = assign$2($target[$sourcePropertyKey], $sourcePropertyValue); } else { $target[$sourcePropertyKey] = $sourcePropertyValue; } } } return $target } var Options$1$1 = { ancestors: [], delimiter: '.', depth: 0, frozen: false, maxDepth: 10, nonenumerable: true, path: false, sealed: false, type: false, }; function getOwnPropertyDescriptor($properties, $propertyKey, $options) { const options = Object.assign({}, Options$1$1, $options, { ancestors: Object.assign([], $options.ancestors) }); const propertyDescriptor = Object.getOwnPropertyDescriptor($properties, $propertyKey); if(!options.nonenumerable && !propertyDescriptor.enumerable) { return } if(!options.ancestors.includes($properties)) { options.ancestors.unshift($properties); } if(options.ancestors.includes(propertyDescriptor.value)) { return } if(options.path) { options.path = (typeOf(options.path) === 'string') ? [options.path, $propertyKey].join(options.delimiter) : $propertyKey; propertyDescriptor.path = options.path; } if(options.type) { propertyDescriptor.type = typeOf(propertyDescriptor.value); } if(options.frozen) { propertyDescriptor.frozen = Object.isFrozen(propertyDescriptor.value); } if(options.sealed) { propertyDescriptor.sealed = Object.isSealed(propertyDescriptor.value); } if(['array', 'object'].includes(typeOf(propertyDescriptor.value))) { propertyDescriptor.value = getOwnPropertyDescriptors(propertyDescriptor.value, options); } return propertyDescriptor } function getOwnPropertyDescriptors($properties, $options) { const propertyDescriptors = {}; const options = Object.assign({}, Options$1$1, $options); if(options.depth >= options.maxDepth) { return propertyDescriptors } else { options.depth++; } for(const [$propertyKey, $propertyDescriptor] of Object.entries(Object.getOwnPropertyDescriptors($properties))) { const propertyDescriptor = getOwnPropertyDescriptor($properties, $propertyKey, options); if(propertyDescriptor !== undefined) { propertyDescriptors[$propertyKey] = propertyDescriptor; } } return propertyDescriptors } var Options$2 = { typeCoercion: false, }; function defineProperty$1($target, $propertyKey, $propertyDescriptor, $options) { const propertyDescriptor = Object.assign({}, $propertyDescriptor); const options = Object.assign({}, Options$2, $options); const typeOfPropertyValue = typeOf(propertyDescriptor.value); if(['array', 'object'].includes(typeOfPropertyValue)) { const propertyValue = isArrayLike(Object.defineProperties( typedObjectLiteral(typeOfPropertyValue), propertyDescriptor.value )) ? [] : {}; propertyDescriptor.value = defineProperties$1(propertyValue, propertyDescriptor.value, options); } else if( options.typeCoercion && Object.getOwnPropertyDescriptor(propertyDescriptor, 'type') !== undefined && !['undefined', 'null'].includes(typeOfPropertyValue) ) { propertyDescriptor.value = Primitives[propertyDescriptor.type](propertyDescriptor.value); } Object.defineProperty($target, $propertyKey, propertyDescriptor); if($propertyDescriptor.sealed) { Object.seal($target[$propertyKey]); } if($propertyDescriptor.frozen) { Object.freeze($target[$propertyKey]); } return $target } function defineProperties$1($target, $propertyDescriptors, $options) { const options = Object.assign({}, Options$2, $options); for(const [ $propertyKey, $propertyDescriptor ] of Object.entries($propertyDescriptors)) { defineProperty$1($target, $propertyKey, $propertyDescriptor, options); } return $target } var Options$1$2 = ($options) => { const options = assign$2({ propertyDescriptors: false, defineProperties: false, replacers: [], revivers: [], }, $options); if(options.propertyDescriptors?.type) { options.replacers.push(function BigintReplacer($key, $value) { if(typeOf($value) === 'bigint') { return String($value) } else { return $value } }); } return options }; function JSONMiddlewares($middlewares, $key, $value) { let value = $value; for(const $middleware of $middlewares) { value = $middleware($key, $value); } return value } class LocalStorageRoute extends EventTarget { constructor($path, $options) { super(); if(!$path) return null const options = Options$1$2($options); const db = localStorage; Object.defineProperties(this, { 'path': { value: $path }, 'raw': { value: function raw() { return db.getItem(this.path) } }, 'get': { value: function get() { const { path } = this; const raw = db.getItem(this.path); if(['undefined', undefined].includes(raw)) { return } const propertyDescriptors = JSON.parse(raw, JSONMiddlewares.bind(null, options.revivers)); const dataTypedObjectLiteral = typedObjectLiteral(propertyDescriptors); const data = (options.propertyDescriptors) ? defineProperties$1( dataTypedObjectLiteral, propertyDescriptors, options.defineProperties ) : propertyDescriptors; this.dispatchEvent(new CustomEvent('get', { detail: { path, raw, data } })); return data } }, 'set': { value: function set($data) { const data = $data; const { path } = this; let raw = (options.propertyDescriptors) ? JSON.stringify( getOwnPropertyDescriptors(data, options.propertyDescriptors), JSONMiddlewares.bind(null, options.replacers) ) : JSON.stringify( data, JSONMiddlewares.bind(null, options.replacers) ); db.setItem(this.path, raw); this.dispatchEvent(new CustomEvent('set', { detail: { path, raw, data } })); return } }, 'remove': { value: function remove() { const { path } = this; const raw = this.raw(); const data = this.get(); db.removeItem(this.path); this.dispatchEvent(new CustomEvent('remove', { detail: { path, raw, data } })); return } }, }); } } class Verification extends EventTarget { constructor($settings) { super(); const settings = Object.assign({}, $settings); Object.defineProperties(this, { 'type': { value: settings.type }, 'key': { value: settings.key }, 'value': { value: settings.value }, 'message': { configurable: true, get() { let message; if(this.pass !== undefined) { message = settings.messages[String(this.pass)](this); Object.defineProperty(this, 'message', { value: message }); } return message } }, 'pass': { writable: true, set pass($pass) { Object.defineProperty(this, 'pass', { value: $pass }); }, }, }); } } const Messages$1 = { 'true': ($validation) => `${$validation.valid}`, 'false': ($validation) => `${$validation.valid}`, }; function report($format = "expand", $prevalidation) { const prevalidation = $prevalidation || this; const schema = prevalidation.schema; const validations = [].concat( prevalidation.advance, prevalidation.deadvance, prevalidation.unadvance ); if($format === "expand") { const _report = typedObjectLiteral$1(schema.type); for(const $validation of validations) { const verifications = [].concat( $validation.advance, $validation.deadvance, $validation.unadvance ); _report[$validation.key] = {}; for(const $verification of verifications) { _report[$validation.key][$verification.type] = {}; if($verification.validation) { _report[$validation.key][$verification.type] = this.report($format, $verification.validation); } else { _report[$validation.key][$verification.type] = $verification; } } } return _report } if($format === "impand") { if(prevali