Forráskód Böngészése

Expose Dish (SyncDish) in API and make it composable.

d98762625 7 éve
szülő
commit
f6c4b5073c

+ 18 - 6
src/core/Dish.mjs

@@ -17,16 +17,27 @@ class Dish {
     /**
      * Dish constructor
      *
-     * @param {Dish} [dish=null] - A dish to clone
+     * @param {Dish || *} [dishOrInput=null] - A dish to clone OR an object
+     * literal to make into a dish
+     * @param {Enum} [type=null] (optional) - A type to accompany object
+     * literal input
      */
-    constructor(dish=null) {
+    constructor(dishOrInput=null, type = null) {
         this.value = [];
         this.type = Dish.BYTE_ARRAY;
 
-        if (dish &&
-            dish.hasOwnProperty("value") &&
-            dish.hasOwnProperty("type")) {
-            this.set(dish.value, dish.type);
+        // Case: dishOrInput is dish object
+        if (dishOrInput &&
+            dishOrInput.hasOwnProperty("value") &&
+            dishOrInput.hasOwnProperty("type")) {
+            this.set(dishOrInput.value, dishOrInput.type);
+        // input and type defined separately
+        } else if (dishOrInput && type) {
+            this.set(dishOrInput, type);
+        // No type declared, so infer it.
+        } else if (dishOrInput) {
+            const inferredType = Dish.typeEnum(dishOrInput.constructor.name);
+            this.set(dishOrInput, inferredType);
         }
     }
 
@@ -56,6 +67,7 @@ class Dish {
             case "big number":
                 return Dish.BIG_NUMBER;
             case "json":
+            case "object": // object constructor name. To allow JSON input in node.
                 return Dish.JSON;
             case "file":
                 return Dish.FILE;

+ 4 - 4
src/node/SyncDish.mjs

@@ -18,13 +18,13 @@ import * as ops from "./index";
 class SyncDish extends Dish {
 
     /** */
-    constructor(dish=null) {
-        super(dish);
-
+    constructor(inputOrDish=null, type=null) {
+        super(inputOrDish);
+        
+        // Add operations to make it composable
         for (const op in ops) {
             this[op] = () => ops[op](this.value);
         }
-
     }
 
     /**

+ 3 - 1
src/node/config/scripts/generateNodeIndex.mjs

@@ -39,6 +39,7 @@ let code = `/**
 
 
 import "babel-polyfill";
+import SyncDish from "./SyncDish";
 import { wrap, help, bake } from "./api";
 import {
 `;
@@ -80,6 +81,7 @@ code += `    };
 
 const chef = generateChef();
 chef.help = help;
+chef.dish = SyncDish;
 `;
 
 includedOperations.forEach((op) => {
@@ -106,7 +108,7 @@ includedOperations.forEach((op) => {
     code += `    ${decapitalise(op)},\n`;
 });
 
-
+code += "    SyncDish as Dish\n";
 code += "};\n";
 
 

+ 3 - 0
src/node/index.mjs

@@ -10,6 +10,7 @@
 
 
 import "babel-polyfill";
+import SyncDish from "./SyncDish";
 import { wrap, help, bake } from "./api";
 import {
     ADD as core_ADD,
@@ -514,6 +515,7 @@ function generateChef() {
 
 const chef = generateChef();
 chef.help = help;
+chef.dish = SyncDish;
 const ADD = chef.ADD;
 const AESDecrypt = chef.AESDecrypt;
 const AESEncrypt = chef.AESEncrypt;
@@ -1237,4 +1239,5 @@ export {
     XPathExpression,
     zlibDeflate,
     zlibInflate,
+    SyncDish as Dish
 };

+ 37 - 1
test/tests/nodeApi/nodeApi.mjs

@@ -16,7 +16,7 @@ import chef from "../../../src/node/index";
 import OperationError from "../../../src/core/errors/OperationError";
 import SyncDish from "../../../src/node/SyncDish";
 
-import { toBase32 } from "../../../src/node/index";
+import { toBase32, Dish } from "../../../src/node/index";
 import TestRegister from "../../TestRegister";
 
 TestRegister.addApiTests([
@@ -282,4 +282,40 @@ TestRegister.addApiTests([
         assert.strictEqual(result.toString(), "begin_something_anananaaaaak_da_aaak_da_aaaaananaaaaaaan_da_aaaaaaanan_da_aaak_end_something");
     }),
 
+    it("Composable Dish: Should have top level Dish object", () => {
+        assert.ok(Dish);
+    }),
+
+    it("Composable Dish: Should construct empty dish object", () => {
+        const dish = new Dish();
+        assert.deepEqual(dish.value, []);
+        assert.strictEqual(dish.type, 0);
+    }),
+
+    it("Composable Dish: constructed dish should have operation prototype functions", () => {
+        const dish = new Dish();
+        assert.ok(dish.translateDateTimeFormat);
+        assert.ok(dish.stripHTTPHeaders);
+        assert.throws(() => dish.someInvalidFunction());
+    }),
+
+    it("Composable Dish: composed function returns another dish", () => {
+        const result = new Dish("some input").toBase32();
+        assert.ok(result instanceof SyncDish);
+    }),
+
+    it("Composable dish: infers type from input if needed", () => {
+        const dish = new Dish("string input");
+        assert.strictEqual(dish.type, 1);
+
+        const numberDish = new Dish(333);
+        assert.strictEqual(numberDish.type, 2);
+
+        const arrayBufferDish = new Dish(Buffer.from("some buffer input").buffer);
+        assert.strictEqual(arrayBufferDish.type, 4);
+
+        const JSONDish = new Dish({key: "value"});
+        assert.strictEqual(JSONDish.type, 6);
+    }),
+
 ]);

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

@@ -791,7 +791,7 @@ jmPGsv1elXxVzqs58UZLD2c3vBhGkU2BV6kRKh+lj/EcVrzsFhGCz/7DKxPoDHLS
 
     it("Scan for embedded files", () => {
         const result = chef.scanForEmbeddedFiles(fs.readFileSync("src/web/static/images/cook_male-32x32.png"));
-        const expected = "Scanning data for \'magic bytes\' which may indicate embedded files.";
+        const expected = "Scanning data for 'magic bytes' which may indicate embedded files.";
         assert.ok(result.toString().indexOf(expected) === 0);
     }),