Wrap async ops in an async wrapper

This commit is contained in:
d98762625 2018-08-16 17:14:28 +01:00
parent a6c0db47ab
commit 7557f43f77
2 changed files with 69 additions and 31 deletions

View File

@ -96,8 +96,28 @@ const ensureIsDish = function ensureIsDish(input) {
return dish;
};
/**
* prepareOp: transform args, make input the right type.
* @param opInstance - instance of the operation
* @param input - operation input
* @param args - operation args
*/
const prepareOp = function prepareOp(opInstance, input, args) {
const dish = ensureIsDish(input);
let transformedArgs;
// Transform object-style args to original args array
if (!Array.isArray(args)) {
transformedArgs = transformArgs(opInstance.args, args);
} else {
transformedArgs = args;
}
const transformedInput = dish.get(opInstance.inputType);
return {transformedInput, transformedArgs};
};
/**
* Wrap an operation to be consumed by node API.
* Checks to see if run function is async or not.
* new Operation().run() becomes operation()
* Perform type conversion on input
* @private
@ -106,29 +126,47 @@ const ensureIsDish = function ensureIsDish(input) {
* some type conversion logic
*/
export function wrap(OpClass) {
/**
* Wrapped operation run function
* @param {*} input
* @param {Object | String[]} args - either in Object or normal args array
* @returns {SyncDish} operation's output, on a Dish.
* @throws {OperationError} if the operation throws one.
*/
const wrapped = (input, args=null) => {
const operation = new OpClass();
const dish = ensureIsDish(input);
// Check to see if class's run function is async.
const opInstance = new OpClass();
const isAsync = opInstance.run.constructor.name === "AsyncFunction";
// Transform object-style args to original args array
if (!Array.isArray(args)) {
args = transformArgs(operation.args, args);
}
const transformedInput = dish.get(operation.inputType);
const result = operation.run(transformedInput, args);
return new SyncDish({
value: result,
type: operation.outputType
});
};
let wrapped;
// If async, wrap must be async.
if (isAsync) {
/**
* Async wrapped operation run function
* @param {*} input
* @param {Object | String[]} args - either in Object or normal args array
* @returns {Promise<SyncDish>} operation's output, on a Dish.
* @throws {OperationError} if the operation throws one.
*/
wrapped = async (input, args=null) => {
const {transformedInput, transformedArgs} = prepareOp(opInstance, input, args);
const result = await opInstance.run(transformedInput, transformedArgs);
return new SyncDish({
value: result,
type: opInstance.outputType
});
};
} else {
/**
* wrapped operation run function
* @param {*} input
* @param {Object | String[]} args - either in Object or normal args array
* @returns {SyncDish} operation's output, on a Dish.
* @throws {OperationError} if the operation throws one.
*/
wrapped = (input, args=null) => {
const {transformedInput, transformedArgs} = prepareOp(opInstance, input, args);
const result = opInstance.run(transformedInput, transformedArgs);
return new SyncDish({
value: result,
type: opInstance.outputType
});
};
}
// used in chef.help
wrapped.opName = OpClass.name;

View File

@ -118,20 +118,20 @@ Tiger-128`;
assert.strictEqual(result.toString(), "Szkkb zh z Xozn");
}),
it("Bcrypt", () => {
const result = chef.bcrypt("Put a Sock In It");
it("Bcrypt", async () => {
const result = await chef.bcrypt("Put a Sock In It");
assert.strictEqual(result.toString(), "$2a$10$ODeP1.6fMsb.ENk2ngPUCO7qTGVPyHA9TqDVcyupyed8FjsiF65L6");
}),
it("bcryptCompare", () => {
const result = chef.bcryptCompare("Put a Sock In It", {
it("bcryptCompare", async() => {
const result = await chef.bcryptCompare("Put a Sock In It", {
hash: "$2a$10$2rT4a3XnIecBsd1H33dMTuyYE1HJ1n9F.V2rjQtAH73rh1qvOf/ae",
});
assert.strictEqual(result.toString(), "Match: Put a Sock In It");
}),
it("Bcrypt Parse", () => {
const result = chef.bcryptParse("$2a$10$ODeP1.6fMsb.ENk2ngPUCO7qTGVPyHA9TqDVcyupyed8FjsiF65L6");
it("Bcrypt Parse", async () => {
const result = await chef.bcryptParse("$2a$10$ODeP1.6fMsb.ENk2ngPUCO7qTGVPyHA9TqDVcyupyed8FjsiF65L6");
const expected = `Rounds: 10
Salt: $2a$10$ODeP1.6fMsb.ENk2ngPUCO
Password hash: 7qTGVPyHA9TqDVcyupyed8FjsiF65L6
@ -567,8 +567,8 @@ Password: 034148`;
assert.strictEqual(result.toString(), expected);
}),
it("Generate PGP Key Pair", () => {
const result = chef.generatePGPKeyPair("Back To the Drawing Board", {
it("Generate PGP Key Pair", async () => {
const result = await chef.generatePGPKeyPair("Back To the Drawing Board", {
keyType: "ECC-256",
});
const expected = `-----BEGIN PGP PRIVATE KEY BLOCK-----
@ -772,7 +772,7 @@ CPU
assert.strictEqual(result.toString(), expected);
}),
it("PGP Encrypt", () => {
it("PGP Encrypt", async () => {
const pbkey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1
@ -793,7 +793,7 @@ jKHiPvjXhSfP3lmrQ7brja9LgSzkiBqQzvPW55G67nGQdUC+mqZNJNlRh+8atf9I
=xw3e
-----END PGP PUBLIC KEY BLOCK-----`;
const result = chef.PGPEncrypt("A Fool and His Money are Soon Parted", {
const result = await chef.PGPEncrypt("A Fool and His Money are Soon Parted", {
publicKeyOfRecipient: pbkey,
});
const expected = `-----BEGIN PGP MESSAGE-----