Last active
November 27, 2019 17:25
-
-
Save burdiuz/f530f5d53f5a74e5155cd43cf060e808 to your computer and use it in GitHub Desktop.
Functions to copy properties between projects including read-only, non-enumerable and get/set
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| source.js |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 'use strict'; | |
| Object.defineProperty(exports, '__esModule', { value: true }); | |
| const { hasOwn } = require('@actualwave/has-own'); | |
| /* | |
| Will throw error on trying to assign non-configurable property twice | |
| */ | |
| const assignOwnPropsUnsafe = (target, ...sources) => { | |
| sources.forEach((source) => Object.defineProperties(target, Object.getOwnPropertyDescriptors(source))); | |
| return target; | |
| }; | |
| const filterSources = (list) => list.filter((source) => source !== undefined && source !== null); | |
| const filterDescriptor = (target, name) => !hasOwn(target, name); | |
| const listPropertyNames = (descriptors) => Object.keys(descriptors); | |
| /* | |
| Allows to create special logic for assigining property descriptors by configuring | |
| touchPropFn - alter every property descriptor | |
| touchSourcesFn - access list of source objects before assigning properties | |
| getDescriptors - function to retrieve property descriptors | |
| filter - decides if property descriptor can be applied to a target | |
| */ | |
| const createAssignOwnProps = ( | |
| touchPropFn = (descriptor) => descriptor, | |
| touchSourcesFn = filterSources, | |
| getDescriptors = Object.getOwnPropertyDescriptors, | |
| listNames = listPropertyNames, | |
| filterProp = filterDescriptor, | |
| ) => (target, ...sources) => { | |
| touchSourcesFn(sources).forEach((source) => { | |
| const descriptors = getDescriptors(source); | |
| listNames(descriptors).forEach((name) => { | |
| if (filterProp(target, name)) { | |
| Object.defineProperty(target, name, touchPropFn(descriptors[name], name, target)); | |
| } | |
| }); | |
| }); | |
| return target; | |
| }; | |
| const assignOwnProps = createAssignOwnProps(); | |
| /* | |
| As you can see -- instead of re-assigning next descriptor for same property, I reversed array, | |
| so last descriptor being used. | |
| */ | |
| const assignOwnPropsOverwrite = createAssignOwnProps(undefined, (list) => filterSources([...list]).reverse()); | |
| /* | |
| Assign properties and alter each with properties from "sharedPart" | |
| Make every property enumerable: | |
| assignOwnPropsAlter(targetObj, { enumerable: true }, sourceObj1, sourceObj2); | |
| Actually overwrite properties: | |
| assignOwnPropsAlter(targetObj, { configurable: true }, sourceObj1, sourceObj2); | |
| */ | |
| const assignOwnPropsAlter = (() => { | |
| let overwritePart; | |
| const assignAndAlter = createAssignOwnProps((descriptor) => ({ ...descriptor, ...overwritePart })); | |
| return (target, sharedPart, ...sources) => { | |
| overwritePart = sharedPart; | |
| return assignAndAlter(target, ...sources); | |
| }; | |
| })(); | |
| exports.assignOwnPropsUnsafe = assignOwnPropsUnsafe; | |
| exports.createAssignOwnProps = createAssignOwnProps; | |
| exports.assignOwnProps = assignOwnProps; | |
| exports.assignOwnPropsOverwrite = assignOwnPropsOverwrite; | |
| exports.assignOwnPropsAlter = assignOwnPropsAlter; | |
| exports.default = assignOwnProps; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "name": "@actualwave/assign-own-props", | |
| "description": "Functions to copy properties between projects including read-only, non-enumerable and get/set", | |
| "version": "0.0.1", | |
| "main": "index.js", | |
| "keywords": [ | |
| "object", | |
| "property", | |
| "assign", | |
| "Object.assign", | |
| "hasOwn", | |
| "getOwnPropertyDescriptors", | |
| "defineProperty", | |
| "defineProperties", | |
| "Object.keys" | |
| ], | |
| "author": { | |
| "name": "Oleg Galaburda", | |
| "email": "[email protected]", | |
| "url": "http://actualwave.com/" | |
| }, | |
| "bugs": { | |
| "url": "https://gist.github.com/burdiuz/f530f5d53f5a74e5155cd43cf060e808", | |
| "email": "[email protected]" | |
| }, | |
| "homepage": "https://gist.github.com/burdiuz/f530f5d53f5a74e5155cd43cf060e808", | |
| "dependencies": { | |
| "@actualwave/has-own": "0.0.1" | |
| }, | |
| "license": "MIT" | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import hasOwn from '@actualwave/has-own'; | |
| /* | |
| Will throw error on trying to assign non-configurable property twice | |
| */ | |
| export const assignOwnPropsUnsafe = (target, ...sources) => { | |
| sources.forEach((source) => Object.defineProperties(target, Object.getOwnPropertyDescriptors(source))); | |
| return target; | |
| }; | |
| const filterSources = (list) => list.filter((source) => source !== undefined && source !== null); | |
| const filterDescriptor = (target, name) => !hasOwn(target, name); | |
| const listPropertyNames = (descriptors) => Object.keys(descriptors); | |
| /* | |
| Allows to create special logic for assigining property descriptors by configuring | |
| touchPropFn - alter every property descriptor | |
| touchSourcesFn - access list of source objects before assigning properties | |
| getDescriptors - function to retrieve property descriptors | |
| filter - decides if property descriptor can be applied to a target | |
| */ | |
| export const createAssignOwnProps = ( | |
| touchPropFn = (descriptor) => descriptor, | |
| touchSourcesFn = filterSources, | |
| getDescriptors = Object.getOwnPropertyDescriptors, | |
| listNames = listPropertyNames, | |
| filterProp = filterDescriptor, | |
| ) => (target, ...sources) => { | |
| touchSourcesFn(sources).forEach((source) => { | |
| const descriptors = getDescriptors(source); | |
| listNames(descriptors).forEach((name) => { | |
| if (filterProp(target, name)) { | |
| Object.defineProperty(target, name, touchPropFn(descriptors[name], name, target)); | |
| } | |
| }); | |
| }); | |
| return target; | |
| }; | |
| export const assignOwnProps = createAssignOwnProps(); | |
| /* | |
| As you can see -- instead of re-assigning next descriptor for same property, I reversed array, | |
| so last descriptor being used. | |
| */ | |
| export const assignOwnPropsOverwrite = createAssignOwnProps(undefined, (list) => filterSources([...list]).reverse()); | |
| /* | |
| Assign properties and alter each with properties from "sharedPart" | |
| Make every property enumerable: | |
| assignOwnPropsAlter(targetObj, { enumerable: true }, sourceObj1, sourceObj2); | |
| Actually overwrite properties: | |
| assignOwnPropsAlter(targetObj, { configurable: true }, sourceObj1, sourceObj2); | |
| */ | |
| export const assignOwnPropsAlter = (() => { | |
| let overwritePart; | |
| const assignAndAlter = createAssignOwnProps((descriptor) => ({ ...descriptor, ...overwritePart })); | |
| return (target, sharedPart, ...sources) => { | |
| overwritePart = sharedPart; | |
| return assignAndAlter(target, ...sources); | |
| }; | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment