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
351 lines (330 loc) • 12 kB
JavaScript
const Primitives = {
'string': String,
'number': Number,
'boolean': Boolean,
'bigint': BigInt,
'undefined': undefined,
'null': null,
};
const PrimitiveKeys = Object.keys(Primitives);
const PrimitiveValues = Object.values(Primitives);
const Objects = {
'object': Object,
'array': Array,
};
const ObjectKeys = Object.keys(Objects);
const ObjectValues = Object.values(Objects);
const Types = Object.assign({}, Primitives, Objects);
const TypeKeys = Object.keys(Types);
const TypeValues = Object.values(Types);
const TypeMethods = [
Primitives.String, Primitives.Number, Primitives.Boolean,
Objects.Object, Objects.Array
];
var index = /*#__PURE__*/Object.freeze({
__proto__: null,
ObjectKeys: ObjectKeys,
ObjectValues: ObjectValues,
Objects: Objects,
PrimitiveKeys: PrimitiveKeys,
PrimitiveValues: PrimitiveValues,
Primitives: Primitives,
TypeKeys: TypeKeys,
TypeMethods: TypeMethods,
TypeValues: TypeValues,
Types: Types
});
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 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 set($path, $source) {
const subpaths = $path.split(new RegExp(regularExpressions.quotationEscape));
const key = subpaths.pop();
const target = (key && !isNaN(key)) ? [] : {};
let subtarget = target;
let subpathIndex = 0;
while(subpathIndex < subpaths.length - 2) {
const $subpath = keypaths[subpathIndex];
if(isNaN($subpath)) { subtarget[$subpath] = {}; }
else { subtarget[$subpath] = {}; }
subtarget = subtarget[$subpath];
subpathIndex++;
}
subtarget[key] = $source;
return target
}
const ValidPropertyTypes = ['string', 'function'];
function expandTree($source, $property) {
const typeOfProperty = typeOf($property);
const typeOfSource = typeOf($source);
if(
!ValidPropertyTypes.includes(typeOfProperty) ||
!ObjectKeys.includes(typeOfSource)
) { return $source }
let target = typedObjectLiteral($source);
for(const [$sourceKey, $sourceValue] of Object.entries($source)) {
const sourceValue = (
ObjectKeys.includes(typeOf($sourceValue))
) ? expandTree($sourceValue, $property) : $sourceValue;
if(typeOfProperty === ValidPropertyTypes[0]) {
target[$sourceKey] = set($property, sourceValue);
}
else if(typeOfProperty === ValidPropertyTypes[1]) {
target[$sourceKey] = $property(sourceValue);
}
}
return target
}
function impandTree($source, $property) {
const typeOfProperty = typeOf($property);
const typeOfSource = typeOf($source);
if(
!['string', 'function'].includes(typeOfProperty) ||
!['array', 'object'].includes(typeOfSource)
) { return $source }
let target = typedObjectLiteral($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
}
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
};
const defaultAccessor = ($target, $property) => {
if($property === undefined) { return $target }
else { return $target[$property] }
};
var Accessors = {
default: defaultAccessor};
const Options$2 = {
depth: 0,
maxDepth: 10,
accessors: [Accessors.default],
ancestors: [],
};
function compandTree($object, $options) {
const _compandTree = [];
const options = Object.assign({}, Options$2, $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($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($target[$sourcePropertyKey], $sourcePropertyValue);
}
else {
$target[$sourcePropertyKey] = $sourcePropertyValue;
}
}
}
return $target
}
function assignConcat($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] = assignConcat($target[$sourcePropertyKey], $sourcePropertyValue);
}
else if(
typeOfTargetPropertyValue === 'array' &&
typeOfSourcePropertyValue === 'array'
) {
$target[$sourcePropertyKey] = $target[$sourcePropertyKey].concat($sourcePropertyValue);
}
else {
$target[$sourcePropertyKey] = $sourcePropertyValue;
}
}
}
return $target
}
var Options$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, $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, $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 = {
typeCoercion: false,
};
function defineProperty($target, $propertyKey, $propertyDescriptor, $options) {
const propertyDescriptor = Object.assign({}, $propertyDescriptor);
const options = Object.assign({}, Options, $options);
const typeOfPropertyValue = typeOf(propertyDescriptor.value);
if(['array', 'object'].includes(typeOfPropertyValue)) {
const propertyValue = isArrayLike(Object.defineProperties(
typedObjectLiteral(typeOfPropertyValue), propertyDescriptor.value
)) ? [] : {};
propertyDescriptor.value = defineProperties(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($target, $propertyDescriptors, $options) {
const options = Object.assign({}, Options, $options);
for(const [
$propertyKey, $propertyDescriptor
] of Object.entries($propertyDescriptors)) {
defineProperty($target, $propertyKey, $propertyDescriptor, options);
}
return $target
}
function freeze($target) {
for(const [$propertyKey, $propertyValue] of Object.entries($target)) {
if(Object.is($propertyValue, $target)) { continue }
if($propertyValue && typeof $propertyValue === 'object') {
freeze($propertyValue);
}
}
return Object.freeze($target)
}
export { assign, assignConcat, compandTree, defineProperties, defineProperty, expandTree, freeze, getOwnPropertyDescriptor, getOwnPropertyDescriptors, impandTree, isArrayLike, regularExpressions, typeOf, typedObjectLiteral, index as variables };
//# sourceMappingURL=recourse.js.map