Comparing version 0.0.1 to 0.1.0
@@ -0,1 +1,8 @@ | ||
0.1.0 / 2014-06-15 | ||
================== | ||
* Add `deprecate.function(fn, message)` | ||
* Add `process.on('deprecation', fn)` emitter | ||
* Automatically generate message when omitted from `deprecate()` | ||
0.0.1 / 2014-06-15 | ||
@@ -2,0 +9,0 @@ ================== |
173
index.js
@@ -11,2 +11,3 @@ /*! | ||
var EventEmitter = require('events').EventEmitter | ||
var relative = require('path').relative | ||
@@ -28,2 +29,42 @@ var supportsColor = require('supports-color') | ||
/** | ||
* Get listener count on event emitter. | ||
*/ | ||
/*istanbul ignore next*/ | ||
var eventListenerCount = EventEmitter.listenerCount | ||
|| function (emitter, type) { return emitter.listeners(type).length } | ||
/** | ||
* Create arguments string to keep arity. | ||
*/ | ||
function createArgumentsString(arity) { | ||
var str = '' | ||
for (var i = 0; i < arity; i++) { | ||
str += ', arg' + i | ||
} | ||
return str.substr(2) | ||
} | ||
/** | ||
* Create stack string from stack. | ||
*/ | ||
function createStackString(stack) { | ||
var str = this.name + ': ' + this.namespace | ||
if (this.message) { | ||
str += ' deprecated ' + this.message | ||
} | ||
for (var i = 0; i < stack.length; i++) { | ||
str += '\n at ' + stack[i].toString() | ||
} | ||
return str | ||
} | ||
/** | ||
* Create deprecate for namespace in caller. | ||
@@ -50,2 +91,4 @@ */ | ||
deprecate.function = wrapfunction | ||
return deprecate | ||
@@ -58,11 +101,24 @@ } | ||
function log(message) { | ||
function log(message, site) { | ||
var caller | ||
var callSite | ||
var i = 0 | ||
var seen = false | ||
var stack = getStack() | ||
var site = callSiteLocation(stack[2]) | ||
var file = this._file | ||
if (site) { | ||
// provided site | ||
callSite = callSiteLocation(stack[1]) | ||
callSite.name = site.name | ||
file = callSite[0] | ||
} else { | ||
// get call site | ||
i = 2 | ||
site = callSiteLocation(stack[i]) | ||
callSite = site | ||
} | ||
// get caller of deprecated thing in relation to file | ||
for (var i = 2; i < stack.length; i++) { | ||
for (; i < stack.length; i++) { | ||
caller = callSiteLocation(stack[i]) | ||
@@ -88,2 +144,16 @@ | ||
// generate automatic message from call site | ||
if (!message) { | ||
message = callSite === site || !callSite.name | ||
? defaultMessage(site) | ||
: defaultMessage(callSite) | ||
} | ||
// emit deprecation if listeners exist | ||
if (eventListenerCount(process, 'deprecation') !== 0) { | ||
var err = DeprecationError(this._namespace, message, stack.slice(i)) | ||
process.emit('deprecation', err) | ||
return | ||
} | ||
// format and write message | ||
@@ -112,6 +182,29 @@ var format = supportsColor && process.stderr.isTTY | ||
return [file, line, colm] | ||
var site = [file, line, colm] | ||
site.callSite = callSite | ||
site.name = callSite.getFunctionName() | ||
return site | ||
} | ||
/** | ||
* Generate a default message from the site. | ||
*/ | ||
function defaultMessage(site) { | ||
var callSite = site.callSite | ||
var funcName = site.name | ||
// make useful anonymous name | ||
if (!funcName) { | ||
funcName = '<anonymous@' + formatLocation(site) + '>' | ||
} | ||
return callSite.getMethodName() | ||
? callSite.getTypeName() + '.' + funcName | ||
: funcName | ||
} | ||
/** | ||
* Format deprecation message without color. | ||
@@ -185,1 +278,73 @@ */ | ||
} | ||
/** | ||
* Return a wrapped function in a deprecation message. | ||
*/ | ||
function wrapfunction(fn, message) { | ||
var args = createArgumentsString(fn.length) | ||
var deprecate = this | ||
var stack = getStack() | ||
var site = callSiteLocation(stack[1]) | ||
site.name = fn.name | ||
var deprecatedfn = eval('(function (' + args + ') {\n' | ||
+ 'log.call(deprecate, message, site)\n' | ||
+ 'return fn.apply(this, arguments)\n' | ||
+ '})') | ||
return deprecatedfn | ||
} | ||
/** | ||
* Create DeprecationError for deprecation | ||
*/ | ||
function DeprecationError(namespace, message, stack) { | ||
var error = new Error() | ||
var stackString | ||
Object.defineProperty(error, 'constructor', { | ||
value: DeprecationError | ||
}) | ||
Object.defineProperty(error, 'message', { | ||
configurable: true, | ||
enumerable: false, | ||
value: message, | ||
writable: true | ||
}) | ||
Object.defineProperty(error, 'name', { | ||
enumerable: false, | ||
configurable: true, | ||
value: 'DeprecationError', | ||
writable: true | ||
}) | ||
Object.defineProperty(error, 'namespace', { | ||
configurable: true, | ||
enumerable: false, | ||
value: namespace, | ||
writable: true | ||
}) | ||
Object.defineProperty(error, 'stack', { | ||
configurable: true, | ||
enumerable: false, | ||
get: function () { | ||
if (stackString !== undefined) { | ||
return stackString | ||
} | ||
// prepare stack trace | ||
return stackString = createStackString.call(this, stack) | ||
}, | ||
set: function setter(val) { | ||
stackString = val | ||
} | ||
}) | ||
return error | ||
} |
{ | ||
"name": "depd", | ||
"description": "Deprecate all the things", | ||
"version": "0.0.1", | ||
"version": "0.1.0", | ||
"author": "Douglas Christopher Wilson <doug@somethingdoug.com>", | ||
@@ -6,0 +6,0 @@ "license": "MIT", |
136
Readme.md
@@ -53,26 +53,46 @@ # depd | ||
## Examples | ||
If the message is omitted, a message is generated for you based on the site | ||
of the `deprecate()` call and will display the name of the function called, | ||
similar to the name displayed in a stack trace. | ||
This will display a deprecated message about "oldfunction" being deprecated | ||
from "my-module" on STDERR. | ||
### deprecate.function(fn, message) | ||
```js | ||
var deprecate = require('depd')('my-cool-module') | ||
Call this function to wrap a given function in a deprecation message on any | ||
call to the function. An optional message can be supplied to provide a custom | ||
message. | ||
exports.oldfunction = function () { | ||
// all calls to function are deprecated | ||
deprecate('oldfunction') | ||
} | ||
### process.on('deprecation', fn) | ||
exports.weirdfunction = function () { | ||
if (arguments.length < 2) { | ||
// calls with 0 or 1 args are deprectaed | ||
deprecate('weirdfunction args < 2') | ||
} | ||
} | ||
This module will allow easy capturing of deprecation errors by emitting the | ||
errors as the type "deprecation" on the global `process`. If there are no | ||
listeners for this type, the errors are written to STDERR as normal, but if | ||
there are any listeners, nothing will be written to STDERR and instead only | ||
emitted. From there, you can write the errors in a different format or to a | ||
logging source. | ||
The error represents the deprecation and is emitted only once with the same | ||
rules as writing to STDERR. The error has the following properties: | ||
- `message` - This is the message given by the library | ||
- `name` - This is always `'DeprecationError'` | ||
- `namespace` - This is the namespace the deprecation came from | ||
- `stack` - This is the stack of the call to the deprecated thing | ||
Example `error.stack` output: | ||
``` | ||
DeprecationError: my-cool-module deprecated oldfunction | ||
at Object.<anonymous> ([eval]-wrapper:6:22) | ||
at Module._compile (module.js:456:26) | ||
at evalScript (node.js:532:25) | ||
at startup (node.js:80:7) | ||
at node.js:902:3 | ||
``` | ||
Then a user calls `mymodule.oldfunction()` and sees (in the given colors, | ||
similar colors and layout to the `debug` module): | ||
## Display | ||
When a user calls a function in your library that you mark deprecated, they | ||
will see the following written to STDERR (in the given colors, similar colors | ||
and layout to the `debug` module): | ||
``` | ||
@@ -103,2 +123,84 @@ bright cyan bright yellow | ||
## Examples | ||
### Deprecating all calls to a function | ||
This will display a deprecated message about "oldfunction" being deprecated | ||
from "my-module" on STDERR. | ||
```js | ||
var deprecate = require('depd')('my-cool-module') | ||
// message automatically derived from function name | ||
// Object.oldfunction | ||
exports.oldfunction = deprecate.function(function oldfunction() { | ||
// all calls to function are deprecated | ||
}) | ||
// specific message | ||
exports.oldfunction = deprecate.function(function () { | ||
// all calls to function are deprecated | ||
}, 'oldfunction') | ||
``` | ||
### Conditionally deprecating a function call | ||
This will display a deprecated message about "weirdfunction" being deprecated | ||
from "my-module" on STDERR when called with less than 2 arguments. | ||
```js | ||
var deprecate = require('depd')('my-cool-module') | ||
exports.weirdfunction = function () { | ||
if (arguments.length < 2) { | ||
// calls with 0 or 1 args are deprecated | ||
deprecate('weirdfunction args < 2') | ||
} | ||
} | ||
``` | ||
When calling `deprecate` as a function, the warning is counted per call site | ||
within your own module, so you can display different deprecations depending | ||
on different situations and the users will still get all the warnings: | ||
```js | ||
var deprecate = require('depd')('my-cool-module') | ||
exports.weirdfunction = function () { | ||
if (arguments.length < 2) { | ||
// calls with 0 or 1 args are deprecated | ||
deprecate('weirdfunction args < 2') | ||
} else if (typeof arguments[0] !== 'string') { | ||
// calls with non-string first argument are deprecated | ||
deprecate('weirdfunction non-string first arg') | ||
} | ||
} | ||
``` | ||
### Deprecating property access | ||
This will display a deprecated message about "oldprop" being deprecated | ||
from "my-module" on STDERR when accessed. A deprecation will be displayed | ||
when setting the value and when getting the value. | ||
```js | ||
var deprecate = require('depd')('my-cool-module') | ||
;(function () { | ||
var value = 'something' | ||
Object.defineProperty(exports, 'oldprop', { | ||
configurable: true, | ||
enumerable: true, | ||
get: function () { | ||
deprecate('get oldprop') | ||
return value | ||
}, | ||
set: function (val) { | ||
deprecate('set oldprop') | ||
return value = val | ||
} | ||
}) | ||
}()) | ||
``` | ||
## License | ||
@@ -105,0 +207,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
16708
264
227
1