<commit_before>"use strict";

var testHelper = require("../test-helper");
var captureArgs = require("../test-helper/capture-args");

testHelper.assertionTests("assert", "isUint16Array", function(
    pass,
    fail,
    msg,
    error
) {
    pass("for Uint16Array", new Uint16Array());
    fail("for Uint32Array", new Uint32Array());
    fail("for Uint8Array", new Uint8Array());
    fail("for array", []);
    fail("for object", {});
    fail("for arguments", captureArgs());
    msg(
        "fail with descriptive message",
        "[assert.isUint16Array] Expected {  } to be a Uint16Array",
        {}
    );
    msg(
        "fail with custom message",
        "[assert.isUint16Array] Nope: Expected {  } to be a Uint16Array",
        {},
        "Nope"
    );
    error(
        "for object",
        {
            code: "ERR_ASSERTION",
            operator: "assert.isUint16Array"
        },
        {}
    );
});
<commit_msg>Rewrite tests for isUint16Array<commit_after>"use strict";

var assert = require("assert");
var captureArgs = require("../test-helper/capture-args");
var referee = require("../referee");

describe("assert.isUint16Array", function() {
    it("should pass for isUint16Array", function() {
        referee.assert.isUint16Array(new Uint16Array());
    });

    it("should fail for Uint32Array", function() {
        assert.throws(
            function() {
                referee.assert.isUint16Array(new Uint32Array());
            },
            function(error) {
                assert.equal(error.code, "ERR_ASSERTION");
                assert.equal(
                    error.message,
                    "[assert.isUint16Array] Expected  to be a Uint16Array"
                );
                assert.equal(error.name, "AssertionError");
                assert.equal(error.operator, "assert.isUint16Array");
                return true;
            }
        );
    });

    it("should fail for Uint8Array", function() {
        assert.throws(
            function() {
                referee.assert.isUint16Array(new Uint8Array());
            },
            function(error) {
                assert.equal(error.code, "ERR_ASSERTION");
                assert.equal(
                    error.message,
                    "[assert.isUint16Array] Expected  to be a Uint16Array"
                );
                assert.equal(error.name, "AssertionError");
                assert.equal(error.operator, "assert.isUint16Array");
                return true;
            }
        );
    });

    it("should fail for Array", function() {
        assert.throws(
            function() {
                referee.assert.isUint16Array([]);
            },
            function(error) {
                assert.equal(error.code, "ERR_ASSERTION");
                assert.equal(
                    error.message,
                    "[assert.isUint16Array] Expected [] to be a Uint16Array"
                );
                assert.equal(error.name, "AssertionError");
                assert.equal(error.operator, "assert.isUint16Array");
                return true;
            }
        );
    });

    it("should fail for Object", function() {
        assert.throws(
            function() {
                referee.assert.isUint16Array({});
            },
            function(error) {
                assert.equal(error.code, "ERR_ASSERTION");
                assert.equal(
                    error.message,
                    "[assert.isUint16Array] Expected {  } to be a Uint16Array"
                );
                assert.equal(error.name, "AssertionError");
                assert.equal(error.operator, "assert.isUint16Array");
                return true;
            }
        );
    });

    it("should fail for arguments", function() {
        assert.throws(
            function() {
                referee.assert.isUint16Array(captureArgs());
            },
            function(error) {
                assert.equal(error.code, "ERR_ASSERTION");
                assert.equal(
                    error.message,
                    "[assert.isUint16Array] Expected {  } to be a Uint16Array"
                );
                assert.equal(error.name, "AssertionError");
                assert.equal(error.operator, "assert.isUint16Array");
                return true;
            }
        );
    });

    it("should fail with custom message", function() {
        var message = "b8895750-3ba7-40f6-bda5-5e769d6c0b62";
        assert.throws(
            function() {
                referee.assert.isUint16Array([], message);
            },
            function(error) {
                assert.equal(error.code, "ERR_ASSERTION");
                assert.equal(
                    error.message,
                    "[assert.isUint16Array] " +
                        message +
                        ": Expected [] to be a Uint16Array"
                );
                assert.equal(error.name, "AssertionError");
                assert.equal(error.operator, "assert.isUint16Array");
                return true;
            }
        );
    });
});

describe("refute.isUint16Array", function() {
    it("should fail for isUint16Array", function() {
        assert.throws(
            function() {
                referee.refute.isUint16Array(new Uint16Array());
            },
            function(error) {
                assert.equal(error.code, "ERR_ASSERTION");
                assert.equal(
                    error.message,
                    "[refute.isUint16Array] Expected  not to be a Uint16Array"
                );
                assert.equal(error.name, "AssertionError");
                assert.equal(error.operator, "refute.isUint16Array");
                return true;
            }
        );
    });

    it("should fail with custom message", function() {
        var message = "7a548ba3-6efc-4300-8af5-7ff42eb9c064";
        assert.throws(
            function() {
                referee.refute.isUint16Array(new Uint16Array(), message);
            },
            function(error) {
                assert.equal(error.code, "ERR_ASSERTION");
                assert.equal(
                    error.message,
                    "[refute.isUint16Array] " +
                        message +
                        ": Expected  not to be a Uint16Array"
                );
                assert.equal(error.name, "AssertionError");
                assert.equal(error.operator, "refute.isUint16Array");
                return true;
            }
        );
    });

    it("should pass for Uint32Array", function() {
        referee.refute.isUint16Array(new Uint32Array());
    });

    it("should pass for Uint8Array", function() {
        referee.refute.isUint16Array(new Uint8Array());
    });

    it("should pass for Array", function() {
        referee.refute.isUint16Array([]);
    });

    it("should pass for Object", function() {
        referee.refute.isUint16Array({});
    });

    it("should pass for arguments", function() {
        referee.refute.isUint16Array(captureArgs());
    });
});
<|endoftext|>


<commit_before>'use strict';

import {ElementRef} from 'angular2/core';

import {RedocComponent, BaseComponent, SchemaManager} from '../base';
import {Tabs, Tab} from '../../common/components/Tabs/tabs';
import JsonPointer from '../../utils/JsonPointer';

@RedocComponent({
  selector: 'json-schema',
  templateUrl: './lib/components/JsonSchema/json-schema.html',
  styleUrls: ['./lib/components/JsonSchema/json-schema.css'],
  directives: [JsonSchema, Tabs, Tab],
  inputs: ['isArray', 'final']
})
@Reflect.metadata('parameters', [[SchemaManager], [ElementRef]])
export default class JsonSchema extends BaseComponent {
  constructor(schemaMgr, elementRef) {
    super(schemaMgr);
    this.$element = elementRef.nativeElement;
    this.final = false;
  }

  prepareModel() {
    this.data = {};
    this.data.properties = [];
    this.data.derived = [];

    if (!this.componentSchema) {
      throw new Error(`Can't load component schema at ${this.pointer}`);
    }

    this.dereference();
    let schema = this.componentSchema;

    if (schema.type === 'array') {
      this.isArray = true;
      if (schema._pointer) {
        this.pointer = JsonPointer.join(schema._pointer, 'items');
      }
      schema = schema.items;
    }
    let normPtr = schema._pointer || this.pointer;
    let derived = this.schemaMgr.findDerivedDefinitions( normPtr );
    if (!this.final && derived.length) {
      this.data.derived = derived;
      this.data.discriminator = schema.discriminator;
    }

    this.joinAllOf(schema, {omitParent: true});

    if (schema.type !== 'object') {
      this.isTrivial = true;
      this._displayType = schema.type;
      if (schema.format) this._displayType = `${this.displayType} <${schema.format}>`;
      return;
    }

    this.pointer = schema._pointer || this.pointer;

    this.requiredMap = {};
    if (this.componentSchema.required) {
      this.componentSchema.required.forEach(prop => this.requiredMap[prop] = true);
    }

    if (!schema.properties) {
      this.isTrivial = true;
      this._displayType = schema.type;
      this._displayTypeHint = 'This field may contain data of any type';
      return;
    }

    let discriminatorFieldIdx = -1;
    let props = Object.keys(schema.properties).map((prop, idx) => {
      let propData = schema.properties[prop];
      let propPointer = JsonPointer.join(this.pointer, ['properties', prop]);
      propData = JsonSchema.injectPropData(propData, prop, propPointer, this.requiredMap, schema);
      if (propData.isDiscriminator) discriminatorFieldIdx = idx;
      return propData;
    });
    // Move discriminator field to the end of properties list
    if (discriminatorFieldIdx > -1) {
      let discrProp = props.splice(discriminatorFieldIdx, 1);
      props.push(discrProp[0]);
    }
    this.data.properties = props;
  }

  static injectPropData(propData, propName, propPointer, requiredMap, schema) {
    let propEnum;

    propData = Object.assign({}, propData);
    propData._name = propName;
    propData.required = propData.required || (requiredMap && requiredMap[propName]);
    propData._displayType = propData.type;
    propData.isDiscriminator = (schema && schema.discriminator === propName);
    propEnum = propData.enum;
    if (propData.type === 'array') {
      let itemType = propData.items.type;
      let itemFormat = propData.items.format;
      propEnum = propData.items.enum;
      if (itemType === 'object' || !itemType) {
        itemType = propData.items.title || 'object';
        propData._pointer = propData.items._pointer
          || JsonPointer.join(propPointer, ['items']);
      }
      propData._displayType = `${itemType}`;
      propData.format = itemFormat;
      propData._isArray = true;
      propData.type = 'array ' + propData.items.type;
    } else if (propData.type === 'object') {
      propData._displayType = propData.title || 'object';
    } else if (!propData.type) {
      propData._displayType = '< * >';
      propData._displayTypeHint = 'This field may contain data of any type';
    } else {
      // here we are sure that property has simple type
      // delete pointer for simple types to not show it as subschema
      if (propData._pointer) {
        propData._pointer = undefined;
        propData._displayType = propData.title ? `${propData.title} (${propData.type})` : propData.type;
      }
    }

    if (propData.format) propData._displayFormat = `<${propData.format}>`;
    if (propEnum) {
      propData.enum = propEnum.map((value) => {
        return {val: value, type: typeof value};
      });
    }

    return propData;
  }

  ngAfterViewInit() {
    // adjust widht only on parent level
    let $el = this.$element.parentElement;
    while($el && $el.tagName !== 'JSON-SCHEMA' && $el.tagName !== 'REDOC') {
      $el = $el.parentElement;
    }
    if ($el && $el.tagName === 'REDOC' ) {
      this.adjustNameColumnWidth();
    }
  }

  adjustNameColumnWidth() {
    // TODO handle internal schemes differently

    let names = [].slice.call(this.$element.querySelectorAll('.param-name-content'));
    let widths = names.map(el => el.offsetWidth);
    let maxWidth = Math.max(...widths);
    if (!maxWidth) return;
    names.forEach(el => {
      el.parentNode.style.minWidth = maxWidth + 'px';
    });

    let discrValues = this.$element.querySelector('tabs ul');
    if (discrValues) discrValues.style.paddingLeft = maxWidth + 'px';
  }
}
<commit_msg>JsonSchema: display object without properties as a simple type<commit_after>'use strict';

import {ElementRef} from 'angular2/core';

import {RedocComponent, BaseComponent, SchemaManager} from '../base';
import {Tabs, Tab} from '../../common/components/Tabs/tabs';
import JsonPointer from '../../utils/JsonPointer';

@RedocComponent({
  selector: 'json-schema',
  templateUrl: './lib/components/JsonSchema/json-schema.html',
  styleUrls: ['./lib/components/JsonSchema/json-schema.css'],
  directives: [JsonSchema, Tabs, Tab],
  inputs: ['isArray', 'final']
})
@Reflect.metadata('parameters', [[SchemaManager], [ElementRef]])
export default class JsonSchema extends BaseComponent {
  constructor(schemaMgr, elementRef) {
    super(schemaMgr);
    this.$element = elementRef.nativeElement;
    this.final = false;
  }

  prepareModel() {
    this.data = {};
    this.data.properties = [];
    this.data.derived = [];

    if (!this.componentSchema) {
      throw new Error(`Can't load component schema at ${this.pointer}`);
    }

    this.dereference();
    let schema = this.componentSchema;

    if (schema.type === 'array') {
      this.isArray = true;
      if (schema._pointer) {
        this.pointer = JsonPointer.join(schema._pointer, 'items');
      }
      schema = schema.items;
    }
    let normPtr = schema._pointer || this.pointer;
    let derived = this.schemaMgr.findDerivedDefinitions( normPtr );
    if (!this.final && derived.length) {
      this.data.derived = derived;
      this.data.discriminator = schema.discriminator;
    }

    this.joinAllOf(schema, {omitParent: true});

    if (schema.type !== 'object') {
      this.isTrivial = true;
      this._displayType = schema.type;
      if (schema.format) this._displayType = `${this.displayType} <${schema.format}>`;
      return;
    }

    this.pointer = schema._pointer || this.pointer;

    this.requiredMap = {};
    if (this.componentSchema.required) {
      this.componentSchema.required.forEach(prop => this.requiredMap[prop] = true);
    }

    let discriminatorFieldIdx = -1;
    let props = Object.keys(schema.properties).map((prop, idx) => {
      let propData = schema.properties[prop];
      let propPointer = JsonPointer.join(this.pointer, ['properties', prop]);
      propData = JsonSchema.injectPropData(propData, prop, propPointer, this.requiredMap, schema);
      if (propData.isDiscriminator) discriminatorFieldIdx = idx;
      return propData;
    });
    // Move discriminator field to the end of properties list
    if (discriminatorFieldIdx > -1) {
      let discrProp = props.splice(discriminatorFieldIdx, 1);
      props.push(discrProp[0]);
    }
    this.data.properties = props;
  }

  static injectPropData(propData, propName, propPointer, requiredMap, schema) {
    let propEnum;

    propData = Object.assign({}, propData);
    propData._name = propName;
    propData.required = propData.required || (requiredMap && requiredMap[propName]);
    propData._displayType = propData.type;
    propData.isDiscriminator = (schema && schema.discriminator === propName);
    propEnum = propData.enum;
    if (propData.type === 'array') {
      let itemType = propData.items.type;
      let itemFormat = propData.items.format;
      propEnum = propData.items.enum;
      if (itemType === 'object' || !itemType) {
        itemType = propData.items.title || 'object';
        propData._pointer = propData.items._pointer
          || JsonPointer.join(propPointer, ['items']);
      }
      propData._displayType = `${itemType}`;
      propData.format = itemFormat;
      propData._isArray = true;
      propData.type = 'array ' + propData.items.type;
    } else if (propData.type === 'object' && propData.properties) {
      propData._displayType = propData.title || 'object';
    } else if (!propData.type) {
      propData._displayType = '< * >';
      propData._displayTypeHint = 'This field may contain data of any type';
    } else {
      // here we are sure that property has simple type (integer, string, object withou properties)
      // delete pointer for simple types to not show it as subschema
      if (propData._pointer) {
        propData._pointer = undefined;
        propData._displayType = propData.title ? `${propData.title} (${propData.type})` : propData.type;
      }
    }

    if (propData.format) propData._displayFormat = `<${propData.format}>`;
    if (propEnum) {
      propData.enum = propEnum.map((value) => {
        return {val: value, type: typeof value};
      });
    }

    return propData;
  }

  ngAfterViewInit() {
    // adjust widht only on parent level
    let $el = this.$element.parentElement;
    while($el && $el.tagName !== 'JSON-SCHEMA' && $el.tagName !== 'REDOC') {
      $el = $el.parentElement;
    }
    if ($el && $el.tagName === 'REDOC' ) {
      this.adjustNameColumnWidth();
    }
  }

  adjustNameColumnWidth() {
    // TODO handle internal schemes differently

    let names = [].slice.call(this.$element.querySelectorAll('.param-name-content'));
    let widths = names.map(el => el.offsetWidth);
    let maxWidth = Math.max(...widths);
    if (!maxWidth) return;
    names.forEach(el => {
      el.parentNode.style.minWidth = maxWidth + 'px';
    });

    let discrValues = this.$element.querySelector('tabs ul');
    if (discrValues) discrValues.style.paddingLeft = maxWidth + 'px';
  }
}
<|endoftext|>


<commit_before>// Generated by CoffeeScript 1.3.3
(function() {
  var op;

  op = require('../../../tasks/package/operators');

  module.exports = function(config) {
    return config.tasks["package"].merge({
      operatorsMap: {
        'annotate:class': op.annotateClass,
        'annotate:file': op.annotateFile,
        'join': op.join,
        'compile': op.compile,
        'uglify': op.uglify,
        'create:directory': op.createDirectory,
        'strip:requires': op.stripRequires,
        'exports:package': op.exportsToPackage,
        'saveToFile': op.saveToFile
      }
    });
  };

}).call(this);
<commit_msg>Add missing updated js.<commit_after>// Generated by CoffeeScript 1.3.3
(function() {
  var op;

  op = require('../../../tasks/package/operators');

  module.exports = function(config) {
    return config.tasks["package"].merge({
      operatorsMap: {
        'annotate:class': op.annotateClass,
        'annotate:file': op.annotateFile,
        'compile': op.compile,
        'create:directory': op.createDirectory,
        'create:file': op.saveToFile,
        'exports:package': op.exportsToPackage,
        'join': op.join,
        'strip:requires': op.stripRequires,
        'uglify': op.uglify
      }
    });
  };

}).call(this);
<|endoftext|>


<commit_before>/**
 * This file contains the private methods for the GCP service to form/sign
 * Google Cloud Storage requests.
 *
 * It uses a modified version of the S3 service private methods to form/sign
 * requests compatible with the Google Cloud Storage XML api.
 */

const AWS = require('aws-sdk');
const GcpSigner = require('./GcpSigner');

module.exports = {
    /**
     * GCP compatible request signer
     * @return {AWS.Signer} AWS Signer
     */
    getSignerClass() {
        return GcpSigner;
    },

    /**
     * set service region
     * @return {undefined}
     */
    validateService() {
        if (!this.config.region) {
            this.config.region = 'us-east-1';
        }
    },

    /**
     * setup listeners for building requests
     * @param {AWS.Request} request - AWS request object
     * @return {undefined}
     */
    setupRequestListeners(request) {
        request.addListener('validate', this.validateBucketEndpoint);
        request.addListener('build', this.addContentType);
        request.addListener('build', this.populateURI);
        request.addListener('build', this.computeContentMd5);
    },

    /**
     * validate that when bucket endpoitn flag is set, root level apis are
     * inaccessible
     * @param {AWS.Request} req - AWS request object
     * @returns {undefined}
     * @api private
     */
    validateBucketEndpoint(req) {
        if (!req.params.Bucket && req.service.config.s3BucketEndpoint) {
            const msg =
                'Cannot send requests to root API with `s3BucketEndpoint` set.';
            throw AWS.util.error(new Error(),
                { code: 'ConfigError', message: msg });
        }
    },

    /**
     * S3 prefers dns-compatible bucket names to be moved from the uri path
     * to the hostname as a sub-domain. This is not possible, even for
     * dns-compat buckets when using SSL and the bucket name contains a dot.
     * The ssl wildcard certificate is only 1-level deep.
     * @param {AWS.Request} req - AWS request object
     * @returns {undefined}
     *
     * @api private
     */
    populateURI(req) {
        const httpRequest = req.httpRequest;
        const b = req.params.Bucket;
        const service = req.service;
        const endpoint = httpRequest.endpoint;

        if (b) {
            if (!service.pathStyleBucketName(b)) {
                if (!service.config.s3BucketEndpoint) {
                    endpoint.hostname = `${b}.${endpoint.hostname}`;
                }
                const port = endpoint.port;
                if (port !== 80 && port !== 443) {
                    endpoint.host = `${endpoint.hostname}:${endpoint.port}`;
                } else {
                    endpoint.host = endpoint.hostname;
                }
                // needed for signing the request
                httpRequest.virtualHostedBucket = b;
                service.removeVirtualHostedBucketFromPath(req);
            }
        }
    },

    /**
     * Takes the bucket name out of the path if bucket is virtual-hosted
     * @param {AWS.Request} req - AWS request object
     * @returns {undefined}
     *
     * @api private
     */
    removeVirtualHostedBucketFromPath(req) {
        const httpRequest = req.httpRequest;
        const bucket = httpRequest.virtualHostedBucket;
        if (bucket && httpRequest.path) {
            httpRequest.path =
                httpRequest.path.replace(new RegExp(`/${bucket}`), '');
            if (httpRequest.path[0] !== '/') {
                httpRequest.path = `/${httpRequest.path}`;
            }
        }
    },

    /**
     * Adds a default content type if none is supplied.
     * @param {AWS.Request} req - AWS request object
     * @returns {undefined}
     *
     * @api private
     */
    addContentType(req) {
        const httpRequest = req.httpRequest;
        if (httpRequest.method === 'GET' || httpRequest.method === 'HEAD') {
            // Content-Type is not set in GET/HEAD requests
            delete httpRequest.headers['Content-Type'];
            return;
        }

        // always have a Content-Type
        if (!httpRequest.headers['Content-Type']) {
            httpRequest.headers['Content-Type'] = 'application/octet-stream';
        }

        const contentType = httpRequest.headers['Content-Type'];
        if (AWS.util.isBrowser()) {
            if (typeof httpRequest.body === 'string' &&
                !contentType.match(/;\s*charset=/)) {
                const charset = '; charset=UTF-8';
                httpRequest.headers['Content-Type'] += charset;
            } else {
                const replaceFn = (_, prefix, charsetName) =>
                    prefix + charsetName.toUpperCase();

                httpRequest.headers['Content-Type'] =
                    contentType.replace(/(;\s*charset=)(.+)$/, replaceFn);
            }
        }
    },

    computableChecksumOperations: {
        putBucketCors: true,
        putBucketLifecycle: true,
        putBucketLifecycleConfiguration: true,
        putBucketTagging: true,
        deleteObjects: true,
        putBucketReplication: true,
    },

    /**
     * Checks whether checksums should be computed for the request.
     * If the request requires checksums to be computed, this will always
     * return true, otherwise it depends on whether
     * {AWS.Config.computeChecksums} is set.
     * @param {AWS.Request} req - the request to check against
     * @return {Boolean} whether to compute checksums for a request.
     *
     * @api private
     */
    willComputeChecksums(req) {
        if (this.computableChecksumOperations[req.operation]) return true;
        if (!this.config.computeChecksums) return false;

        // TODO: compute checksums for Stream objects
        if (!AWS.util.Buffer.isBuffer(req.httpRequest.body) &&
                typeof req.httpRequest.body !== 'string') {
            return false;
        }
        return false;
    },

    /**
     * A listener that computes the Content-MD5 and sets it in the header.
     * @param {AWS.Request} req - AWS request object
     * @returns {undefined}
     *
     * @see AWS.S3.willComputeChecksums
     * @api private
     */
    computeContentMd5(req) {
        if (req.service.willComputeChecksums(req)) {
            const md5 = AWS.util.crypto.md5(req.httpRequest.body, 'base64');
            // eslint-disable-next-line no-param-reassign
            req.httpRequest.headers['Content-MD5'] = md5;
        }
    },

    /**
     * Returns true if the bucket name should be left in the URI path for
     * a request to S3.    This function takes into account the current
     * endpoint protocol (e.g. http or https).
     * @param {string} bucketName - bucket name
     * @returns {Boolean} whether request should use path style
     *
     * @api private
     */
    pathStyleBucketName(bucketName) {
        // user can force path style requests via the configuration
        if (this.config.s3ForcePathStyle) return true;
        if (this.config.s3BucketEndpoint) return false;

        if (this.dnsCompatibleBucketName(bucketName)) {
            return this.config.sslEnabled && bucketName.match(/\./);
        }
        return true; // not dns compatible names must always use path style
    },

    /**
     * Returns true if the bucket name is DNS compatible. Buckets created
     * outside of the classic region MUST be DNS compatible.
     * @param {string} bucketName - bucket name
     * @returns {Boolean} whether bucket name is dns compatible
     *
     * @api private
     */
    dnsCompatibleBucketName(bucketName) {
        const b = bucketName;
        const domain = new RegExp(/^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$/);
        const ipAddress = new RegExp(/(\d+\.){3}\d+/);
        const dots = new RegExp(/\.\./);
        return b.match(domain) && !b.match(ipAddress) && !b.match(dots);
    },
};
<commit_msg>improvement: parse and include gcp request id on errors<commit_after>/**
 * This file contains the private methods for the GCP service to form/sign
 * Google Cloud Storage requests.
 *
 * It uses a modified version of the S3 service private methods to form/sign
 * requests compatible with the Google Cloud Storage XML api.
 */

const AWS = require('aws-sdk');
const GcpSigner = require('./GcpSigner');

module.exports = {
    /**
     * GCP compatible request signer
     * @return {AWS.Signer} AWS Signer
     */
    getSignerClass() {
        return GcpSigner;
    },

    /**
     * set service region
     * @return {undefined}
     */
    validateService() {
        if (!this.config.region) {
            this.config.region = 'us-east-1';
        }
    },

    /**
     * setup listeners for building requests
     * @param {AWS.Request} request - AWS request object
     * @return {undefined}
     */
    setupRequestListeners(request) {
        request.addListener('validate', this.validateBucketEndpoint);
        request.addListener('build', this.addContentType);
        request.addListener('build', this.populateURI);
        request.addListener('build', this.computeContentMd5);
        request.addListener('extractError', this.extractRequestIds);
    },

    /**
     * validate that when bucket endpoitn flag is set, root level apis are
     * inaccessible
     * @param {AWS.Request} req - AWS request object
     * @returns {undefined}
     * @api private
     */
    validateBucketEndpoint(req) {
        if (!req.params.Bucket && req.service.config.s3BucketEndpoint) {
            const msg =
                'Cannot send requests to root API with `s3BucketEndpoint` set.';
            throw AWS.util.error(new Error(),
                { code: 'ConfigError', message: msg });
        }
    },

    /**
     * S3 prefers dns-compatible bucket names to be moved from the uri path
     * to the hostname as a sub-domain. This is not possible, even for
     * dns-compat buckets when using SSL and the bucket name contains a dot.
     * The ssl wildcard certificate is only 1-level deep.
     * @param {AWS.Request} req - AWS request object
     * @returns {undefined}
     *
     * @api private
     */
    populateURI(req) {
        const httpRequest = req.httpRequest;
        const b = req.params.Bucket;
        const service = req.service;
        const endpoint = httpRequest.endpoint;

        if (b) {
            if (!service.pathStyleBucketName(b)) {
                if (!service.config.s3BucketEndpoint) {
                    endpoint.hostname = `${b}.${endpoint.hostname}`;
                }
                const port = endpoint.port;
                if (port !== 80 && port !== 443) {
                    endpoint.host = `${endpoint.hostname}:${endpoint.port}`;
                } else {
                    endpoint.host = endpoint.hostname;
                }
                // needed for signing the request
                httpRequest.virtualHostedBucket = b;
                service.removeVirtualHostedBucketFromPath(req);
            }
        }
    },

    /**
     * Takes the bucket name out of the path if bucket is virtual-hosted
     * @param {AWS.Request} req - AWS request object
     * @returns {undefined}
     *
     * @api private
     */
    removeVirtualHostedBucketFromPath(req) {
        const httpRequest = req.httpRequest;
        const bucket = httpRequest.virtualHostedBucket;
        if (bucket && httpRequest.path) {
            httpRequest.path =
                httpRequest.path.replace(new RegExp(`/${bucket}`), '');
            if (httpRequest.path[0] !== '/') {
                httpRequest.path = `/${httpRequest.path}`;
            }
        }
    },

    /**
     * Adds a default content type if none is supplied.
     * @param {AWS.Request} req - AWS request object
     * @returns {undefined}
     *
     * @api private
     */
    addContentType(req) {
        const httpRequest = req.httpRequest;
        if (httpRequest.method === 'GET' || httpRequest.method === 'HEAD') {
            // Content-Type is not set in GET/HEAD requests
            delete httpRequest.headers['Content-Type'];
            return;
        }

        // always have a Content-Type
        if (!httpRequest.headers['Content-Type']) {
            httpRequest.headers['Content-Type'] = 'application/octet-stream';
        }

        const contentType = httpRequest.headers['Content-Type'];
        if (AWS.util.isBrowser()) {
            if (typeof httpRequest.body === 'string' &&
                !contentType.match(/;\s*charset=/)) {
                const charset = '; charset=UTF-8';
                httpRequest.headers['Content-Type'] += charset;
            } else {
                const replaceFn = (_, prefix, charsetName) =>
                    prefix + charsetName.toUpperCase();

                httpRequest.headers['Content-Type'] =
                    contentType.replace(/(;\s*charset=)(.+)$/, replaceFn);
            }
        }
    },

    computableChecksumOperations: {
        putBucketCors: true,
        putBucketLifecycle: true,
        putBucketLifecycleConfiguration: true,
        putBucketTagging: true,
        deleteObjects: true,
        putBucketReplication: true,
    },

    /**
     * Checks whether checksums should be computed for the request.
     * If the request requires checksums to be computed, this will always
     * return true, otherwise it depends on whether
     * {AWS.Config.computeChecksums} is set.
     * @param {AWS.Request} req - the request to check against
     * @return {Boolean} whether to compute checksums for a request.
     *
     * @api private
     */
    willComputeChecksums(req) {
        if (this.computableChecksumOperations[req.operation]) return true;
        if (!this.config.computeChecksums) return false;

        // TODO: compute checksums for Stream objects
        if (!AWS.util.Buffer.isBuffer(req.httpRequest.body) &&
                typeof req.httpRequest.body !== 'string') {
            return false;
        }
        return false;
    },

    /**
     * A listener that computes the Content-MD5 and sets it in the header.
     * @param {AWS.Request} req - AWS request object
     * @returns {undefined}
     *
     * @see AWS.S3.willComputeChecksums
     * @api private
     */
    computeContentMd5(req) {
        if (req.service.willComputeChecksums(req)) {
            const md5 = AWS.util.crypto.md5(req.httpRequest.body, 'base64');
            // eslint-disable-next-line no-param-reassign
            req.httpRequest.headers['Content-MD5'] = md5;
        }
    },

    /**
     * Returns true if the bucket name should be left in the URI path for
     * a request to S3.    This function takes into account the current
     * endpoint protocol (e.g. http or https).
     * @param {string} bucketName - bucket name
     * @returns {Boolean} whether request should use path style
     *
     * @api private
     */
    pathStyleBucketName(bucketName) {
        // user can force path style requests via the configuration
        if (this.config.s3ForcePathStyle) return true;
        if (this.config.s3BucketEndpoint) return false;

        if (this.dnsCompatibleBucketName(bucketName)) {
            return this.config.sslEnabled && bucketName.match(/\./);
        }
        return true; // not dns compatible names must always use path style
    },

    /**
     * Returns true if the bucket name is DNS compatible. Buckets created
     * outside of the classic region MUST be DNS compatible.
     * @param {string} bucketName - bucket name
     * @returns {Boolean} whether bucket name is dns compatible
     *
     * @api private
     */
    dnsCompatibleBucketName(bucketName) {
        const b = bucketName;
        const domain = new RegExp(/^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$/);
        const ipAddress = new RegExp(/(\d+\.){3}\d+/);
        const dots = new RegExp(/\.\./);
        return b.match(domain) && !b.match(ipAddress) && !b.match(dots);
    },

    /**
     * Extracts GCP specific request ids from the http response.
     * @param {object} resp - response object
     * @returns {undefined}
     * @api private
     */
    extractRequestIds(resp) {
        const requestId = resp.httpResponse.headers ?
            resp.httpResponse.headers['x-guploader-uploadid'] : null;
        if (resp.error) {
             // eslint-disable-next-line no-param-reassign
            resp.error.requestId = resp.requestId || requestId;
        }
    },
};
<|endoftext|>


<commit_before>exports.register = function (server, options, next) {

  const plugins = [

  ];

  // register all the plugins
  server.register(plugins, function (err) {
    exports.ready(err, server, next);
  });
};

exports.ready = function (err, server, next) {

  if (err) { throw err; }

  next();
};

exports.register.attributes = {
  name: '__plugin-name__',
  version: 1
};
<commit_msg>update templates/plugin/index.js<commit_after>const pkg = require('./package.json');

exports.register = function (server, options, next) {

  // implement your plugin here

  // if you depend on another plugin being registered first,
  // then declare that dependency here and specify a callback
  // to be executed after the depedencies are resolved
  // server.dependency(['uku-bearer-token', 'uku-heroku-client'], exports.ready);
  next();
};

// based on the example above, this will be
// be called if/when the uku-bearer-token
// and uku-heroku-client dependencies are
// resolved in the project registering this plugin
exports.ready = function (server, next) {

  // perhaps register some http endpoints?
  // server.route(require('./lib/routes'));

  next();
};

exports.register.attributes = {
  name: pkg.name,
  version: pkg.version
};
<|endoftext|>


<commit_before>const {defer} = require('rx')
const log = require('sepal/log').getLogger('ee')
const {limiter$} = require('../eeLimiter')
const {v4: uuid} = require('uuid')
const {promise$} = require('sepal/rxjs')
const {retry} = require('sepal/rxjs/operators')
const {EEException} = require('sepal/ee/exception')

const DEFAULT_MAX_RETRIES = 5

module.exports = ee => {

    const config = {
        maxRetries: DEFAULT_MAX_RETRIES
    }

    const setMaxRetries = maxRetries => {
        log.debug(`Setting default max retries to ${maxRetries}`)
        config.maxRetries = maxRetries
    }

    const $ = ({operation, operationId = uuid().substr(-4), ee, maxRetries = config.maxRetries}) =>
        defer(() =>
            limiter$(
                promise$(
                    (resolve, reject) => {
                        const report = Report(operation, operationId)
                        try {
                            ee(
                                result => {
                                    log.debug(report())
                                    resolve(result)
                                },
                                error => {
                                    log.debug(report(error))
                                    reject(createEEException(error, operation, operationId))
                                }
                            )
                        } catch (error) {
                            log.debug(report(error))
                            reject(createEEException(error, operation, operationId))
                        }
                    }
                ).pipe(
                    retry(maxRetries)
                ), operationId
            )
        )

    const getAssetRoots$ = maxRetries =>
        $({
            operation: 'get asset roots',
            ee: (resolve, reject) =>
                ee.data.getAssetRoots(
                    (assetRoots, error) => {
                        log.error('assetRoots', assetRoots)
                        return error
                            ? reject(error)
                            : resolve(assetRoots.map(({id}) => id))
                    }
                ),
            maxRetries
        })

    const getAsset$ = (eeId, maxRetries) =>
        $({
            operation: `get asset (${eeId})`,
            ee: (resolve, reject) =>
                ee.data.getAsset(eeId, (result, error) =>
                    error
                        ? reject(error)
                        : resolve(result)
                ),
            maxRetries
        })

    const deleteAsset$ = (eeId, maxRetries) =>
        $({
            operation: `delete asset (${eeId})`,
            ee: (resolve, reject) =>
                ee.data.deleteAsset(eeId, (_, error) =>
                    error
                        ? reject(error)
                        : resolve()
                ),
            maxRetries
        })

    const getInfo$ = (eeObject, description, maxRetries) =>
        $({
            operation: `get info${description ? ` (${description})` : ''}`,
            ee: (resolve, reject) =>
                eeObject.getInfo((result, error) =>
                    error
                        ? reject(error)
                        : resolve(result)),
            maxRetries
        })

    const getMap$ = (eeObject, visParams, description, maxRetries) =>
        $({
            operation: `get map ${description ? ` (${description})` : ''}`,
            ee: (resolve, reject) =>
                eeObject.getMap(
                    visParams,
                    (map, error) => {
                        if (error) {
                            reject(error)
                        } else {
                            const urlTemplate = map.formatTileUrl(0, 0, 0)
                                .replace(new RegExp('(.*)/0/0/0(.*)'), '$1/{z}/{x}/{y}$2')
                            resolve({
                                mapId: map.mapid,
                                token: map.token,
                                urlTemplate
                            })
                        }
                    }
                ),
            maxRetries
        })

    const sepal = {
        getAuthType() {
            return this.authType
        },
        setAuthType(authType) {
            this.authType = authType
        }
    }

    const isNull = o =>
        ee.List([o]).map(o => o, true).size().eq(0)

    return {setMaxRetries, $, getAssetRoots$, getAsset$, deleteAsset$, getInfo$, getMap$, isNull, sepal}
}

const Report = (operation, operationId) => {
    const t0 = Date.now()
    const prefix = `Earth Engine <${operation}> [${operationId}]`
    log.trace(`${prefix} starting`)
    return error => {
        const t1 = Date.now()
        return `${prefix} ${error ? `error: ${error}` : 'completed'} (${t1 - t0}ms)`
    }
}

const createEEException = (error, operation, operationId) =>
    new EEException(`Failed to ${operation}: ${error}`, {
        cause: error,
        userMessage: {
            message: `Earth Engine: ${error}`,
            key: 'gee.error.earthEngineException',
            args: {earthEngineMessage: error}
        },
        operationId
    })
<commit_msg>Removed debug log.<commit_after>const {defer} = require('rx')
const log = require('sepal/log').getLogger('ee')
const {limiter$} = require('../eeLimiter')
const {v4: uuid} = require('uuid')
const {promise$} = require('sepal/rxjs')
const {retry} = require('sepal/rxjs/operators')
const {EEException} = require('sepal/ee/exception')

const DEFAULT_MAX_RETRIES = 5

module.exports = ee => {

    const config = {
        maxRetries: DEFAULT_MAX_RETRIES
    }

    const setMaxRetries = maxRetries => {
        log.debug(`Setting default max retries to ${maxRetries}`)
        config.maxRetries = maxRetries
    }

    const $ = ({operation, operationId = uuid().substr(-4), ee, maxRetries = config.maxRetries}) =>
        defer(() =>
            limiter$(
                promise$(
                    (resolve, reject) => {
                        const report = Report(operation, operationId)
                        try {
                            ee(
                                result => {
                                    log.debug(report())
                                    resolve(result)
                                },
                                error => {
                                    log.debug(report(error))
                                    reject(createEEException(error, operation, operationId))
                                }
                            )
                        } catch (error) {
                            log.debug(report(error))
                            reject(createEEException(error, operation, operationId))
                        }
                    }
                ).pipe(
                    retry(maxRetries)
                ), operationId
            )
        )

    const getAssetRoots$ = maxRetries =>
        $({
            operation: 'get asset roots',
            ee: (resolve, reject) =>
                ee.data.getAssetRoots(
                    (assetRoots, error) =>
                        error
                            ? reject(error)
                            : resolve(assetRoots.map(({id}) => id))
                ),
            maxRetries
        })

    const getAsset$ = (eeId, maxRetries) =>
        $({
            operation: `get asset (${eeId})`,
            ee: (resolve, reject) =>
                ee.data.getAsset(eeId, (result, error) =>
                    error
                        ? reject(error)
                        : resolve(result)
                ),
            maxRetries
        })

    const deleteAsset$ = (eeId, maxRetries) =>
        $({
            operation: `delete asset (${eeId})`,
            ee: (resolve, reject) =>
                ee.data.deleteAsset(eeId, (_, error) =>
                    error
                        ? reject(error)
                        : resolve()
                ),
            maxRetries
        })

    const getInfo$ = (eeObject, description, maxRetries) =>
        $({
            operation: `get info${description ? ` (${description})` : ''}`,
            ee: (resolve, reject) =>
                eeObject.getInfo((result, error) =>
                    error
                        ? reject(error)
                        : resolve(result)),
            maxRetries
        })

    const getMap$ = (eeObject, visParams, description, maxRetries) =>
        $({
            operation: `get map ${description ? ` (${description})` : ''}`,
            ee: (resolve, reject) =>
                eeObject.getMap(
                    visParams,
                    (map, error) => {
                        if (error) {
                            reject(error)
                        } else {
                            const urlTemplate = map.formatTileUrl(0, 0, 0)
                                .replace(new RegExp('(.*)/0/0/0(.*)'), '$1/{z}/{x}/{y}$2')
                            resolve({
                                mapId: map.mapid,
                                token: map.token,
                                urlTemplate
                            })
                        }
                    }
                ),
            maxRetries
        })

    const sepal = {
        getAuthType() {
            return this.authType
        },
        setAuthType(authType) {
            this.authType = authType
        }
    }

    const isNull = o =>
        ee.List([o]).map(o => o, true).size().eq(0)

    return {setMaxRetries, $, getAssetRoots$, getAsset$, deleteAsset$, getInfo$, getMap$, isNull, sepal}
}

const Report = (operation, operationId) => {
    const t0 = Date.now()
    const prefix = `Earth Engine <${operation}> [${operationId}]`
    log.trace(`${prefix} starting`)
    return error => {
        const t1 = Date.now()
        return `${prefix} ${error ? `error: ${error}` : 'completed'} (${t1 - t0}ms)`
    }
}

const createEEException = (error, operation, operationId) =>
    new EEException(`Failed to ${operation}: ${error}`, {
        cause: error,
        userMessage: {
            message: `Earth Engine: ${error}`,
            key: 'gee.error.earthEngineException',
            args: {earthEngineMessage: error}
        },
        operationId
    })
<|endoftext|>


<commit_before>import createComponentCard from '../utils/create-component-card';

// map card names to component names
export const CARD_COMPONENT_MAP = {
    hr: 'koenig-card-hr',
    image: 'koenig-card-image',
    markdown: 'koenig-card-markdown',
    'card-markdown': 'koenig-card-markdown', // backwards-compat with markdown editor
    html: 'koenig-card-html',
    code: 'koenig-card-code',
    embed: 'koenig-card-embed',
    bookmark: 'koenig-card-bookmark',
    gallery: 'koenig-card-gallery',
    email: 'koenig-card-email',
    button: 'koenig-card-button',
    callout: 'koenig-card-callout',
    nft: 'koenig-card-nft',
    toggle: 'koenig-card-accordion',
    'email-cta': 'koenig-card-email-cta',
    paywall: 'koenig-card-paywall',
    file: 'koenig-card-file',
    audio: 'koenig-card-audio',
    video: 'koenig-card-video'
};

// map card names to generic icons (used for ghost elements when dragging)
export const CARD_ICON_MAP = {
    hr: 'koenig/kg-card-type-divider',
    image: 'koenig/kg-card-type-image',
    markdown: 'koenig/kg-card-type-markdown',
    'card-markdown': 'koenig/kg-card-type-markdown',
    html: 'koenig/kg-card-type-html',
    code: 'koenig/kg-card-type-gen-embed',
    embed: 'koenig/kg-card-type-gen-embed',
    bookmark: 'koenig/kg-card-type-bookmark',
    gallery: 'koenig/kg-card-type-gallery',
    email: 'koenig/kg-card-type-gen-embed',
    button: 'koenig/kg-card-type-gen-embed',
    callout: 'koenig/kg-card-type-callout',
    nft: 'koenig/kg-card-type-gen-embed',
    toggle: 'koenig/kg-card-type-accordion',
    'email-cta': 'koenig/kg-card-type-gen-embed',
    paywall: 'koenig/kg-card-type-divider',
    file: 'koenig/kg-card-type-divider',
    audio: 'koenig/kg-card-type-divider',
    video: 'koenig/kg-card-type-video'
};

// TODO: move koenigOptions directly into cards now that card components register
// themselves so that they are available on card.component
export default [
    createComponentCard('card-markdown'), // backwards-compat with markdown editor
    createComponentCard('code'),
    createComponentCard('embed', {hasEditMode: false}),
    createComponentCard('bookmark', {hasEditMode: false}),
    createComponentCard('hr', {hasEditMode: false, selectAfterInsert: false}),
    createComponentCard('html'),
    createComponentCard('image', {hasEditMode: false}),
    createComponentCard('markdown'),
    createComponentCard('gallery', {hasEditMode: false}),
    createComponentCard('email'),
    createComponentCard('email-cta'),
    createComponentCard('button'),
    createComponentCard('callout'),
    createComponentCard('nft', {hasEditMode: false}),
    createComponentCard('toggle'),
    createComponentCard('file'),
    createComponentCard('audio'),
    createComponentCard('video'),
    createComponentCard('paywall', {hasEditMode: false, selectAfterInsert: false})
];

export const CARD_MENU = [
    {
        title: 'Primary',
        rowLength: 1,
        items: [{
            label: 'Image',
            icon: 'koenig/kg-card-type-image',
            desc: 'Upload, or embed with /image [url]',
            iconClass: 'kg-card-type-native',
            matches: ['image', 'img'],
            type: 'card',
            replaceArg: 'image',
            params: ['src'],
            payload: {
                triggerBrowse: true
            }
        },
        {
            label: 'Markdown',
            icon: 'koenig/kg-card-type-markdown',
            desc: 'Insert a Markdown editor card',
            iconClass: 'kg-card-type-native',
            matches: ['markdown', 'md'],
            type: 'card',
            replaceArg: 'markdown'
        },
        {
            label: 'HTML',
            icon: 'koenig/kg-card-type-html',
            desc: 'Insert a raw HTML card',
            iconClass: 'kg-card-type-native',
            matches: ['html'],
            type: 'card',
            replaceArg: 'html'
        },
        {
            label: 'Gallery',
            icon: 'koenig/kg-card-type-gallery',
            desc: 'Create an image gallery',
            iconClass: 'kg-card-type-native',
            matches: ['gallery'],
            type: 'card',
            replaceArg: 'gallery'
        },
        {
            label: 'Divider',
            icon: 'koenig/kg-card-type-divider',
            desc: 'Insert a dividing line',
            iconClass: 'kg-card-type-native',
            matches: ['divider', 'horizontal-rule', 'hr'],
            type: 'card',
            replaceArg: 'hr'
        },
        {
            label: 'Bookmark',
            icon: 'koenig/kg-card-type-bookmark',
            desc: 'Embed a link as a visual bookmark',
            matches: ['bookmark'],
            type: 'card',
            replaceArg: 'bookmark',
            params: ['url']
        },
        {
            label: 'Email content',
            icon: 'koenig/kg-card-type-email',
            desc: 'Only visible when delivered by email',
            matches: ['email'],
            type: 'card',
            replaceArg: 'email',
            postType: 'post'
        },
        {
            label: 'Email call to action',
            icon: 'koenig/kg-card-type-email-cta',
            desc: 'Target free or paid members with a CTA',
            matches: ['email', 'cta'],
            type: 'card',
            replaceArg: 'email-cta',
            postType: 'post'
        },
        {
            label: 'Public preview',
            icon: 'koenig/kg-card-type-paywall',
            desc: 'Attract signups with a public intro',
            matches: ['public preview', 'preview', 'paywall'],
            type: 'card',
            replaceArg: 'paywall'
        },
        {
            label: 'Button',
            icon: 'koenig/kg-card-type-button',
            desc: 'Add a button to your post',
            matches: ['button'],
            type: 'card',
            replaceArg: 'button',
            isAvailable: 'feature.buttonCard'
        },
        {
            label: 'Callout',
            icon: 'koenig/kg-card-type-callout',
            desc: 'Info boxes that stand out',
            matches: ['callout'],
            type: 'card',
            replaceArg: 'callout',
            isAvailable: 'feature.calloutCard'
        },
        {
            label: 'GIF',
            icon: 'koenig/kg-card-type-gif',
            desc: 'Add with /gif [url or search term]',
            iconClass: 'kg-card-type-unsplash',
            matches: ['gif', 'giphy', 'tenor'],
            type: 'card',
            replaceArg: 'image',
            params: ['searchTerm'],
            payload: {
                imageSelector: 'tenor'
            },
            isAvailable: ['feature.gifsCard', 'config.tenor.apiKey']
        },
        {
            label: 'Toggle',
            icon: 'koenig/kg-card-type-accordion',
            desc: 'Add collapsible content',
            matches: ['toggle'],
            type: 'card',
            replaceArg: 'toggle',
            isAvailable: 'feature.accordionCard'
        },
        {
            label: 'File',
            icon: 'koenig/kg-card-type-accordion',
            desc: 'Add a file',
            matches: ['file'],
            type: 'card',
            replaceArg: 'file',
            isAvailable: 'feature.fileCard'
        },
        {
            label: 'Audio',
            icon: 'koenig/kg-card-type-accordion',
            desc: 'Add an audio file',
            matches: ['audio'],
            type: 'card',
            replaceArg: 'audio',
            isAvailable: 'feature.audioCard'
        },
        {
            label: 'Video',
            icon: 'koenig/kg-card-type-accordion',
            desc: 'Add a video file',
            matches: ['video'],
            type: 'card',
            replaceArg: 'video',
            isAvailable: 'feature.videoCard'
        }]
    },
    {
        title: 'Embed',
        rowLength: 1,
        items: [{
            label: 'YouTube',
            icon: 'koenig/kg-card-type-youtube',
            desc: '/youtube [video url]',
            matches: ['youtube'],
            type: 'card',
            replaceArg: 'embed',
            params: ['url']
        },
        {
            label: 'Twitter',
            icon: 'koenig/kg-card-type-twitter',
            desc: '/twitter [tweet url]',
            matches: ['twitter'],
            type: 'card',
            replaceArg: 'embed',
            params: ['url']
        },
        {
            label: 'Unsplash',
            icon: 'koenig/kg-card-type-unsplash',
            desc: '/unsplash [search-term or url]',
            iconClass: 'kg-card-type-unsplash',
            matches: ['unsplash'],
            type: 'card',
            replaceArg: 'image',
            params: ['searchTerm'],
            payload: {
                imageSelector: 'unsplash'
            },
            isAvailable: 'settings.unsplash'
        },
        {
            label: 'Vimeo',
            icon: 'koenig/kg-card-type-vimeo',
            desc: '/vimeo [video url]',
            matches: ['vimeo'],
            type: 'card',
            replaceArg: 'embed',
            params: ['url']
        },
        {
            label: 'CodePen',
            icon: 'koenig/kg-card-type-codepen',
            desc: '/codepen [pen url]',
            iconClass: 'kg-card-type-codepen',
            matches: ['codepen'],
            type: 'card',
            replaceArg: 'embed',
            params: ['url']
        },
        {
            label: 'Spotify',
            icon: 'koenig/kg-card-type-spotify',
            desc: '/spotify [track or playlist url]',
            matches: ['spotify'],
            type: 'card',
            replaceArg: 'embed',
            params: ['url']
        },
        {
            label: 'SoundCloud',
            icon: 'koenig/kg-card-type-soundcloud',
            desc: '/soundcloud [track or playlist url]',
            matches: ['soundcloud'],
            type: 'card',
            replaceArg: 'embed',
            params: ['url']
        },
        {
            label: 'NFT',
            icon: 'koenig/kg-card-type-nft',
            desc: '/nft [opensea url]',
            iconClass: 'kg-card-type-native',
            matches: ['nft', 'opensea'],
            type: 'card',
            replaceArg: 'embed',
            params: ['url'],
            isAvailable: 'feature.nftCard'
        },
        {
            label: 'Other...',
            icon: 'koenig/kg-card-type-other',
            desc: '/embed [url]',
            iconClass: 'kg-card-type-native',
            matches: ['embed'],
            type: 'card',
            replaceArg: 'embed',
            params: ['url']
        }]
    }
];
<commit_msg>Fixed copy for GIF card menu<commit_after>import createComponentCard from '../utils/create-component-card';

// map card names to component names
export const CARD_COMPONENT_MAP = {
    hr: 'koenig-card-hr',
    image: 'koenig-card-image',
    markdown: 'koenig-card-markdown',
    'card-markdown': 'koenig-card-markdown', // backwards-compat with markdown editor
    html: 'koenig-card-html',
    code: 'koenig-card-code',
    embed: 'koenig-card-embed',
    bookmark: 'koenig-card-bookmark',
    gallery: 'koenig-card-gallery',
    email: 'koenig-card-email',
    button: 'koenig-card-button',
    callout: 'koenig-card-callout',
    nft: 'koenig-card-nft',
    toggle: 'koenig-card-accordion',
    'email-cta': 'koenig-card-email-cta',
    paywall: 'koenig-card-paywall',
    file: 'koenig-card-file',
    audio: 'koenig-card-audio',
    video: 'koenig-card-video'
};

// map card names to generic icons (used for ghost elements when dragging)
export const CARD_ICON_MAP = {
    hr: 'koenig/kg-card-type-divider',
    image: 'koenig/kg-card-type-image',
    markdown: 'koenig/kg-card-type-markdown',
    'card-markdown': 'koenig/kg-card-type-markdown',
    html: 'koenig/kg-card-type-html',
    code: 'koenig/kg-card-type-gen-embed',
    embed: 'koenig/kg-card-type-gen-embed',
    bookmark: 'koenig/kg-card-type-bookmark',
    gallery: 'koenig/kg-card-type-gallery',
    email: 'koenig/kg-card-type-gen-embed',
    button: 'koenig/kg-card-type-gen-embed',
    callout: 'koenig/kg-card-type-callout',
    nft: 'koenig/kg-card-type-gen-embed',
    toggle: 'koenig/kg-card-type-accordion',
    'email-cta': 'koenig/kg-card-type-gen-embed',
    paywall: 'koenig/kg-card-type-divider',
    file: 'koenig/kg-card-type-divider',
    audio: 'koenig/kg-card-type-divider',
    video: 'koenig/kg-card-type-video'
};

// TODO: move koenigOptions directly into cards now that card components register
// themselves so that they are available on card.component
export default [
    createComponentCard('card-markdown'), // backwards-compat with markdown editor
    createComponentCard('code'),
    createComponentCard('embed', {hasEditMode: false}),
    createComponentCard('bookmark', {hasEditMode: false}),
    createComponentCard('hr', {hasEditMode: false, selectAfterInsert: false}),
    createComponentCard('html'),
    createComponentCard('image', {hasEditMode: false}),
    createComponentCard('markdown'),
    createComponentCard('gallery', {hasEditMode: false}),
    createComponentCard('email'),
    createComponentCard('email-cta'),
    createComponentCard('button'),
    createComponentCard('callout'),
    createComponentCard('nft', {hasEditMode: false}),
    createComponentCard('toggle'),
    createComponentCard('file'),
    createComponentCard('audio'),
    createComponentCard('video'),
    createComponentCard('paywall', {hasEditMode: false, selectAfterInsert: false})
];

export const CARD_MENU = [
    {
        title: 'Primary',
        rowLength: 1,
        items: [{
            label: 'Image',
            icon: 'koenig/kg-card-type-image',
            desc: 'Upload, or embed with /image [url]',
            iconClass: 'kg-card-type-native',
            matches: ['image', 'img'],
            type: 'card',
            replaceArg: 'image',
            params: ['src'],
            payload: {
                triggerBrowse: true
            }
        },
        {
            label: 'Markdown',
            icon: 'koenig/kg-card-type-markdown',
            desc: 'Insert a Markdown editor card',
            iconClass: 'kg-card-type-native',
            matches: ['markdown', 'md'],
            type: 'card',
            replaceArg: 'markdown'
        },
        {
            label: 'HTML',
            icon: 'koenig/kg-card-type-html',
            desc: 'Insert a raw HTML card',
            iconClass: 'kg-card-type-native',
            matches: ['html'],
            type: 'card',
            replaceArg: 'html'
        },
        {
            label: 'Gallery',
            icon: 'koenig/kg-card-type-gallery',
            desc: 'Create an image gallery',
            iconClass: 'kg-card-type-native',
            matches: ['gallery'],
            type: 'card',
            replaceArg: 'gallery'
        },
        {
            label: 'Divider',
            icon: 'koenig/kg-card-type-divider',
            desc: 'Insert a dividing line',
            iconClass: 'kg-card-type-native',
            matches: ['divider', 'horizontal-rule', 'hr'],
            type: 'card',
            replaceArg: 'hr'
        },
        {
            label: 'Bookmark',
            icon: 'koenig/kg-card-type-bookmark',
            desc: 'Embed a link as a visual bookmark',
            matches: ['bookmark'],
            type: 'card',
            replaceArg: 'bookmark',
            params: ['url']
        },
        {
            label: 'Email content',
            icon: 'koenig/kg-card-type-email',
            desc: 'Only visible when delivered by email',
            matches: ['email'],
            type: 'card',
            replaceArg: 'email',
            postType: 'post'
        },
        {
            label: 'Email call to action',
            icon: 'koenig/kg-card-type-email-cta',
            desc: 'Target free or paid members with a CTA',
            matches: ['email', 'cta'],
            type: 'card',
            replaceArg: 'email-cta',
            postType: 'post'
        },
        {
            label: 'Public preview',
            icon: 'koenig/kg-card-type-paywall',
            desc: 'Attract signups with a public intro',
            matches: ['public preview', 'preview', 'paywall'],
            type: 'card',
            replaceArg: 'paywall'
        },
        {
            label: 'Button',
            icon: 'koenig/kg-card-type-button',
            desc: 'Add a button to your post',
            matches: ['button'],
            type: 'card',
            replaceArg: 'button',
            isAvailable: 'feature.buttonCard'
        },
        {
            label: 'Callout',
            icon: 'koenig/kg-card-type-callout',
            desc: 'Info boxes that stand out',
            matches: ['callout'],
            type: 'card',
            replaceArg: 'callout',
            isAvailable: 'feature.calloutCard'
        },
        {
            label: 'GIF',
            icon: 'koenig/kg-card-type-gif',
            desc: '/gif [url or search term]',
            iconClass: 'kg-card-type-unsplash',
            matches: ['gif', 'giphy', 'tenor'],
            type: 'card',
            replaceArg: 'image',
            params: ['searchTerm'],
            payload: {
                imageSelector: 'tenor'
            },
            isAvailable: ['feature.gifsCard', 'config.tenor.apiKey']
        },
        {
            label: 'Toggle',
            icon: 'koenig/kg-card-type-accordion',
            desc: 'Add collapsible content',
            matches: ['toggle'],
            type: 'card',
            replaceArg: 'toggle',
            isAvailable: 'feature.accordionCard'
        },
        {
            label: 'File',
            icon: 'koenig/kg-card-type-accordion',
            desc: 'Add a file',
            matches: ['file'],
            type: 'card',
            replaceArg: 'file',
            isAvailable: 'feature.fileCard'
        },
        {
            label: 'Audio',
            icon: 'koenig/kg-card-type-accordion',
            desc: 'Add an audio file',
            matches: ['audio'],
            type: 'card',
            replaceArg: 'audio',
            isAvailable: 'feature.audioCard'
        },
        {
            label: 'Video',
            icon: 'koenig/kg-card-type-accordion',
            desc: 'Add a video file',
            matches: ['video'],
            type: 'card',
            replaceArg: 'video',
            isAvailable: 'feature.videoCard'
        }]
    },
    {
        title: 'Embed',
        rowLength: 1,
        items: [{
            label: 'YouTube',
            icon: 'koenig/kg-card-type-youtube',
            desc: '/youtube [video url]',
            matches: ['youtube'],
            type: 'card',
            replaceArg: 'embed',
            params: ['url']
        },
        {
            label: 'Twitter',
            icon: 'koenig/kg-card-type-twitter',
            desc: '/twitter [tweet url]',
            matches: ['twitter'],
            type: 'card',
            replaceArg: 'embed',
            params: ['url']
        },
        {
            label: 'Unsplash',
            icon: 'koenig/kg-card-type-unsplash',
            desc: '/unsplash [search-term or url]',
            iconClass: 'kg-card-type-unsplash',
            matches: ['unsplash'],
            type: 'card',
            replaceArg: 'image',
            params: ['searchTerm'],
            payload: {
                imageSelector: 'unsplash'
            },
            isAvailable: 'settings.unsplash'
        },
        {
            label: 'Vimeo',
            icon: 'koenig/kg-card-type-vimeo',
            desc: '/vimeo [video url]',
            matches: ['vimeo'],
            type: 'card',
            replaceArg: 'embed',
            params: ['url']
        },
        {
            label: 'CodePen',
            icon: 'koenig/kg-card-type-codepen',
            desc: '/codepen [pen url]',
            iconClass: 'kg-card-type-codepen',
            matches: ['codepen'],
            type: 'card',
            replaceArg: 'embed',
            params: ['url']
        },
        {
            label: 'Spotify',
            icon: 'koenig/kg-card-type-spotify',
            desc: '/spotify [track or playlist url]',
            matches: ['spotify'],
            type: 'card',
            replaceArg: 'embed',
            params: ['url']
        },
        {
            label: 'SoundCloud',
            icon: 'koenig/kg-card-type-soundcloud',
            desc: '/soundcloud [track or playlist url]',
            matches: ['soundcloud'],
            type: 'card',
            replaceArg: 'embed',
            params: ['url']
        },
        {
            label: 'NFT',
            icon: 'koenig/kg-card-type-nft',
            desc: '/nft [opensea url]',
            iconClass: 'kg-card-type-native',
            matches: ['nft', 'opensea'],
            type: 'card',
            replaceArg: 'embed',
            params: ['url'],
            isAvailable: 'feature.nftCard'
        },
        {
            label: 'Other...',
            icon: 'koenig/kg-card-type-other',
            desc: '/embed [url]',
            iconClass: 'kg-card-type-native',
            matches: ['embed'],
            type: 'card',
            replaceArg: 'embed',
            params: ['url']
        }]
    }
];
<|endoftext|>


<commit_before>/* -*- Mode: js2; tab-width: 4; indent-tabs-mode: nil; -*-
 * vim: set ts=4 sw=4 et tw=99 ft=js:
 */
// we split up assignment operators +=/-=/etc into their
// component operator + assignment so we can mark lhs as
// setLocal/setGlobal/etc, and rhs getLocal/getGlobal/etc

import { TransformPass } from '../node-visitor';
import { startGenerator } from '../echo-util';
import * as b from '../ast-builder';
import { reportError } from '../errors';

let updateGen = startGenerator();
let freshUpdate = () => `%update_${updateGen()}`;

export class DesugarUpdateAssignments extends TransformPass {

    constructor (options) {
        super(options);
        this.debug = true;
        this.updateGen = startGenerator();
    }

    visitProgram (n) {
        n.prepends = [];
        n = super.visitProgram(n, n);
        if (n.prepends.length > 0)
            n.body = n.prepends.concat(n.body);
        return n;
    }

    visitBlock (n) {
        n.prepends = [];
        n = super.visitBlock(n, n);
        if (n.prepends.length > 0)
            n.body = n.prepends.concat(n.body);
        return n;
    }

    visitAssignmentExpression (n, parentBlock) {
        n = super.visitAssignmentExpression(n, parentBlock);

        // we only care about the $= operators, where $ = *,/,-,+,%,etc
        if (n.operator.length === 1)
            return n;

        if (n.left.type === b.Identifier) {
            // for identifiers we just expand a += b to a = a + b
            n.right = b.binaryExpression(n.left, n.operator[0], n.right);
            n.operator = '=';
            return n;
        }

        if (n.left.type === b.MemberExpression) {
            let complex_exp = (n) => {
                if (!n)                    return false;
                if (n.type === b.Literal)    return false;
                if (n.type === b.Identifier) return false;
                return true;
            };

            let prepend_update = () => {
                let update_id = b.identifier(freshUpdate());
                parentBlock.prepends.unshift(b.letDeclaration(update_id, b.undefinedLit()));
                return update_id;
            };

            let object_exp = n.left.object;
            let prop_exp = n.left.property;

            let expressions = [];

            if (complex_exp(object_exp)) {
                let update_id = prepend_update();
                expressions.push(b.assignmentExpression(update_id, '=', object_exp));
                n.left.object = update_id;
            }

            if (complex_exp(prop_exp)) {
                let update_id = prepend_update();
                expressions.push(b.assignmentExpression(update_id, '=', prop_exp));
                n.left.property = update_id;
            }

            n.right = b.binaryExpression(b.memberExpression(n.left.object, n.left.property, n.computed), n.operator[0], n.right);
            n.operator = "=";

            if (expressions.length !== 0) {
                expressions.push(n);
                return b.sequenceExpression(expressions);
            }

            return n;
        }

        reportError(Error, `unexpected expression type ${n.left.type} in update assign expression.`, this.filename, n.left.loc);
    }
}
<commit_msg>fix update assignments of the form `a[0] *= 5;`.<commit_after>/* -*- Mode: js2; tab-width: 4; indent-tabs-mode: nil; -*-
 * vim: set ts=4 sw=4 et tw=99 ft=js:
 */
// we split up assignment operators +=/-=/etc into their
// component operator + assignment so we can mark lhs as
// setLocal/setGlobal/etc, and rhs getLocal/getGlobal/etc

import { TransformPass } from '../node-visitor';
import { startGenerator } from '../echo-util';
import * as b from '../ast-builder';
import { reportError } from '../errors';

let updateGen = startGenerator();
let freshUpdate = () => `%update_${updateGen()}`;

export class DesugarUpdateAssignments extends TransformPass {

    constructor (options) {
        super(options);
        this.debug = true;
        this.updateGen = startGenerator();
    }

    visitProgram (n) {
        n.prepends = [];
        n = super.visitProgram(n, n);
        if (n.prepends.length > 0)
            n.body = n.prepends.concat(n.body);
        return n;
    }

    visitBlock (n) {
        n.prepends = [];
        n = super.visitBlock(n, n);
        if (n.prepends.length > 0)
            n.body = n.prepends.concat(n.body);
        return n;
    }

    visitAssignmentExpression (n, parentBlock) {
        n = super.visitAssignmentExpression(n, parentBlock);

        // we only care about the $= operators, where $ = *,/,-,+,%,etc
        if (n.operator.length === 1)
            return n;

        if (n.left.type === b.Identifier) {
            // for identifiers we just expand a += b to a = a + b
            n.right = b.binaryExpression(n.left, n.operator[0], n.right);
            n.operator = '=';
            return n;
        }

        if (n.left.type === b.MemberExpression) {
            let complex_exp = (n) => {
                if (!n)                    return false;
                if (n.type === b.Literal)    return false;
                if (n.type === b.Identifier) return false;
                return true;
            };

            let prepend_update = () => {
                let update_id = b.identifier(freshUpdate());
                parentBlock.prepends.unshift(b.letDeclaration(update_id, b.undefinedLit()));
                return update_id;
            };

            let object_exp = n.left.object;
            let prop_exp = n.left.property;

            let expressions = [];

            if (complex_exp(object_exp)) {
                let update_id = prepend_update();
                expressions.push(b.assignmentExpression(update_id, '=', object_exp));
                n.left.object = update_id;
            }

            if (complex_exp(prop_exp)) {
                let update_id = prepend_update();
                expressions.push(b.assignmentExpression(update_id, '=', prop_exp));
                n.left.property = update_id;
            }

            n.right = b.binaryExpression(b.memberExpression(n.left.object, n.left.property, n.left.computed), n.operator[0], n.right);
            n.operator = "=";

            if (expressions.length !== 0) {
                expressions.push(n);
                return b.sequenceExpression(expressions);
            }

            return n;
        }

        reportError(Error, `unexpected expression type ${n.left.type} in update assign expression.`, this.filename, n.left.loc);
    }
}
<|endoftext|>


<commit_before>var eventTypes = require('../uuids').ballEventNotification;

function activateNotificationEvents(prop, characteristic, service) {
  characteristic.notify(true, function(error) {
    if (error) { console.log('ERROR: ' + error); }
  });

  characteristic.on('read', function(data) {
    var type = data.toString('hex', 0, 1);

    switch (type) {
      case eventTypes.catch:
        emitEvent('catch', prop, service); break;
      case eventTypes.throw:
        emitEvent('throw', prop, service); break;
      case eventTypes.drop:
        emitEvent('drop', prop, service); break;
      case eventTypes.idle:
        emitEvent('idle', prop, service); break;
    }
  });
}

function emitEvent(type, prop, service) {
  prop.emit(type);
  service.emit(type, prop);
}

module.exports = activateNotificationEvents;<commit_msg>Pass prop object to event handlers of props. Mirrors API of service event handlers.<commit_after>var eventTypes = require('../uuids').ballEventNotification;

function activateNotificationEvents(prop, characteristic, service) {
  characteristic.notify(true, function(error) {
    if (error) { console.log('ERROR: ' + error); }
  });

  characteristic.on('read', function(data) {
    var type = data.toString('hex', 0, 1);

    switch (type) {
      case eventTypes.catch:
        emitEvent('catch', prop, service); break;
      case eventTypes.throw:
        emitEvent('throw', prop, service); break;
      case eventTypes.drop:
        emitEvent('drop', prop, service); break;
      case eventTypes.idle:
        emitEvent('idle', prop, service); break;
    }
  });
}

function emitEvent(type, prop, service) {
  prop.emit(type, prop);
  service.emit(type, prop);
}

module.exports = activateNotificationEvents;<|endoftext|>


<commit_before>import React from 'react';
import styled from 'styled-components';
import UIState from 'ui/states/UIState';
import RequestLogState from 'ui/states/RequestLogState';
import MocksState from 'ui/states/MocksState';

const HorizontalHandle = styled.div`
  width: 100%;
  height: 4px;
  cursor: ns-resize;
  background-color: transparent;
`;

const VerticalHandle = styled.div`
  position: absolute;
  width: 3px;
  top: 0;
  bottom: -100vh;
  right: 0;
  cursor: ew-resize;
  background-color: transparent;
  border-right: ${(props) => props.theme.darkBorder};
  z-index: 2147483645;
`;

class ResizeHandle extends React.Component {

  initResize = (event) => {
    if (event.button !== 0) {
      // Disable resizing on right click
      return;
    }

    if (this.props.value === 'editorHeight') {
      this.start = event.clientY;
      this.initialSize = UIState.editorHeight;
    }

    if (this.props.value === 'mocksSidebarWidth') {
      this.start = event.clientX;
      this.initialSize = MocksState.sidebarWidth;
    }

    if (this.props.value.startsWith('logColumn')) {
      this.start = event.clientX;
      this.initialSize = RequestLogState.columns[this.props.value.replace('logColumns.', '')];
    }

    document.addEventListener('mousemove', this.resize);
    document.addEventListener('mouseup', this.stopResize);
  };

  resize = (event) => {
    event.stopPropagation();
    event.preventDefault();

    if (this.props.value === 'editorHeight') {
      const delta = this.start - event.clientY;

      UIState.setEditorHeight(this.initialSize + delta);
    }

    if (this.props.value === 'mocksSidebarWidth') {
      const delta = event.clientX - this.start;

      MocksState.resizeSidebar(this.initialSize + delta);
    }

    if (this.props.value.startsWith('logColumn')) {
      const columnName = this.props.value.split('.')[1];
      const delta = event.clientX - this.start;

      RequestLogState.resizeColumn(columnName, this.initialSize + delta);
    }
  };

  stopResize = () => {
    document.removeEventListener('mousemove', this.resize, false);
    document.removeEventListener('mouseup', this.stopResize, false);
  };

  render() {
    let Handle;

    if (this.props.value === 'editorHeight') {
      Handle = HorizontalHandle;
    }

    if (this.props.value === 'mocksSidebarWidth') {
      Handle = VerticalHandle;
    }

    if (this.props.value.startsWith('logColumn')) {
      Handle = VerticalHandle;
    }

    return (
      <Handle onMouseDown={ this.initResize } data-resize-handle/>
    );
  }
}

export default ResizeHandle;<commit_msg>fix iframe catching resizing events by adding overlay to the document<commit_after>import React from 'react';
import styled from 'styled-components';
import UIState from 'ui/states/UIState';
import RequestLogState from 'ui/states/RequestLogState';
import MocksState from 'ui/states/MocksState';

const HorizontalHandle = styled.div`
  width: 100%;
  height: 4px;
  cursor: ns-resize;
  background-color: transparent;
`;

const VerticalHandle = styled.div`
  position: absolute;
  width: 3px;
  top: 0;
  bottom: -100vh;
  right: 0;
  cursor: ew-resize;
  background-color: transparent;
  border-right: ${(props) => props.theme.darkBorder};
  z-index: 2147483645;
`;

class ResizeHandle extends React.Component {

  addOverlay = () => {
    this.overlay = document.createElement('div');
    this.overlay.style.position = 'fixed';
    this.overlay.style.top = '0';
    this.overlay.style.bottom = '0';
    this.overlay.style.left = '0';
    this.overlay.style.right = '0';
    this.overlay.style.zIndex = '2147483647';

    document.body.appendChild(this.overlay);
  };

  removeOverlay = () => {
    document.body.removeChild(this.overlay);
    this.overlay = null;
  };

  initResize = (event) => {
    if (event.button !== 0) {
      // Disable resizing on right click
      return;
    }

    if (this.props.value === 'editorHeight') {
      this.start = event.clientY;
      this.initialSize = UIState.editorHeight;
    }

    if (this.props.value === 'mocksSidebarWidth') {
      this.start = event.clientX;
      this.initialSize = MocksState.sidebarWidth;
    }

    if (this.props.value.startsWith('logColumn')) {
      this.start = event.clientX;
      this.initialSize = RequestLogState.columns[this.props.value.replace('logColumns.', '')];
    }

    this.addOverlay();
    document.addEventListener('mousemove', this.resize);
    document.addEventListener('mouseup', this.stopResize);
  };

  resize = (event) => {
    event.stopPropagation();
    event.preventDefault();

    if (this.props.value === 'editorHeight') {
      const delta = this.start - event.clientY;

      UIState.setEditorHeight(this.initialSize + delta);
    }

    if (this.props.value === 'mocksSidebarWidth') {
      const delta = event.clientX - this.start;

      MocksState.resizeSidebar(this.initialSize + delta);
    }

    if (this.props.value.startsWith('logColumn')) {
      const columnName = this.props.value.split('.')[1];
      const delta = event.clientX - this.start;

      RequestLogState.resizeColumn(columnName, this.initialSize + delta);
    }
  };

  stopResize = () => {
    this.removeOverlay();
    document.removeEventListener('mousemove', this.resize, false);
    document.removeEventListener('mouseup', this.stopResize, false);
  };

  render() {
    let Handle;

    if (this.props.value === 'editorHeight') {
      Handle = HorizontalHandle;
    }

    if (this.props.value === 'mocksSidebarWidth') {
      Handle = VerticalHandle;
    }

    if (this.props.value.startsWith('logColumn')) {
      Handle = VerticalHandle;
    }

    return (
      <Handle onMouseDown={ this.initResize } data-resize-handle/>
    );
  }
}

export default ResizeHandle;<|endoftext|>