Goal: Show and Advanced Accessor Binary Write.
- 
This function advancedBinaryKV demonstrates creating, marshalling and unmarshalling binary docs.
 - 
Requires Eventing Storage (or metadata collection) a "source" collection, and a "destination" collection.
 - 
Needs a Binding of type "bucket alias" (as documented in the Scriptlet).
 - 
Will operate on any mutation where the KEY or meta.id starts with "advancedbinarykv".
 - 
The function will create two documents: a binary document and a normal JSON document.
 - 
Each document will be updated via the Advanced Accessor couchbase.upsert() and then will be verified.
 - 
The verification and logging will demonstrate binary marshalling and unmarshalling.
 - 
The return value of couchbase.upsert() on success will indicate either "datatype":"json" or "datatype":"binary"
 
- 
advancedBinaryKV
 - 
Input Data/Mutation
 - 
Output Data/Logged
 
// To run configure the settings for this Function, advancedBinaryKV, as follows:
//
// Version 7.1+
//   "Function Scope"
//     *.* (or try bulk.data if non-privileged)
// Version 7.0+
//   "Listen to Location"
//     bulk.data.source
//   "Eventing Storage"
//     rr100.eventing.metadata
//   Binding(s)
//    1. "binding type", "alias name...", "bucket.scope.collection", "Access"
//       "bucket alias", "dst_col",       "bulk.data.destination",   "read and write"
//
// Version 6.6.2
//   "Source Bucket"
//     source
//   "MetaData Bucket"
//     metadata
//   Binding(s)
//    1. "binding type", "alias name...", "bucket",      "Access"
//       "bucket alias", "dst_col",       "destination", "read and write"
function OnUpdate(doc, meta) {
    if (!meta.id.startsWith("advancedbinarykv")) return;
    var doc_is_binary = true;
    var prefix;
    var wrkdoc;
    var is_bin_ary = [true, false];
    // loop twice first create a binary doc and then create a normal JSON doc
    for (let doc_is_binary of is_bin_ary) {
        if (doc_is_binary) {
            // Note, we could create binary docs via 'cbc'
            //     "cbc create bindoc -V '^LZ' -U couchbase://localhost/source -u Administrator -P password"
            // However it is easier to make a binary document via pure JavaScript code
            prefix = "bindoc";
            var arr = new Uint8Array([1, 0, 2, 3]);
            var bindoc = arr.buffer;
            wrkdoc = bindoc;
        } else {
            // make a normal JSON doc
            prefix = "jsondoc";
            wrkdoc = {
                "jsondoc": 1
            };
        }
        // ========================================================================
        // Test basic Bucket Op, i.e. JavaScript map exposed via a bucket binding
        dst_col[prefix + "_put"] = wrkdoc;
        // ========================================================================
        // Test Advanced Accessors
        // Make a key for Advanced Accessor tests ( note, "datatype" in meta is not needed / ignored )
        var key = prefix + "_upsert";
        var new_meta = { "id": key };
        log("1 RUN couchbase.upsert(dst_col,", new_meta, ",", wrkdoc, ")");
        var result = couchbase.upsert(dst_col, new_meta, wrkdoc);
        if (result.success) {
            log('2 success adv. upsert: result', result);
        } else {
            log('2 failure adv. upsert: id', key, 'result', result);
        }
        var tmp = couchbase.get(dst_col, {  "id": key });
        log('3 couchbase.get(dst_col', {  "id": key }, ') => ', tmp);
        couchbase.upsert(dst_col, { "id": key + "_from_adv_get",  "datatype": "bin" }, tmp.doc);
        var tag;
        var disp;
        if (tmp.meta.datatype && tmp.meta.datatype == "binary") {
            tag = "binary";
            disp = new Uint8Array(tmp.doc);
            log('4 ' + tag + ' equal = ' + buffersEqual(tmp.doc, wrkdoc), '(was binary so unmarshalled)', disp);
        } else {
            tag = "json";
            disp = tmp.doc;
            log('4 ' + tag + ' equal = ' + (JSON.stringify(tmp.doc) === JSON.stringify(wrkdoc)),
                '(was json so just the doc)', disp);
        }
    }
}
function buffersEqual(buf1, buf2) {
    if (buf1.byteLength != buf2.byteLength) return false;
    var dv1 = new Uint8Array(buf1);
    var dv2 = new Uint8Array(buf2);
    for (var i = 0; i != buf1.byteLength; i++) {
        if (dv1[i] != dv2[i]) return false;
    }
    return true;
}
INPUT: KEY advancedbinarykv:1
{
  "id": 1,
  "type": "advancedbinarykv"
}
2021-07-19T11:16:20.566-07:00 [INFO] "1 RUN couchbase.upsert(dst_col," {"id":"bindoc_upsert"} "," {} ")"
2021-07-19T11:16:20.566-07:00 [INFO] "2 success adv. upsert: result" {"meta":{"id":"bindoc_upsert","cas":"1626718580566458368"},"success":true}
2021-07-19T11:16:20.567-07:00 [INFO] "3 couchbase.get(dst_col" {"id":"bindoc_upsert"} ") => " {"doc":{},"meta":{"id":"bindoc_upsert","cas":"1626718580566458368","datatype":"binary"},"success":true}
2021-07-19T11:16:20.567-07:00 [INFO] "4 binary equal = true" "(was binary so unmarshalled)" {"0":1,"1":0,"2":2,"3":3}
2021-07-19T11:16:20.567-07:00 [INFO] "1 RUN couchbase.upsert(dst_col," {"id":"jsondoc_upsert"} "," {"jsondoc":1} ")"
2021-07-19T11:16:20.568-07:00 [INFO] "2 success adv. upsert: result" {"meta":{"id":"jsondoc_upsert","cas":"1626718580568031232"},"success":true}
2021-07-19T11:16:20.568-07:00 [INFO] "3 couchbase.get(dst_col" {"id":"jsondoc_upsert"} ") => " {"doc":{"jsondoc":1},"meta":{"id":"jsondoc_upsert","cas":"1626718580568031232","datatype":"json"},"success":true}
2021-07-19T11:16:20.568-07:00 [INFO] "4 json equal = true" "(was json so just the doc)" {"jsondoc":1}