Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

esmodule

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

esmodule - npm Package Compare versions

Comparing version
0.0.1
to
0.0.2
+5
.esdoc.json
{
"source": "./lib",
"destination": "./dist/api/esdoc",
"plugins": [{"name": "esdoc-standard-plugin"}]
}
language: node_js
node_js:
- 6.0
after_success: npm run coverage
/**
* @module esmodule
* @author Vyacheslav Aristov <vv.aristov@gmail.com>
* @license MIT
*/
export * from './assembler'
import test from 'ava'
import { Assembler } from '../lib/assembler'
let undefined
const { getTargetOf } = Assembler
class Example extends Object {}
Example.prototype.foo = null
Example.prototype.bar = null
class ExampleAssembler extends Assembler {
setPropertyFilter(name) {
return super.setPropertyFilter(name) && name !== 'nom'
}
set foo(foo) {
this.target.foo = foo
}
get foo() {
return this.target.foo
}
get target() {
return getTargetOf(this)
}
static get defaultPropertyName() {
return 'foo'
}
static get targetPropertyName() {
return 'target'
}
static get interface() {
return Example
}
}
test('interface', t => {
t.is(Assembler.interface, Object)
})
test('defaultPropertyName', t => {
t.is(Assembler.defaultPropertyName, undefined)
})
test('create', t => {
t.deepEqual(Assembler.create(), {})
})
test('getTargetOf', t => {
const obj = {}
t.is(Assembler.getTargetOf(obj), null)
})
test('getInstanceOf', t => {
t.is(Assembler.getInstanceOf({}), null)
})
test('new Assembler + getTargetOf + getInstanceOf', t => {
const instance = new Assembler
const target = Assembler.getTargetOf(instance)
t.deepEqual(target, {})
t.true(target instanceof Assembler.interface)
t.is(Assembler.getTargetOf(target), target)
t.is(Assembler.getInstanceOf(target), instance)
t.is(Assembler.getInstanceOf(instance), instance)
})
test('setProperty(name, new String)', t => {
const instance = new ExampleAssembler
instance.setProperty('foo', '123')
t.is(instance.foo, '123')
t.is(instance.target.foo, '123')
})
test('setProperty(name, undefined)', t => {
const instance = new ExampleAssembler
instance.setProperty('foo', undefined)
t.is(instance.foo, null)
t.is(instance.target.foo, null)
})
test('setProperty(name, new String) -> setPropertyFallback', t => {
const instance = new ExampleAssembler
instance.setProperty('bar', '456')
t.is(instance.bar, undefined)
t.is(instance.target.bar, '456')
})
test('setProperty(name, undefined) -> setPropertyFallback', t => {
const instance = new ExampleAssembler
instance.setProperty('bar', undefined)
t.is(instance.bar, undefined)
t.is(instance.target.bar, null)
})
test('setProperty -> setPropertyFallback -> setPropertyMismatch', t => {
const instance = new ExampleAssembler
t.throws(() => instance.setProperty('wiz', '789'))
t.throws(() => instance.setProperty('wiz', undefined))
})
test('Assign filtered property', t => {
const instance = new ExampleAssembler
instance.assign({ nom : '777' })
t.is(instance.nom, undefined)
t.is(instance.target.nom, undefined)
})
test('Init by defined properties', t => {
const instance = new ExampleAssembler
instance.init({
foo : '123',
bar : '456'
})
t.is(instance.foo, '123')
t.is(instance.target.foo, '123')
t.is(instance.bar, undefined)
t.is(instance.target.bar, '456')
})
test('Init by not defined property', t => {
t.throws(() => new ExampleAssembler({ wiz : '789' }))
t.throws(() => new ExampleAssembler({ wiz : undefined }))
})
test('Init by the default property', t => {
const instance = new ExampleAssembler
instance.init('123')
t.is(instance.foo, '123')
t.is(instance.target.foo, '123')
t.deepEqual(getTargetOf(new Assembler('will be ignored')), {})
})
test('Init by explicit target setting', t => {
const target = new Example
const instance = new ExampleAssembler({ target })
t.is(instance.target, target)
t.throws(() => new ExampleAssembler({ target : 'wrong' }))
})
+109
-77
let undefined
const INIT_PROPERTY_NAME = 'init'
const INSTANCE_PROPERTY_NAME = '__instance__'
const TARGET_PROPERTY_NAME = '__target__'
const TYPE_UNDEFINED = 'undefined'
const storage = new WeakMap
const key = Symbol()
/**
* @summary Assembler is a simple class, which helps to assemble another JavaScript objects.
*/
export class Assembler {
/**
* Create the assembler instance and assemble the specified object
* Initializes the object by all passed init arguments
* Create and initialize target by specified initialing object
* @param {*} [init]
*/
constructor(init) {
this.assemble(init)
}
/**
* Instantiate and initialize the specified object
* @param {*} [init] initializing dictionary
* @returns {Object|*}
*/
assemble(init) {
this.create(init)
this.init(init)
return this[TARGET_PROPERTY_NAME]
}
/**
* Create the defined object
* @param {*} [init] initializing dictionary
* Create target and link it with the assembler instance
* @param {*} [init] initializing object
*/
create(init) {
this.setInstanceOf(init && init.constructor === Object?
this.constructor.create(init) :
this.constructor.create())
const constructor = this.constructor
const { targetPropertyName } = constructor
if(targetPropertyName !== undefined
&& init && init.constructor === Object && init.hasOwnProperty(targetPropertyName)) {
constructor.setTargetOf(this, init[targetPropertyName])
}
else {
constructor.setTargetOf(this, init && init.constructor === Object?
constructor.create(init) :
constructor.create())
}
}
/**
* This is a handshake between the Assembler instance and a target
* @param {Object|*} target
* Initialize target by specified initializing object
* @param {*} [init] initializing object
*/
setInstanceOf(target) {
this[TARGET_PROPERTY_NAME] = target
target[INSTANCE_PROPERTY_NAME] = this
}
/**
* Initialize target with the specified properties
* @param {*} [init] initializing dictionary
*/
init(init) {

@@ -55,17 +45,22 @@ if(init && init.constructor === Object) {

}
else if(typeof init !== TYPE_UNDEFINED) {
this.assign({ [this.constructor.initPropertyName] : init })
else if(init !== undefined) {
const { defaultPropertyName } = this.constructor
if(defaultPropertyName !== undefined) {
this.setProperty(defaultPropertyName, init)
}
}
else this.assign({})
}
/**
* Assign specified properties on the instance if they are not static
* Assign properties from specified initializing object
* @param {{}} init
*/
assign(init) {
const { constructor } = this
for(let prop in init) {
if(init.hasOwnProperty(prop) && !(prop in constructor)) {
this.setProperty(prop, init[prop])
const { defaultPropertyName } = this.constructor
if(defaultPropertyName !== undefined && init.hasOwnProperty(defaultPropertyName)) {
this.setProperty(defaultPropertyName, init[defaultPropertyName])
}
for(const name in init) {
if(init.hasOwnProperty(name) && this.setPropertyFilter(name)) {
this.setProperty(name, init[name])
}

@@ -76,21 +71,27 @@ }

/**
* Set a single property if it is in this and not undefined or fallback otherwise
* @param {String} name
* @param {String} value
* Set a single property if it is in this and is not undefined or fallback otherwise
* @param {string} name
* @param {*} value
*/
setProperty(name, value) {
if(value !== undefined) {
if(name in this) this[name] = value
else this.setPropertyFallback(name, value)
if(name in this) {
if(value !== undefined) {
this[name] = value
}
}
else this.setPropertyFallback(name, value)
}
/**
* Set a signle property on target if it is in target or mismatch otherwise
* @param name
* @param value
* Set a single property on target if it is in target and is not undefined or mismatch otherwise
* @param {string} name
* @param {*} value
*/
setPropertyFallback(name, value) {
const target = this[TARGET_PROPERTY_NAME]
if(name in target) target[name] = value
const target = this[key]
if(name in target) {
if(value !== undefined) {
target[name] = value
}
}
else this.setPropertyMismatch(name)

@@ -100,37 +101,78 @@ }

/**
* Throw the "set property mismatch" error
* @param {String} prop mismatched property name
* @param {string} name
* @returns {boolean}
*/
setPropertyMismatch(prop) {
const name = this.constructor.name
throw Error(`The property "${ prop }" is not found on the ${ name } instance`)
setPropertyFilter(name) {
const { defaultPropertyName, targetPropertyName } = this.constructor
return name !== targetPropertyName && name !== defaultPropertyName
}
/**
* Create the interface prototype object and define it's properties if they are specified
* Handle a mismatched property assignment
* @param {string} name mismatched property name
*/
setPropertyMismatch(name) {
throw Error(`The property '${ name }' is not found on the '${ this.constructor.name }' instance.`)
}
/**
* Create a target specified by interface
* @param {{}} [init]
* @returns {Object}
*/
static create({ properties } = this) {
return Object.create(this.interface.prototype, properties)
static create(init) {
return new this.interface
}
/**
* Get an instance of the target or an instance itself
* @param {Assembler|Object|*} target
* Get an instance of the target or the instance itself or null if it's not a target
* @param {Assembler|Object|*} object
* @returns {Assembler|*|null}
*/
static getInstanceOf(target) {
return target instanceof Assembler? target : target[INSTANCE_PROPERTY_NAME]
static getInstanceOf(object) {
return object instanceof Assembler?
object :
storage.get(object) || null
}
/**
* This property name is used for the `init.constructor !== Object` cases
* @returns {String}
* Get a target of the instance or the target itself or null if it's not a target
* @param {Assembler|Object|*} object
* @returns {Object|*|null}
*/
static get initPropertyName() {
return INIT_PROPERTY_NAME
static getTargetOf(object) {
return object instanceof Assembler?
object[key] :
storage.has(object)? object : null
}
/**
* Link target and the assembler instance together
* @param {Assembler|*} instance
* @param {Object|*} target
*/
static setTargetOf(instance, target) {
const _interface = instance.constructor.interface
if(target instanceof _interface || target.constructor === _interface) {
instance[key] = target
storage.set(target, instance)
}
else throw TypeError(`Failed to execute 'setTargetOf' on '${ instance.constructor.name }': target is not of expected type.`)
}
/**
* This property name is used for the `init.constructor !== Object` case
* @returns {undefined|string}
* @abstract
*/
static get defaultPropertyName() {}
/**
* This property name may be used to explicitly set target of the instance
* @returns {undefined|string}
* @abstract
*/
static get targetPropertyName() {}
/**
* A default interface of a target object

@@ -142,12 +184,2 @@ * @returns {ObjectConstructor|*}

}
/**
* Default undefined properties
* @returns {undefined|*}
*/
static get properties() {
return undefined
}
}
Object.defineProperty(Assembler.prototype, TARGET_PROPERTY_NAME, { writable : true, value : null })
{
"name": "esmodule",
"version": "0.0.1",
"version": "0.0.2",
"description": "ES object assembler library",
"main": "lib/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "nyc ava",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"api": "rm -rf dist/api && npm run jsdoc && npm run esdoc",
"esdoc": "esdoc",
"jsdoc": "jsdoc lib/* -d dist/api/jsdoc --verbose"
},

@@ -17,8 +21,9 @@ "repository": {

"target",
"assemble",
"create",
"init",
"assign",
"interface",
"properties"
"property",
"fallback",
"mismatch",
"interface"
],

@@ -30,3 +35,45 @@ "author": "Vyacheslav Aristov <vv.aristov@gmail.ru>",

},
"homepage": "https://github.com/aristov/esmodule#readme"
"homepage": "https://github.com/aristov/esmodule#readme",
"devDependencies": {
"ava": "^0.25.0",
"babel-plugin-istanbul": "^4.1.6",
"babel-preset-env": "^1.7.0",
"babel-register": "^6.26.0",
"coveralls": "^3.0.1",
"esdoc": "^1.1.0",
"esdoc-standard-plugin": "^1.0.0",
"jsdoc": "^3.5.5",
"nyc": "^12.0.2"
},
"ava": {
"verbose": true
},
"babel": {
"presets": [
"env"
],
"ignore": "test.js",
"env": {
"development": {
"sourceMaps": "inline"
},
"test": {
"plugins": [
"istanbul"
]
}
}
},
"nyc": {
"require": [
"babel-register"
],
"reporter": [
"lcov",
"text"
],
"sourceMap": false,
"instrument": false,
"report-dir": "dist/coverage"
}
}
# esmodule
[![NPM Version](https://img.shields.io/npm/v/esmodule.svg)](https://www.npmjs.com/package/esmodule)
[![Build Status](https://travis-ci.org/aristov/esmodule.svg?branch=master)](https://travis-ci.org/aristov/esmodule)
[![Coverage Status](https://coveralls.io/repos/github/aristov/esmodule/badge.svg?branch=master)](https://coveralls.io/github/aristov/esmodule?branch=master)
[![dependencies Status](https://david-dm.org/aristov/esmodule/status.svg)](https://david-dm.org/aristov/esmodule)
[![devDependencies Status](https://david-dm.org/aristov/esmodule/dev-status.svg)](https://david-dm.org/aristov/esmodule?type=dev)
_work in progress_

@@ -13,3 +19,3 @@

## Development
## Testing

@@ -20,3 +26,3 @@ ```

npm install
npm run webpack
npm test
```

@@ -23,0 +29,0 @@

Sorry, the diff of this file is not supported yet