Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

custom-ability

Package Overview
Dependencies
Maintainers
1
Versions
30
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

custom-ability - npm Package Compare versions

Comparing version 1.3.2 to 1.3.3

44

lib/custom-ability.js
(function() {
'use strict';
var defineProperty, extend, extendFilter, injectMethods, isArray, isBoolean, isFunction,
var defineProperty, extend, extendFilter, getNonEnumNames, injectMethod, injectMethods, injectMethodsFromNonEnum, isArray, isBoolean, isFunction,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

@@ -18,4 +18,32 @@

injectMethod = require('util-ex/lib/injectMethod');
defineProperty = require('util-ex/lib/defineProperty');
getNonEnumNames = require('util-ex/lib/get-non-enumerable-names');
injectMethodsFromNonEnum = function(aTargetClass, aObject, filter) {
var nonEnumNames, result;
nonEnumNames = getNonEnumNames(aObject);
result = [];
nonEnumNames.forEach(function(k) {
var v;
if (!filter || filter(k)) {
if (k[0] === '$' && isFunction(v = aObject[k])) {
k = k.substr(1);
if (isFunction(aTargetClass[k])) {
injectMethod(aTargetClass, k, v);
} else if (aTargetClass[k] != null) {
throw new TypeError('the same non-null name is not function:' + k);
} else {
aTargetClass[k] = v;
}
delete aObject[k];
result.push(k);
}
}
});
return result;
};
module.exports = function(abilityClass, aCoreMethod, isGetClassFunc) {

@@ -51,4 +79,10 @@ var abilityFn, filter, getAdditionalAbility;

if ((aOptions == null) || !(aOptions.include || aOptions.exclude)) {
extend(aClass, AbilityClass);
extend(aClass.prototype, AbilityClass.prototype);
vExcludes = injectMethodsFromNonEnum(aClass, AbilityClass);
extendFilter(aClass, AbilityClass, function(k) {
return !(__indexOf.call(vExcludes, k) >= 0);
});
vExcludes = injectMethodsFromNonEnum(aClass.prototype, AbilityClass.prototype);
extend(aClass.prototype, AbilityClass.prototype, function(k) {
return !(__indexOf.call(vExcludes, k) >= 0);
});
} else {

@@ -81,2 +115,6 @@ vIncludes = aOptions.include;

};
vAbilities = injectMethodsFromNonEnum(aClass, AbilityClass, vFilter);
vAbilities = vAbilities.concat(injectMethodsFromNonEnum(aClass.prototype, AbilityClass.prototype, vFilter));
vExcludes = vExcludes.concat(vAbilities);
vAbilities = void 0;
filterMethods = function(methods) {

@@ -83,0 +121,0 @@ var k;

4

package.json
{
"name": "custom-ability",
"version": "1.3.2",
"version": "1.3.3",
"description": "make custom ability more easy. generate the ability which can be added to any class directly.",

@@ -20,3 +20,3 @@ "homepage": "https://github.com/snowyu/custom-ability.js",

"inherits-ex": "~1.0.6",
"util-ex": "~0.3.2"
"util-ex": "^0.3.8"
},

@@ -23,0 +23,0 @@ "devDependencies": {

@@ -11,2 +11,139 @@ ### custom-ability [![Build Status](https://img.shields.io/travis/snowyu/custom-ability.js/master.png)](http://travis-ci.org/snowyu/custom-ability.js) [![npm](https://img.shields.io/npm/v/custom-ability.svg)](https://npmjs.org/package/custom-ability) [![downloads](https://img.shields.io/npm/dm/custom-ability.svg)](https://npmjs.org/package/custom-ability) [![license](https://img.shields.io/npm/l/custom-ability.svg)](https://npmjs.org/package/custom-ability)

## Usage
suppose we wanna add the RefCount ability to any class directly.
the RefCount ability will add the following members to your class.
and you should implement the `destroy` method which will be called
by `release`/`free`.
* properties:
* RefCount *(integer)*: the reference count.
* methods:
* `release()`/`free()`: Decrements reference count for this instance.
If it is becoming less than 0, the object would be (self) destroyed.
* `addRef()`: Increments the reference count for this instance
and returns the new reference count.
**Note**: The same name of the methods will be replaced via the ability.
These old methods will be lost. So, you must confirm whether there are the
same methods in your class before you apply the new ability.
```coffee
customAbility = require 'custom-ability'
class RefCountable
# define the instance methods here:
release: ->
result = --@RefCount
@destroy() unless result >= 0
result
free: @::release
addRef: ->
if not isUndefined @RefCount
++@RefCount
else
@RefCount = 1
# the class methods if any:
@someClassMethod: ->
module.exports = customAbility RefCountable, 'addRef'
```
do not forget to add the `"ability"` keyword to your package.json which means
the ability power with it.
```js
// package.json
"keywords": [
"ability",
...
],
```
do not forget to add the `"ability.js"` file on your package root folder too.
now user use this ability like this:
```coffee
refable = require 'ref-object/ability'
class MyClass
refable MyClass
destroy: ->console.log 'destroy'
my = new MyClass
my.addRef()
my.free() # nothing
my.free() # print the 'destroy' here.
```
More complicated example, you can see the [events-ex/src/eventable.coffee](https://github.com/snowyu/events-ex.js).
## additional $abilities
In order to make certain ability to work, you need to modify some methods
of the class. this time we need the "additional abilities" now. eg, the
event-able ability to [AbstractObject](https://github.com/snowyu/abstract-object).
We need to send a notification event when the state of the object changes.
So the event-able of [AbstractObject](https://github.com/snowyu/abstract-object)
should be:
```coffee
eventable = require 'events-ex/eventable'
eventableOptions = require './eventable-options'
module.exports = (aClass, aOptions)->
eventable aClass, eventableOptions(aOptions)
```
```coffee
# eventable-options.coffee
module.exports = (aOptions)->
aOptions = {} unless aOptions
aOptions.methods = {} unless aOptions.methods
extend aOptions.methods,
# override methods:
setObjectState: (value, emitted = true)->
self= @self
@super.call(self, value)
self.emit value, self if emitted
return
...
return aOptions
# more detail on [AbstractObject/src/eventable-options.coffee](https://github.com/snowyu/abstract-object)
```
the original `eventable('events-ex/eventable')` is no useful for AbstractObject.
but we wanna the original `eventable('events-ex/eventable')` knows the changes
and use it automatically.
```coffee
eventable = require 'events-ex/eventable'
class MyClass
inherits MyClass, AbstractObject
eventable MyClass
```
you just do this on the AbstractObject:
```coffee
AbstractObject = require('./lib/abstract-object')
AbstractObject.$abilities =
# "Eventable" is the AbilityClass name
Eventable: require('./lib/eventable-options')
module.exports = AbstractObject
```
# API

@@ -20,3 +157,3 @@

* customAbility(abilityClass[, coreMethod[, isGetClassFunction]])
## customAbility(abilityClass[, coreMethod[, isGetClassFunction]])

@@ -41,3 +178,3 @@ __arguments__

* note: the `coreMethod` could not be excluded. It's always added to the class.
* `methods `*(object)*: hooked methods to the class
* `methods `*(object)*: injected/hooked methods to the class
* key: the method name to hook.

@@ -47,8 +184,37 @@ * value: the new method function, if original method is exists or not in replacedMethods:

* `this.self` is the original `this` object.
* `classMethods` *(object)*: hooked class methods to the class
* `classMethods` *(object)*: hooked class methods to the class, it's the same as the `methods`.
* `replacedMethods` *(array)*: the method name in the array will be replaced the original
method directly.
# Specification
## V1.3.3
+ use the injectMethods(AOP) for the methods of non-enumerable and beginning with '$' in an ability
to call `super` method.
```coffee
customAbility = require 'custom-ability'
class PropertyManagerAbility
constructor: ->@initialize.call @, arguments[gOptPos]
# the non-enumerable property and beginning with '$' will
# be injected to `initialize` method
defineProperty @::, '$initialize', ->
options = arugments[gOptPos]
options?={}
that = @
if @super and @self
inherited = @super
that = @self
inherited.apply(that, arugments)
that._initialize options if isFunction that._initialize
that.defineProperties(options.attributes)
that.assign(options)
module.exports = customAbility PropertyManagerAbility, 'assign'
```
## V1.3.x

@@ -154,135 +320,1 @@

```
## Usage
suppose we wanna add the RefCount ability to any class directly.
the RefCount ability will add the following members to your class.
and you should implement the `destroy` method which will be called
by `release`/`free`.
* properties:
* RefCount *(integer)*: the reference count.
* methods:
* `release()`/`free()`: Decrements reference count for this instance.
If it is becoming less than 0, the object would be (self) destroyed.
* `addRef()`: Increments the reference count for this instance
and returns the new reference count.
```coffee
customAbility = require 'custom-ability'
class RefCountable
# define the instance methods here:
release: ->
result = --@RefCount
@destroy() unless result >= 0
result
free: @::release
addRef: ->
if not isUndefined @RefCount
++@RefCount
else
@RefCount = 1
# the class methods if any:
@someClassMethod: ->
module.exports = customAbility RefCountable, 'addRef'
```
do not forget to add the `"ability"` keyword to your package.json which means
the ability power with it.
```js
// package.json
"keywords": [
"ability",
...
],
```
do not forget to add the `"ability.js"` file on your package root folder too.
now user use this ability like this:
```coffee
refable = require 'ref-object/ability'
class MyClass
refable MyClass
destroy: ->console.log 'destroy'
my = new MyClass
my.addRef()
my.free() # nothing
my.free() # print the 'destroy' here.
```
More complicated example, you can see the [events-ex/src/eventable.coffee](https://github.com/snowyu/events-ex.js).
## additional $abilities
In order to make certain ability to work, you need to modify some methods
of the class. this time we need the "additional abilities" now. eg, the
event-able ability to [AbstractObject](https://github.com/snowyu/abstract-object).
We need to send a notification event when the state of the object changes.
So the event-able of [AbstractObject](https://github.com/snowyu/abstract-object)
should be:
```coffee
eventable = require 'events-ex/eventable'
eventableOptions = require './eventable-options'
module.exports = (aClass, aOptions)->
eventable aClass, eventableOptions(aOptions)
```
```coffee
# eventable-options.coffee
module.exports = (aOptions)->
aOptions = {} unless aOptions
aOptions.methods = {} unless aOptions.methods
extend aOptions.methods,
# override methods:
setObjectState: (value, emitted = true)->
self= @self
@super.call(self, value)
self.emit value, self if emitted
return
...
return aOptions
# more detail on [AbstractObject/src/eventable-options.coffee](https://github.com/snowyu/abstract-object)
```
the original `eventable('events-ex/eventable')` is no useful for AbstractObject.
but we wanna the original `eventable('events-ex/eventable')` knows the changes
and use it automatically.
```coffee
eventable = require 'events-ex/eventable'
class MyClass
inherits MyClass, AbstractObject
eventable MyClass
```
you just do this on the AbstractObject:
```coffee
AbstractObject = require('./lib/abstract-object')
AbstractObject.$abilities =
# "Eventable" is the AbilityClass name
Eventable: require('./lib/eventable-options')
module.exports = AbstractObject
```

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc