浏览代码

Wrap async ops in an async wrapper

d98762625 7 年之前
父节点
当前提交
7557f43f77
共有 2 个文件被更改,包括 70 次插入32 次删除
  1. 60 22
      src/node/api.mjs
  2. 10 10
      test/tests/nodeApi/ops.mjs

+ 60 - 22
src/node/api.mjs

@@ -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);
-
-        // 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
-        });
-    };
+    // Check to see if class's run function is async.
+    const opInstance = new OpClass();
+    const isAsync = opInstance.run.constructor.name === "AsyncFunction";
+
+    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;

+ 10 - 10
test/tests/nodeApi/ops.mjs

@@ -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-----