<commit_before>/*
## API docs? Nope, ape docs!

---
ape is a command line tool to generate documentation from your comments.
It parses your source code files, and strips markdown formatted comments out,
it then puts your code in github-flavored-markdown code blocks, and displays the comments in line.

It wasn't written to be fancy, but rather to have a simple, automated way of keeping docs on github up to date.

To use:

    sudo npm install -g ape
    ape [list of files or directories]
*/

// Require dependencies
var fs = require('fs'),
    path = require('path'),
    gfm = require('ghm'),
    hljs = require('hljs'),
    jade = require('jade');

// This is the exported function that does the actual parsing and documentation generation
exports.generate_doc = function (filename, outputFormat, outputPath, template, callback) {
    path.exists(filename, function (exists) {
        if (exists) {
            var code = fs.readFileSync(filename).toString().split('\n');
            parse_code(filename, code, outputFormat, outputPath, template, callback);
        } else {
            callback(new Error('file does not exist ' + filename));
        }
    });
};

/*
This function is a helper for frontends, to make it simpler to determine if a file can be processed by ape.
It returns a callback with a single boolean parameter indicating if the file is supported
*/
exports.supported = function (filename, callback) {
    var lang = languages[path.extname(filename)];
    if (typeof lang === 'undefined' ) {
        callback(false);
    } else {
        callback(true);
    }
};

// A simple helper function to return the dictionary of comment regexs, determined by the file extension
function get_language(filename) {
    var lang = languages[path.extname(filename)];
    return lang;
}

/*
This is the main function to parse the line array of source code, and return a new line array
containing the formatted text
*/
function parse_code(filename, code, outputFormat, outputPath, template, callback) {
    var parsed_code = [],
        this_line,
        in_comment,
        in_code,
        spaces,
        lang = get_language(filename),
        commentblock = [],
        codeblock = [],
        tempblock = [];

    if (typeof lang === 'undefined') return;

    function pushblock() {
        parsed_code.push({ code: codeblock.join('\n'), comment: commentblock.join('\n') });
        codeblock = [];
        commentblock = [];
        in_code = false;
    }

    for (var i = 0, l = code.length; i < l; i++) {
        this_line = code[i];
        if (this_line.match(lang.comment) && !in_comment && !this_line.match(/^#\!/)) {
            if (in_code) pushblock();
            commentblock.push(this_line.replace(lang.comment, ''))
        } else if (this_line.match(lang.start) && !in_comment) {
            if (lang.name === 'python' && in_code) {
                while (codeblock[codeblock.length - 1].trim() !== '') {
                    tempblock.push(codeblock.pop());
                }
            }
            if (in_code) pushblock();
            if (lang.name === 'python') {
                for (var ti = 0, tl = tempblock.length; ti < tl; ti++) {
                    codeblock.push(tempblock.pop());
                }
            }
            in_comment = true;
            spaces = this_line.match(/^\s+/);
            if (spaces) spaces = spaces[0].length;
            this_line = this_line.replace(lang.start, '');
            if (this_line.match(lang.end)) {
                this_line = this_line.replace(lang.end, '');
                in_comment = false;
            }
            if (this_line.trim() !== '') commentblock.push(this_line);
        } else if (this_line.match(lang.end) && in_comment) {
            this_line = this_line.replace(lang.end, '');
            if (this_line.trim() !== '') commentblock.push(this_line);
            in_comment = false;
        } else if (this_line.trim() === '' && !in_comment && !in_code) {
            pushblock();
        } else {
            if (in_comment) {
                if (lang.name === 'python') this_line = this_line.substring(spaces);
                commentblock.push(this_line);
            } else {
                if (!in_code && this_line.trim() !== '') in_code = true;
                codeblock.push(this_line);
            }
        }
    }

    pushblock();

    if (outputFormat === 'md') {
        write_md(filename, parsed_code, outputPath, callback);
    } else if (outputFormat === 'html') {
        write_html(filename, parsed_code, outputPath, template, callback);
    }
}

// This function writes the parsed output to a markdown file, matching the original source's filename but changing the extension to .md
function write_md(filename, parsed_code, outputPath, callback) {
    var outfile,
        outcode = '';

    if (typeof outputPath === 'undefined') {
        outfile = filename.replace(path.extname(filename), '.md');
    } else {
        outfile = path.join(outputPath, path.basename(filename).replace(path.extname(filename), '.md'));
    }

    for (var i = 0, l = parsed_code.length; i < l; i++) {
        if (parsed_code[i].comment !== '') outcode += parsed_code[i].comment + '\n\n';
        if (parsed_code[i].code !== '') outcode += '```' + get_language(filename).name + '\n' + parsed_code[i].code + '\n```\n\n';
    }

    fs.writeFileSync(outfile, outcode, 'utf8');
    callback(null, outfile);
}

// This function writes parsed output to html
function write_html(filename, parsed_code, outputPath, template, callback) {
    var outfile,
        templatePath,
        template;

    if (typeof outputPath === 'undefined') {
        outfile = filename.replace(path.extname(filename), '.html');
    } else {
        outfile = path.join(outputPath, path.basename(filename).replace(path.extname(filename), '.html'));
    }

    if (typeof template === 'undefined') {
        templatePath = path.join(__dirname, 'template.jade');
    } else {
        templatePath = template;
    }

    template = fs.readFileSync(__dirname + '/template.jade', 'utf-8');
    var fn = jade.compile(template);
    fs.writeFileSync(outfile, fn({ gfm: gfm, data: parsed_code, hljs: hljs, lang: get_language(filename).name }));
    callback(null, outfile);
}

/*
Here we define our supported languages. Each language is a dictionary, keyed on the file extension. Inside the dictionary
we have the the following items:

* 'name': the identifier that we output to the markdown for code blocks
* 'comment': is a regex that will match a single line comment for the specific language, but does NOT include the text on the line, only the comment
* 'start': a regular expression to match the beginning of a multi-line commment block. 'start' should only match if it's on the beginning
of a line
* 'end': the partner regex to 'start' matching the end of a multi-line comment only if the match is at the end of a line.
*/
var C_LINE_COMMENT = /^\s*\/\/\s?/,
    C_BLOCK_COMMENT_START = /^\s*\/\*\s?/,
    C_BLOCK_COMMENT_END = /\*\/\s*$/,
    HASH_LINE_COMMENT = /^\s*#\s?/,
    NEVER_MATCH = /a\bc/;
var languages = {
    '.js': { name: 'javascript', comment: C_LINE_COMMENT, start: C_BLOCK_COMMENT_START, end: C_BLOCK_COMMENT_END },
    '.py': { name: 'python', comment: HASH_LINE_COMMENT, start: /^\s*\"\"\"\s?/, end: /\"\"\"\s*$/ },
    '.rb': { name: 'ruby', comment: HASH_LINE_COMMENT, start: /^\s*\=begin\s?/, end: /\=end\s*$/ },
    '.lua': { name: 'lua', comment: /^\s*--\s?/, start: /^\s*--\[\[\s?/, end: /--\]\]\s*$/ },
    '.coffee': { name: 'coffeescript', comment: /^\s*#(?!##)\s?/, start: /^\s*###\s?/, end: /###\s*$/ },
    '.php': { name: 'php', comment: /^\s*(?:#|\/\/\s?)/, start: C_BLOCK_COMMENT_START, end: C_BLOCK_COMMENT_END },
    '.c': { name: null, comment: C_LINE_COMMENT, start: C_BLOCK_COMMENT_START, end: C_BLOCK_COMMENT_END },
    '.h': { name: null, comment: C_LINE_COMMENT, start: C_BLOCK_COMMENT_START, end: C_BLOCK_COMMENT_END },
    '.pl': { name: 'perl', comment: HASH_LINE_COMMENT, start: NEVER_MATCH, end: NEVER_MATCH },
    '.cpp': { name: 'cpp', comment: C_LINE_COMMENT, start: C_BLOCK_COMMENT_START, end: C_BLOCK_COMMENT_END }
};
<commit_msg>Add support for C#, ObjC, SQL, Bash, CSS<commit_after>/*
## API docs? Nope, ape docs!

---
ape is a command line tool to generate documentation from your comments.
It parses your source code files, and strips markdown formatted comments out,
it then puts your code in github-flavored-markdown code blocks, and displays the comments in line.

It wasn't written to be fancy, but rather to have a simple, automated way of keeping docs on github up to date.

To use:

    sudo npm install -g ape
    ape [list of files or directories]
*/

// Require dependencies
var fs = require('fs'),
    path = require('path'),
    gfm = require('ghm'),
    hljs = require('hljs'),
    jade = require('jade');

// This is the exported function that does the actual parsing and documentation generation
exports.generate_doc = function (filename, outputFormat, outputPath, template, callback) {
    path.exists(filename, function (exists) {
        if (exists) {
            var code = fs.readFileSync(filename).toString().split('\n');
            parse_code(filename, code, outputFormat, outputPath, template, callback);
        } else {
            callback(new Error('file does not exist ' + filename));
        }
    });
};

/*
This function is a helper for frontends, to make it simpler to determine if a file can be processed by ape.
It returns a callback with a single boolean parameter indicating if the file is supported
*/
exports.supported = function (filename, callback) {
    var lang = languages[path.extname(filename)];
    if (typeof lang === 'undefined' ) {
        callback(false);
    } else {
        callback(true);
    }
};

// A simple helper function to return the dictionary of comment regexs, determined by the file extension
function get_language(filename) {
    var lang = languages[path.extname(filename)];
    return lang;
}

/*
This is the main function to parse the line array of source code, and return a new line array
containing the formatted text
*/
function parse_code(filename, code, outputFormat, outputPath, template, callback) {
    var parsed_code = [],
        this_line,
        in_comment,
        in_code,
        spaces,
        lang = get_language(filename),
        commentblock = [],
        codeblock = [],
        tempblock = [];

    if (typeof lang === 'undefined') return;

    function pushblock() {
        parsed_code.push({ code: codeblock.join('\n'), comment: commentblock.join('\n') });
        codeblock = [];
        commentblock = [];
        in_code = false;
    }

    for (var i = 0, l = code.length; i < l; i++) {
        this_line = code[i];
        if (this_line.match(lang.comment) && !in_comment && !this_line.match(/^#\!/)) {
            if (in_code) pushblock();
            commentblock.push(this_line.replace(lang.comment, ''))
        } else if (this_line.match(lang.start) && !in_comment) {
            if (lang.name === 'python' && in_code) {
                while (codeblock[codeblock.length - 1].trim() !== '') {
                    tempblock.push(codeblock.pop());
                }
            }
            if (in_code) pushblock();
            if (lang.name === 'python') {
                for (var ti = 0, tl = tempblock.length; ti < tl; ti++) {
                    codeblock.push(tempblock.pop());
                }
            }
            in_comment = true;
            spaces = this_line.match(/^\s+/);
            if (spaces) spaces = spaces[0].length;
            this_line = this_line.replace(lang.start, '');
            if (this_line.match(lang.end)) {
                this_line = this_line.replace(lang.end, '');
                in_comment = false;
            }
            if (this_line.trim() !== '') commentblock.push(this_line);
        } else if (this_line.match(lang.end) && in_comment) {
            this_line = this_line.replace(lang.end, '');
            if (this_line.trim() !== '') commentblock.push(this_line);
            in_comment = false;
        } else if (this_line.trim() === '' && !in_comment && !in_code) {
            pushblock();
        } else {
            if (in_comment) {
                if (lang.name === 'python') this_line = this_line.substring(spaces);
                commentblock.push(this_line);
            } else {
                if (!in_code && this_line.trim() !== '') in_code = true;
                codeblock.push(this_line);
            }
        }
    }

    pushblock();

    if (outputFormat === 'md') {
        write_md(filename, parsed_code, outputPath, callback);
    } else if (outputFormat === 'html') {
        write_html(filename, parsed_code, outputPath, template, callback);
    }
}

// This function writes the parsed output to a markdown file, matching the original source's filename but changing the extension to .md
function write_md(filename, parsed_code, outputPath, callback) {
    var outfile,
        outcode = '';

    if (typeof outputPath === 'undefined') {
        outfile = filename.replace(path.extname(filename), '.md');
    } else {
        outfile = path.join(outputPath, path.basename(filename).replace(path.extname(filename), '.md'));
    }

    for (var i = 0, l = parsed_code.length; i < l; i++) {
        if (parsed_code[i].comment !== '') outcode += parsed_code[i].comment + '\n\n';
        if (parsed_code[i].code !== '') outcode += '```' + get_language(filename).name + '\n' + parsed_code[i].code + '\n```\n\n';
    }

    fs.writeFileSync(outfile, outcode, 'utf8');
    callback(null, outfile);
}

// This function writes parsed output to html
function write_html(filename, parsed_code, outputPath, template, callback) {
    var outfile,
        templatePath,
        template;

    if (typeof outputPath === 'undefined') {
        outfile = filename.replace(path.extname(filename), '.html');
    } else {
        outfile = path.join(outputPath, path.basename(filename).replace(path.extname(filename), '.html'));
    }

    if (typeof template === 'undefined') {
        templatePath = path.join(__dirname, 'template.jade');
    } else {
        templatePath = template;
    }

    template = fs.readFileSync(__dirname + '/template.jade', 'utf-8');
    var fn = jade.compile(template);
    fs.writeFileSync(outfile, fn({ gfm: gfm, data: parsed_code, hljs: hljs, lang: get_language(filename).name }));
    callback(null, outfile);
}

/*
Here we define our supported languages. Each language is a dictionary, keyed on the file extension. Inside the dictionary
we have the the following items:

* 'name': the identifier that we output to the markdown for code blocks
* 'comment': is a regex that will match a single line comment for the specific language, but does NOT include the text on the line, only the comment
* 'start': a regular expression to match the beginning of a multi-line commment block. 'start' should only match if it's on the beginning
of a line
* 'end': the partner regex to 'start' matching the end of a multi-line comment only if the match is at the end of a line.
*/
var C_LINE_COMMENT = /^\s*\/\/\s?/,
    C_BLOCK_COMMENT_START = /^\s*\/\*\s?/,
    C_BLOCK_COMMENT_END = /\*\/\s*$/,
    HASH_LINE_COMMENT = /^\s*#\s?/,
    NEVER_MATCH = /a\bc/;
var languages = {
    '.js': { name: 'javascript', comment: C_LINE_COMMENT, start: C_BLOCK_COMMENT_START, end: C_BLOCK_COMMENT_END },
    '.py': { name: 'python', comment: HASH_LINE_COMMENT, start: /^\s*\"\"\"\s?/, end: /\"\"\"\s*$/ },
    '.rb': { name: 'ruby', comment: HASH_LINE_COMMENT, start: /^\s*\=begin\s?/, end: /\=end\s*$/ },
    '.lua': { name: 'lua', comment: /^\s*--\s?/, start: /^\s*--\[\[\s?/, end: /--\]\]\s*$/ },
    '.coffee': { name: 'coffeescript', comment: /^\s*#(?!##)\s?/, start: /^\s*###\s?/, end: /###\s*$/ },
    '.php': { name: 'php', comment: /^\s*(?:#|\/\/\s?)/, start: C_BLOCK_COMMENT_START, end: C_BLOCK_COMMENT_END },
    '.c': { name: null, comment: C_LINE_COMMENT, start: C_BLOCK_COMMENT_START, end: C_BLOCK_COMMENT_END },
    '.h': { name: null, comment: C_LINE_COMMENT, start: C_BLOCK_COMMENT_START, end: C_BLOCK_COMMENT_END },
    '.pl': { name: 'perl', comment: HASH_LINE_COMMENT, start: NEVER_MATCH, end: NEVER_MATCH },
    '.cpp': { name: 'cpp', comment: C_LINE_COMMENT, start: C_BLOCK_COMMENT_START, end: C_BLOCK_COMMENT_END },
    '.cs': { name: 'cs', comment: C_LINE_COMMENT, start: C_BLOCK_COMMENT_START, end: C_BLOCK_COMMENT_END },
    '.m': { name: 'objectivec', comment C_LINE_COMMENT, start: C_BLOCK_COMMENT_START, end: C_BLOCK_COMMENT_END },
    '.sql': { name: 'sql', comment: /^\s*--\s?/, start: C_BLOCK_COMMENT_START, end: C_BLOCK_COMMENT_END },
    '.sh': { name: 'bash', comment: HASH_LINE_COMMENT, start: NEVER_MATCH, end: NEVER_MATCH },
    '.css': { name: 'css', comment: NEVER_MATCH, start: C_BLOCK_COMMENT_START, end: C_BLOCK_COMMENT_END }
};
<|endoftext|>


<commit_before>Package.describe({
  summary: 'Timestamp behavior for Meteor Astronomy',
  version: '0.4.1',
  name: 'jagi:astronomy-timestamp-behavior',
  git: 'https://github.com/jagi/meteor-astronomy-timestamp-behavior.git'
});

Package.onUse(function(api) {
  api.versionsFrom('1.1.0.2');

  api.use('jagi:astronomy-behaviors@0.5.1');
  api.use('underscore');

  // Behavior.
  api.addFiles('lib/behavior/events.js', ['client', 'server']);
  api.addFiles('lib/behavior/behavior.js', ['client', 'server']);
});
<commit_msg>Bump version number to 0.4.2<commit_after>Package.describe({
  summary: 'Timestamp behavior for Meteor Astronomy',
  version: '0.4.2',
  name: 'jagi:astronomy-timestamp-behavior',
  git: 'https://github.com/jagi/meteor-astronomy-timestamp-behavior.git'
});

Package.onUse(function(api) {
  api.versionsFrom('1.1.0.2');

  api.use('jagi:astronomy-behaviors@0.5.1');
  api.use('underscore');

  // Behavior.
  api.addFiles('lib/behavior/events.js', ['client', 'server']);
  api.addFiles('lib/behavior/behavior.js', ['client', 'server']);
});
<|endoftext|>


<commit_before>// Copyright 2002-2013, University of Colorado Boulder

/**
 * An observable property, notifies registered observers when the value changes.
 *
 * Uses the 'Constructor' pattern for object creation, which has the downside that
 * all properties are created once for each instance. It would be nice if our functions
 * were shared. But since the only way to create private fields is in the constructor,
 * and the functions need access to those private fields, there doesn't seem to be
 * any choice but to define the functions in the constructor.
 *
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( function( require ) {
  'use strict';

  var axon = require( 'AXON/axon' );

  /**
   * @param {*} value
   * @constructor
   */
  axon.Property = function Property( value ) {

    //Store the internal value and the initial value
    this._value = value;
    this._initialValue = value;
    this._observers = [];
  };

  axon.Property.prototype = {

    /**
     * Gets the value.  You can also use the es5 getter (property.value) but this means is provided for inner loops or internal code that must be fast.
     * @return {*}
     */
    get: function() {
      return this._value;
    },

    /**
     * Sets the value and notifies registered observers.  You can also use the es5 getter (property.value) but this means is provided for inner loops or internal code that must be fast.
     * If the value hasn't changed, this is a no-op.
     *
     * @param {*} value
     */
    set: function( value ) {
      if ( value !== this._value ) {
        var oldValue = this._value;
        this._value = value;
        var observersCopy = this._observers.slice(); // make a copy, in case notification results in removeObserver
        for ( var i = 0; i < observersCopy.length; i++ ) {
          observersCopy[i]( value, oldValue );
        }
      }
    },

    //Use this method when mutating a value (not replacing with a new instance) and you want to send notifications about the change.
    //This is different from the normal axon strategy, but may be necessary to prevent memory allocations.
    //This method is unsafe for removing observers because it assumes the observer list not modified, to save another allocation
    //Only provides the new reference as a callback (no oldvalue)
    //See https://github.com/phetsims/axon/issues/6
    notifyObserversUnsafe: function() {
      for ( var i = 0; i < this._observers.length; i++ ) {
        this._observers[i]( this._value );
      }
    },

    /**
     * Resets the value to the initial value.
     */
    reset: function() {
      this.set( this._initialValue );
    },

    /**
     * This function returns a bound function that sets the specified value.  For use in creating closures e.g. with gui classes.
     * For instance, to have a button that sets a property to true, instead of using
     * button.click(function(){property.set(true);});
     * you could use
     * button.click(property._set(true));
     * @param value the value to use when the setter is called.
     * @return a function that can be used to set the specified value.
     */
    _set: function( value ) {
      return this.set.bind( this, value );
    },

    get value() { return this.get(); },

    set value( newValue ) { this.set( newValue ); },

    /**
     * Adds an observer and notifies it immediately.
     * If observer is already registered, this is a no-op.
     * The initial notification provides the current value for newValue and null for oldValue.
     *
     * @param {Function} observer a function of the form observer(newValue,oldValue)
     */
    link: function( observer ) {
      if ( this._observers.indexOf( observer ) === -1 ) {
        this._observers.push( observer );
        observer( this._value, null ); // null should be used when an object is expected but unavailable
      }
    },

    /**
     * Removes an observer.
     * If observer is not registered, this is a no-op.
     *
     * @param {Function} observer
     */
    unlink: function( observer ) {
      var index = this._observers.indexOf( observer );
      if ( index !== -1 ) {
        this._observers.splice( index, 1 );
      }
    },

    /**
     * Add an observer to the Property, without calling it back right away.  This is used when you need to register a listener without an immediate callback.
     * @param {Function} observer  a function with a single argument, which is the value of the property at the time the function is called.
     */
    lazyLink: function( observer ) {
      if ( this._observers.indexOf( observer ) === -1 ) {
        this._observers.push( observer );
      }
    },

    //Provide toString for console debugging, see http://stackoverflow.com/questions/2485632/valueof-vs-tostring-in-javascript
    toString: function() {return 'Property{' + this.get() + '}'; },
    valueOf: function() {return this.toString();},

    /**
     * Add a listener so that it will only fire once (and not on registration)
     *
     * I can see two ways to implement this:
     * (a) add a field to the observer so after notifications it can be checked and possibly removed. Disadvantage: will make everything slower even if not using 'once'
     * (b) wrap the observer in a new function which will call the observer and then remove itself.  Disadvantage: cannot remove an observer added using 'once'
     * To avoid possible performance problems, use a wrapper function, and return it as a handle in case the 'once' listener must be removed before it is called once
     *
     * @param observer the listener which should be called back only for one property change (and not on registration)
     * @returns {Function} the wrapper handle in case the wrapped function needs to be removed with 'unlink' before it is called once
     */
    once: function( observer ) {
      var property = this;
      var wrapper = function( newValue, oldValue ) {
        observer( newValue, oldValue );
        property.unlink( wrapper );
      };
      this.lazyLink( wrapper );
      return wrapper;
    },

    /**
     * Links an object's named attribute to this property.  Returns a handle so it can be removed.
     * Example: modelVisibleProperty.linkAttribute(view,'visible');
     *
     * @param object
     * @param attributeName
     */
    linkAttribute: function( object, attributeName ) {
      var handle = function( value ) {object[attributeName] = value;};
      this.link( handle );
      return handle;
    },

    /**
     * Returns a new DerivedProperty which is true/false based on whether the value matches (based on ===) the passed in argument.
     * @param value
     * @returns {axon.DerivedProperty}
     */
    valueEquals: function( value ) {
      return new axon.DerivedProperty( [this], function( propertyValue ) { return propertyValue === value; } );
    },

    /**
     * Two way communication for not, so you can set the value and have it come back to the parent
     * Note that noting about the following code is specific to booleans, although this should probably be used mostly for booleans.
     * To unlink both listeners attached unlink a property created with not(), use detach()
     */
    not: function() {
      var parentProperty = this;
      var childProperty = new axon.Property( !this.value );

      var setParentToChild = function( value ) {childProperty.set( !value );};
      parentProperty.link( setParentToChild );

      var setChildToParent = function( value ) {parentProperty.set( !value );};
      childProperty.link( setChildToParent );

      childProperty.detach = function() {
        parentProperty.unlink( setParentToChild );
        childProperty.unlink( setChildToParent );
      };
      return childProperty;
    },

    /**
     * Convenience function for debugging a property values.  It prints the new value on registration and when changed.
     * @param name debug name to be printed on the console
     * @returns {Function} the handle to the linked listener in case it needs to be removed later
     */
    debug: function( name ) {
      var listener = function( value ) { console.log( name, value ); };
      this.link( listener );
      return listener;
    }
  };

  return axon.Property;
} );<commit_msg>Property changes to allow mixing into Vector2 and other similar files<commit_after>// Copyright 2002-2013, University of Colorado Boulder

/**
 * An observable property, notifies registered observers when the value changes.
 *
 * Uses the 'Constructor' pattern for object creation, which has the downside that
 * all properties are created once for each instance. It would be nice if our functions
 * were shared. But since the only way to create private fields is in the constructor,
 * and the functions need access to those private fields, there doesn't seem to be
 * any choice but to define the functions in the constructor.
 *
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( function( require ) {
  'use strict';

  var axon = require( 'AXON/axon' );

  /**
   * @param {*} value
   * @constructor
   */
  axon.Property = function Property( value ) {

    //Store the internal value and the initial value
    this.storeValue( value );        // typically sets this._value
    this.storeInitialValue( value ); // typically sets this._initialValue
    this._observers = [];
  };

  axon.Property.prototype = {

    /**
     * Gets the value.  You can also use the es5 getter (property.value) but this means is provided for inner loops or internal code that must be fast.
     * @return {*}
     */
    get: function() {
      return this._value;
    },

    /**
     * Sets the value and notifies registered observers.  You can also use the es5 getter (property.value) but this means is provided for inner loops or internal code that must be fast.
     * If the value hasn't changed, this is a no-op.
     *
     * @param {*} value
     */
    set: function( value ) {
      if ( !this.equalsValue( value ) ) {
        this._setAndNotifyObservers( value );
      }
      return this;
    },

    // whether this property will not "change" when the passed-in value is set
    equalsValue: function( value ) {
      return value === this._value;
    },

    // store the current (new) value
    storeValue: function( value ) {
      this._value = value;
    },

    // store the initial value
    storeInitialValue: function( value ) {
      this._initialValue = value;
    },

    _setAndNotifyObservers: function( value ) {
      var oldValue = this.get();
      this.storeValue( value );
      this._notifyObservers( oldValue );
    },

    _notifyObservers: function( oldValue ) {
      var value = this.get();
      // TODO: JO: avoid slice() by storing observers array correctly
      var observersCopy = this._observers.slice(); // make a copy, in case notification results in removeObserver
      for ( var i = 0; i < observersCopy.length; i++ ) {
        observersCopy[i]( value, oldValue );
      }
    },

    //Use this method when mutating a value (not replacing with a new instance) and you want to send notifications about the change.
    //This is different from the normal axon strategy, but may be necessary to prevent memory allocations.
    //This method is unsafe for removing observers because it assumes the observer list not modified, to save another allocation
    //Only provides the new reference as a callback (no oldvalue)
    //See https://github.com/phetsims/axon/issues/6
    notifyObserversUnsafe: function() {
      var value = this.get();
      for ( var i = 0; i < this._observers.length; i++ ) {
        this._observers[i]( value );
      }
    },

    /**
     * Resets the value to the initial value.
     */
    reset: function() {
      this.set( this._initialValue );
    },

    /**
     * This function returns a bound function that sets the specified value.  For use in creating closures e.g. with gui classes.
     * For instance, to have a button that sets a property to true, instead of using
     * button.click(function(){property.set(true);});
     * you could use
     * button.click(property._set(true));
     * @param value the value to use when the setter is called.
     * @return a function that can be used to set the specified value.
     */
    _set: function( value ) {
      return this.set.bind( this, value );
    },

    get value() { return this.get(); },

    set value( newValue ) { this.set( newValue ); },

    /**
     * Adds an observer and notifies it immediately.
     * If observer is already registered, this is a no-op.
     * The initial notification provides the current value for newValue and null for oldValue.
     *
     * @param {Function} observer a function of the form observer(newValue,oldValue)
     */
    link: function( observer ) {
      if ( this._observers.indexOf( observer ) === -1 ) {
        this._observers.push( observer );
        observer( this.get(), null ); // null should be used when an object is expected but unavailable
      }
    },

    /**
     * Removes an observer.
     * If observer is not registered, this is a no-op.
     *
     * @param {Function} observer
     */
    unlink: function( observer ) {
      var index = this._observers.indexOf( observer );
      if ( index !== -1 ) {
        this._observers.splice( index, 1 );
      }
    },

    /**
     * Add an observer to the Property, without calling it back right away.  This is used when you need to register a listener without an immediate callback.
     * @param {Function} observer  a function with a single argument, which is the value of the property at the time the function is called.
     */
    lazyLink: function( observer ) {
      if ( this._observers.indexOf( observer ) === -1 ) {
        this._observers.push( observer );
      }
    },

    //Provide toString for console debugging, see http://stackoverflow.com/questions/2485632/valueof-vs-tostring-in-javascript
    toString: function() {return 'Property{' + this.get() + '}'; },
    valueOf: function() {return this.toString();},

    /**
     * Add a listener so that it will only fire once (and not on registration)
     *
     * I can see two ways to implement this:
     * (a) add a field to the observer so after notifications it can be checked and possibly removed. Disadvantage: will make everything slower even if not using 'once'
     * (b) wrap the observer in a new function which will call the observer and then remove itself.  Disadvantage: cannot remove an observer added using 'once'
     * To avoid possible performance problems, use a wrapper function, and return it as a handle in case the 'once' listener must be removed before it is called once
     *
     * @param observer the listener which should be called back only for one property change (and not on registration)
     * @returns {Function} the wrapper handle in case the wrapped function needs to be removed with 'unlink' before it is called once
     */
    once: function( observer ) {
      var property = this;
      var wrapper = function( newValue, oldValue ) {
        observer( newValue, oldValue );
        property.unlink( wrapper );
      };
      this.lazyLink( wrapper );
      return wrapper;
    },

    /**
     * Links an object's named attribute to this property.  Returns a handle so it can be removed.
     * Example: modelVisibleProperty.linkAttribute(view,'visible');
     *
     * @param object
     * @param attributeName
     */
    linkAttribute: function( object, attributeName ) {
      var handle = function( value ) {object[attributeName] = value;};
      this.link( handle );
      return handle;
    },

    /**
     * Returns a new DerivedProperty which is true/false based on whether the value matches (based on ===) the passed in argument.
     * @param value
     * @returns {axon.DerivedProperty}
     */
    valueEquals: function( value ) {
      return new axon.DerivedProperty( [this], function( propertyValue ) { return propertyValue === value; } );
    },

    /**
     * Two way communication for not, so you can set the value and have it come back to the parent
     * Note that noting about the following code is specific to booleans, although this should probably be used mostly for booleans.
     * To unlink both listeners attached unlink a property created with not(), use detach()
     */
    not: function() {
      var parentProperty = this;
      var childProperty = new axon.Property( !this.value );

      var setParentToChild = function( value ) {childProperty.set( !value );};
      parentProperty.link( setParentToChild );

      var setChildToParent = function( value ) {parentProperty.set( !value );};
      childProperty.link( setChildToParent );

      childProperty.detach = function() {
        parentProperty.unlink( setParentToChild );
        childProperty.unlink( setChildToParent );
      };
      return childProperty;
    },

    /**
     * Convenience function for debugging a property values.  It prints the new value on registration and when changed.
     * @param name debug name to be printed on the console
     * @returns {Function} the handle to the linked listener in case it needs to be removed later
     */
    debug: function( name ) {
      var listener = function( value ) { console.log( name, value ); };
      this.link( listener );
      return listener;
    }
  };

  return axon.Property;
} );
<|endoftext|>


<commit_before>Package.describe({
  name: 'canotto90:settings-conf-manager',
  summary: 'Lets you see and change app settings (both public and private). Meant for tunning settings without going to the file.',
  version: '0.0.1',
  git: 'https://github.com/taromero/settings-conf-manager'
})

Package.onUse(function(api) {
  api.versionsFrom('1.0.1')
  api.use([
    'kevohagan:sweetalert@0.3.2',
    'canotto90:swal-forms@0.0.5'
  ], 'client')
  api.addFiles('client.js', 'client')
  api.addFiles('server.js', 'server')
})
<commit_msg>Made the package debugOnly<commit_after>Package.describe({
  name: 'canotto90:settings-conf-manager',
  summary: 'Lets you see and change app settings (both public and private)',
  version: '0.1.0',
  git: 'https://github.com/taromero/settings-conf-manager',
  debugOnly: true
})

Package.onUse(function(api) {
  api.versionsFrom('1.0.1')
  api.use([
    'kevohagan:sweetalert@0.3.2',
    'canotto90:swal-forms@0.0.5'
  ], 'client')
  api.addFiles('client.js', 'client')
  api.addFiles('server.js', 'server')
})
<|endoftext|>


<commit_before>// Copyright 2013-2018, University of Colorado Boulder

/**
 * An observable property which notifies listeners when the value changes.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( function( require ) {
  'use strict';

  // modules
  var axon = require( 'AXON/axon' );
  var Emitter = require( 'AXON/Emitter' );
  var inherit = require( 'PHET_CORE/inherit' );
  var Multilink = require( 'AXON/Multilink' );
  var units = require( 'AXON/units' );
  var PhetioObject = require( 'TANDEM/PhetioObject' );
  var Tandem = require( 'TANDEM/Tandem' );

  // constants
  var TYPEOF_STRINGS = [ 'string', 'number', 'boolean', 'function' ];

  /**
   * @param {*} value - the initial value of the property
   * @param {Object} [options] - options
   * @constructor
   */
  function Property( value, options ) {

    var self = this;

    options = _.extend( {

      tandem: Tandem.optional, // workaround for https://github.com/phetsims/tandem/issues/50

      // {function|string|null} type of the value.
      // If {function}, the function must be a constructor.
      // If {string}, the string must be one of the primitive types listed in TYPEOF_STRINGS.
      // Unused if null.
      // Examples:
      // valueType: Vector2
      // valueType: 'string'
      // valueType: 'number'
      valueType: null,

      // {*[]|null} valid values for this Property. Unused if null.
      // Example:
      // validValues: [ 'horizontal', 'vertical' ]
      validValues: null,

      // {function|null} function that validates the value. Single argument is the value, returns boolean. Unused if null.
      // Example:
      // isValidValue: function( value ) { return Util.isInteger( value ) && value >= 0; }
      isValidValue: null,

      // useDeepEquality: true => Use the `equals` method on the values
      // useDeepEquality: false => Use === for equality test
      useDeepEquality: false,

      // If marked as highFrequency: true, the event will be omitted when the query parameter phetioEmitHighFrequencyEvents=false
      highFrequency: false,

      // {string|null} units for the number, see units.js
      units: null
    }, options );

    // validate options
    assert && assertOptionValueType( options.valueType );
    assert && assert( options.validValues === null || Array.isArray( options.validValues ),
      'validValues must be an array: ' + options.validValues );
    assert && assert( options.isValidValue === null || typeof options.isValidValue === 'function',
      'isValidValue must be a function: ' + options.isValidValue );

    assert && options.units && assert( units.isValidUnits( options.units ), 'invalid units: ' + options.units );

    PhetioObject.call( this, options );

    // @public (phet-io) Units, if any.  See units.js for valid values
    this.units = options.units;

    // @private (read-only) whether to use the values' equals method or === equality
    // useDeepEquality: true => Use the `equals` method on the values
    // useDeepEquality: false => Use === for equality test
    this.useDeepEquality = options.useDeepEquality;

    // @private {function|false} value validation function, false if assertions are disabled
    this.assertPropertyValidateValue = assert && function( value ) {

      options.valueType && assertValueType( value, options.valueType );

      options.validValues && assert( options.validValues.indexOf( value ) !== -1,
        'value is not a member of validValues: ' + value );

      options.isValidValue && assert( options.isValidValue( value ),
        'value failed isValidValue test: ' + value );
    };

    // verify that validValues meet other validation criteria
    if ( this.assertPropertyValidateValue && options.validValues ) {
      options.validValues.forEach( function( value ) {
        self.assertPropertyValidateValue( value );
      } );
    }

    // validate the initial value
    this.assertPropertyValidateValue && this.assertPropertyValidateValue( value );

    // When running as phet-io, if the tandem is specified, the type must be specified.
    // This assertion helps in instrumenting code that has the tandem but not type
    Tandem.validationEnabled() && this.tandem.isSuppliedAndEnabled() && assert && assert( !!options.phetioType,
      'Value type passed to Property must be specified. Tandem.phetioID: ' + this.tandem.phetioID );

    // When running as phet-io, if the tandem is specified, the type must be specified.
    // This assertion helps in instrumenting code that has the tandem but not type
    Tandem.validationEnabled() && this.tandem.isSuppliedAndEnabled() && assert && assert( !!options.phetioType.elementType,
      'phetioType.elementType must be specified. Tandem.phetioID: ' + this.tandem.phetioID );

    // @private - Store the internal value and the initial value
    this._value = value;

    // @private - Initial value
    this._initialValue = value;

    // @public (phet-io)
    this.validValues = options.validValues;

    // @private (unit-tests) - emit1 is called when the value changes (or on link)
    // Also used in ShapePlacementBoard.js at the moment
    this.changedEmitter = new Emitter();

    // @public (read-only, scenery) {boolean} indicate whether the Property has been disposed
    this.isDisposed = false;

    // @private
    this.changeEventOptions = {
      highFrequency: options.highFrequency
    };
  }

  axon.register( 'Property', Property );

  /**
   * Verifies the value of option valueType, fails assertion if invalid.
   * @param {function|string|null} valueType
   */
  function assertOptionValueType( valueType ) {

    if ( !assert ) {
      throw new Error( 'call this function only when assertions are enabled' );
    }

    assert( typeof valueType === 'function' || typeof valueType === 'string' || valueType === null,
      'valueType must be {function|string|null}, valueType=' + valueType );

    // {string} valueType must be one of the primitives in TYPEOF_STRINGS, for typeof comparison
    if ( typeof valueType === 'string' ) {
      assert( _.includes( TYPEOF_STRINGS, valueType ),
        'valueType is a string, but not one of the supported primitive types: ' + valueType );
    }
  }

  /**
   * Performs valueType validation on a value. Fails an assertion if invalid.
   * @param {*} value
   * @param {function|string|null} valueType
   */
  function assertValueType( value, valueType ) {

    if ( !assert ) {
      throw new Error( 'call this function only when assertions are enabled' );
    }

    if ( typeof valueType === 'string' ) {

      // primitive type
      assert( typeof value === valueType, 'value should have typeof ' + valueType + ', value=' + value );
    }
    else if ( typeof valueType === 'function' ) {

      // constructor
      assert( value instanceof valueType, 'value should be instanceof ' + valueType.name + ', value=' + value );
    }
    else {

      // we should never get here, but just in case...
      assert( valueType === null, 'invalid valueType: ' + valueType );
    }
  }

  return inherit( PhetioObject, Property, {

      /**
       * Gets the value.
       * You can also use the es5 getter (property.value) but this means is provided for inner loops
       * or internal code that must be fast.
       * @returns {*}
       * @public
       */
      get: function() {
        return this._value;
      },

      /**
       * Sets the value and notifies listeners.
       * You can also use the es5 getter (property.value) but this means is provided for inner loops
       * or internal code that must be fast.
       * If the value hasn't changed, this is a no-op.
       *
       * @param {*} value
       * @returns {Property} this instance, for chaining.
       * @public
       */
      set: function( value ) {
        this.assertPropertyValidateValue && this.assertPropertyValidateValue( value );
        if ( !this.equalsValue( value ) ) {
          this._setAndNotifyListeners( value );
        }
        return this;
      },

      /**
       * Returns true if and only if the specified value equals the value of this property
       * @param {Object} value
       * @returns {boolean}
       * @private
       */
      equalsValue: function( value ) {
        return this.areValuesEqual( value, this._value );
      },

      /**
       * Determines equality semantics for the wrapped type, including whether notifications are sent out when the
       * wrapped value changes, and whether onValue is triggered.
       *
       * useDeepEquality: true => Use the `equals` method on the values
       * useDeepEquality: false => Use === for equality test
       *
       * Alternatively different implementation can be provided by subclasses or instances to change the equals
       * definition. See #10 and #73 and #115
       * @param {Object} a - should have the same type as Property element type
       * @param {Object} b - should have the same type as Property element type
       * @returns {boolean}
       * @private
       */
      areValuesEqual: function( a, b ) {
        if ( this.useDeepEquality && a && b && a.constructor === b.constructor ) {

          assert && assert( !!a.equals, 'no equals function for 1st arg' );
          assert && assert( !!b.equals, 'no equals function for 2nd arg' );
          assert && assert( a.equals( b ) === b.equals( a ), 'incompatible equality checks' );
          return a.equals( b );
        }
        else {

          // Reference equality for objects, value equality for primitives
          return a === b;
        }
      },

      // @public
      get initialValue() {
        return this._initialValue;
      },

      // @private
      _setAndNotifyListeners: function( value ) {
        var oldValue = this.get();
        this._value = value;
        this._notifyListeners( oldValue );
      },

      // @private
      _notifyListeners: function( oldValue ) {

        // We must short circuit based on tandem here as a guard against the toStateObject calls
        this.tandem.isSuppliedAndEnabled() && this.startEvent( 'model', 'changed', {
          oldValue: this.phetioType.elementType.toStateObject( oldValue ),
          newValue: this.phetioType.elementType.toStateObject( this.get() ),
          units: this.phetioType && this.phetioType.units
        }, this.changeEventOptions );

        this.changedEmitter.emit2( this.get(), oldValue );

        this.tandem.isSuppliedAndEnabled() && this.endEvent();
      },

      /**
       * Use this method when mutating a value (not replacing with a new instance) and you want to send notifications about the change.
       * This is different from the normal axon strategy, but may be necessary to prevent memory allocations.
       * This method is unsafe for removing listeners because it assumes the listener list not modified, to save another allocation
       * Only provides the new reference as a callback (no oldvalue)
       * See https://github.com/phetsims/axon/issues/6
       * @public
       */
      notifyListenersStatic: function() {
        this.changedEmitter.emit1( this.get() );
      },

      /**
       * Resets the value to the initial value.
       * @public
       */
      reset: function() {
        this.set( this._initialValue );
      },

      // @public
      get value() { return this.get(); },

      // @public
      set value( newValue ) { this.set( newValue ); },

      /**
       * Adds listener and calls it immediately. If listener is already registered, this is a no-op. The initial
       * notification provides the current value for newValue and null for oldValue.
       *
       * @param {function} listener a function of the form listener(newValue,oldValue)
       * @public
       */
      link: function( listener ) {
        this.changedEmitter.addListener( listener );
        listener( this.get(), null ); // null should be used when an object is expected but unavailable
      },

      /**
       * Add an listener to the Property, without calling it back right away.
       * This is used when you need to register a listener without an immediate callback.
       *
       * @param {function} listener - a function with a single argument, which is the value of the property at the time the function is called.
       * @public
       */
      lazyLink: function( listener ) {
        this.changedEmitter.addListener( listener );
      },

      /**
       * Removes a listener. If listener is not registered, this is a no-op.
       *
       * @param {function} listener
       * @public
       */
      unlink: function( listener ) {
        this.changedEmitter.removeListener( listener );
      },

      /**
       * Removes all listeners. If no listeners are registered, this is a no-op.
       */
      unlinkAll: function() {
        this.changedEmitter.removeAllListeners();
      },

      /**
       * Links an object's named attribute to this property.  Returns a handle so it can be removed using Property.unlink();
       * Example: modelVisibleProperty.linkAttribute(view,'visible');
       *
       * @param object
       * @param attributeName
       * @public
       */
      linkAttribute: function( object, attributeName ) {
        var handle = function( value ) {object[ attributeName ] = value;};
        this.link( handle );
        return handle;
      },

      /**
       * Unlink an listener added with linkAttribute.  Note: the args of linkAttribute do not match the args of
       * unlinkAttribute: here, you must pass the listener handle returned by linkAttribute rather than object and attributeName
       *
       * @param {function} listener
       * @public
       */
      unlinkAttribute: function( listener ) {
        this.unlink( listener );
      },

      // @public Provide toString for console debugging, see http://stackoverflow.com/questions/2485632/valueof-vs-tostring-in-javascript
      toString: function() {return 'Property{' + this.get() + '}'; },

      // @public
      valueOf: function() {return this.toString();},

      /**
       * Convenience function for debugging a property values.  It prints the new value on registration and when changed.
       * @param name debug name to be printed on the console
       * @returns {function} the handle to the linked listener in case it needs to be removed later
       * @public
       */
      debug: function( name ) {
        var listener = function( value ) { console.log( name, value ); };
        this.link( listener );
        return listener;
      },

      /**
       * Modifies the value of this Property with the ! operator.  Works for booleans and non-booleans.
       * @public
       */
      toggle: function() {
        this.value = !this.value;
      },

      // @public Ensures that the Property is eligible for GC
      dispose: function() {

        assert && assert( !this.isDisposed, 'cannot be disposed twice' );

        this.isDisposed = true; // TODO: move this to PhetioObject?

        // remove any listeners that are still attached to this property
        this.unlinkAll();

        PhetioObject.prototype.dispose.call( this );
      },

      /**
       * Checks whether a listener is registered with this Property
       * @param {function} listener
       * @returns {boolean}
       * @public
       */
      hasListener: function( listener ) {
        return this.changedEmitter.hasListener( listener );
      },

      /**
       * Returns true if there are any listeners.
       * @returns {boolean}
       * @public
       */
      hasListeners: function() {
        assert && assert( arguments.length === 0, 'Property.hasListeners should be called without arguments' );
        return this.changedEmitter.hasListeners();
      }
    },

    //statics
    {
      /**
       * Registers a listener with multiple properties, then notifies the listener immediately.
       * @param {Property[]} properties
       * @param {function} listener function that takes values from the properties and returns nothing
       * @returns {Multilink}
       * @static
       */
      multilink: function( properties, listener ) {
        return new Multilink( properties, listener, false );
      },

      /**
       * Registers an listener with multiple properties *without* an immediate callback with current values.
       * @param {Property[]} properties
       * @param {function} listener function that takes values from the properties and returns nothing
       * @returns {Multilink}
       * @static
       */
      lazyMultilink: function( properties, listener ) {
        return new Multilink( properties, listener, true );
      },

      /**
       * Unlinks an listener that was added with multilink or lazyMultilink.
       * @param {Multilink} multilink
       * @static
       */
      unmultilink: function( multilink ) {
        multilink.dispose();
      }
    } );
} );
<commit_msg>Renamed _setAndNotifyListeners => setValueAndNotifyListeners and changed visibility, see https://github.com/phetsims/scenery/issues/817<commit_after>// Copyright 2013-2018, University of Colorado Boulder

/**
 * An observable property which notifies listeners when the value changes.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( function( require ) {
  'use strict';

  // modules
  var axon = require( 'AXON/axon' );
  var Emitter = require( 'AXON/Emitter' );
  var inherit = require( 'PHET_CORE/inherit' );
  var Multilink = require( 'AXON/Multilink' );
  var units = require( 'AXON/units' );
  var PhetioObject = require( 'TANDEM/PhetioObject' );
  var Tandem = require( 'TANDEM/Tandem' );

  // constants
  var TYPEOF_STRINGS = [ 'string', 'number', 'boolean', 'function' ];

  /**
   * @param {*} value - the initial value of the property
   * @param {Object} [options] - options
   * @constructor
   */
  function Property( value, options ) {

    var self = this;

    options = _.extend( {

      tandem: Tandem.optional, // workaround for https://github.com/phetsims/tandem/issues/50

      // {function|string|null} type of the value.
      // If {function}, the function must be a constructor.
      // If {string}, the string must be one of the primitive types listed in TYPEOF_STRINGS.
      // Unused if null.
      // Examples:
      // valueType: Vector2
      // valueType: 'string'
      // valueType: 'number'
      valueType: null,

      // {*[]|null} valid values for this Property. Unused if null.
      // Example:
      // validValues: [ 'horizontal', 'vertical' ]
      validValues: null,

      // {function|null} function that validates the value. Single argument is the value, returns boolean. Unused if null.
      // Example:
      // isValidValue: function( value ) { return Util.isInteger( value ) && value >= 0; }
      isValidValue: null,

      // useDeepEquality: true => Use the `equals` method on the values
      // useDeepEquality: false => Use === for equality test
      useDeepEquality: false,

      // If marked as highFrequency: true, the event will be omitted when the query parameter phetioEmitHighFrequencyEvents=false
      highFrequency: false,

      // {string|null} units for the number, see units.js
      units: null
    }, options );

    // validate options
    assert && assertOptionValueType( options.valueType );
    assert && assert( options.validValues === null || Array.isArray( options.validValues ),
      'validValues must be an array: ' + options.validValues );
    assert && assert( options.isValidValue === null || typeof options.isValidValue === 'function',
      'isValidValue must be a function: ' + options.isValidValue );

    assert && options.units && assert( units.isValidUnits( options.units ), 'invalid units: ' + options.units );

    PhetioObject.call( this, options );

    // @public (phet-io) Units, if any.  See units.js for valid values
    this.units = options.units;

    // @private (read-only) whether to use the values' equals method or === equality
    // useDeepEquality: true => Use the `equals` method on the values
    // useDeepEquality: false => Use === for equality test
    this.useDeepEquality = options.useDeepEquality;

    // @private {function|false} value validation function, false if assertions are disabled
    this.assertPropertyValidateValue = assert && function( value ) {

      options.valueType && assertValueType( value, options.valueType );

      options.validValues && assert( options.validValues.indexOf( value ) !== -1,
        'value is not a member of validValues: ' + value );

      options.isValidValue && assert( options.isValidValue( value ),
        'value failed isValidValue test: ' + value );
    };

    // verify that validValues meet other validation criteria
    if ( this.assertPropertyValidateValue && options.validValues ) {
      options.validValues.forEach( function( value ) {
        self.assertPropertyValidateValue( value );
      } );
    }

    // validate the initial value
    this.assertPropertyValidateValue && this.assertPropertyValidateValue( value );

    // When running as phet-io, if the tandem is specified, the type must be specified.
    // This assertion helps in instrumenting code that has the tandem but not type
    Tandem.validationEnabled() && this.tandem.isSuppliedAndEnabled() && assert && assert( !!options.phetioType,
      'Value type passed to Property must be specified. Tandem.phetioID: ' + this.tandem.phetioID );

    // When running as phet-io, if the tandem is specified, the type must be specified.
    // This assertion helps in instrumenting code that has the tandem but not type
    Tandem.validationEnabled() && this.tandem.isSuppliedAndEnabled() && assert && assert( !!options.phetioType.elementType,
      'phetioType.elementType must be specified. Tandem.phetioID: ' + this.tandem.phetioID );

    // @private - Store the internal value and the initial value
    this._value = value;

    // @private - Initial value
    this._initialValue = value;

    // @public (phet-io)
    this.validValues = options.validValues;

    // @private (unit-tests) - emit1 is called when the value changes (or on link)
    // Also used in ShapePlacementBoard.js at the moment
    this.changedEmitter = new Emitter();

    // @public (read-only, scenery) {boolean} indicate whether the Property has been disposed
    this.isDisposed = false;

    // @private
    this.changeEventOptions = {
      highFrequency: options.highFrequency
    };
  }

  axon.register( 'Property', Property );

  /**
   * Verifies the value of option valueType, fails assertion if invalid.
   * @param {function|string|null} valueType
   */
  function assertOptionValueType( valueType ) {

    if ( !assert ) {
      throw new Error( 'call this function only when assertions are enabled' );
    }

    assert( typeof valueType === 'function' || typeof valueType === 'string' || valueType === null,
      'valueType must be {function|string|null}, valueType=' + valueType );

    // {string} valueType must be one of the primitives in TYPEOF_STRINGS, for typeof comparison
    if ( typeof valueType === 'string' ) {
      assert( _.includes( TYPEOF_STRINGS, valueType ),
        'valueType is a string, but not one of the supported primitive types: ' + valueType );
    }
  }

  /**
   * Performs valueType validation on a value. Fails an assertion if invalid.
   * @param {*} value
   * @param {function|string|null} valueType
   */
  function assertValueType( value, valueType ) {

    if ( !assert ) {
      throw new Error( 'call this function only when assertions are enabled' );
    }

    if ( typeof valueType === 'string' ) {

      // primitive type
      assert( typeof value === valueType, 'value should have typeof ' + valueType + ', value=' + value );
    }
    else if ( typeof valueType === 'function' ) {

      // constructor
      assert( value instanceof valueType, 'value should be instanceof ' + valueType.name + ', value=' + value );
    }
    else {

      // we should never get here, but just in case...
      assert( valueType === null, 'invalid valueType: ' + valueType );
    }
  }

  return inherit( PhetioObject, Property, {

      /**
       * Gets the value.
       * You can also use the es5 getter (property.value) but this means is provided for inner loops
       * or internal code that must be fast.
       * @returns {*}
       * @public
       */
      get: function() {
        return this._value;
      },

      /**
       * Sets the value and notifies listeners.
       * You can also use the es5 getter (property.value) but this means is provided for inner loops
       * or internal code that must be fast.
       * If the value hasn't changed, this is a no-op.
       *
       * @param {*} value
       * @returns {Property} this instance, for chaining.
       * @public
       */
      set: function( value ) {
        this.assertPropertyValidateValue && this.assertPropertyValidateValue( value );
        if ( !this.equalsValue( value ) ) {
          this.setValueAndNotifyListeners( value );
        }
        return this;
      },

      /**
       * Returns true if and only if the specified value equals the value of this property
       * @param {Object} value
       * @returns {boolean}
       * @private
       */
      equalsValue: function( value ) {
        return this.areValuesEqual( value, this._value );
      },

      /**
       * Determines equality semantics for the wrapped type, including whether notifications are sent out when the
       * wrapped value changes, and whether onValue is triggered.
       *
       * useDeepEquality: true => Use the `equals` method on the values
       * useDeepEquality: false => Use === for equality test
       *
       * Alternatively different implementation can be provided by subclasses or instances to change the equals
       * definition. See #10 and #73 and #115
       * @param {Object} a - should have the same type as Property element type
       * @param {Object} b - should have the same type as Property element type
       * @returns {boolean}
       * @private
       */
      areValuesEqual: function( a, b ) {
        if ( this.useDeepEquality && a && b && a.constructor === b.constructor ) {

          assert && assert( !!a.equals, 'no equals function for 1st arg' );
          assert && assert( !!b.equals, 'no equals function for 2nd arg' );
          assert && assert( a.equals( b ) === b.equals( a ), 'incompatible equality checks' );
          return a.equals( b );
        }
        else {

          // Reference equality for objects, value equality for primitives
          return a === b;
        }
      },

      // @public
      get initialValue() {
        return this._initialValue;
      },

      /**
       * Updates the value of this node
       * @param {*} value - the new value this Property will take, which is different than the previous value.
       * @protected - can be overridden.
       */
      setValueAndNotifyListeners: function( value ) {
        var oldValue = this.get();
        this._value = value;
        this._notifyListeners( oldValue );
      },

      // @private
      _notifyListeners: function( oldValue ) {

        // We must short circuit based on tandem here as a guard against the toStateObject calls
        this.tandem.isSuppliedAndEnabled() && this.startEvent( 'model', 'changed', {
          oldValue: this.phetioType.elementType.toStateObject( oldValue ),
          newValue: this.phetioType.elementType.toStateObject( this.get() ),
          units: this.phetioType && this.phetioType.units
        }, this.changeEventOptions );

        this.changedEmitter.emit2( this.get(), oldValue );

        this.tandem.isSuppliedAndEnabled() && this.endEvent();
      },

      /**
       * Use this method when mutating a value (not replacing with a new instance) and you want to send notifications about the change.
       * This is different from the normal axon strategy, but may be necessary to prevent memory allocations.
       * This method is unsafe for removing listeners because it assumes the listener list not modified, to save another allocation
       * Only provides the new reference as a callback (no oldvalue)
       * See https://github.com/phetsims/axon/issues/6
       * @public
       */
      notifyListenersStatic: function() {
        this.changedEmitter.emit1( this.get() );
      },

      /**
       * Resets the value to the initial value.
       * @public
       */
      reset: function() {
        this.set( this._initialValue );
      },

      // @public
      get value() { return this.get(); },

      // @public
      set value( newValue ) { this.set( newValue ); },

      /**
       * Adds listener and calls it immediately. If listener is already registered, this is a no-op. The initial
       * notification provides the current value for newValue and null for oldValue.
       *
       * @param {function} listener a function of the form listener(newValue,oldValue)
       * @public
       */
      link: function( listener ) {
        this.changedEmitter.addListener( listener );
        listener( this.get(), null ); // null should be used when an object is expected but unavailable
      },

      /**
       * Add an listener to the Property, without calling it back right away.
       * This is used when you need to register a listener without an immediate callback.
       *
       * @param {function} listener - a function with a single argument, which is the value of the property at the time the function is called.
       * @public
       */
      lazyLink: function( listener ) {
        this.changedEmitter.addListener( listener );
      },

      /**
       * Removes a listener. If listener is not registered, this is a no-op.
       *
       * @param {function} listener
       * @public
       */
      unlink: function( listener ) {
        this.changedEmitter.removeListener( listener );
      },

      /**
       * Removes all listeners. If no listeners are registered, this is a no-op.
       */
      unlinkAll: function() {
        this.changedEmitter.removeAllListeners();
      },

      /**
       * Links an object's named attribute to this property.  Returns a handle so it can be removed using Property.unlink();
       * Example: modelVisibleProperty.linkAttribute(view,'visible');
       *
       * @param object
       * @param attributeName
       * @public
       */
      linkAttribute: function( object, attributeName ) {
        var handle = function( value ) {object[ attributeName ] = value;};
        this.link( handle );
        return handle;
      },

      /**
       * Unlink an listener added with linkAttribute.  Note: the args of linkAttribute do not match the args of
       * unlinkAttribute: here, you must pass the listener handle returned by linkAttribute rather than object and attributeName
       *
       * @param {function} listener
       * @public
       */
      unlinkAttribute: function( listener ) {
        this.unlink( listener );
      },

      // @public Provide toString for console debugging, see http://stackoverflow.com/questions/2485632/valueof-vs-tostring-in-javascript
      toString: function() {return 'Property{' + this.get() + '}'; },

      // @public
      valueOf: function() {return this.toString();},

      /**
       * Convenience function for debugging a property values.  It prints the new value on registration and when changed.
       * @param name debug name to be printed on the console
       * @returns {function} the handle to the linked listener in case it needs to be removed later
       * @public
       */
      debug: function( name ) {
        var listener = function( value ) { console.log( name, value ); };
        this.link( listener );
        return listener;
      },

      /**
       * Modifies the value of this Property with the ! operator.  Works for booleans and non-booleans.
       * @public
       */
      toggle: function() {
        this.value = !this.value;
      },

      // @public Ensures that the Property is eligible for GC
      dispose: function() {

        assert && assert( !this.isDisposed, 'cannot be disposed twice' );

        this.isDisposed = true; // TODO: move this to PhetioObject?

        // remove any listeners that are still attached to this property
        this.unlinkAll();

        PhetioObject.prototype.dispose.call( this );
      },

      /**
       * Checks whether a listener is registered with this Property
       * @param {function} listener
       * @returns {boolean}
       * @public
       */
      hasListener: function( listener ) {
        return this.changedEmitter.hasListener( listener );
      },

      /**
       * Returns true if there are any listeners.
       * @returns {boolean}
       * @public
       */
      hasListeners: function() {
        assert && assert( arguments.length === 0, 'Property.hasListeners should be called without arguments' );
        return this.changedEmitter.hasListeners();
      }
    },

    //statics
    {
      /**
       * Registers a listener with multiple properties, then notifies the listener immediately.
       * @param {Property[]} properties
       * @param {function} listener function that takes values from the properties and returns nothing
       * @returns {Multilink}
       * @static
       */
      multilink: function( properties, listener ) {
        return new Multilink( properties, listener, false );
      },

      /**
       * Registers an listener with multiple properties *without* an immediate callback with current values.
       * @param {Property[]} properties
       * @param {function} listener function that takes values from the properties and returns nothing
       * @returns {Multilink}
       * @static
       */
      lazyMultilink: function( properties, listener ) {
        return new Multilink( properties, listener, true );
      },

      /**
       * Unlinks an listener that was added with multilink or lazyMultilink.
       * @param {Multilink} multilink
       * @static
       */
      unmultilink: function( multilink ) {
        multilink.dispose();
      }
    } );
} );
<|endoftext|>


<commit_before>'use strict';

//
// Module: API
// ===========
//
// Abstraction for the basic `GET`/`POST` operations of Twitter's REST API.
//
// Methods
// -------
//
// + [Constructor/Initialize](#constructor)
// + [GET](#get)
// + [POST](#post)
//
// Usage
// -----
//
// ```
// var TwitterLib = require('twitter-rest-lite'),
// api = new TwitterLib.API(var_with_keys);
//
// api.get(url, params, callback);
//
// api.post(url, data, callback);
// ```
//
//
// Constructor
// -----------
//
// #### Parameters
//
// + `uri`           - base URI's to use (this should be provided by the
// library itself)
// + `opts`          - `Object` with user-provided params
//   - `consumer_key` - required
//   - `consumer_secret` - required
//   - `token` - required
//   - `token_secret` - required
//
// #### Returns
//
// An `Object` with methods `get` and `post`.
//
// #### Code
function API(uri, opts) {
  this.uri = uri;

  /* checking the required arguments */
  [
    'consumer_key',
    'consumer_secret',
    'token',
    'token_secret'
  ].forEach(function (item) {
    if (opts[item] == null)
      throw new Error('There\'s a required argument missing: ' + item);
  });

  this.opts = opts;
}

//
//
// Public: Abstract GET request to the API
// ---------------------------------------
//
// #### Parameters
//
// + `url`             - String
// + `params`          - [Optional] Object with params to be passed
// + `callback`        - Callback Function
//
// #### Returns
//
// A `Callback` with two parameters. First is an `Error Object` and second
// the body of the response in an `Object`.
//
// #### Example
//
// ```js
// api.get('/statuses/user_timeline.json', {
//   screen_name: 'random',
//   count: 1
// }, function (err, response) {
//   if (err)
//     throw err;
//
//   console.log(response);
// });
// ```
// #### Code
API.prototype.get = function(url, params, callback) {
  var self = this;
  var request = require('request');
  var helper = require('./helper');

  helper.check(url, 'string', '', 'Missing URL parameter', callback);

  url = self.uri.base + url;

  if ((params != null) && (typeof params === 'object')) {
    var qs = require('querystring');
    url += '?' + qs.stringify(params);
  }

  request({
    method: 'GET',
    uri: url,
    oauth: self.opts,
    json: true,
  }, function (err, response, body) {
    return callback(err, body);
  });
};

//
//
// Public: abstract POST request to the API
// ----------------------------------------
//
// #### Parameters
//
// + `url`             - String
// + `data`            - [Required] Object with data
// + `callback`        - Callback Function
//
// #### Returns
//
// A `Callback` with two parameters: `Error Object` and `Object` with
// body response from Twitter's API server.
//
// #### Example
//
// ```js
// api.post('/statuses/update.json', {
//   status: "This is an update to twitter!"
// }, function (err, response) {
//   if (err)
//     throw err;
//
//   console.log(response);
// });
// ```
//
// #### Code
API.prototype.post = function(url, data, callback) {
  var self = this;
  var request = require('request');
  var body = null;
  var helper = require('./helper');

  helper.check(url, 'string', '', 'Missing URL parameter', callback);

  url = self.uri.base + url;

  if (data != null)
    body = JSON.stringify(data);

  request({
    method: 'POST',
    uri: url,
    oauth: self.opts,
    form: data
  }, function (err, response, body) {
    return callback(err, body);
  });
};

module.exports = API;
<commit_msg>lib/api#post: cleaning up<commit_after>'use strict';

//
// Module: API
// ===========
//
// Abstraction for the basic `GET`/`POST` operations of Twitter's REST API.
//
// Methods
// -------
//
// + [Constructor/Initialize](#constructor)
// + [GET](#get)
// + [POST](#post)
//
// Usage
// -----
//
// ```
// var TwitterLib = require('twitter-rest-lite'),
// api = new TwitterLib.API(var_with_keys);
//
// api.get(url, params, callback);
//
// api.post(url, data, callback);
// ```
//
//
// Constructor
// -----------
//
// #### Parameters
//
// + `uri`           - base URI's to use (this should be provided by the
// library itself)
// + `opts`          - `Object` with user-provided params
//   - `consumer_key` - required
//   - `consumer_secret` - required
//   - `token` - required
//   - `token_secret` - required
//
// #### Returns
//
// An `Object` with methods `get` and `post`.
//
// #### Code
function API(uri, opts) {
  this.uri = uri;

  /* checking the required arguments */
  [
    'consumer_key',
    'consumer_secret',
    'token',
    'token_secret'
  ].forEach(function (item) {
    if (opts[item] == null)
      throw new Error('There\'s a required argument missing: ' + item);
  });

  this.opts = opts;
}

//
//
// Public: Abstract GET request to the API
// ---------------------------------------
//
// #### Parameters
//
// + `url`             - String
// + `params`          - [Optional] Object with params to be passed
// + `callback`        - Callback Function
//
// #### Returns
//
// A `Callback` with two parameters. First is an `Error Object` and second
// the body of the response in an `Object`.
//
// #### Example
//
// ```js
// api.get('/statuses/user_timeline.json', {
//   screen_name: 'random',
//   count: 1
// }, function (err, response) {
//   if (err)
//     throw err;
//
//   console.log(response);
// });
// ```
// #### Code
API.prototype.get = function(url, params, callback) {
  var self = this;
  var request = require('request');
  var helper = require('./helper');

  helper.check(url, 'string', '', 'Missing URL parameter', callback);

  url = self.uri.base + url;

  if ((params != null) && (typeof params === 'object')) {
    var qs = require('querystring');
    url += '?' + qs.stringify(params);
  }

  request({
    method: 'GET',
    uri: url,
    oauth: self.opts,
    json: true,
  }, function (err, response, body) {
    return callback(err, body);
  });
};

//
//
// Public: abstract POST request to the API
// ----------------------------------------
//
// #### Parameters
//
// + `url`             - String
// + `data`            - [Required] Object with data
// + `callback`        - Callback Function
//
// #### Returns
//
// A `Callback` with two parameters: `Error Object` and `Object` with
// body response from Twitter's API server.
//
// #### Example
//
// ```js
// api.post('/statuses/update.json', {
//   status: "This is an update to twitter!"
// }, function (err, response) {
//   if (err)
//     throw err;
//
//   console.log(response);
// });
// ```
//
// #### Code
API.prototype.post = function(url, data, callback) {
  var self = this;
  var request = require('request');
  var helper = require('./helper');

  helper.check(url, 'string', '', 'Missing URL parameter', callback);
  helper.check(data, 'object', null, 'Missing data parameter', callback);

  url = self.uri.base + url;

  request({
    method: 'POST',
    uri: url,
    oauth: self.opts,
    form: data
  }, function (err, response, body) {
    return callback(err, body);
  });
};

module.exports = API;
<|endoftext|>


<commit_before>Package.describe({
  summary: "S3 signed uploads for meteorjs.",
  version: "0.0.2-rc.1",
  git: "https://github.com/jimmiebtlr/meteor-s3-signed-upload.git"
});

Package.on_use(function(api){
  api.use(['mrt:aws-sdk@0.2.0'],'server');
  api.use(['aldeed:simple-schema@0.7.0']);
  api.export(['uploadFile'],'client');
  api.export(['S3SignedUploadTmp'],'server');

  api.add_files([
    'client.js'
  ], 'client');

  api.add_files([
    'server.js'
  ], 'server');
});
<commit_msg>Bump version<commit_after>Package.describe({
  summary: "S3 signed uploads for meteorjs.",
  version: "0.0.3-rc.1",
  git: "https://github.com/jimmiebtlr/meteor-s3-signed-upload.git"
});

Package.on_use(function(api){
  api.use(['mrt:aws-sdk@0.2.0'],'server');
  api.use(['aldeed:simple-schema@0.7.0']);
  api.export(['uploadFile'],'client');
  api.export(['S3SignedUploadTmp'],'server');

  api.add_files([
    'client.js'
  ], 'client');

  api.add_files([
    'server.js'
  ], 'server');
});
<|endoftext|>