<commit_before>/**
* Copyright 2012-2018, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var scatterAttrs = require('../scatter/attributes');
var colorAttrs = require('../../components/colorscale/attributes');
var scatterGlAttrs = require('../scattergl/attributes');
var cartesianIdRegex = require('../../plots/cartesian/constants').idRegex;
var templatedArray = require('../../plot_api/plot_template').templatedArray;
var extendFlat = require('../../lib/extend').extendFlat;

var scatterMarkerAttrs = scatterAttrs.marker;
var scatterMarkerLineAttrs = scatterMarkerAttrs.line;

var markerAttrs = extendFlat(colorAttrs('marker'), {
    symbol: scatterMarkerAttrs.symbol,
    size: extendFlat({}, scatterMarkerAttrs.size, {editType: 'markerSize'}),
    sizeref: scatterMarkerAttrs.sizeref,
    sizemin: scatterMarkerAttrs.sizemin,
    sizemode: scatterMarkerAttrs.sizemode,
    opacity: scatterMarkerAttrs.opacity,
    colorbar: scatterMarkerAttrs.colorbar,
    line: extendFlat({}, colorAttrs('marker.line'), {
        width: scatterMarkerLineAttrs.width,
        editType: 'calc'
    }),
    editType: 'calc'
});

markerAttrs.color.editType = markerAttrs.cmin.editType = markerAttrs.cmax.editType = 'style';

function makeAxesValObject(axLetter) {
    return {
        valType: 'info_array',
        freeLength: true,
        role: 'info',
        editType: 'calc',
        items: {
            valType: 'subplotid',
            regex: cartesianIdRegex[axLetter],
            editType: 'plot'
        },
        description: [
            'Sets the list of ' + axLetter + ' axes',
            'corresponding to dimensions of this splom trace.',
            'By default, a splom will match the first N ' + axLetter + 'axes',
            'where N is the number of input dimensions.',
            'Note that, in case where `diagonal.visible` is false and `showupperhalf`',
            'or `showlowerhalf` is false, this splom trace will generate',
            'one less x-axis and one less y-axis.',
        ].join(' ')
    };
}

module.exports = {
    dimensions: templatedArray('dimension', {
        visible: {
            valType: 'boolean',
            role: 'info',
            dflt: true,
            editType: 'calc',
            description: [
                'Determines whether or not this dimension is shown on the graph.',
                'Note that even visible false dimension contribute to the',
                'default grid generate by this splom trace.'
            ].join(' ')
        },
        label: {
            valType: 'string',
            role: 'info',
            editType: 'calc',
            description: 'Sets the label corresponding to this splom dimension.'
        },
        values: {
            valType: 'data_array',
            role: 'info',
            editType: 'calc+clearAxisTypes',
            description: 'Sets the dimension values to be plotted.'
        },

        axis: {
            type: {
                valType: 'enumerated',
                values: ['linear', 'log', 'date', 'category'],
                role: 'info',
                editType: 'calc+clearAxisTypes',
                description: [
                    'Sets the axis type for this dimension\'s generated',
                    'x and y axes.',
                    'Note that the axis `type` values set in layout take',
                    'precedence over this attribute.'
                ].join(' ')
            },

            editType: 'calc+clearAxisTypes'
        },

        // TODO should add an attribute to pin down x only vars and y only vars
        // like https://seaborn.pydata.org/generated/seaborn.pairplot.html
        // x_vars and y_vars

        // maybe more axis defaulting option e.g. `showgrid: false`

        editType: 'calc+clearAxisTypes'
    }),

    // mode: {}, (only 'markers' for now)

    text: extendFlat({}, scatterGlAttrs.text, {
        description: [
            'Sets text elements associated with each (x,y) pair to appear on hover.',
            'If a single string, the same string appears over',
            'all the data points.',
            'If an array of string, the items are mapped in order to the',
            'this trace\'s (x,y) coordinates.'
        ].join(' ')
    }),

    marker: markerAttrs,

    xaxes: makeAxesValObject('x'),
    yaxes: makeAxesValObject('y'),

    diagonal: {
        visible: {
            valType: 'boolean',
            role: 'info',
            dflt: true,
            editType: 'calc',
            description: [
                'Determines whether or not subplots on the diagonal are displayed.'
            ].join(' ')
        },

        // type: 'scattergl' | 'histogram' | 'box' | 'violin'
        // ...
        // more options

        editType: 'calc'
    },

    showupperhalf: {
        valType: 'boolean',
        role: 'info',
        dflt: true,
        editType: 'calc',
        description: [
            'Determines whether or not subplots on the upper half',
            'from the diagonal are displayed.'
        ].join(' ')
    },
    showlowerhalf: {
        valType: 'boolean',
        role: 'info',
        dflt: true,
        editType: 'calc',
        description: [
            'Determines whether or not subplots on the lower half',
            'from the diagonal are displayed.'
        ].join(' ')
    },

    selected: {
        marker: scatterGlAttrs.selected.marker,
        editType: 'calc'
    },
    unselected: {
        marker: scatterGlAttrs.unselected.marker,
        editType: 'calc'
    },

    opacity: scatterGlAttrs.opacity
};
<commit_msg>don't bother optimizing splom 'marker.line' edits<commit_after>/**
* Copyright 2012-2018, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var scatterAttrs = require('../scatter/attributes');
var colorAttrs = require('../../components/colorscale/attributes');
var scatterGlAttrs = require('../scattergl/attributes');
var cartesianIdRegex = require('../../plots/cartesian/constants').idRegex;
var templatedArray = require('../../plot_api/plot_template').templatedArray;
var extendFlat = require('../../lib/extend').extendFlat;

var scatterMarkerAttrs = scatterAttrs.marker;
var scatterMarkerLineAttrs = scatterMarkerAttrs.line;

var markerLineAttrs = extendFlat(colorAttrs('marker.line', {editTypeOverride: 'calc'}), {
    width: extendFlat({}, scatterMarkerLineAttrs.width, {editType: 'calc'}),
    editType: 'calc'
});

var markerAttrs = extendFlat(colorAttrs('marker'), {
    symbol: scatterMarkerAttrs.symbol,
    size: extendFlat({}, scatterMarkerAttrs.size, {editType: 'markerSize'}),
    sizeref: scatterMarkerAttrs.sizeref,
    sizemin: scatterMarkerAttrs.sizemin,
    sizemode: scatterMarkerAttrs.sizemode,
    opacity: scatterMarkerAttrs.opacity,
    colorbar: scatterMarkerAttrs.colorbar,
    line: markerLineAttrs,
    editType: 'calc'
});

markerAttrs.color.editType = markerAttrs.cmin.editType = markerAttrs.cmax.editType = 'style';

function makeAxesValObject(axLetter) {
    return {
        valType: 'info_array',
        freeLength: true,
        role: 'info',
        editType: 'calc',
        items: {
            valType: 'subplotid',
            regex: cartesianIdRegex[axLetter],
            editType: 'plot'
        },
        description: [
            'Sets the list of ' + axLetter + ' axes',
            'corresponding to dimensions of this splom trace.',
            'By default, a splom will match the first N ' + axLetter + 'axes',
            'where N is the number of input dimensions.',
            'Note that, in case where `diagonal.visible` is false and `showupperhalf`',
            'or `showlowerhalf` is false, this splom trace will generate',
            'one less x-axis and one less y-axis.',
        ].join(' ')
    };
}

module.exports = {
    dimensions: templatedArray('dimension', {
        visible: {
            valType: 'boolean',
            role: 'info',
            dflt: true,
            editType: 'calc',
            description: [
                'Determines whether or not this dimension is shown on the graph.',
                'Note that even visible false dimension contribute to the',
                'default grid generate by this splom trace.'
            ].join(' ')
        },
        label: {
            valType: 'string',
            role: 'info',
            editType: 'calc',
            description: 'Sets the label corresponding to this splom dimension.'
        },
        values: {
            valType: 'data_array',
            role: 'info',
            editType: 'calc+clearAxisTypes',
            description: 'Sets the dimension values to be plotted.'
        },

        axis: {
            type: {
                valType: 'enumerated',
                values: ['linear', 'log', 'date', 'category'],
                role: 'info',
                editType: 'calc+clearAxisTypes',
                description: [
                    'Sets the axis type for this dimension\'s generated',
                    'x and y axes.',
                    'Note that the axis `type` values set in layout take',
                    'precedence over this attribute.'
                ].join(' ')
            },

            editType: 'calc+clearAxisTypes'
        },

        // TODO should add an attribute to pin down x only vars and y only vars
        // like https://seaborn.pydata.org/generated/seaborn.pairplot.html
        // x_vars and y_vars

        // maybe more axis defaulting option e.g. `showgrid: false`

        editType: 'calc+clearAxisTypes'
    }),

    // mode: {}, (only 'markers' for now)

    text: extendFlat({}, scatterGlAttrs.text, {
        description: [
            'Sets text elements associated with each (x,y) pair to appear on hover.',
            'If a single string, the same string appears over',
            'all the data points.',
            'If an array of string, the items are mapped in order to the',
            'this trace\'s (x,y) coordinates.'
        ].join(' ')
    }),

    marker: markerAttrs,

    xaxes: makeAxesValObject('x'),
    yaxes: makeAxesValObject('y'),

    diagonal: {
        visible: {
            valType: 'boolean',
            role: 'info',
            dflt: true,
            editType: 'calc',
            description: [
                'Determines whether or not subplots on the diagonal are displayed.'
            ].join(' ')
        },

        // type: 'scattergl' | 'histogram' | 'box' | 'violin'
        // ...
        // more options

        editType: 'calc'
    },

    showupperhalf: {
        valType: 'boolean',
        role: 'info',
        dflt: true,
        editType: 'calc',
        description: [
            'Determines whether or not subplots on the upper half',
            'from the diagonal are displayed.'
        ].join(' ')
    },
    showlowerhalf: {
        valType: 'boolean',
        role: 'info',
        dflt: true,
        editType: 'calc',
        description: [
            'Determines whether or not subplots on the lower half',
            'from the diagonal are displayed.'
        ].join(' ')
    },

    selected: {
        marker: scatterGlAttrs.selected.marker,
        editType: 'calc'
    },
    unselected: {
        marker: scatterGlAttrs.unselected.marker,
        editType: 'calc'
    },

    opacity: scatterGlAttrs.opacity
};
<|endoftext|>


<commit_before>import utils from './utils'
import ThreeSixtyRenderer from './three_sixty_renderer'
import DeviceOrientationControls from './device_orientation_controls'
import MouseControls from './mouse_controls'
import {
  VideoTexture,
  LinearFilter,
  Scene,
  Object3D,
  Vector3,
  PerspectiveCamera,
  RGBFormat,
} from 'threejs360'

export class ThreeSixtyVideoViewer {
  constructor(options={}) {
    Object.assign(this, options);
    // provide defaults for this;
    let {height, width, container} = this;
    this.renderer = new ThreeSixtyRenderer({height, width, container});
    this.camera = new PerspectiveCamera(80, height / width, 0.1, 100);
    this.scene = this.createScene();
    this.scene.add(this.camera);
    this.mouseControls = new MouseControls(this.camera, this.renderer.renderer.domElement);
    this.motionControls = new DeviceOrientationControls(this.camera);
    this.createTexture();
  }

  createTexture() {
    if (this.video) {
      this._createVideoTexture(this.video)
    } else {
      this._createVideoElement((el) => this._createVideoTexture(el));
    }
  }

  setSize(size) {
    this.renderer.setSize(size);
  }

  render() {
    var loop = () => {
      this.mouseControls.update();
      this.renderer.render(this.scene, this.camera);
      requestAnimationFrame(loop);
    };
    loop();
  }

  _createVideoElement(cb) {
    let el = document.createElement('video');
    el.src = this.source;
    el.loop = this.loop || false;
    el.setAttribute('crossorigin', 'anonymous');
    el.autoplay = "true";
    el.addEventListener('canplaythrough', () => cb(el));
    el.addEventListener('error', () => this.onError());
  }

  _createVideoTexture(el) {
    var texture = new VideoTexture(el);
    texture.minFilter = LinearFilter;
    texture.magFilter = LinearFilter;
    texture.format = RGBFormat;
    texture.generateMipmaps = false;
    texture.needsUpdate = true;
    this.renderer.setTexture(texture);
    this.scene.getObjectByName('photo').children = [this.renderer.mesh];
    this.render();
  }

  createScene() {
    var scene = new Scene();
    var group = new Object3D();
    group.name = 'photo';
    scene.add(group);
    return scene;
  }

  onError() {
    console.log('error loading video');
  }
}
<commit_msg>add todo<commit_after>import utils from './utils'
import ThreeSixtyRenderer from './three_sixty_renderer'
import DeviceOrientationControls from './device_orientation_controls'
import MouseControls from './mouse_controls'
import {
  VideoTexture,
  LinearFilter,
  Scene,
  Object3D,
  Vector3,
  PerspectiveCamera,
  RGBFormat,
} from 'threejs360'

export class ThreeSixtyVideoViewer {
  constructor(options={}) {
    //TODO: provide defaults for this;
    Object.assign(this, options);
    let {height, width, container} = this;
    this.renderer = new ThreeSixtyRenderer({height, width, container});
    this.camera = new PerspectiveCamera(80, height / width, 0.1, 100);
    this.scene = this.createScene();
    this.scene.add(this.camera);
    this.mouseControls = new MouseControls(this.camera, this.renderer.renderer.domElement);
    this.motionControls = new DeviceOrientationControls(this.camera);
    this.createTexture();
  }

  createTexture() {
    if (this.video) {
      this._createVideoTexture(this.video)
    } else {
      this._createVideoElement((el) => this._createVideoTexture(el));
    }
  }

  setSize(size) {
    this.renderer.setSize(size);
  }

  render() {
    var loop = () => {
      this.mouseControls.update();
      this.renderer.render(this.scene, this.camera);
      requestAnimationFrame(loop);
    };
    loop();
  }

  _createVideoElement(cb) {
    let el = document.createElement('video');
    el.src = this.source;
    el.loop = this.loop || false;
    el.setAttribute('crossorigin', 'anonymous');
    el.autoplay = "true";
    el.addEventListener('canplaythrough', () => cb(el));
    el.addEventListener('error', () => this.onError());
  }

  _createVideoTexture(el) {
    var texture = new VideoTexture(el);
    texture.minFilter = LinearFilter;
    texture.magFilter = LinearFilter;
    texture.format = RGBFormat;
    texture.generateMipmaps = false;
    texture.needsUpdate = true;
    this.renderer.setTexture(texture);
    this.scene.getObjectByName('photo').children = [this.renderer.mesh];
    this.render();
  }

  createScene() {
    var scene = new Scene();
    var group = new Object3D();
    group.name = 'photo';
    scene.add(group);
    return scene;
  }

  onError() {
    console.log('error loading video');
  }
}
<|endoftext|>


<commit_before>/**
* Copyright 2012-2017, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var annAttrs = require('../../components/annotations/attributes');
var extendFlat = require('../../lib/extend').extendFlat;

module.exports = {

    domain: {
        x: {
            valType: 'info_array',
            role: 'info',
            items: [
                {valType: 'number', min: 0, max: 1},
                {valType: 'number', min: 0, max: 1}
            ],
            dflt: [0, 1],
            description: [
                'Sets the horizontal domain of this `table` trace',
                '(in plot fraction).'
            ].join(' ')
        },
        y: {
            valType: 'info_array',
            role: 'info',
            items: [
                {valType: 'number', min: 0, max: 1},
                {valType: 'number', min: 0, max: 1}
            ],
            dflt: [0, 1],
            description: [
                'Sets the vertical domain of this `table` trace',
                '(in plot fraction).'
            ].join(' ')
        }
    },

    columnwidth: {
        valType: 'number',
        arrayOk: true,
        dflt: null,
        role: 'style',
        description: 'The width of cells.'
    },

    columnorder: {
        valType: 'data_array',
        role: 'info',
        description: [
            'Specifies the rendered order of the data columns; for example, a value `2` at position `0`',
            'means that column index `0` in the data will be rendered as the',
            'third column, as columns have an index base of zero.'
        ].join(' ')
    },

    header: {

        values: {
            valType: 'data_array',
            role: 'info',
            dflt: [],
            description: [
                'Dimension values. `values[n]` represents the value of the `n`th point in the dataset,',
                'therefore the `values` vector for all dimensions must be the same (longer vectors',
                'will be truncated). Each value must be a finite number.'
            ].join(' ')
        },

        format: {
            valType: 'data_array',
            role: 'info',
            dflt: [],
            description: [
                'Sets the cell value formatting rule using d3 formatting mini-language',
                'which is similar to those of Python. See',
                'https://github.com/d3/d3-format/blob/master/README.md#locale_format'
            ].join(' ')
        },

        prefix: {
            valType: 'string',
            arrayOk: true,
            dflt: null,
            role: 'style',
            description: 'Prefix for cell values.'
        },

        suffix: {
            valType: 'string',
            arrayOk: true,
            dflt: null,
            role: 'style',
            description: 'Suffix for cell values.'
        },

        height: {
            valType: 'number',
            dflt: 28,
            role: 'style',
            description: 'The height of cells.'
        },

        align: extendFlat({}, annAttrs.align, {arrayOk: true}),
        valign: extendFlat({}, annAttrs.valign, {arrayOk: true}),

        line: {
            width: {
                valType: 'number',
                arrayOk: true,
                role: 'style'
            },
            color: {
                valType: 'color',
                arrayOk: true,
                role: 'style'
            }
        },

        fill: {
            color: {
                valType: 'color',
                arrayOk: true,
                role: 'style',
                description: [
                    'Sets the cell fill color. It accepts either a specific color',
                    ' or an array of colors.'
                ].join('')
            }
        },

        font: {
            family: {
                valType: 'string',
                arrayOk: true,
                role: 'style',
                noBlank: true,
                strict: true,
                description: [
                    'HTML font family - the typeface that will be applied by the web browser.',
                    'The web browser will only be able to apply a font if it is available on the system',
                    'which it operates. Provide multiple font families, separated by commas, to indicate',
                    'the preference in which to apply fonts if they aren\'t available on the system.',
                    'The plotly service (at https://plot.ly or on-premise) generates images on a server,',
                    'where only a select number of',
                    'fonts are installed and supported.',
                    'These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*,',
                    '*Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*,',
                    '*PT Sans Narrow*, *Raleway*, *Times New Roman*.'
                ].join(' ')
            },
            size: {
                valType: 'number',
                arrayOk: true,
                role: 'style'
            },
            color: {
                valType: 'color',
                arrayOk: true,
                role: 'style'
            }
        }
    },

    cells: {

        values: {
            valType: 'data_array',
            role: 'info',
            dflt: [],
            description: [
                'Dimension values. `values[n]` represents the value of the `n`th point in the dataset,',
                'therefore the `values` vector for all dimensions must be the same (longer vectors',
                'will be truncated). Each value must be a finite number.'
            ].join(' ')
        },

        format: {
            valType: 'data_array',
            role: 'info',
            dflt: [],
            description: [
                'Sets the cell value formatting rule using d3 formatting mini-language',
                'which is similar to those of Python. See',
                'https://github.com/d3/d3-format/blob/master/README.md#locale_format'
            ].join(' ')
        },

        prefix: {
            valType: 'string',
            arrayOk: true,
            dflt: null,
            role: 'style',
            description: 'Prefix for cell values.'
        },

        suffix: {
            valType: 'string',
            arrayOk: true,
            dflt: null,
            role: 'style',
            description: 'Suffix for cell values.'
        },

        height: {
            valType: 'number',
            dflt: 20,
            role: 'style',
            description: 'The height of cells.'
        },

        align: extendFlat({}, annAttrs.align, {arrayOk: true}),
        valign: extendFlat({}, annAttrs.valign, {arrayOk: true}),

        line: {
            width: {
                valType: 'number',
                arrayOk: true,
                role: 'style'
            },
            color: {
                valType: 'color',
                arrayOk: true,
                role: 'style'
            }
        },

        fill: {
            color: {
                valType: 'color',
                arrayOk: true,
                role: 'style',
                description: [
                    'Sets the cell fill color. It accepts either a specific color',
                    ' or an array of colors.'
                ].join('')
            }
        },

        font: {
            family: {
                valType: 'string',
                arrayOk: true,
                role: 'style',
                noBlank: true,
                strict: true,
                description: [
                    'HTML font family - the typeface that will be applied by the web browser.',
                    'The web browser will only be able to apply a font if it is available on the system',
                    'which it operates. Provide multiple font families, separated by commas, to indicate',
                    'the preference in which to apply fonts if they aren\'t available on the system.',
                    'The plotly service (at https://plot.ly or on-premise) generates images on a server,',
                    'where only a select number of',
                    'fonts are installed and supported.',
                    'These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*,',
                    '*Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*,',
                    '*PT Sans Narrow*, *Raleway*, *Times New Roman*.'
                ].join(' ')
            },
            size: {
                valType: 'number',
                arrayOk: true,
                role: 'style'
            },
            color: {
                valType: 'color',
                arrayOk: true,
                role: 'style'
            }
        }
    }
};
<commit_msg>doc change<commit_after>/**
* Copyright 2012-2017, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var annAttrs = require('../../components/annotations/attributes');
var extendFlat = require('../../lib/extend').extendFlat;

module.exports = {

    domain: {
        x: {
            valType: 'info_array',
            role: 'info',
            items: [
                {valType: 'number', min: 0, max: 1},
                {valType: 'number', min: 0, max: 1}
            ],
            dflt: [0, 1],
            description: [
                'Sets the horizontal domain of this `table` trace',
                '(in plot fraction).'
            ].join(' ')
        },
        y: {
            valType: 'info_array',
            role: 'info',
            items: [
                {valType: 'number', min: 0, max: 1},
                {valType: 'number', min: 0, max: 1}
            ],
            dflt: [0, 1],
            description: [
                'Sets the vertical domain of this `table` trace',
                '(in plot fraction).'
            ].join(' ')
        }
    },

    columnwidth: {
        valType: 'number',
        arrayOk: true,
        dflt: null,
        role: 'style',
        description: 'The width of cells.'
    },

    columnorder: {
        valType: 'data_array',
        role: 'info',
        description: [
            'Specifies the rendered order of the data columns; for example, a value `2` at position `0`',
            'means that column index `0` in the data will be rendered as the',
            'third column, as columns have an index base of zero.'
        ].join(' ')
    },

    header: {

        values: {
            valType: 'data_array',
            role: 'info',
            dflt: [],
            description: [
                'Header cell values. `values[m][n]` represents the value of the `n`th point in column `m`,',
                'therefore the `values[m]` vector length for all columns must be the same (longer vectors',
                'will be truncated). Each value must be a finite number or a string.'
            ].join(' ')
        },

        format: {
            valType: 'data_array',
            role: 'info',
            dflt: [],
            description: [
                'Sets the cell value formatting rule using d3 formatting mini-language',
                'which is similar to those of Python. See',
                'https://github.com/d3/d3-format/blob/master/README.md#locale_format'
            ].join(' ')
        },

        prefix: {
            valType: 'string',
            arrayOk: true,
            dflt: null,
            role: 'style',
            description: 'Prefix for cell values.'
        },

        suffix: {
            valType: 'string',
            arrayOk: true,
            dflt: null,
            role: 'style',
            description: 'Suffix for cell values.'
        },

        height: {
            valType: 'number',
            dflt: 28,
            role: 'style',
            description: 'The height of cells.'
        },

        align: extendFlat({}, annAttrs.align, {arrayOk: true}),
        valign: extendFlat({}, annAttrs.valign, {arrayOk: true}),

        line: {
            width: {
                valType: 'number',
                arrayOk: true,
                role: 'style'
            },
            color: {
                valType: 'color',
                arrayOk: true,
                role: 'style'
            }
        },

        fill: {
            color: {
                valType: 'color',
                arrayOk: true,
                role: 'style',
                description: [
                    'Sets the cell fill color. It accepts either a specific color',
                    ' or an array of colors.'
                ].join('')
            }
        },

        font: {
            family: {
                valType: 'string',
                arrayOk: true,
                role: 'style',
                noBlank: true,
                strict: true,
                description: [
                    'HTML font family - the typeface that will be applied by the web browser.',
                    'The web browser will only be able to apply a font if it is available on the system',
                    'which it operates. Provide multiple font families, separated by commas, to indicate',
                    'the preference in which to apply fonts if they aren\'t available on the system.',
                    'The plotly service (at https://plot.ly or on-premise) generates images on a server,',
                    'where only a select number of',
                    'fonts are installed and supported.',
                    'These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*,',
                    '*Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*,',
                    '*PT Sans Narrow*, *Raleway*, *Times New Roman*.'
                ].join(' ')
            },
            size: {
                valType: 'number',
                arrayOk: true,
                role: 'style'
            },
            color: {
                valType: 'color',
                arrayOk: true,
                role: 'style'
            }
        }
    },

    cells: {

        values: {
            valType: 'data_array',
            role: 'info',
            dflt: [],
            description: [
                'Cell values. `values[m][n]` represents the value of the `n`th point in column `m`,',
                'therefore the `values[m]` vector length for all columns must be the same (longer vectors',
                'will be truncated). Each value must be a finite number or a string.'
            ].join(' ')
        },

        format: {
            valType: 'data_array',
            role: 'info',
            dflt: [],
            description: [
                'Sets the cell value formatting rule using d3 formatting mini-language',
                'which is similar to those of Python. See',
                'https://github.com/d3/d3-format/blob/master/README.md#locale_format'
            ].join(' ')
        },

        prefix: {
            valType: 'string',
            arrayOk: true,
            dflt: null,
            role: 'style',
            description: 'Prefix for cell values.'
        },

        suffix: {
            valType: 'string',
            arrayOk: true,
            dflt: null,
            role: 'style',
            description: 'Suffix for cell values.'
        },

        height: {
            valType: 'number',
            dflt: 20,
            role: 'style',
            description: 'The height of cells.'
        },

        align: extendFlat({}, annAttrs.align, {arrayOk: true}),
        valign: extendFlat({}, annAttrs.valign, {arrayOk: true}),

        line: {
            width: {
                valType: 'number',
                arrayOk: true,
                role: 'style'
            },
            color: {
                valType: 'color',
                arrayOk: true,
                role: 'style'
            }
        },

        fill: {
            color: {
                valType: 'color',
                arrayOk: true,
                role: 'style',
                description: [
                    'Sets the cell fill color. It accepts either a specific color',
                    ' or an array of colors.'
                ].join('')
            }
        },

        font: {
            family: {
                valType: 'string',
                arrayOk: true,
                role: 'style',
                noBlank: true,
                strict: true,
                description: [
                    'HTML font family - the typeface that will be applied by the web browser.',
                    'The web browser will only be able to apply a font if it is available on the system',
                    'which it operates. Provide multiple font families, separated by commas, to indicate',
                    'the preference in which to apply fonts if they aren\'t available on the system.',
                    'The plotly service (at https://plot.ly or on-premise) generates images on a server,',
                    'where only a select number of',
                    'fonts are installed and supported.',
                    'These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*,',
                    '*Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*,',
                    '*PT Sans Narrow*, *Raleway*, *Times New Roman*.'
                ].join(' ')
            },
            size: {
                valType: 'number',
                arrayOk: true,
                role: 'style'
            },
            color: {
                valType: 'color',
                arrayOk: true,
                role: 'style'
            }
        }
    }
};
<|endoftext|>


<commit_before>import utils from './utils'
import ThreeSixtyRenderer from './three_sixty_renderer'
import CameraControls from './camera_controls'
import {
    VideoTexture,
    LinearFilter,
    Scene,
    Object3D,
    Vector3,
    PerspectiveCamera,
    RGBFormat,
} from 'threejs360'

export class ThreeSixtyVideoViewer {
  constructor(options={}) {
    Object.assign(this, options);
    // provide defaults for this;
    let {height, width, container} = this;
    this.renderer = new ThreeSixtyRenderer({height, width, container});
    this.camera = new PerspectiveCamera(80, height / width, 0.1, 100);
    this.scene = this.createScene();
    this.scene.add(this.camera);
    this.controls = new CameraControls(this.camera, this.renderer.renderer.domElement);
    this.createVideoElement(this.createTexture.bind(this));
  }

  render() {
      var loop = () => {
          this.controls.update();
          this.renderer.render(this.scene, this.camera);
          requestAnimationFrame(loop);
      };
      loop();
  }

  createVideoElement(cb) {
      let el = document.createElement('video');
      this.el = el;
      el.src = this.source;
      el.loop = this.loop || false;
      el.setAttribute('crossorigin', 'anonymous');
      el.addEventListener('canplaythrough', () => cb(el));
      el.addEventListener('error', () => this.onError());
  }

  createTexture(el) {
    var texture = new VideoTexture(el);
    texture.minFilter = LinearFilter;
    texture.magFilter = LinearFilter;
    texture.format = RGBFormat;
    texture.generateMipmaps = false;
    texture.needsUpdate = true;
    this.renderer.setTexture(texture);
    this.scene.getObjectByName('photo').children = [this.renderer.mesh];
    this.render();
  }

  createScene() {
    var scene = new Scene();
    var group = new Object3D();
    group.name = 'photo';
    scene.add(group);
    return scene;
  }

  onError(err) {
      console.log('error loading video');
      console.log(err);
  }
}
<commit_msg>keep texture creation agnostic<commit_after>import utils from './utils'
import ThreeSixtyRenderer from './three_sixty_renderer'
import CameraControls from './camera_controls'
import {
  VideoTexture,
  LinearFilter,
  Scene,
  Object3D,
  Vector3,
  PerspectiveCamera,
  RGBFormat,
} from 'threejs360'

export class ThreeSixtyVideoViewer {
  constructor(options={}) {
    Object.assign(this, options);
    // provide defaults for this;
    let {height, width, container} = this;
    this.renderer = new ThreeSixtyRenderer({height, width, container});
    this.camera = new PerspectiveCamera(80, height / width, 0.1, 100);
    this.scene = this.createScene();
    this.scene.add(this.camera);
    this.controls = new CameraControls(this.camera, this.renderer.renderer.domElement);
    this.createTexture();
  }

  createTexture() {
    this._createVideoElement((el) => this._createVideoTexture(el));
  }

  render() {
    var loop = () => {
      this.controls.update();
      this.renderer.render(this.scene, this.camera);
      requestAnimationFrame(loop);
    };
    loop();
  }

  _createVideoElement(cb) {
    let el = document.createElement('video');
    el.src = this.source;
    el.loop = this.loop || false;
    el.setAttribute('crossorigin', 'anonymous');
    el.autoplay = "true";
    el.addEventListener('canplaythrough', () => cb(el));
    el.addEventListener('error', () => this.onError());
  }

  _createVideoTexture(el) {
    var texture = new VideoTexture(el);
    texture.minFilter = LinearFilter;
    texture.magFilter = LinearFilter;
    texture.format = RGBFormat;
    texture.generateMipmaps = false;
    texture.needsUpdate = true;
    this.renderer.setTexture(texture);
    this.scene.getObjectByName('photo').children = [this.renderer.mesh];
    this.render();
  }

  createScene() {
    var scene = new Scene();
    var group = new Object3D();
    group.name = 'photo';
    scene.add(group);
    return scene;
  }

  onError() {
    console.log('error loading video');
  }
}
<|endoftext|>


<commit_before>const { Command } = require('discord-akairo');
const Logger = require('../../../util/Logger');

function exec(message, args) {
    if (!args.id) {
        Logger.warn('No message ID provided to see edits.');
        return message.delete();
    }

    const quotee = args.channel.messages.get(args.id);

    if (!quotee) {
        Logger.warn('Your message ID was invalid or the message is not cached.');
        return message.delete();
    }

    const color = this.client.color(message);
    const embed = this.client.util.embed()
    .setColor(color)
    .setAuthor(`${quotee.author.username}#${quotee.author.discriminator}`, quotee.author.displayAvatarURL)
    .setFooter(`${quotee.id} | Edit History`);

    for (const [i, edit] of quotee.edits.entries()) {
        embed.addField(i === 0 ? 'Latest' : i === quotee.edits.length - 1 ? 'Original' : `Edit ${quotee.edits.length - i - 1}`, edit.content);
    }

    return message.edit(args.text, { embed });
}

module.exports = new Command('edits', exec, {
    aliases: ['edits'],
    args: [
        {
            id: 'id'
        },
        {
            id: 'text',
            match: 'rest'
        },
        {
            id: 'channel',
            type: function type(word) {
                if (!word) return null;
                const channel = this.client.channels.get(word);
                if (!channel || channel.type === 'voice') return null;
                return channel;
            },
            match: 'prefix',
            prefix: 'channel:',
            default: m => m.channel
        }
    ],
    clientPermissions: ['EMBED_LINKS'],
    category: 'info'
});
<commit_msg>Delete edits.js<commit_after><|endoftext|>


<commit_before>const { Command } = require('discord-akairo');

function exec(message, args){
    if (!args.id){
        this.client.logger.log(3, 'No message ID provided to quote.');
        return message.delete();
    }

    const color = this.client.color(message);

    return message.channel.fetchMessages({ around: args.id, limit: 3 }).then(messages => {
        const quotee = messages.get(args.id);

        const embed = this.client.util.embed()
        .setDescription(quotee.content || '\u200B')
        .setAuthor(`${quotee.author.username}#${quotee.author.discriminator}`, quotee.author.displayAvatarURL)
        .setFooter(quotee.id)
        .setTimestamp(quotee.createdAt)
        .setColor(color);

        if (quotee.attachments.size) embed.setThumbnail(quotee.attachments.first().url);

        return message.edit(message.content.slice(message.content.search(args.id) + args.id.length + 1), { embed });
    }).catch(err => {
        if (err.response && err.response.badRequest){
            this.client.logger.log(3, 'Your message ID was invalid.');
            return message.delete();
        }

        throw err;
    });
}

module.exports = new Command('quote', exec, {
    aliases: ['quote', 'q'],
    args: [
        {
            id: 'id'
        }
    ],
    category: 'util'
});
<commit_msg>Check if attachment is a URL in quote<commit_after>const { Command } = require('discord-akairo');
const { URL } = require('url');
const path = require('path');

function exec(message, args){
    if (!args.id){
        this.client.logger.log(3, 'No message ID provided to quote.');
        return message.delete();
    }

    const color = this.client.color(message);

    return message.channel.fetchMessages({ around: args.id, limit: 3 }).then(messages => {
        const quotee = messages.get(args.id);

        const embed = this.client.util.embed()
        .setDescription(quotee.content || '\u200B')
        .setAuthor(`${quotee.author.username}#${quotee.author.discriminator}`, quotee.author.displayAvatarURL)
        .setFooter(quotee.id)
        .setTimestamp(quotee.createdAt)
        .setColor(color);

        if (quotee.attachments.size){
            try {
                const url = new URL(quotee.attachments.first().url);
                const ext = path.extname(url.pathname);
                if (['.png', '.jpg', '.jpeg', '.gif', '.webp'].includes(ext)) embed.setThumbnail(quotee.attachments.first().url);
            } catch (err) {
                if (err.message !== 'Invalid URL') throw err;
            }
        }

        return message.edit(message.content.slice(message.content.search(args.id) + args.id.length + 1), { embed });
    }).catch(err => {
        if (err.response && err.response.badRequest){
            this.client.logger.log(3, 'Your message ID was invalid.');
            return message.delete();
        }

        throw err;
    });
}

module.exports = new Command('quote', exec, {
    aliases: ['quote', 'q'],
    args: [
        {
            id: 'id'
        }
    ],
    category: 'util'
});
<|endoftext|>


<commit_before>import { parseMemberCookie } from './cookieUtils';

const isProd = process.env.NODE_ENV === 'production';

export const MEMBER_ID_COOKIE = isProd ? 'MEETUP_MEMBER' : 'MEETUP_MEMBER_DEV';
export const clickCookieOptions = {
	isSecure: isProd,
	isHttpOnly: false,
	domain: `${isProd ? '' : '.dev'}.meetup.com`,
};

export const clickToClickRecord = request => click => {
	return {
		timestamp: click.timestamp,
		requestId: request.id,
		memberId: parseInt(parseMemberCookie(request.state).id, 10) || 0,
		lineage: click.lineage,
		linkText: click.linkText || '',
		coordX: click.coords[0],
		coordY: click.coords[1],
	};
};

export default function processClickTracking(request, reply) {
	const rawCookieValue = (request.state || {})['click-track'];
	// It's possible that multiple cookies with the same value were sent, e.g.
	// one value for .dev.meetup.com and another for .meetup.com - parse only the first
	const cookieValue = rawCookieValue instanceof Array ? rawCookieValue[0] : rawCookieValue;
	if (!cookieValue) {
		return;
	}

	try {
		const cookieJSON = decodeURIComponent(cookieValue);
		const { history } = JSON.parse(cookieJSON);
		history
			.map(clickToClickRecord(request))
			.forEach(clickRecord =>
				request.log(['click'], JSON.stringify(clickRecord))
			);
	} catch(err) {
		console.error(JSON.stringify({
			message: 'Could not parse click-track cookie',
			cookieValue,
			error: err.stack,
		}));
		return;
	}

	reply.unstate('click-track', clickCookieOptions);
	return;
}

<commit_msg>cleanup that var<commit_after>import { parseMemberCookie } from './cookieUtils';

const isProd = process.env.NODE_ENV === 'production';

export const clickCookieOptions = {
	isSecure: isProd,
	isHttpOnly: false,
	domain: `${isProd ? '' : '.dev'}.meetup.com`,
};

export const clickToClickRecord = request => click => {
	return {
		timestamp: click.timestamp,
		requestId: request.id,
		memberId: parseInt(parseMemberCookie(request.state).id, 10) || 0,
		lineage: click.lineage,
		linkText: click.linkText || '',
		coordX: click.coords[0],
		coordY: click.coords[1],
	};
};

export default function processClickTracking(request, reply) {
	const rawCookieValue = (request.state || {})['click-track'];
	// It's possible that multiple cookies with the same value were sent, e.g.
	// one value for .dev.meetup.com and another for .meetup.com - parse only the first
	const cookieValue = rawCookieValue instanceof Array ? rawCookieValue[0] : rawCookieValue;
	if (!cookieValue) {
		return;
	}

	try {
		const cookieJSON = decodeURIComponent(cookieValue);
		const { history } = JSON.parse(cookieJSON);
		history
			.map(clickToClickRecord(request))
			.forEach(clickRecord =>
				request.log(['click'], JSON.stringify(clickRecord))
			);
	} catch(err) {
		console.error(JSON.stringify({
			message: 'Could not parse click-track cookie',
			cookieValue,
			error: err.stack,
		}));
		return;
	}

	reply.unstate('click-track', clickCookieOptions);
	return;
}

<|endoftext|>


<commit_before>/* @flow */
/**
 *  Copyright (c) 2015, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 */

import invariant from '../jsutils/invariant';
import keyValMap from '../jsutils/keyValMap';
import { valueFromAST } from './valueFromAST';
import { TokenKind } from '../language/lexer';
import { parse } from '../language/parser';
import type { Source } from '../language/source';
import { getDirectiveValues } from '../execution/values';

import * as Kind from '../language/kinds';

import type {
  Location,
  DocumentNode,
  TypeNode,
  NamedTypeNode,
  SchemaDefinitionNode,
  TypeDefinitionNode,
  ScalarTypeDefinitionNode,
  ObjectTypeDefinitionNode,
  FieldDefinitionNode,
  InputValueDefinitionNode,
  InterfaceTypeDefinitionNode,
  UnionTypeDefinitionNode,
  EnumTypeDefinitionNode,
  EnumValueDefinitionNode,
  InputObjectTypeDefinitionNode,
  DirectiveDefinitionNode,
} from '../language/ast';

import { GraphQLSchema } from '../type/schema';

import {
  GraphQLString,
  GraphQLInt,
  GraphQLFloat,
  GraphQLBoolean,
  GraphQLID,
} from '../type/scalars';

import {
  GraphQLScalarType,
  GraphQLObjectType,
  GraphQLInterfaceType,
  GraphQLUnionType,
  GraphQLEnumType,
  GraphQLInputObjectType,
  GraphQLList,
  GraphQLNonNull,
  assertInputType,
  assertOutputType,
} from '../type/definition';

import type {
  GraphQLType,
  GraphQLNamedType,
  GraphQLInputType,
  GraphQLOutputType,
} from '../type/definition';

import {
  GraphQLDirective,
  GraphQLSkipDirective,
  GraphQLIncludeDirective,
  GraphQLDeprecatedDirective,
} from '../type/directives';

import type {
  DirectiveLocationEnum
} from '../type/directives';

import {
  __Schema,
  __Directive,
  __DirectiveLocation,
  __Type,
  __Field,
  __InputValue,
  __EnumValue,
  __TypeKind,
} from '../type/introspection';

function buildWrappedType(
  innerType: GraphQLType,
  inputTypeNode: TypeNode
): GraphQLType {
  if (inputTypeNode.kind === Kind.LIST_TYPE) {
    return new GraphQLList(buildWrappedType(innerType, inputTypeNode.type));
  }
  if (inputTypeNode.kind === Kind.NON_NULL_TYPE) {
    const wrappedType = buildWrappedType(innerType, inputTypeNode.type);
    invariant(!(wrappedType instanceof GraphQLNonNull), 'No nesting nonnull.');
    return new GraphQLNonNull(wrappedType);
  }
  return innerType;
}

function getNamedTypeNode(typeNode: TypeNode): NamedTypeNode {
  let namedType = typeNode;
  while (
    namedType.kind === Kind.LIST_TYPE ||
    namedType.kind === Kind.NON_NULL_TYPE
  ) {
    namedType = namedType.type;
  }
  return namedType;
}

/**
 * This takes the ast of a schema document produced by the parse function in
 * src/language/parser.js.
 *
 * If no schema definition is provided, then it will look for types named Query
 * and Mutation.
 *
 * Given that AST it constructs a GraphQLSchema. The resulting schema
 * has no resolve methods, so execution will use default resolvers.
 */
export function buildASTSchema(ast: DocumentNode): GraphQLSchema {
  if (!ast || ast.kind !== Kind.DOCUMENT) {
    throw new Error('Must provide a document ast.');
  }

  let schemaDef: ?SchemaDefinitionNode;

  const typeDefs: Array<TypeDefinitionNode> = [];
  const nodeMap: {[name: string]: TypeDefinitionNode} = Object.create(null);
  const directiveDefs: Array<DirectiveDefinitionNode> = [];
  for (let i = 0; i < ast.definitions.length; i++) {
    const d = ast.definitions[i];
    switch (d.kind) {
      case Kind.SCHEMA_DEFINITION:
        if (schemaDef) {
          throw new Error('Must provide only one schema definition.');
        }
        schemaDef = d;
        break;
      case Kind.SCALAR_TYPE_DEFINITION:
      case Kind.OBJECT_TYPE_DEFINITION:
      case Kind.INTERFACE_TYPE_DEFINITION:
      case Kind.ENUM_TYPE_DEFINITION:
      case Kind.UNION_TYPE_DEFINITION:
      case Kind.INPUT_OBJECT_TYPE_DEFINITION:
        const typeName = d.name.value;
        if (nodeMap[typeName]) {
          throw new Error(`Type "${typeName}" was defined more than once.`);
        }
        typeDefs.push(d);
        nodeMap[typeName] = d;
        break;
      case Kind.DIRECTIVE_DEFINITION:
        directiveDefs.push(d);
        break;
    }
  }

  let queryTypeName;
  let mutationTypeName;
  let subscriptionTypeName;
  if (schemaDef) {
    schemaDef.operationTypes.forEach(operationType => {
      const typeName = operationType.type.name.value;
      if (operationType.operation === 'query') {
        if (queryTypeName) {
          throw new Error('Must provide only one query type in schema.');
        }
        if (!nodeMap[typeName]) {
          throw new Error(
            `Specified query type "${typeName}" not found in document.`
          );
        }
        queryTypeName = typeName;
      } else if (operationType.operation === 'mutation') {
        if (mutationTypeName) {
          throw new Error('Must provide only one mutation type in schema.');
        }
        if (!nodeMap[typeName]) {
          throw new Error(
            `Specified mutation type "${typeName}" not found in document.`
          );
        }
        mutationTypeName = typeName;
      } else if (operationType.operation === 'subscription') {
        if (subscriptionTypeName) {
          throw new Error('Must provide only one subscription type in schema.');
        }
        if (!nodeMap[typeName]) {
          throw new Error(
            `Specified subscription type "${typeName}" not found in document.`
          );
        }
        subscriptionTypeName = typeName;
      }
    });
  } else {
    if (nodeMap.Query) {
      queryTypeName = 'Query';
    }
    if (nodeMap.Mutation) {
      mutationTypeName = 'Mutation';
    }
    if (nodeMap.Subscription) {
      subscriptionTypeName = 'Subscription';
    }
  }

  if (!queryTypeName) {
    throw new Error(
      'Must provide schema definition with query type or a type named Query.'
    );
  }

  const innerTypeMap = {
    String: GraphQLString,
    Int: GraphQLInt,
    Float: GraphQLFloat,
    Boolean: GraphQLBoolean,
    ID: GraphQLID,
    __Schema,
    __Directive,
    __DirectiveLocation,
    __Type,
    __Field,
    __InputValue,
    __EnumValue,
    __TypeKind,
  };

  const types = typeDefs.map(def => typeDefNamed(def.name.value));

  const directives = directiveDefs.map(getDirective);

  // If specified directives were not explicitly declared, add them.
  if (!directives.some(directive => directive.name === 'skip')) {
    directives.push(GraphQLSkipDirective);
  }

  if (!directives.some(directive => directive.name === 'include')) {
    directives.push(GraphQLIncludeDirective);
  }

  if (!directives.some(directive => directive.name === 'deprecated')) {
    directives.push(GraphQLDeprecatedDirective);
  }

  return new GraphQLSchema({
    query: getObjectType(nodeMap[queryTypeName]),
    mutation: mutationTypeName ?
      getObjectType(nodeMap[mutationTypeName]) :
      null,
    subscription: subscriptionTypeName ?
      getObjectType(nodeMap[subscriptionTypeName]) :
      null,
    types,
    directives,
    astNode: schemaDef,
  });

  function getDirective(
    directiveNode: DirectiveDefinitionNode
  ): GraphQLDirective {
    return new GraphQLDirective({
      name: directiveNode.name.value,
      description: getDescription(directiveNode),
      locations: directiveNode.locations.map(
        node => ((node.value: any): DirectiveLocationEnum)
      ),
      args: directiveNode.arguments && makeInputValues(directiveNode.arguments),
      astNode: directiveNode,
    });
  }

  function getObjectType(typeNode: TypeDefinitionNode): GraphQLObjectType {
    const type = typeDefNamed(typeNode.name.value);
    invariant(
      type instanceof GraphQLObjectType,
      'AST must provide object type.'
    );
    return (type: any);
  }

  function produceType(typeNode: TypeNode): GraphQLType {
    const typeName = getNamedTypeNode(typeNode).name.value;
    const typeDef = typeDefNamed(typeName);
    return buildWrappedType(typeDef, typeNode);
  }

  function produceInputType(typeNode: TypeNode): GraphQLInputType {
    return assertInputType(produceType(typeNode));
  }

  function produceOutputType(typeNode: TypeNode): GraphQLOutputType {
    return assertOutputType(produceType(typeNode));
  }

  function produceObjectType(typeNode: TypeNode): GraphQLObjectType {
    const type = produceType(typeNode);
    invariant(type instanceof GraphQLObjectType, 'Expected Object type.');
    return type;
  }

  function produceInterfaceType(typeNode: TypeNode): GraphQLInterfaceType {
    const type = produceType(typeNode);
    invariant(type instanceof GraphQLInterfaceType, 'Expected Interface type.');
    return type;
  }

  function typeDefNamed(typeName: string): GraphQLNamedType {
    if (innerTypeMap[typeName]) {
      return innerTypeMap[typeName];
    }

    if (!nodeMap[typeName]) {
      throw new Error(`Type "${typeName}" not found in document.`);
    }

    const innerTypeDef = makeSchemaDef(nodeMap[typeName]);
    if (!innerTypeDef) {
      throw new Error(`Nothing constructed for "${typeName}".`);
    }
    innerTypeMap[typeName] = innerTypeDef;
    return innerTypeDef;
  }

  function makeSchemaDef(def) {
    if (!def) {
      throw new Error('def must be defined');
    }
    switch (def.kind) {
      case Kind.OBJECT_TYPE_DEFINITION:
        return makeTypeDef(def);
      case Kind.INTERFACE_TYPE_DEFINITION:
        return makeInterfaceDef(def);
      case Kind.ENUM_TYPE_DEFINITION:
        return makeEnumDef(def);
      case Kind.UNION_TYPE_DEFINITION:
        return makeUnionDef(def);
      case Kind.SCALAR_TYPE_DEFINITION:
        return makeScalarDef(def);
      case Kind.INPUT_OBJECT_TYPE_DEFINITION:
        return makeInputObjectDef(def);
      default:
        throw new Error(`Type kind "${def.kind}" not supported.`);
    }
  }

  function makeTypeDef(def: ObjectTypeDefinitionNode) {
    const typeName = def.name.value;
    return new GraphQLObjectType({
      name: typeName,
      description: getDescription(def),
      fields: () => makeFieldDefMap(def),
      interfaces: () => makeImplementedInterfaces(def),
      astNode: def,
    });
  }

  function makeFieldDefMap(
    def: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode
  ) {
    return keyValMap(
      def.fields,
      field => field.name.value,
      field => ({
        type: produceOutputType(field.type),
        description: getDescription(field),
        args: makeInputValues(field.arguments),
        deprecationReason: getDeprecationReason(field),
        astNode: field,
      })
    );
  }

  function makeImplementedInterfaces(def: ObjectTypeDefinitionNode) {
    return def.interfaces &&
      def.interfaces.map(iface => produceInterfaceType(iface));
  }

  function makeInputValues(values: Array<InputValueDefinitionNode>) {
    return keyValMap(
      values,
      value => value.name.value,
      value => {
        const type = produceInputType(value.type);
        return {
          type,
          description: getDescription(value),
          defaultValue: valueFromAST(value.defaultValue, type),
          astNode: value,
        };
      }
    );
  }

  function makeInterfaceDef(def: InterfaceTypeDefinitionNode) {
    const typeName = def.name.value;
    return new GraphQLInterfaceType({
      name: typeName,
      description: getDescription(def),
      fields: () => makeFieldDefMap(def),
      astNode: def,
      resolveType: cannotExecuteSchema,
    });
  }

  function makeEnumDef(def: EnumTypeDefinitionNode) {
    const enumType = new GraphQLEnumType({
      name: def.name.value,
      description: getDescription(def),
      values: keyValMap(
        def.values,
        enumValue => enumValue.name.value,
        enumValue => ({
          description: getDescription(enumValue),
          deprecationReason: getDeprecationReason(enumValue),
          astNode: enumValue,
        })
      ),
      astNode: def,
    });

    return enumType;
  }

  function makeUnionDef(def: UnionTypeDefinitionNode) {
    return new GraphQLUnionType({
      name: def.name.value,
      description: getDescription(def),
      types: def.types.map(t => produceObjectType(t)),
      resolveType: cannotExecuteSchema,
      astNode: def,
    });
  }

  function makeScalarDef(def: ScalarTypeDefinitionNode) {
    return new GraphQLScalarType({
      name: def.name.value,
      description: getDescription(def),
      astNode: def,
      serialize: () => null,
      // Note: validation calls the parse functions to determine if a
      // literal value is correct. Returning null would cause use of custom
      // scalars to always fail validation. Returning false causes them to
      // always pass validation.
      parseValue: () => false,
      parseLiteral: () => false,
    });
  }

  function makeInputObjectDef(def: InputObjectTypeDefinitionNode) {
    return new GraphQLInputObjectType({
      name: def.name.value,
      description: getDescription(def),
      fields: () => makeInputValues(def.fields),
      astNode: def,
    });
  }
}

/**
 * Given a field or enum value node, returns the string value for the
 * deprecation reason.
 */
export function getDeprecationReason(
  node: EnumValueDefinitionNode | FieldDefinitionNode
): ?string {
  const deprecated = getDirectiveValues(GraphQLDeprecatedDirective, node);
  return deprecated && (deprecated.reason: any);
}

/**
 * Given an ast node, returns its string description based on a contiguous
 * block full-line of comments preceding it.
 */
export function getDescription(node: { loc?: Location }): ?string {
  const loc = node.loc;
  if (!loc) {
    return;
  }
  const comments = [];
  let minSpaces;
  let token = loc.startToken.prev;
  while (
    token &&
    token.kind === TokenKind.COMMENT &&
    token.next && token.prev &&
    token.line + 1 === token.next.line &&
    token.line !== token.prev.line
  ) {
    const value = String(token.value);
    const spaces = leadingSpaces(value);
    if (minSpaces === undefined || spaces < minSpaces) {
      minSpaces = spaces;
    }
    comments.push(value);
    token = token.prev;
  }
  return comments
    .reverse()
    .map(comment => comment.slice(minSpaces))
    .join('\n');
}

/**
 * A helper function to build a GraphQLSchema directly from a source
 * document.
 */
export function buildSchema(source: string | Source): GraphQLSchema {
  return buildASTSchema(parse(source));
}

// Count the number of spaces on the starting side of a string.
function leadingSpaces(str) {
  let i = 0;
  for (; i < str.length; i++) {
    if (str[i] !== ' ') {
      break;
    }
  }
  return i;
}

function cannotExecuteSchema() {
  throw new Error(
    'Generated Schema cannot use Interface or Union types for execution.'
  );
}
<commit_msg>remove dead code from buildASTSchema<commit_after>/* @flow */
/**
 *  Copyright (c) 2015, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 */

import invariant from '../jsutils/invariant';
import keyValMap from '../jsutils/keyValMap';
import { valueFromAST } from './valueFromAST';
import { TokenKind } from '../language/lexer';
import { parse } from '../language/parser';
import type { Source } from '../language/source';
import { getDirectiveValues } from '../execution/values';

import * as Kind from '../language/kinds';

import type {
  Location,
  DocumentNode,
  TypeNode,
  NamedTypeNode,
  SchemaDefinitionNode,
  TypeDefinitionNode,
  ScalarTypeDefinitionNode,
  ObjectTypeDefinitionNode,
  FieldDefinitionNode,
  InputValueDefinitionNode,
  InterfaceTypeDefinitionNode,
  UnionTypeDefinitionNode,
  EnumTypeDefinitionNode,
  EnumValueDefinitionNode,
  InputObjectTypeDefinitionNode,
  DirectiveDefinitionNode,
} from '../language/ast';

import { GraphQLSchema } from '../type/schema';

import {
  GraphQLString,
  GraphQLInt,
  GraphQLFloat,
  GraphQLBoolean,
  GraphQLID,
} from '../type/scalars';

import {
  GraphQLScalarType,
  GraphQLObjectType,
  GraphQLInterfaceType,
  GraphQLUnionType,
  GraphQLEnumType,
  GraphQLInputObjectType,
  GraphQLList,
  GraphQLNonNull,
  assertInputType,
  assertOutputType,
} from '../type/definition';

import type {
  GraphQLType,
  GraphQLNamedType,
  GraphQLInputType,
  GraphQLOutputType,
} from '../type/definition';

import {
  GraphQLDirective,
  GraphQLSkipDirective,
  GraphQLIncludeDirective,
  GraphQLDeprecatedDirective,
} from '../type/directives';

import type {
  DirectiveLocationEnum
} from '../type/directives';

import {
  __Schema,
  __Directive,
  __DirectiveLocation,
  __Type,
  __Field,
  __InputValue,
  __EnumValue,
  __TypeKind,
} from '../type/introspection';

function buildWrappedType(
  innerType: GraphQLType,
  inputTypeNode: TypeNode
): GraphQLType {
  if (inputTypeNode.kind === Kind.LIST_TYPE) {
    return new GraphQLList(buildWrappedType(innerType, inputTypeNode.type));
  }
  if (inputTypeNode.kind === Kind.NON_NULL_TYPE) {
    const wrappedType = buildWrappedType(innerType, inputTypeNode.type);
    invariant(!(wrappedType instanceof GraphQLNonNull), 'No nesting nonnull.');
    return new GraphQLNonNull(wrappedType);
  }
  return innerType;
}

function getNamedTypeNode(typeNode: TypeNode): NamedTypeNode {
  let namedType = typeNode;
  while (
    namedType.kind === Kind.LIST_TYPE ||
    namedType.kind === Kind.NON_NULL_TYPE
  ) {
    namedType = namedType.type;
  }
  return namedType;
}

/**
 * This takes the ast of a schema document produced by the parse function in
 * src/language/parser.js.
 *
 * If no schema definition is provided, then it will look for types named Query
 * and Mutation.
 *
 * Given that AST it constructs a GraphQLSchema. The resulting schema
 * has no resolve methods, so execution will use default resolvers.
 */
export function buildASTSchema(ast: DocumentNode): GraphQLSchema {
  if (!ast || ast.kind !== Kind.DOCUMENT) {
    throw new Error('Must provide a document ast.');
  }

  let schemaDef: ?SchemaDefinitionNode;

  const typeDefs: Array<TypeDefinitionNode> = [];
  const nodeMap: {[name: string]: TypeDefinitionNode} = Object.create(null);
  const directiveDefs: Array<DirectiveDefinitionNode> = [];
  for (let i = 0; i < ast.definitions.length; i++) {
    const d = ast.definitions[i];
    switch (d.kind) {
      case Kind.SCHEMA_DEFINITION:
        if (schemaDef) {
          throw new Error('Must provide only one schema definition.');
        }
        schemaDef = d;
        break;
      case Kind.SCALAR_TYPE_DEFINITION:
      case Kind.OBJECT_TYPE_DEFINITION:
      case Kind.INTERFACE_TYPE_DEFINITION:
      case Kind.ENUM_TYPE_DEFINITION:
      case Kind.UNION_TYPE_DEFINITION:
      case Kind.INPUT_OBJECT_TYPE_DEFINITION:
        const typeName = d.name.value;
        if (nodeMap[typeName]) {
          throw new Error(`Type "${typeName}" was defined more than once.`);
        }
        typeDefs.push(d);
        nodeMap[typeName] = d;
        break;
      case Kind.DIRECTIVE_DEFINITION:
        directiveDefs.push(d);
        break;
    }
  }

  let queryTypeName;
  let mutationTypeName;
  let subscriptionTypeName;
  if (schemaDef) {
    schemaDef.operationTypes.forEach(operationType => {
      const typeName = operationType.type.name.value;
      if (operationType.operation === 'query') {
        if (queryTypeName) {
          throw new Error('Must provide only one query type in schema.');
        }
        if (!nodeMap[typeName]) {
          throw new Error(
            `Specified query type "${typeName}" not found in document.`
          );
        }
        queryTypeName = typeName;
      } else if (operationType.operation === 'mutation') {
        if (mutationTypeName) {
          throw new Error('Must provide only one mutation type in schema.');
        }
        if (!nodeMap[typeName]) {
          throw new Error(
            `Specified mutation type "${typeName}" not found in document.`
          );
        }
        mutationTypeName = typeName;
      } else if (operationType.operation === 'subscription') {
        if (subscriptionTypeName) {
          throw new Error('Must provide only one subscription type in schema.');
        }
        if (!nodeMap[typeName]) {
          throw new Error(
            `Specified subscription type "${typeName}" not found in document.`
          );
        }
        subscriptionTypeName = typeName;
      }
    });
  } else {
    if (nodeMap.Query) {
      queryTypeName = 'Query';
    }
    if (nodeMap.Mutation) {
      mutationTypeName = 'Mutation';
    }
    if (nodeMap.Subscription) {
      subscriptionTypeName = 'Subscription';
    }
  }

  if (!queryTypeName) {
    throw new Error(
      'Must provide schema definition with query type or a type named Query.'
    );
  }

  const innerTypeMap = {
    String: GraphQLString,
    Int: GraphQLInt,
    Float: GraphQLFloat,
    Boolean: GraphQLBoolean,
    ID: GraphQLID,
    __Schema,
    __Directive,
    __DirectiveLocation,
    __Type,
    __Field,
    __InputValue,
    __EnumValue,
    __TypeKind,
  };

  const types = typeDefs.map(def => typeDefNamed(def.name.value));

  const directives = directiveDefs.map(getDirective);

  // If specified directives were not explicitly declared, add them.
  if (!directives.some(directive => directive.name === 'skip')) {
    directives.push(GraphQLSkipDirective);
  }

  if (!directives.some(directive => directive.name === 'include')) {
    directives.push(GraphQLIncludeDirective);
  }

  if (!directives.some(directive => directive.name === 'deprecated')) {
    directives.push(GraphQLDeprecatedDirective);
  }

  return new GraphQLSchema({
    query: getObjectType(nodeMap[queryTypeName]),
    mutation: mutationTypeName ?
      getObjectType(nodeMap[mutationTypeName]) :
      null,
    subscription: subscriptionTypeName ?
      getObjectType(nodeMap[subscriptionTypeName]) :
      null,
    types,
    directives,
    astNode: schemaDef,
  });

  function getDirective(
    directiveNode: DirectiveDefinitionNode
  ): GraphQLDirective {
    return new GraphQLDirective({
      name: directiveNode.name.value,
      description: getDescription(directiveNode),
      locations: directiveNode.locations.map(
        node => ((node.value: any): DirectiveLocationEnum)
      ),
      args: directiveNode.arguments && makeInputValues(directiveNode.arguments),
      astNode: directiveNode,
    });
  }

  function getObjectType(typeNode: TypeDefinitionNode): GraphQLObjectType {
    const type = typeDefNamed(typeNode.name.value);
    invariant(
      type instanceof GraphQLObjectType,
      'AST must provide object type.'
    );
    return (type: any);
  }

  function produceType(typeNode: TypeNode): GraphQLType {
    const typeName = getNamedTypeNode(typeNode).name.value;
    const typeDef = typeDefNamed(typeName);
    return buildWrappedType(typeDef, typeNode);
  }

  function produceInputType(typeNode: TypeNode): GraphQLInputType {
    return assertInputType(produceType(typeNode));
  }

  function produceOutputType(typeNode: TypeNode): GraphQLOutputType {
    return assertOutputType(produceType(typeNode));
  }

  function produceObjectType(typeNode: TypeNode): GraphQLObjectType {
    const type = produceType(typeNode);
    invariant(type instanceof GraphQLObjectType, 'Expected Object type.');
    return type;
  }

  function produceInterfaceType(typeNode: TypeNode): GraphQLInterfaceType {
    const type = produceType(typeNode);
    invariant(type instanceof GraphQLInterfaceType, 'Expected Interface type.');
    return type;
  }

  function typeDefNamed(typeName: string): GraphQLNamedType {
    if (!innerTypeMap[typeName]) {
      if (!nodeMap[typeName]) {
        throw new Error(`Type "${typeName}" not found in document.`);
      }
      innerTypeMap[typeName] = makeSchemaDef(nodeMap[typeName]);
    }
    return innerTypeMap[typeName];
  }

  function makeSchemaDef(def) {
    switch (def.kind) {
      case Kind.OBJECT_TYPE_DEFINITION:
        return makeTypeDef(def);
      case Kind.INTERFACE_TYPE_DEFINITION:
        return makeInterfaceDef(def);
      case Kind.ENUM_TYPE_DEFINITION:
        return makeEnumDef(def);
      case Kind.UNION_TYPE_DEFINITION:
        return makeUnionDef(def);
      case Kind.SCALAR_TYPE_DEFINITION:
        return makeScalarDef(def);
      case Kind.INPUT_OBJECT_TYPE_DEFINITION:
        return makeInputObjectDef(def);
      default:
        throw new Error(`Type kind "${def.kind}" not supported.`);
    }
  }

  function makeTypeDef(def: ObjectTypeDefinitionNode) {
    const typeName = def.name.value;
    return new GraphQLObjectType({
      name: typeName,
      description: getDescription(def),
      fields: () => makeFieldDefMap(def),
      interfaces: () => makeImplementedInterfaces(def),
      astNode: def,
    });
  }

  function makeFieldDefMap(
    def: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode
  ) {
    return keyValMap(
      def.fields,
      field => field.name.value,
      field => ({
        type: produceOutputType(field.type),
        description: getDescription(field),
        args: makeInputValues(field.arguments),
        deprecationReason: getDeprecationReason(field),
        astNode: field,
      })
    );
  }

  function makeImplementedInterfaces(def: ObjectTypeDefinitionNode) {
    return def.interfaces &&
      def.interfaces.map(iface => produceInterfaceType(iface));
  }

  function makeInputValues(values: Array<InputValueDefinitionNode>) {
    return keyValMap(
      values,
      value => value.name.value,
      value => {
        const type = produceInputType(value.type);
        return {
          type,
          description: getDescription(value),
          defaultValue: valueFromAST(value.defaultValue, type),
          astNode: value,
        };
      }
    );
  }

  function makeInterfaceDef(def: InterfaceTypeDefinitionNode) {
    return new GraphQLInterfaceType({
      name: def.name.value,
      description: getDescription(def),
      fields: () => makeFieldDefMap(def),
      astNode: def,
      resolveType: cannotExecuteSchema,
    });
  }

  function makeEnumDef(def: EnumTypeDefinitionNode) {
    return new GraphQLEnumType({
      name: def.name.value,
      description: getDescription(def),
      values: keyValMap(
        def.values,
        enumValue => enumValue.name.value,
        enumValue => ({
          description: getDescription(enumValue),
          deprecationReason: getDeprecationReason(enumValue),
          astNode: enumValue,
        })
      ),
      astNode: def,
    });
  }

  function makeUnionDef(def: UnionTypeDefinitionNode) {
    return new GraphQLUnionType({
      name: def.name.value,
      description: getDescription(def),
      types: def.types.map(t => produceObjectType(t)),
      resolveType: cannotExecuteSchema,
      astNode: def,
    });
  }

  function makeScalarDef(def: ScalarTypeDefinitionNode) {
    return new GraphQLScalarType({
      name: def.name.value,
      description: getDescription(def),
      astNode: def,
      serialize: () => null,
      // Note: validation calls the parse functions to determine if a
      // literal value is correct. Returning null would cause use of custom
      // scalars to always fail validation. Returning false causes them to
      // always pass validation.
      parseValue: () => false,
      parseLiteral: () => false,
    });
  }

  function makeInputObjectDef(def: InputObjectTypeDefinitionNode) {
    return new GraphQLInputObjectType({
      name: def.name.value,
      description: getDescription(def),
      fields: () => makeInputValues(def.fields),
      astNode: def,
    });
  }
}

/**
 * Given a field or enum value node, returns the string value for the
 * deprecation reason.
 */
export function getDeprecationReason(
  node: EnumValueDefinitionNode | FieldDefinitionNode
): ?string {
  const deprecated = getDirectiveValues(GraphQLDeprecatedDirective, node);
  return deprecated && (deprecated.reason: any);
}

/**
 * Given an ast node, returns its string description based on a contiguous
 * block full-line of comments preceding it.
 */
export function getDescription(node: { loc?: Location }): ?string {
  const loc = node.loc;
  if (!loc) {
    return;
  }
  const comments = [];
  let minSpaces;
  let token = loc.startToken.prev;
  while (
    token &&
    token.kind === TokenKind.COMMENT &&
    token.next && token.prev &&
    token.line + 1 === token.next.line &&
    token.line !== token.prev.line
  ) {
    const value = String(token.value);
    const spaces = leadingSpaces(value);
    if (minSpaces === undefined || spaces < minSpaces) {
      minSpaces = spaces;
    }
    comments.push(value);
    token = token.prev;
  }
  return comments
    .reverse()
    .map(comment => comment.slice(minSpaces))
    .join('\n');
}

/**
 * A helper function to build a GraphQLSchema directly from a source
 * document.
 */
export function buildSchema(source: string | Source): GraphQLSchema {
  return buildASTSchema(parse(source));
}

// Count the number of spaces on the starting side of a string.
function leadingSpaces(str) {
  let i = 0;
  for (; i < str.length; i++) {
    if (str[i] !== ' ') {
      break;
    }
  }
  return i;
}

function cannotExecuteSchema() {
  throw new Error(
    'Generated Schema cannot use Interface or Union types for execution.'
  );
}
<|endoftext|>


<commit_before>export default function deprecationWarning(oldname, newname, link) {
  if (process.env.NODE_ENV !== 'production') {
    let message = `${oldname} is deprecated. Use ${newname} instead.`;
    console.warn(message);

    if (link) {
      console.warn(`You can read more about it here ${link}`);
    }
  }
}
<commit_msg>[IE9] Check for console before using console.warn<commit_after>function warn(message) {
  if (window.console && (typeof console.warn === 'function')) {
    console.warn(message);
  }
}

export default function deprecationWarning(oldname, newname, link) {
  if (process.env.NODE_ENV !== 'production') {
    let message = `${oldname} is deprecated. Use ${newname} instead.`;
    warn(message);

    if (link) {
      warn(`You can read more about it here ${link}`);
    }
  }
}
<|endoftext|>


<commit_before>/**
* @license Apache-2.0
*
* Copyright (c) 2021 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// MODULES //

import config from './../config.js';
import PACKAGE_DATA_CACHE from './caches/package_data.js';

// MAIN //

/**
* Retrieves the list of packages for for a specified documentation version.
*
* @private
* @param {string} version - documentation version
* @param {Callback} clbk - callback invoked upon retrieving the lsit of packages
*/
function fetchPackageList( version, clbk ) {
	var total;
	var count;
	var o;

	total = 1;
	count = 0;

	o = PACKAGE_DATA_CACHE[ version ];
	if ( o && o.packages ) {
		done();
	} else {
		fetch( config.mount+version+'/package_list.json' )
			.then( toJSON )
			.then( onPackages )
			.catch( done );
	}

	/**
	* Callback invoked upon receiving a JSON resource.
	*
	* @private
	* @param {Object} res - response
	* @returns {Promise} promise to resolve the response as JSON
	*/
	function toJSON( res ) {
		return res.json();
	}

	/**
	* Callback invoked upon resolving a list of packages.
	*
	* @private
	* @param {StringArray} list - list of packages
	*/
	function onPackages( list ) {
		if ( PACKAGE_DATA_CACHE[ version ] === void 0 ) {
			PACKAGE_DATA_CACHE[ version ] = {};
		}
		PACKAGE_DATA_CACHE[ version ].packages = list;
		done();
	}

	/**
	* Callback invoked upon resolving a package resource.
	*
	* @private
	* @param {Error} [error] - error object
	* @returns {void}
	*/
	function done( error ) {
		if ( error ) {
			return clbk( error );
		}
		count += 1;
		if ( count === total ) {
			return clbk();
		}
	}
}

// EXPORTS //

export default fetchPackageList;
<commit_msg>Fix typos<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2021 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// MODULES //

import config from './../config.js';
import PACKAGE_DATA_CACHE from './caches/package_data.js';

// MAIN //

/**
* Retrieves the list of packages for a specified documentation version.
*
* @private
* @param {string} version - documentation version
* @param {Callback} clbk - callback invoked upon retrieving the list of packages
*/
function fetchPackageList( version, clbk ) {
	var total;
	var count;
	var o;

	total = 1;
	count = 0;

	o = PACKAGE_DATA_CACHE[ version ];
	if ( o && o.packages ) {
		done();
	} else {
		fetch( config.mount+version+'/package_list.json' )
			.then( toJSON )
			.then( onPackages )
			.catch( done );
	}

	/**
	* Callback invoked upon receiving a JSON resource.
	*
	* @private
	* @param {Object} res - response
	* @returns {Promise} promise to resolve the response as JSON
	*/
	function toJSON( res ) {
		return res.json();
	}

	/**
	* Callback invoked upon resolving a list of packages.
	*
	* @private
	* @param {StringArray} list - list of packages
	*/
	function onPackages( list ) {
		if ( PACKAGE_DATA_CACHE[ version ] === void 0 ) {
			PACKAGE_DATA_CACHE[ version ] = {};
		}
		PACKAGE_DATA_CACHE[ version ].packages = list;
		done();
	}

	/**
	* Callback invoked upon resolving a package resource.
	*
	* @private
	* @param {Error} [error] - error object
	* @returns {void}
	*/
	function done( error ) {
		if ( error ) {
			return clbk( error );
		}
		count += 1;
		if ( count === total ) {
			return clbk();
		}
	}
}

// EXPORTS //

export default fetchPackageList;
<|endoftext|>


<commit_before>var Backbone = require('backbone');
var LayerAnalysisViewFactory = require('../../../../../../javascripts/cartodb3/editor/layers/layer-analysis-view-factory');
var LayerAnalysisSourceView = require('../../../../../../javascripts/cartodb3/editor/layers/analysis-views/layer-analysis-source-view');
var LayerDefinitionModel = require('../../../../../../javascripts/cartodb3/data/layer-definition-model');
var AnalysisSourceModel = require('../../../../../../javascripts/cartodb3/data/analysis/analysis-source-model');

describe('editor/layers/analysis-views/layer-analysis-source-view', function () {
  beforeEach(function () {
    this.analysisDefinitionModel = new AnalysisSourceModel({
      id: 'a0',
      table_name: 'districts'
    }, {
      configModel: {}
    });

    this.layerDefinitionModel = new LayerDefinitionModel({
      id: 'l1',
      letter: 'a',
      kind: 'cartodb',
      name: 'Layer A',
      table_name: 'districts'
    }, {
      configModel: {}
    });

    this.layerAnalysisViewFactory = new LayerAnalysisViewFactory({});
  });

  describe('a layer with its own source analysis', function () {
    beforeEach(function () {
      this.view = new LayerAnalysisSourceView({
        model: this.analysisDefinitionModel,
        layerDefinitionModel: this.layerDefinitionModel,
        layerAnalysisViewFactory: this.layerAnalysisViewFactory
      });

      this.view.render();
    });

    it('should have no leaks', function () {
      expect(this.view).toHaveNoLeaks();
    });

    it('should render correctly', function () {
      expect(this.view.$el.text()).toContain('a0 districts');
    });
  });

  describe('a layer with a referenced source analysis', function () {
    beforeEach(function () {
      this.layerDefinitionModel2 = new LayerDefinitionModel({
        id: 'l2',
        letter: 'b',
        kind: 'cartodb',
        table_name: 'districts'
      }, {
        configModel: {},
        collection: new Backbone.Collection([this.layerDefinitionModel])
      });

      this.view = new LayerAnalysisSourceView({
        model: this.analysisDefinitionModel,
        layerDefinitionModel: this.layerDefinitionModel2,
        layerAnalysisViewFactory: this.layerAnalysisViewFactory
      });

      this.view.render();
    });

    it('should render correctly', function () {
      expect(this.view.$el.text()).toContain('a Layer A');
    });
  });
});
<commit_msg>Renames layers<commit_after>var Backbone = require('backbone');
var LayerAnalysisViewFactory = require('../../../../../../javascripts/cartodb3/editor/layers/layer-analysis-view-factory');
var LayerAnalysisSourceView = require('../../../../../../javascripts/cartodb3/editor/layers/analysis-views/layer-analysis-source-view');
var LayerDefinitionModel = require('../../../../../../javascripts/cartodb3/data/layer-definition-model');
var AnalysisSourceModel = require('../../../../../../javascripts/cartodb3/data/analysis/analysis-source-model');

describe('editor/layers/analysis-views/layer-analysis-source-view', function () {
  beforeEach(function () {
    this.analysisDefinitionModel = new AnalysisSourceModel({
      id: 'a0',
      table_name: 'districts'
    }, {
      configModel: {}
    });

    this.layerDefinitionModelA = new LayerDefinitionModel({
      id: 'l1',
      letter: 'a',
      kind: 'cartodb',
      name: 'Layer A',
      table_name: 'districts'
    }, {
      configModel: {}
    });

    this.layerAnalysisViewFactory = new LayerAnalysisViewFactory({});
  });

  describe('a layer with its own source analysis', function () {
    beforeEach(function () {
      this.view = new LayerAnalysisSourceView({
        model: this.analysisDefinitionModel,
        layerDefinitionModel: this.layerDefinitionModelA,
        layerAnalysisViewFactory: this.layerAnalysisViewFactory
      });

      this.view.render();
    });

    it('should have no leaks', function () {
      expect(this.view).toHaveNoLeaks();
    });

    it('should render correctly', function () {
      expect(this.view.$el.text()).toContain('a0 districts');
    });
  });

  describe('a layer with a referenced source analysis', function () {
    beforeEach(function () {
      this.layerDefinitionModelB = new LayerDefinitionModel({
        id: 'l2',
        letter: 'b',
        kind: 'cartodb',
        table_name: 'districts'
      }, {
        configModel: {},
        collection: new Backbone.Collection([this.layerDefinitionModelA])
      });

      this.view = new LayerAnalysisSourceView({
        model: this.analysisDefinitionModel,
        layerDefinitionModel: this.layerDefinitionModelB,
        layerAnalysisViewFactory: this.layerAnalysisViewFactory
      });

      this.view.render();
    });

    it('should render correctly', function () {
      expect(this.view.$el.text()).toContain('a Layer A');
    });
  });
});
<|endoftext|>