Comparing version 3.2.3 to 3.3.0
@@ -96,21 +96,9 @@ /** | ||
} | ||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||
// TODO: add support for flaverr/bluebird/lodash-style dictionary negotiation rules | ||
// and then get rid of this message. | ||
// ``` | ||
else if (_.isArray(negotiationRule)) { | ||
// you can bind multiple LCs at the same time | ||
// (array rules are automatically split into sub-rules) | ||
} | ||
else if (_.isObject(negotiationRule) && !_.isArray(negotiationRule) && !_.isFunction(negotiationRule)) { | ||
throw flaverr({ | ||
name: | ||
'UsageError', | ||
message: | ||
'Bluebird-style (`{}`) error negotiation is not yet supported for `.'+lcType+'()`, '+ | ||
'so please stick to specifying a string that matches the Error\'s `.code` property '+ | ||
'for now. In the mean time, if you need to use more involved Error negotiation while '+ | ||
'intercepting or tolerating an error you can still accomplish this by refactoring your '+ | ||
'code.\n'+ | ||
' [?] For advice or assistance, come visit https://sailsjs.com/support' | ||
}); | ||
// flaverr/bluebird/lodash-style dictionary negotiation rules are now supported. | ||
} | ||
// ``` | ||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||
else { | ||
@@ -122,3 +110,3 @@ throw flaverr({ | ||
'Invalid usage of `.'+lcType+'()`. Invalid error negotiation rule: `'+util.inspect(negotiationRule,{depth:null})+'`.\n'+ | ||
' [?] See https://sailsjs.com/support for help.' | ||
' [?] For advice or assistance, come visit https://sailsjs.com/support' | ||
}, deferred._omen); | ||
@@ -140,7 +128,18 @@ } | ||
deferred._userlandAfterExecLCs.push({ | ||
type: lcType, | ||
rule: negotiationRule, | ||
handler: handler | ||
}); | ||
if (_.isArray(negotiationRule)) { | ||
for (var i=0; i<negotiationRule.length; i++) { | ||
deferred._userlandAfterExecLCs.push({ | ||
type: lcType, | ||
rule: negotiationRule[i], | ||
handler: handler | ||
}); | ||
}//∞ | ||
} | ||
else { | ||
deferred._userlandAfterExecLCs.push({ | ||
type: lcType, | ||
rule: negotiationRule, | ||
handler: handler | ||
}); | ||
} | ||
@@ -147,0 +146,0 @@ return deferred; |
@@ -5,3 +5,2 @@ /** | ||
// var assert = require('assert'); | ||
var util = require('util'); | ||
@@ -227,9 +226,5 @@ var _ = require('@sailshq/lodash'); | ||
break; | ||
} else if (_.isString(lcDef.rule) && arguments[0].code === lcDef.rule) { | ||
} else if (flaverr.taste(lcDef.rule, arguments[0])) { | ||
matchingUserlandLC = lcDef; | ||
break; | ||
} else { | ||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||
// TODO: add support for bluebird style dictionary rules | ||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||
} | ||
@@ -288,11 +283,36 @@ }//∞ | ||
} catch (err) { | ||
throw flaverr({ | ||
name: | ||
'UsageError', | ||
message: | ||
'Encountered unexpected error in `.'+matchingUserlandLC.type+'()` handler. '+ | ||
err.message, | ||
raw: | ||
err | ||
}); | ||
// If this is an .intercept() handler, then it's possible the handler threw on purpose, | ||
// perhaps because it was attempting to send a special signal to its caller (e.g. the | ||
// implementation of an action/helper/etc) where it presumably has a special meaning. | ||
// So in this case, we customize the error message to reflect that possibility and to | ||
// suggest an appropriate resolution. | ||
if (matchingUserlandLC.type === 'intercept') { | ||
throw flaverr({ | ||
name: | ||
'UsageError', | ||
message: | ||
'Caught unexpected error in `.intercept()` handler, which should not throw:\n'+ | ||
flaverr.parseOrBuildError(err).message+'\n'+ | ||
'If this was intentional, i.e. to communicate a signal to the caller, then\n'+ | ||
'please just return the new or modified error you would like to use instead.\n'+ | ||
'The value returned to `.intercept()` will be used as the new Error.\n'+ | ||
' [?] See https://sailsjs.com/support for help.', | ||
raw: | ||
err | ||
}, self._omen); | ||
} | ||
else { | ||
// Otherwise, we'll just consider this a standard unexpected error: | ||
throw flaverr({ | ||
name: | ||
'UsageError', | ||
message: | ||
'Encountered unexpected error in `.'+matchingUserlandLC.type+'()` handler. '+ | ||
flaverr.parseOrBuildError(err).message+'\n'+ | ||
' [?] See https://sailsjs.com/support for help.', | ||
raw: | ||
err | ||
}, self._omen); | ||
} | ||
} | ||
@@ -316,15 +336,45 @@ | ||
else if (matchingUserlandLC.type === 'intercept') { | ||
if (!_.isError(resultFromHandler)) { | ||
throw flaverr({ | ||
name: 'UsageError', | ||
message: | ||
'Unexpected value returned from .intercept() handler. '+ | ||
'Expected an Error instance but instead, got: '+resultFromHandler | ||
}, self._omen); | ||
} | ||
else { | ||
arguments[0] = resultFromHandler; | ||
} | ||
}//fi | ||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||
// Normally, these errors must ALWAYS be Error instances already. | ||
// But for this special case, where the original Error value | ||
// is being overridden through the use of `.intercept()`, we'd | ||
// LIKE to make a special exception to the rule (no pun intended.) | ||
// | ||
// There's only one problem: Because of bluebird's "maybeWrapAsError" | ||
// implementation, we can't send certain non-Errors through to it | ||
// (specifically primitives) because they get autowrapped. | ||
// | ||
// > Here's the relevant bit of code: | ||
// > https://github.com/petkaantonov/bluebird/blob/e8d8525a0517280d11d6c77ae6b61df86419232b/src/promisify.js#L182-L184 | ||
// | ||
// Again, most of the time, this would be fine. But while bluebird's | ||
// looking out for us here is admirable, there are some situations. | ||
// where this is not welcome -- such as when trying to throw a string. | ||
// | ||
// > Why throw a string? | ||
// > This is useful for throwing special signals-- e.g. from the inside | ||
// > of an actions2 action or a helper in Sails, a machine's fn in a | ||
// > machinepack, or from a commandline script. | ||
// | ||
// So anyway, to work around this, we have to come up with a consistent | ||
// way of wrapping up non-Errors to look like Errors. That's what we | ||
// do next. | ||
// | ||
// ** Note that we also do this in a couple of other places in parley. ** | ||
// ** (look for `flaverr.parseOrBuildError()` calls) ** | ||
// | ||
// > (If ever we find ourselves wanting to revert this approach, the old | ||
// > code that used to check for non-Errors was removed in parley@376208fd1c0ab70e7a6b9c4ecfa563ec0d77a3a8. | ||
// > But... as mentioned above-- there are some good reasons to keep things | ||
// > the new way that they are now.) | ||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||
var interceptError = flaverr.parseOrBuildError(resultFromHandler, self._omen); | ||
// Stuff the Error in our arguments. | ||
arguments[0] = interceptError; | ||
}//fi </ if this is an .intercept() > | ||
}//fi </ if there is a matching userland LC > | ||
@@ -429,8 +479,6 @@ }//fi </ if we got an error AND any userland LCs were provided > | ||
} catch (unexpectedErrorFromCallback) { | ||
throw flaverr({ | ||
name: 'Envelope', | ||
throw flaverr.wrap({ | ||
code: 'E_ESCAPE_HATCH', | ||
traceRef: self, | ||
raw: unexpectedErrorFromCallback | ||
}); | ||
traceRef: self | ||
}, unexpectedErrorFromCallback, self._omen); | ||
} | ||
@@ -541,3 +589,4 @@ }//• | ||
'finish). Otherwise, you can set the timeout to 0 to disable it.\n'+ | ||
' [?] See https://sailsjs.com/support for help.' | ||
' [?] See https://sailsjs.com/support for help.', | ||
traceRef: self | ||
}, self._omen); | ||
@@ -597,18 +646,6 @@ return cb(err); | ||
// Ensure we're dealing w/ an Error instance. | ||
// > Note that async+await/bluebird/Node 8 errors are not necessarily "true" Error instances, | ||
// > as per _.isError() anyway (see https://github.com/node-machine/machine/commits/6b9d9590794e33307df1f7ba91e328dd236446a9). | ||
// > So if we want to keep a reasonable stack trace, we have to be a bit more relaxed here and | ||
// > tolerate these sorts of "errors" directly as well (by tweezing out the `cause`, which is | ||
// > where the original Error lives.) | ||
if (_.isError(err)) { /* ok */ } | ||
else if (_.isObject(err) && err.cause && _.isError(err.cause)) { err = err.cause; } | ||
else if (_.isString(err)) { err = flaverr({ message: err, raw: err }, self._omen); } | ||
else { err = flaverr({ message: util.inspect(err, {depth: 5}), raw: err }, self._omen); } | ||
err = flaverr.parseOrBuildError(err, self._omen); | ||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||
// ^ FUTURE: Better error message for this fourth case? | ||
// (see the `exits.error` impl in the machine runner for comparison, | ||
// and be sure to try any changes out by hand to experience the message | ||
// before deciding. It's definitely not cut and dry whether there should | ||
// even be a custom message in this case, or if just displaying the output | ||
// as the `message` -- like we currently do -- is more appropriate) | ||
// ^ FUTURE: Better error message for non-Errors? | ||
// (See impl of parseOrBuildError() in flaverr for more context.) | ||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||
@@ -706,14 +743,7 @@ | ||
var err; | ||
if (_.isError(e)) { err = e; } | ||
else if (_.isObject(e) && e.cause && _.isError(e.cause)) { err = e.cause; } //<< see above for more info | ||
else if (_.isString(e)) { err = flaverr({ message: e, raw: e }, self._omen); } | ||
else { err = flaverr({ message: util.inspect(e, {depth: 5}), raw: e }, self._omen); } | ||
// Ensure we end up with an Error instance. | ||
var err = flaverr.parseOrBuildError(e, self._omen); | ||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||
// ^ FUTURE: Better error message for this fourth case? | ||
// (see the `exits.error` impl in the machine runner for comparison, | ||
// and be sure to try any changes out by hand to experience the message | ||
// before deciding. It's definitely not cut and dry whether there should | ||
// even be a custom message in this case, or if just displaying the output | ||
// as the `message` -- like we currently do -- is more appropriate) | ||
// ^ FUTURE: Better error message for non-Errors? | ||
// (See impl of parseOrBuildError() in flaverr for more context.) | ||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||
@@ -725,4 +755,4 @@ | ||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||
// FUTURE: Consider using the more detailed explanation for ALL 4 (!!) of the above cases | ||
// (and use omens for them too -- even the Error instances!) | ||
// FUTURE: Consider using the more detailed explanation for ALL (!!) of the above cases | ||
// handled by `.parseOrBuildError()` -- and use omens for them too...even the Error instances! | ||
// > see other "FUTURE" block above to read about the other stuff we'd want to do first-- | ||
@@ -888,5 +918,5 @@ // > and also note that we'd almost certainly want to leave out the bit about "available | ||
var getPromise = bluebird.promisify(this.exec, { context: this }); | ||
// ^^This is equivalent to `bluebird.promisify(this.exec).bind(this)` | ||
// > The reason we have to use `.bind()` here is so that `.exec()` gets | ||
// > called w/ the appropriate context. (If we were using closures instead | ||
// ^^The `{context: this}` thing is equivalent to `bluebird.promisify(this.exec).bind(this)`, | ||
// > more or less. The reason we have to use `.bind()` here is so that `.exec()` | ||
// > gets called w/ the appropriate context. (If we were using closures instead | ||
// > of a prototypal thing, we wouldn't have to do this.) | ||
@@ -1006,3 +1036,3 @@ | ||
console.log(); | ||
console.log(util.inspect(result, {depth:null})); | ||
console.log(util.inspect(result, {depth: null})); | ||
console.log('- - - - - - - - - - - - - - - - - - - - - - - -'); | ||
@@ -1009,0 +1039,0 @@ } |
{ | ||
"name": "parley", | ||
"version": "3.2.3", | ||
"version": "3.3.0", | ||
"description": "Practical, lightweight flow control for Node.js. Supports `await`, callbacks and promises.", | ||
@@ -30,3 +30,3 @@ "main": "lib/parley.js", | ||
"bluebird": "3.2.1", | ||
"flaverr": "^1.2.1" | ||
"flaverr": "^1.5.1" | ||
}, | ||
@@ -33,0 +33,0 @@ "devDependencies": { |
@@ -257,3 +257,2 @@ parley | ||
```javascript | ||
@@ -273,2 +272,4 @@ // Recommended approach (available in Node.js >= v7.9) | ||
} | ||
// … | ||
``` | ||
@@ -403,2 +404,37 @@ | ||
#### Tolerating errors | ||
Sometimes, you just don't care. | ||
```javascript | ||
var result = await sails.stdlib('fs').readJson({ source: './package.json' }) | ||
.tolerate('notFound', ()=>{ | ||
return { | ||
name: 'not-a-real-package', | ||
description: 'This is not a real package, and I don\'t care.' | ||
}; | ||
}); | ||
// Now `result` is either the contents of the real package.json file... or our fake stuff. | ||
``` | ||
#### Catching and rethrowing errors | ||
But sometimes, you care a little _too_ much. | ||
```javascript | ||
var result = await sails.stdlib('fs').readJson({ source: './package.json' }) | ||
.intercept('notFound', (err)=>{ | ||
return flaverr({ | ||
message: 'No package.json file could be found in the current working directory. And I care _very_ much.', | ||
code: 'E_WHERE_IS_MY_PACKAGE_JSON' | ||
}, err); | ||
}); | ||
// If the package.json file doesn't exist, we will have now thrown a much more useful error. | ||
``` | ||
### Flow control | ||
@@ -405,0 +441,0 @@ |
@@ -334,2 +334,25 @@ /** | ||
describe('practical benchmark', function(){ | ||
var DOES_CURRENT_NODE_VERSION_SUPPORT_AWAIT = process.version.match(/^v8\./); | ||
if (DOES_CURRENT_NODE_VERSION_SUPPORT_AWAIT) { | ||
it('should be performant enough when calling fake "find" w/ `await` (using bench())', function (done){ | ||
bench('mock "await find()"', [ | ||
async function (next){ | ||
var result; | ||
try { | ||
result = await find({ where: {id:3, x:30} }); | ||
} catch (err) { | ||
return next(err); | ||
} | ||
return next(); | ||
} | ||
], done); | ||
}); | ||
} | ||
it('should be performant enough when calling fake "find" w/ .exec() (using bench())', function (done){ | ||
@@ -336,0 +359,0 @@ bench('mock "find().exec()"', [ |
Sorry, the diff of this file is not supported yet
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
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
208247
3030
925
Updatedflaverr@^1.5.1