<commit_before>/*jslint browser: true*/

(function( vui ) {

	'use strict';

	// Check if the provided vui global is defined, otherwise try to require it if
	// we're in a CommonJS environment; otherwise we'll just fail out
	if( vui === undefined ) {
		if( typeof require === 'function' ) {
			vui = require('../../core');
		} else {
			throw new Error('load vui first');
		}
	}

	// Export the vui object if we're in a CommonJS environment.
	// It will already be on the window otherwise
	if( typeof module === 'object' && typeof module.exports === 'object' ) {
		module.exports = vui;
	}

	var $ = vui.$;

	$.widget( "vui.vui_accordion", {

		options: {},

		_create: function() {

			var me = this;

			var $accordion = $( this.element );

			var displayMode = $accordion.attr( 'data-display-mode' );
			if ( displayMode !== 'stacked' ) {
				displayMode = 'accordion';
			}

			this.option( 'displayMode', displayMode );

			$accordion
				.attr( 'role', 'tablist' )
				.attr(
					'aria-multiselectable',
					displayMode !== 'accordion'
				);

			$.each(
				$accordion.find( '.vui-accordion-header' ),
				function( index, headerNode ) {
					me._initializePanel(
						$accordion,
						$( headerNode ),
						( index === 0 )
					);
				}
			);

		},

		_destroy: function () {

			var $accordion = $( this.element );

			$accordion
				.removeAttr( 'role' )
				.removeAttr( 'aria-multiselectable' );

			$.each(
				$accordion.find( '.vui-accordion-toggle' ),
				function( index, toggleNode ) {
					$( toggleNode ).remove();
				}
			);

			$.each(
				$accordion.find( '.vui-accordion-header' ),
				function( index, headerNode ) {
					$( headerNode )
						.removeAttr( 'role' )
						.removeAttr( 'aria-controls' )
						.removeAttr( 'aria-expanded' )
						.removeAttr( 'aria-selected' )
						.removeAttr( 'tabindex' )
						.removeClass( 'vui-accordion-header-active' )
						.removeClass( 'vui-accordion-header-interactive' )
						.unbind( 'click' )
						.unbind( 'focus' )
						.unbind( 'blur' )
						.unbind( 'keydown' )
						.unbind( 'keyup' );
				}
			);

			$.each(
				$accordion.find( '.vui-accordion-content' ),
				function( index, contentNode ) {

					var $content = $( contentNode );
					$content
						.removeAttr( 'role' )
						.removeAttr( 'aria-labelledby' )
						.removeAttr( 'aria-hidden' )
						.removeClass( 'vui-accordion-content-active' );

					if ( $content.data( 'hasGeneratedId' ) ) {
						$content.removeAttr( 'id' );
					}

				}
			);

		},

		_setOption: function( key, value ) {
			if ( key === 'displayMode' ) {
				if ( value === 'stacked' ) {
					value = 'stacked';
				} else {
					value = 'accordion';
				}
				$( this.element ).attr( 'data-display-mode', value );
			}
			$.Widget.prototype._setOption.apply( this, arguments );
		},

		collapseAll: function() {

			var me = this;

			$.each(
				$( this.element ).find( '.vui-accordion-header' ),
				function( index, headerNode ) {
					me._collapsePanel( $( headerNode ) );
				}
			);

		},

		_collapsePanel: function( $header ) {

			if ( !$header.hasClass( 'vui-accordion-panel-expanded' ) ) {
				return;
			}

			$( this.element ).trigger(
				'collapsePanel', {
					header: $header.get(0)
				}
			);

			$header.attr( 'aria-expanded', 'false' )
				.removeClass( 'vui-accordion-panel-expanded' );

			this._updateIcon( $header, false );

			var contentId = $header.attr( 'data-content-id' );

			var contentNode = document.getElementById( contentId );
			if ( contentNode === null ) {
				return;
			}

			$( contentNode )
				.attr( 'aria-hidden', 'true' )
				.attr( 'visibility', 'hidden' )
				.slideUp(250,'swing');

		},

		_expandPanel: function( $header ) {

			var $accordion = $( this.element );

			if ( this.option( 'displayMode' ) === 'accordion' ) {
				$accordion.vui_accordion( 'collapseAll' );
			}

			$accordion.trigger(
				'expandPanel', {
					header: $header.get( 0 ),
					isFirstExpand: !$header.data( 'hasExpanded' )
				}
			);

			$header.attr( 'aria-expanded', 'true' )
				.addClass( 'vui-accordion-panel-expanded' )
				.data( 'hasExpanded', true );

			this._updateIcon( $header, true );

			var contentId = $header.attr( 'data-content-id' );

			var contentNode = document.getElementById( contentId );
			if ( contentNode === null ) {
				return;
			}

			$( contentNode )
				.attr( 'aria-hidden', 'false' )
				.attr( 'visibility', 'visibile' )
				.slideDown(250,'swing');

		},

		_initializePanel: function( $accordion, $header, isFocusable ) {

			var me = this;

			var $content = me._tryGetContent( $header );
			if ( $content === null ) {
				return;
			}

			var contentId = $header.attr( 'data-content-id' );

			var isExpanded = ( $header.attr( 'data-expanded' ) === 'true' ) && !$content.is( ':empty' );
			var labelledById = $header.attr( 'data-content-labelledby' );

			var $headerContent = $header.find( '.vui-accordion-header-content:first-child' );

			var isHeaderInteractive = ( $headerContent.length !== 0 );

			var togglePanel = function() {
				if ( $header.hasClass( 'vui-accordion-panel-expanded' ) ) {
					me._collapsePanel( $header );
				} else {
					me._expandPanel( $header );
				}
			};

			var isEnabled = !$content.is( ':empty' );

			if ( !isExpanded ) {
				$content.attr( 'visibility', 'hidden' );
			}

			if ( isHeaderInteractive ) {

				$header.addClass( 'vui-accordion-header-interactive' );

				var toggle = document.createElement( 'div' );
				toggle.className = 'vui-accordion-toggle';

				var toggleIcon = toggle.appendChild( document.createElement( 'div' ) );
				if ( isExpanded ) {
					toggleIcon.className = 'vui-accordion-toggle-icon vui-icon-accordion-expanded';
				} else {
					toggleIcon.className = 'vui-accordion-toggle-icon vui-icon-accordion-collapsed';
				}

				$header.prepend( toggle );
			}

			$header
				.attr( 'role', 'tab' )
				.attr( 'aria-controls', contentId )
				.attr( 'aria-expanded', isExpanded )
				.attr( 'aria-selected', isFocusable ? 'true' : 'false' )
				.attr( 'tabindex', isFocusable ? '0' : '-1' )
				.css( 'padding', isHeaderInteractive ? '0' : 'auto' )
				.data( 'hasExpanded', isExpanded )
				.removeAttr( 'data-expanded' )
				.click( function( e ) {

					if ( !isEnabled ) {
						return;
					}

					var eventTarget = e.target;

					while ( eventTarget !== $header.get( 0 ) && eventTarget !== null ) {

						if ( eventTarget === $headerContent.get( 0 ) || $( eventTarget ).is( ':focusable' ) ) {
							return;
						}

						eventTarget = eventTarget.parentNode;
					}

					togglePanel();

				} ).focus( function() {

					$header.addClass( 'vui-accordion-header-active' );
					$content.addClass( 'vui-accordion-content-active' );

				} ).blur( function() {

					$header.removeClass( 'vui-accordion-header-active' );
					$content.removeClass( 'vui-accordion-content-active' );

				} ).keydown( function( e ) {

					// prevent scrolling page when arrow keys, home, or end are pressed
					if ( e.keyCode >=35 && e.keyCode <=40 || e.keyCode==32 ) {
						e.preventDefault();
						return false;
					}

					return true;

				} ).keyup( function( e ) {

					if ( e.keyCode === 13 || e.keyCode === 32 ) {
						// enter/space
						if ( !isEnabled ) {
							return;
						}
						togglePanel();
					} else if ( e.keyCode === 39 || e.keyCode === 40 ) {
						// down/right
						me._focusPanel( $header, me._tryGetNextPanel( $header ) );
					} else if ( e.keyCode === 37 || e.keyCode === 38 ) {
						// up/left
						me._focusPanel( $header, me._tryGetPreviousPanel( $header ) );
					} else if ( e.keyCode === 35 ) {
						// end - last panel
						me._focusPanel( $header, me._getLastPanelHeader() );
					} else if ( e.keyCode === 36 ) {
						// home - first panel
						me._focusPanel( $header, me._getFirstPanelHeader() );
					}

				} );

			if ( !isEnabled ) {
				$header
					.attr( 'aria-disabled', 'true' )
					.addClass( 'vui-accordion-header-disabled' );
			}

			$content
				.attr( 'role', 'tabpanel' )
				.attr( 'aria-labelledby', labelledById )
				.attr( 'aria-hidden', 'true' );

			if ( isExpanded ) {

				if ( this.option( 'displayMode' ) === 'accordion' ) {
					$.each(
						$accordion.find( '.vui-accordion-panel-expanded' ),
						function( index, panelNode ) {
							me._collapsePanel( $( panelNode ) );
						}
					);
				}

				$header.addClass( 'vui-accordion-panel-expanded' );

				setTimeout( function() {
					$accordion.trigger(
						'expandPanel', {
							header: $header.get( 0 ),
							isFirstExpand: true
						}
					);
				}, 0 );

				$content
					.attr( 'aria-hidden', 'false' )
					.show();

			}

		},

		_focusPanel: function( $currentHeader, $header ) {

			if ( $header === null ) {
				return;
			}

			$currentHeader
				.attr( 'tabindex', '-1' )
				.attr( 'aria-selected', 'false' );

			$header
				.attr( 'tabindex', '0' )
				.attr( 'aria-selected', 'true' )
				.focus();

		},

		_getFirstPanelHeader: function() {
			var $headers = $( this.element )
				.find( '.vui-accordion-header');
			return $( $headers[ 0 ] );
		},

		_getLastPanelHeader: function() {
			var $headers = $( this.element )
				.find( '.vui-accordion-header');
			return $( $headers[ $headers.length - 1 ] );
		},

		_tryGetContent: function( $header ) {

			var contentId = $header.attr( 'data-content-id' );

			if ( contentId !== undefined ) {
				var contentNode = document.getElementById( contentId );
				if ( contentNode !== null ) {
					return $( contentNode );
				} else {
					return null;
				}
			}

			var $nextElement = $header.next( '.vui-accordion-content' );
			if ( $nextElement.length !== 0 ) {

				contentId = $nextElement.attr( 'id' );
				if ( contentId === undefined ) {

					$nextElement.uniqueId()
						.data( 'hasGeneratedId', true );

					contentId = $nextElement.attr( 'id' );
				}

				$header.attr( 'data-content-id', contentId );

				return $nextElement;

			}

			return null;

		},

		_tryGetPreviousPanel: function( $header ) {

			var $previousElement = $header.prev();

			if ( $previousElement.length === 0 ) {
				return this._getLastPanelHeader();
			} else if ( $previousElement.hasClass( 'vui-accordion-header' ) ) {
				return $previousElement;
			} else {
				return this._tryGetPreviousPanel( $previousElement );
			}

		},

		_tryGetNextPanel: function( $header ) {

			var $nextElement = $header.next();

			if ( $nextElement.length === 0 ) {
				return this._getFirstPanelHeader();
			} else if ( $nextElement.hasClass( 'vui-accordion-header' ) ) {
				return $nextElement;
			} else {
				return this._tryGetNextPanel( $nextElement );
			}

		},

		_updateIcon: function( $header, isExpanded ) {

			var toggleIcon = $header.find( '.vui-accordion-toggle-icon' );
			if ( toggleIcon.length > 0 ) {
				if ( isExpanded ) {
					toggleIcon.addClass( 'vui-icon-accordion-expanded' );
					toggleIcon.removeClass( 'vui-icon-accordion-collapsed' );
				} else {
					toggleIcon.addClass( 'vui-icon-accordion-collapsed' );
					toggleIcon.removeClass( 'vui-icon-accordion-expanded' );
				}
			}

		}

	} );

	vui.addClassInitializer(
			'vui-accordion',
			function( node ) {
				$( node ).vui_accordion();
			}
		);

})( window.vui );<commit_msg>Removing vui stuff since it was only needed for the vui.addClassInitializer call.<commit_after>/*jslint browser: true*/

(function() {

	'use strict';

	$.widget( "vui.vui_accordion", {

		options: {},

		_create: function() {

			var me = this;

			var $accordion = $( this.element );

			var displayMode = $accordion.attr( 'data-display-mode' );
			if ( displayMode !== 'stacked' ) {
				displayMode = 'accordion';
			}

			this.option( 'displayMode', displayMode );

			$accordion
				.attr( 'role', 'tablist' )
				.attr(
					'aria-multiselectable',
					displayMode !== 'accordion'
				);

			$.each(
				$accordion.find( '.vui-accordion-header' ),
				function( index, headerNode ) {
					me._initializePanel(
						$accordion,
						$( headerNode ),
						( index === 0 )
					);
				}
			);

		},

		_destroy: function () {

			var $accordion = $( this.element );

			$accordion
				.removeAttr( 'role' )
				.removeAttr( 'aria-multiselectable' );

			$.each(
				$accordion.find( '.vui-accordion-toggle' ),
				function( index, toggleNode ) {
					$( toggleNode ).remove();
				}
			);

			$.each(
				$accordion.find( '.vui-accordion-header' ),
				function( index, headerNode ) {
					$( headerNode )
						.removeAttr( 'role' )
						.removeAttr( 'aria-controls' )
						.removeAttr( 'aria-expanded' )
						.removeAttr( 'aria-selected' )
						.removeAttr( 'tabindex' )
						.removeClass( 'vui-accordion-header-active' )
						.removeClass( 'vui-accordion-header-interactive' )
						.unbind( 'click' )
						.unbind( 'focus' )
						.unbind( 'blur' )
						.unbind( 'keydown' )
						.unbind( 'keyup' );
				}
			);

			$.each(
				$accordion.find( '.vui-accordion-content' ),
				function( index, contentNode ) {

					var $content = $( contentNode );
					$content
						.removeAttr( 'role' )
						.removeAttr( 'aria-labelledby' )
						.removeAttr( 'aria-hidden' )
						.removeClass( 'vui-accordion-content-active' );

					if ( $content.data( 'hasGeneratedId' ) ) {
						$content.removeAttr( 'id' );
					}

				}
			);

		},

		_setOption: function( key, value ) {
			if ( key === 'displayMode' ) {
				if ( value === 'stacked' ) {
					value = 'stacked';
				} else {
					value = 'accordion';
				}
				$( this.element ).attr( 'data-display-mode', value );
			}
			$.Widget.prototype._setOption.apply( this, arguments );
		},

		collapseAll: function() {

			var me = this;

			$.each(
				$( this.element ).find( '.vui-accordion-header' ),
				function( index, headerNode ) {
					me._collapsePanel( $( headerNode ) );
				}
			);

		},

		_collapsePanel: function( $header ) {

			if ( !$header.hasClass( 'vui-accordion-panel-expanded' ) ) {
				return;
			}

			$( this.element ).trigger(
				'collapsePanel', {
					header: $header.get(0)
				}
			);

			$header.attr( 'aria-expanded', 'false' )
				.removeClass( 'vui-accordion-panel-expanded' );

			this._updateIcon( $header, false );

			var contentId = $header.attr( 'data-content-id' );

			var contentNode = document.getElementById( contentId );
			if ( contentNode === null ) {
				return;
			}

			$( contentNode )
				.attr( 'aria-hidden', 'true' )
				.attr( 'visibility', 'hidden' )
				.slideUp(250,'swing');

		},

		_expandPanel: function( $header ) {

			var $accordion = $( this.element );

			if ( this.option( 'displayMode' ) === 'accordion' ) {
				$accordion.vui_accordion( 'collapseAll' );
			}

			$accordion.trigger(
				'expandPanel', {
					header: $header.get( 0 ),
					isFirstExpand: !$header.data( 'hasExpanded' )
				}
			);

			$header.attr( 'aria-expanded', 'true' )
				.addClass( 'vui-accordion-panel-expanded' )
				.data( 'hasExpanded', true );

			this._updateIcon( $header, true );

			var contentId = $header.attr( 'data-content-id' );

			var contentNode = document.getElementById( contentId );
			if ( contentNode === null ) {
				return;
			}

			$( contentNode )
				.attr( 'aria-hidden', 'false' )
				.attr( 'visibility', 'visibile' )
				.slideDown(250,'swing');

		},

		_initializePanel: function( $accordion, $header, isFocusable ) {

			var me = this;

			var $content = me._tryGetContent( $header );
			if ( $content === null ) {
				return;
			}

			var contentId = $header.attr( 'data-content-id' );

			var isExpanded = ( $header.attr( 'data-expanded' ) === 'true' ) && !$content.is( ':empty' );
			var labelledById = $header.attr( 'data-content-labelledby' );

			var $headerContent = $header.find( '.vui-accordion-header-content:first-child' );

			var isHeaderInteractive = ( $headerContent.length !== 0 );

			var togglePanel = function() {
				if ( $header.hasClass( 'vui-accordion-panel-expanded' ) ) {
					me._collapsePanel( $header );
				} else {
					me._expandPanel( $header );
				}
			};

			var isEnabled = !$content.is( ':empty' );

			if ( !isExpanded ) {
				$content.attr( 'visibility', 'hidden' );
			}

			if ( isHeaderInteractive ) {

				$header.addClass( 'vui-accordion-header-interactive' );

				var toggle = document.createElement( 'div' );
				toggle.className = 'vui-accordion-toggle';

				var toggleIcon = toggle.appendChild( document.createElement( 'div' ) );
				if ( isExpanded ) {
					toggleIcon.className = 'vui-accordion-toggle-icon vui-icon-accordion-expanded';
				} else {
					toggleIcon.className = 'vui-accordion-toggle-icon vui-icon-accordion-collapsed';
				}

				$header.prepend( toggle );
			}

			$header
				.attr( 'role', 'tab' )
				.attr( 'aria-controls', contentId )
				.attr( 'aria-expanded', isExpanded )
				.attr( 'aria-selected', isFocusable ? 'true' : 'false' )
				.attr( 'tabindex', isFocusable ? '0' : '-1' )
				.css( 'padding', isHeaderInteractive ? '0' : 'auto' )
				.data( 'hasExpanded', isExpanded )
				.removeAttr( 'data-expanded' )
				.click( function( e ) {

					if ( !isEnabled ) {
						return;
					}

					var eventTarget = e.target;

					while ( eventTarget !== $header.get( 0 ) && eventTarget !== null ) {

						if ( eventTarget === $headerContent.get( 0 ) || $( eventTarget ).is( ':focusable' ) ) {
							return;
						}

						eventTarget = eventTarget.parentNode;
					}

					togglePanel();

				} ).focus( function() {

					$header.addClass( 'vui-accordion-header-active' );
					$content.addClass( 'vui-accordion-content-active' );

				} ).blur( function() {

					$header.removeClass( 'vui-accordion-header-active' );
					$content.removeClass( 'vui-accordion-content-active' );

				} ).keydown( function( e ) {

					// prevent scrolling page when arrow keys, home, or end are pressed
					if ( e.keyCode >=35 && e.keyCode <=40 || e.keyCode==32 ) {
						e.preventDefault();
						return false;
					}

					return true;

				} ).keyup( function( e ) {

					if ( e.keyCode === 13 || e.keyCode === 32 ) {
						// enter/space
						if ( !isEnabled ) {
							return;
						}
						togglePanel();
					} else if ( e.keyCode === 39 || e.keyCode === 40 ) {
						// down/right
						me._focusPanel( $header, me._tryGetNextPanel( $header ) );
					} else if ( e.keyCode === 37 || e.keyCode === 38 ) {
						// up/left
						me._focusPanel( $header, me._tryGetPreviousPanel( $header ) );
					} else if ( e.keyCode === 35 ) {
						// end - last panel
						me._focusPanel( $header, me._getLastPanelHeader() );
					} else if ( e.keyCode === 36 ) {
						// home - first panel
						me._focusPanel( $header, me._getFirstPanelHeader() );
					}

				} );

			if ( !isEnabled ) {
				$header
					.attr( 'aria-disabled', 'true' )
					.addClass( 'vui-accordion-header-disabled' );
			}

			$content
				.attr( 'role', 'tabpanel' )
				.attr( 'aria-labelledby', labelledById )
				.attr( 'aria-hidden', 'true' );

			if ( isExpanded ) {

				if ( this.option( 'displayMode' ) === 'accordion' ) {
					$.each(
						$accordion.find( '.vui-accordion-panel-expanded' ),
						function( index, panelNode ) {
							me._collapsePanel( $( panelNode ) );
						}
					);
				}

				$header.addClass( 'vui-accordion-panel-expanded' );

				setTimeout( function() {
					$accordion.trigger(
						'expandPanel', {
							header: $header.get( 0 ),
							isFirstExpand: true
						}
					);
				}, 0 );

				$content
					.attr( 'aria-hidden', 'false' )
					.show();

			}

		},

		_focusPanel: function( $currentHeader, $header ) {

			if ( $header === null ) {
				return;
			}

			$currentHeader
				.attr( 'tabindex', '-1' )
				.attr( 'aria-selected', 'false' );

			$header
				.attr( 'tabindex', '0' )
				.attr( 'aria-selected', 'true' )
				.focus();

		},

		_getFirstPanelHeader: function() {
			var $headers = $( this.element )
				.find( '.vui-accordion-header');
			return $( $headers[ 0 ] );
		},

		_getLastPanelHeader: function() {
			var $headers = $( this.element )
				.find( '.vui-accordion-header');
			return $( $headers[ $headers.length - 1 ] );
		},

		_tryGetContent: function( $header ) {

			var contentId = $header.attr( 'data-content-id' );

			if ( contentId !== undefined ) {
				var contentNode = document.getElementById( contentId );
				if ( contentNode !== null ) {
					return $( contentNode );
				} else {
					return null;
				}
			}

			var $nextElement = $header.next( '.vui-accordion-content' );
			if ( $nextElement.length !== 0 ) {

				contentId = $nextElement.attr( 'id' );
				if ( contentId === undefined ) {

					$nextElement.uniqueId()
						.data( 'hasGeneratedId', true );

					contentId = $nextElement.attr( 'id' );
				}

				$header.attr( 'data-content-id', contentId );

				return $nextElement;

			}

			return null;

		},

		_tryGetPreviousPanel: function( $header ) {

			var $previousElement = $header.prev();

			if ( $previousElement.length === 0 ) {
				return this._getLastPanelHeader();
			} else if ( $previousElement.hasClass( 'vui-accordion-header' ) ) {
				return $previousElement;
			} else {
				return this._tryGetPreviousPanel( $previousElement );
			}

		},

		_tryGetNextPanel: function( $header ) {

			var $nextElement = $header.next();

			if ( $nextElement.length === 0 ) {
				return this._getFirstPanelHeader();
			} else if ( $nextElement.hasClass( 'vui-accordion-header' ) ) {
				return $nextElement;
			} else {
				return this._tryGetNextPanel( $nextElement );
			}

		},

		_updateIcon: function( $header, isExpanded ) {

			var toggleIcon = $header.find( '.vui-accordion-toggle-icon' );
			if ( toggleIcon.length > 0 ) {
				if ( isExpanded ) {
					toggleIcon.addClass( 'vui-icon-accordion-expanded' );
					toggleIcon.removeClass( 'vui-icon-accordion-collapsed' );
				} else {
					toggleIcon.addClass( 'vui-icon-accordion-collapsed' );
					toggleIcon.removeClass( 'vui-icon-accordion-expanded' );
				}
			}

		}

	} );

} )();<|endoftext|>


<commit_before>'use strict';

const { getGraphQLInput } = require('./input');
const {
  isIntrospectionQuery,
  handleIntrospection,
} = require('./introspection');
const { getMainDef, getFragments } = require('./top_level');
const { parseActions } = require('./actions');
const { augmentActions } = require('./augment');
const { getSummary } = require('./summary');
const { parseModels } = require('./models');
const { fireResolvers } = require('./resolver');
const { assembleActions } = require('./assemble');
const { selectFields } = require('./select');
const { parseResponse } = require('./response');

// GraphQL query handling
const executeGraphql = async function (
  {
    idl: { GraphQLSchema: schema, shortcuts: { modelsMap } },
    queryVars,
    payload,
    goal,
    mInput,
  },
  nextLayer,
) {
  const {
    query,
    variables,
    operationName,
    queryDocument,
  } = getGraphQLInput({ queryVars, payload });

  // Introspection GraphQL query
  if (isIntrospectionQuery({ query })) {
    return handleIntrospection({
      schema,
      queryDocument,
      variables,
      operationName,
    });
  }

  const { selectionSet } = getMainDef({ queryDocument, operationName, goal });
  const fragments = getFragments({ queryDocument });
  const { actions } = parseActions({ selectionSet, fragments, variables });

  const actionsA = augmentActions({ actions });

  const { topArgs, operationSummary } = getSummary({ actions: actionsA });

  const actionsB = parseModels({ actions: actionsA, modelsMap });

  const actionsC = await fireResolvers({
    actions: actionsB,
    nextLayer,
    mInput,
  });

  const responseData = assembleActions({ actions: actionsC });

  const responseDataA = selectFields({ responseData, actions: actionsC });

  const response = parseResponse({
    responseData: responseDataA,
    actions: actionsC,
  });

  return { response, topArgs, operationSummary };
};

module.exports = {
  executeGraphql,
};
<commit_msg>Move line<commit_after>'use strict';

const { getGraphQLInput } = require('./input');
const {
  isIntrospectionQuery,
  handleIntrospection,
} = require('./introspection');
const { getMainDef, getFragments } = require('./top_level');
const { parseActions } = require('./actions');
const { augmentActions } = require('./augment');
const { getSummary } = require('./summary');
const { parseModels } = require('./models');
const { fireResolvers } = require('./resolver');
const { assembleActions } = require('./assemble');
const { selectFields } = require('./select');
const { parseResponse } = require('./response');

// GraphQL query handling
const executeGraphql = async function (
  {
    idl: { GraphQLSchema: schema, shortcuts: { modelsMap } },
    queryVars,
    payload,
    goal,
    mInput,
  },
  nextLayer,
) {
  const {
    query,
    variables,
    operationName,
    queryDocument,
  } = getGraphQLInput({ queryVars, payload });

  // Introspection GraphQL query
  if (isIntrospectionQuery({ query })) {
    return handleIntrospection({
      schema,
      queryDocument,
      variables,
      operationName,
    });
  }

  const { selectionSet } = getMainDef({ queryDocument, operationName, goal });
  const fragments = getFragments({ queryDocument });
  const { actions } = parseActions({ selectionSet, fragments, variables });

  const actionsA = augmentActions({ actions });

  const actionsB = parseModels({ actions: actionsA, modelsMap });
  const { topArgs, operationSummary } = getSummary({ actions: actionsB });

  const actionsC = await fireResolvers({
    actions: actionsB,
    nextLayer,
    mInput,
  });

  const responseData = assembleActions({ actions: actionsC });

  const responseDataA = selectFields({ responseData, actions: actionsC });

  const response = parseResponse({
    responseData: responseDataA,
    actions: actionsC,
  });

  return { response, topArgs, operationSummary };
};

module.exports = {
  executeGraphql,
};
<|endoftext|>


<commit_before>/**
 * Created by danielabrao on 4/11/16.
 */
/*jslint node:true*/
(function () {
    'use strict';
    var Gpio = require('onoff').Gpio,
        color0 = new Gpio(18, 'out'),
        color1 = new Gpio(5, 'out'),
        color2 = new Gpio(6, 'out'),
        optionSelected;

    function handleSwitches(switch1, switch2) {
        console.log('here');
        try {
            switch1.writeSync(0);
            switch2.writeSync(0);
        } catch (e) {
            console.log(["Error occurred turning the lights off: ", e].join(""));
        }
    }

    module.exports = function (app) {

        app.post('/changeLightState', function (req, res) {
            optionSelected = req.body.selectedLight;
            console.log(optionSelected);

            if (optionSelected === '1') {
                handleSwitches(color1, color2);
                color0.writeSync(1, function () {
                    res.status(200).send("Switch 0 turned on");
                });
            }

            if (optionSelected === '2') {
                handleSwitches(color0, color2);
                color1.writeSync(1, function () {
                    res.status(200).send("Switch 1 turned on");
                });
            }

            if (optionSelected === '3') {
                handleSwitches(color0, color1);
                color2.writeSync(1, function () {
                    res.status(200).send("Switch 2 turned on");
                });
            }

        });

    };

}());<commit_msg>debug<commit_after>/**
 * Created by danielabrao on 4/11/16.
 */
/*jslint node:true*/
(function () {
    'use strict';
    var Gpio = require('onoff').Gpio,
        color0 = new Gpio(18, 'out'),
        color1 = new Gpio(5, 'out'),
        color2 = new Gpio(6, 'out'),
        optionSelected;

    function handleSwitches(switch1, switch2) {
        console.log('here');
        try {
            switch1.writeSync(0);
            switch2.writeSync(0);
        } catch (e) {
            console.log(["Error occurred turning the lights off: ", e].join(""));
        }
    }

    module.exports = function (app) {

        app.post('/changeLightState', function (req, res) {
            optionSelected = req.body.selectedLight;
            console.log(optionSelected);

            if (optionSelected === '1') {
                handleSwitches(color1, color2);
                return color0.writeSync(1, function () {
                    console.log('tatata');
                    return res.status(200).send("Switch 0 turned on");
                });
            }

            if (optionSelected === '2') {
                handleSwitches(color0, color2);
                color1.writeSync(1, function () {
                    res.status(200).send("Switch 1 turned on");
                });
            }

            if (optionSelected === '3') {
                handleSwitches(color0, color1);
                return color2.writeSync(1, function () {
                    console.log('tatata3');
                    return res.status(200).send("Switch 2 turned on");
                });
            }

        });

    };

}());<|endoftext|>


<commit_before>'use strict';

var async              = require('async');
var extend             = require('util')._extend;
var bucketNameComposer = require('../private/bucket_name_composer');

/**
 * Update properties for the model instance data
 * @param {String} model The model name
 * @param {Object} data The model data
 * @param {Function} [apiCallback] The callback function
 */
module.exports = function(modelName, id, data, apiCallback){
  var self = this;

  if (!id) throw new Error('Riak updateAttributes called for a document with no id');

  async.waterfall([
    find,
    merge,
    save
  ], apiCallback);

  function find(callback){
    self.find(modelName, id, function(error, result){
      if (error)   return callback(error);
      if (!result) return apiCallback(null, null);

      callback(error, result);
    });
  }

  function merge(document, callback){
    callback(null, extend(document, data));
  }

  function save(updatedDocument, callback){
    self.db.save(bucketNameComposer(self, modelName), id, updatedDocument, function(error, success){
      if (error) return callback(error);

      callback(null, updatedDocument);
    });
  }
};
<commit_msg>add meta call to update riak save<commit_after>'use strict';

var async              = require('async');
var extend             = require('util')._extend;
var bucketNameComposer = require('../private/bucket_name_composer');

/**
 * Update properties for the model instance data
 * @param {String} model The model name
 * @param {Object} data The model data
 * @param {Function} [apiCallback] The callback function
 */
module.exports = function(modelName, id, data, apiCallback){
  var self = this;

  if (!id) throw new Error('Riak updateAttributes called for a document with no id');

  async.waterfall([
    find,
    merge,
    save
  ], apiCallback);

  function find(callback){
    self.find(modelName, id, function(error, result){
      if (error)   return callback(error);
      if (!result) return apiCallback(null, null);

      callback(error, result);
    });
  }

  function merge(document, callback){
    callback(null, extend(document, data));
  }

  function save(updatedDocument, callback){
    self.db.save(bucketNameComposer(self, modelName), id, updatedDocument, { returnbody: false }, function(error, success){
      console.log(arguments);

      if (error) return callback(error);

      callback(null, updatedDocument);
    });
  }
};
<|endoftext|>


<commit_before>/*
  Load in PhraseApp translations with v2 API.
  Must specify an API token, a locale, and a format.
  Default format returned is js for i18n-node-2.
*/

var request = require('request');
var fs = require('fs');
var _ = require('lodash');

var path = 'https://api.phraseapp.com/v2';

module.exports = {
  initialize: function(options, callback) {
    if (!options.access_token || !options.project_id) {
      throw new Error('Must supply a value for access_token and project_id');
    }

    if (!callback) {
      callback = function(err) {
        if (err) { throw new Error(err); }
      };
    }

    var config = module.exports.configure(options);
    module.exports.download(config, function(err, res) {
      if (err) { return callback(err); }
    });
  },

  configure: function(options) {
    var default_options = {
      file_format: "node_json",
      file_extension: "js",
      location: process.cwd()
    };

    return _.merge(default_options, options);
  },

  download: function(options, callback) {
    module.exports.fetchLocales(options,
      function (err, locales) {
        if (!err) {
          _.each(locales, function(l) {
            module.exports.downloadTranslationFile(l, options, function(err, res) {
              if (!err) {
                console.log("Translation for " + l + " downloaded successfully.");
                return callback(null, 'Success');
              } else {
                console.error("Error downloading " + l + ".", err);
                return callback(err);
              }
            });
          });
        }
      });
  },

  fetchLocales: function(options, callback) {
    var locales;

    request(path + '/projects/' + options.project_id + '/locales?access_token=' + options.access_token, function(err, res, body) {
      if (!err && res.statusCode == 200) {
        locales = _.pluck(JSON.parse(body), "code");
        return callback(null, locales);
      } else if (err) {
        console.error("An error occurred when fetching locales", err);
        return callback(err);
      }
    });
  },

  downloadTranslationFile: function(locale, options, callback) {
    var translationPath = path + '/projects/' + options.project_id + '/locales/' + locale + '/download?access_token=' + options.access_token + '&file_format=' + options.file_format;
    console.log(translationPath);

    request(translationPath, function(err, res, body) {
      if (!err && res.statusCode == 200) {
        var fileName = options.location + "/" + locale + "." + options.file_extension;

        fs.writeFile(fileName, body, function(err) {
          if (err) {
            return console.error("An error occured when downloading translation file", err);
          }

          return callback(null, fileName);
        })
      } else if (err) {
        console.error("An error occured when downloading translation file", err);
        return callback(err);
      }
    });
  }
}<commit_msg>Remove console.logs<commit_after>/*
  Load in PhraseApp translations with v2 API.
  Must specify an API token, a locale, and a format.
  Default format returned is js for i18n-node-2.
*/

var request = require('request');
var fs = require('fs');
var _ = require('lodash');

var path = 'https://api.phraseapp.com/v2';

module.exports = {
  initialize: function(options, callback) {
    if (!options.access_token || !options.project_id) {
      throw new Error('Must supply a value for access_token and project_id');
    }

    if (!callback) {
      callback = function(err) {
        if (err) { throw new Error(err); }
      };
    }

    var config = module.exports.configure(options);
    module.exports.download(config, function(err, res) {
      if (err) { return callback(err); }
    });
  },

  configure: function(options) {
    var default_options = {
      file_format: "node_json",
      file_extension: "js",
      location: process.cwd()
    };

    return _.merge(default_options, options);
  },

  download: function(options, callback) {
    module.exports.fetchLocales(options,
      function (err, locales) {
        if (!err) {
          _.each(locales, function(l) {
            module.exports.downloadTranslationFile(l, options, function(err, res) {
              if (!err) {
                console.log("Translation for " + l + " downloaded successfully.");
                return callback(null, 'Success');
              } else {
                console.error("Error downloading " + l + ".", err);
                return callback(err);
              }
            });
          });
        }
      });
  },

  fetchLocales: function(options, callback) {
    var locales;

    request(path + '/projects/' + options.project_id + '/locales?access_token=' + options.access_token, function(err, res, body) {
      if (!err && res.statusCode == 200) {
        locales = _.pluck(JSON.parse(body), "code");
        return callback(null, locales);
      } else if (err) {
        console.error("An error occurred when fetching locales", err);
        return callback(err);
      }
    });
  },

  downloadTranslationFile: function(locale, options, callback) {
    var translationPath = path + '/projects/' + options.project_id + '/locales/' + locale + '/download?access_token=' + options.access_token + '&file_format=' + options.file_format;

    request(translationPath, function(err, res, body) {
      if (!err && res.statusCode == 200) {
        var fileName = options.location + "/" + locale + "." + options.file_extension;

        fs.writeFile(fileName, body, function(err) {
          if (err) {
            return console.error("An error occured when downloading translation file", err);
          }

          return callback(null, fileName);
        })
      } else if (err) {
        console.error("An error occured when downloading translation file", err);
        return callback(err);
      }
    });
  }
}<|endoftext|>


<commit_before>var express = require('express')
var app = express()

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/academydb');

var bodyParser = require('body-parser');
var paragraph = require('./model/paragraph.model');

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.raw());
app.use(bodyParser.json());
app.use(function(req, res, next) {
	res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST');
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type, Authorization');
    res.setHeader('Content-Type', 'application/json');
    next();
});

app.set('json spaces', 2);

app.post('/api/paragraph/create', function(req, res) {

	var newParagraph = paragraph(req.body);

	if (!req.body){

	 	return res.sendStatus(400);

	}else{

	 	newParagraph.save(function(err) {
	 	  if (err){ res.send(err); };
	 	  res.send('Paragraph created!');
	 	});

	}

});

app.get('/api/paragraph/:id', function(req, res) {

	paragraph.findById(req.params.id, function(err,paragraph){

		res.send(paragraph);

	});

});

app.get('/api/paragraph/', function(req, res) {

	paragraph.find(function(err,paragraph){

		res.send(paragraph);

	});

});

app.listen(82);
console.log("App listening on port 82");
<commit_msg>changing service and add paragraph service<commit_after>var express = require('express')
var app = express()

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/academydb');

var bodyParser = require('body-parser');
var paragraph = require('./model/paragraph.model');

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.raw());
app.use(bodyParser.json());
app.use(function(req, res, next) {
	res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST');
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type, Authorization');
    res.setHeader('Content-Type', 'application/json');
    next();
});

app.set('json spaces', 2);

app.post('/api/paragraph/create', function(req, res) {

	var newParagraph = paragraph(req.body);

	if (!req.body){

	 	return res.sendStatus(400);

	}else{

	 	newParagraph.save(function(err) {
	 	  if (err){ res.send(err); };
	 	  res.send('Paragraph created!');
	 	});

	}

});

app.get('/api/paragraph/:id', function(req, res) {

	paragraph.findById(req.params.id, function(err,paragraph){

		res.send(paragraph);

	});

});

app.get('/api/paragraph', function(req, res) {

	paragraph.find(function(err,paragraph){

		res.send(paragraph);

	});

});

app.listen(82);
console.log("App listening on port 82");
<|endoftext|>


<commit_before>#!/usr/bin/env node

// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

/*eslint no-console: [0] */
/*eslint no-process-exit: [0] */
/*eslint max-params: [2, 6] */
/*eslint max-statements: [2, 40] */
'use strict';

var TChannel = require('tchannel');
var TChannelAsThrift = require('tchannel/as/thrift');
var TChannelAsJSON = require('tchannel/as/json');
var myLocalIp = require('my-local-ip');
var DebugLogtron = require('debug-logtron');
var rc = require('rc');
var rcUtils = require('rc/lib/utils');
var camelCaseKeys = require('camelcase-keys');
var traverse = require('traverse');
var extend = require('xtend');

var fmt = require('util').format;
var console = require('console');
var process = require('process');
var spawn = require('child_process').spawn;
var fs = require('fs');
var path = require('path');
var url = require('url');
var assert = require('assert');

var safeJsonParse = require('safe-json-parse/tuple');

var Logger = require('./logger');
var Benchmark = require('./benchmark');
var HealthLogger = require('./health-logger');
var TCurlAsHttp = require('./as-http');

var shon = require('shon/parse');
var ShonCursor = require('shon/cursor');
var ShonIterator = require('shon/iterator');
var ShonDelegate = require('shon/delegate');

var packageJson = require('./package.json');

module.exports = main;

var command = require('./tcurl.json');
var healthCommand = require('./health.json');

// delegate implements error(message, err), response(res), exit()
function main(argv, delegate) {

    var args = ['tcurl'].concat(argv);
    var cursor = new ShonCursor(args, 1);
    var iterator = new ShonIterator(cursor);
    var shonDelegate = new ShonDelegate({
        cursor: cursor,
        logUsage: help
    });
    var config = shon(command, iterator, shonDelegate);

    if (config === null) {
        return shonDelegate.end();
    }

    if (shonDelegate.trumped === 'help') {
        return help();
    } else if (shonDelegate.trumped === 'man') {
        return man();
    } else if (shonDelegate.trumped === 'version') {
        delegate = delegate || new Logger();
        return delegate.log(packageJson.version);
    } else if (shonDelegate.trumped === 'health') {
        cursor = new ShonCursor(args, 1);
        iterator = new ShonIterator(cursor);
        shonDelegate = new ShonDelegate({
            cursor: cursor,
            logUsage: help
        });
        config = shon(healthCommand, iterator, shonDelegate);
        delegate = delegate || new HealthLogger();
        config.thrift = path.join(__dirname, 'meta.thrift');
        config.endpoint = 'Meta::health';
    }

    config = extend(
        rc('tcurl', {}, config),
        env(),
        config
    );

    config = parseArgs(config);

    var tcurl = new TCurl();

    delegate = delegate || new Logger();

    if (config.rate) {
        var benchmark = new Benchmark({
            tcurl: tcurl,
            cmdOptions: config,
            logger: delegate
        });
        return benchmark.run(function done() {
            tcurl.client.close();
            delegate.exit();
        });
    }

    return tcurl.request(config, delegate);
}

function env() {
    var envConf = rcUtils.env('TCURL_');
    return traverse(envConf).map(camelcaseObjectKeys);

    function camelcaseObjectKeys(value) {
        if (typeof value === 'object') {
            this.update(camelCaseKeys(value));
        }
    }
}

main.exec = function execMain(str, delegate) {
    main(str, delegate);
};

function help() {
    console.log(fs.readFileSync(path.join(__dirname, 'usage.txt').trim(), 'utf8'));
}

function man() {
    var options = {
        cwd: process.cwd(),
        /*eslint no-process-env: [0] */
        env: process.env,
        setsid: false,
        customFds: [0, 1, 2]
    };

    spawn('man', [path.join(__dirname, 'man', 'tcurl.1')], options);
}

function parseArgs(argv) {
    var service = argv.service;
    var endpoint = argv.endpoint;
    var health = argv.health;

    // Prefer peer specified at the command line over peerlist
    var peers;
    if (argv.peers.length) {
        peers = argv.peers;
    } else if (argv.hostlist) {
        peers = parsePeerlist(argv.hostlist);
        if (peers === null) {
            return null;
        }
    } else {
        console.error('Must specify at least one peer with -p|--peer or -P|--peerlist');
        help();
        process.exit(-1);
    }

    var ip;
    function normalizePeer(address) {
        if (!ip) {
            ip = myLocalIp();
        }
        var parsedUri = url.parse('tchannel://' + address);
        if (parsedUri.hostname === 'localhost') {
            parsedUri.hostname = ip;
        }
        assert(parsedUri.hostname, 'host required');
        assert(parsedUri.port, 'port required');
        return parsedUri.hostname + ':' + parsedUri.port;
    }

    peers = peers.map(normalizePeer);

    if (!health && !endpoint) {
        console.error('Please specify an endpoint or --health');
        return null;
    }

    if (!service) {
        console.error('Please specify a service');
        return null;
    }

    var argScheme;
    if (argv.raw) {
        argScheme = 'raw';
    } else if (argv.http) {
        argScheme = 'http';
    } else if (argv.json) {
        argScheme = 'json';
    } else if (argv.thrift || health || endpoint.indexOf('::') >= 0) {
        argScheme = 'thrift';
    } else {
        argScheme = 'json';
    }

    return {
        body: argv.body,
        head: argv.head,
        jsonHead: argv.jsonHead,
        jsonBody: argv.jsonBody,
        shardKey: argv.shardKey,
        service: service,
        endpoint: endpoint,
        peers: peers,
        argScheme: argScheme,
        thrift: argv.thrift,
        strict: argv.strict,
        http: argv.http,
        raw: argv.raw,
        timeout: argv.timeout,
        health: health,
        time: argv.time,
        requests: argv.requests,
        delay: argv.delay,
        rate: argv.rate
    };
}

function parsePeerlist(peerlist) {
    var text;
    try {
        text = fs.readFileSync(peerlist, 'utf-8');
    } catch (err) {
        console.error('Could not read peer list', peerlist);
        console.error(err.message);
        return null;
    }
    var json;
    try {
        json = JSON.parse(text);
    } catch (err) {
        console.error('Could not parse peer list', peerlist);
        console.error(err.message);
        return null;
    }
    return json;
}

function TCurl(opts) {
    if (!(this instanceof TCurl)) {
        return new TCurl(opts);
    }

    var self = this;
    self.subChannel = null;
    self.client = null;
}

TCurl.prototype.parseJsonArgs = function parseJsonArgs(opts, delegate) {
    if (opts.raw) {
        return null;
    }

    var tuple = null;
    if (opts.head) {
        opts.jsonHead = opts.head;
    } if (opts.jsonHead) {
        tuple = safeJsonParse(opts.jsonHead);
        opts.jsonHead = tuple[1] || opts.jsonHead;
    }
    if (tuple && tuple[0]) {
        delegate.error('Failed to parse arg2 (i.e., head) as JSON');
        delegate.error(tuple[0]);
    }

    tuple = null;
    if (opts.body) {
        opts.jsonBody = opts.body;
    } else if (opts.jsonBody) {
        tuple = safeJsonParse(opts.jsonBody);
        opts.jsonBody = tuple[1] || opts.jsonBody;
    }
    if (tuple && tuple[0]) {
        delegate.error('Failed to parse arg3 (i.e., body) as JSON');
        delegate.error(tuple[0]);
    }

    return null;
};

TCurl.prototype.findThriftEntryPoint = function findThriftEntryPoint(opts, delegate) {
    var self = this;
    if (opts.thrift == null) {
        return null;
    }
    opts.thrift = path.resolve(opts.thrift);
    try {
        var files = fs.readdirSync(opts.thrift);
    } catch (err) {
        if (err.code === 'ENOTDIR') {
            return opts.thrift;
        }
    }
    var basename = opts.service + '.thrift';
    if (files.indexOf(basename) >= 0) {
        return path.join(opts.thrift, basename);
    }
    return null;
};

TCurl.prototype.prepare = function prepare(opts, delegate) {
    var self = this;

    // May report errors for arg2, arg3, or both
    self.parseJsonArgs(opts, delegate);
    if (delegate.exitCode) {
        return delegate.exit();
    }

    self.client = TChannel({
        logger: DebugLogtron('tcurl')
    });

    self.subChannel = self.client.makeSubChannel({
        serviceName: opts.service,
        peers: opts.peers,
        requestDefaults: {
            serviceName: opts.service,
            headers: {
                cn: 'tcurl'
            }
        }
    });
};

TCurl.prototype.createRequest = function createRequest(opts) {
    var self = this;
    var headers = opts.shardKey ? {sk: opts.shardKey} : {};
    return self.subChannel.request({
        timeout: opts.timeout || 100,
        hasNoParent: true,
        serviceName: opts.service,
        headers: headers
    });
};

TCurl.prototype.send = function send(opts, request, delegate) {
    var self = this;

    if (opts.argScheme === 'thrift') {
        self.asThrift(opts, request, delegate, done);
    } else if (opts.argScheme === 'http') {
        self.asHTTP(opts, self.client, self.subChannel, delegate, done);
    } else if (opts.argScheme === 'json') {
        self.asJSON(opts, request, delegate, done);
        // TODO fix argument order for each of these
    } else {
        self.asRaw(opts, request, delegate, done);
    }

    function done() {
        if (!opts.rate) {
            self.client.close();
        }
    }
};

TCurl.prototype.request = function tcurlRequest(opts, delegate) {
    var self = this;
    self.prepare(opts, delegate);
    self.send(opts, self.createRequest(opts), delegate);
};

TCurl.prototype.asThrift = function asThrift(opts, request, delegate, done) {
    var self = this;

    var entryPoint = self.findThriftEntryPoint(opts, delegate);

    if (entryPoint === null) {
        delegate.error('Must specify a thrift file with -t|--thrift for Thrift endpoints');
        delegate.error('or specify --json for JSON endpoints that contain ::');
        done();
        return delegate.exit();
    }

    var sender;
    try {
        sender = new TChannelAsThrift({
            entryPoint: entryPoint,
            strict: opts.strict
        });
    } catch (err) {
        if (err.name === 'SyntaxError') {
            // TODO works for now: does not work with include support unless
            // errors are annotated with the source file name.
            delegate.error(opts.thrift + ':' + err.line + ':' + err.column + ': Thrift Syntax Error');
            delegate.error(err.message);
        } else {
            delegate.error('Error parsing Thrift IDL');
            delegate.error(err);
            delegate.error('Consider using --no-strict to bypass mandatory optional/required fields');
        }
        done();
        return delegate.exit();
    }

    // The following is a hack to produce a nice error message when
    // the endpoint does not exist. It is a temporary solution based
    // on the thriftify interface. How the existence of this endpoint
    // is checked and this error thrown will change when we move to
    // the thriftrw rewrite.
    try {
        sender.send(request, opts.endpoint, opts.jsonHead,
            opts.jsonBody, onResponse);
    } catch (err) {
        // TODO untangle this mess
        if (err.message === fmt('type %s_args not found', opts.endpoint)) {
            delegate.error(fmt('%s endpoint does not exist', opts.endpoint));
        } else if (err.message.lastIndexOf('Got unexpected unserializable thrift', 0) === 0) {
            delegate.error('Invalid body for Thrift request');
            delegate.log(err);
        } else {
            delegate.error('Error response received for the as-thrift request.');
            delegate.error(err);
        }
        done();
        return delegate.exit();
    }

    function onResponse(err, res, arg2, arg3) {
        done();
        self.onResponse(err, res, arg2, arg3, opts, delegate);
    }
};

TCurl.prototype.asRaw = function asRaw(opts, request, delegate, done) {
    var self = this;
    request.headers.as = 'raw';
    request.send(opts.endpoint, opts.jsonHead, opts.jsonBody,
        onResponse);

    function onResponse(err, res, arg2, arg3) {
        done();
        self.onResponse(err, res, arg2, arg3, opts, delegate);
    }
};

TCurl.prototype.asHTTP = function asHTTP(opts, client, subChan, delegate, done) {
    var asHttp = TCurlAsHttp({
        channel: client,
        subChannel: subChan,
        method: opts.http,
        endpoint: opts.endpoint,
        headers: opts.jsonHead,
        body: opts.jsonBody,
        done: done,
        logger: delegate
    });
    asHttp.send();
};

TCurl.prototype.asJSON = function asJSON(opts, request, delegate, done) {
    var self = this;
    var sender = new TChannelAsJSON();

    var body = opts.jsonBody == null ? {} : opts.jsonBody;

    sender.send(request, opts.endpoint, opts.jsonHead, body, onResponse);

    function onResponse(err, res, arg2, arg3) {
        done();
        self.onResponse(err, res, arg2, arg3, opts, delegate);
    }
};

TCurl.prototype.onResponse = function onResponse(err, res, arg2, arg3, opts, delegate) {
    if (typeof delegate.handleReponse === 'function') {
        delegate.handleReponse(err, res, arg2, arg3, opts);
    }

    if (err) {
        delegate.error(err);
        return delegate.exit();
    }

    if (arg2 !== undefined && res) {
        res.head = arg2;
    }
    if (arg3 !== undefined && res) {
        res.jsonBody = arg3;
    }

    delegate.response(res, opts);
    return delegate.exit();
};

if (require.main === module) {
    main(process.argv.slice(2));
}
<commit_msg>Fix reference error when health options do not parse<commit_after>#!/usr/bin/env node

// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

/*eslint no-console: [0] */
/*eslint no-process-exit: [0] */
/*eslint max-params: [2, 6] */
/*eslint max-statements: [2, 40] */
'use strict';

var TChannel = require('tchannel');
var TChannelAsThrift = require('tchannel/as/thrift');
var TChannelAsJSON = require('tchannel/as/json');
var myLocalIp = require('my-local-ip');
var DebugLogtron = require('debug-logtron');
var rc = require('rc');
var rcUtils = require('rc/lib/utils');
var camelCaseKeys = require('camelcase-keys');
var traverse = require('traverse');
var extend = require('xtend');

var fmt = require('util').format;
var console = require('console');
var process = require('process');
var spawn = require('child_process').spawn;
var fs = require('fs');
var path = require('path');
var url = require('url');
var assert = require('assert');

var safeJsonParse = require('safe-json-parse/tuple');

var Logger = require('./logger');
var Benchmark = require('./benchmark');
var HealthLogger = require('./health-logger');
var TCurlAsHttp = require('./as-http');

var shon = require('shon/parse');
var ShonCursor = require('shon/cursor');
var ShonIterator = require('shon/iterator');
var ShonDelegate = require('shon/delegate');

var packageJson = require('./package.json');

module.exports = main;

var command = require('./tcurl.json');
var healthCommand = require('./health.json');

// delegate implements error(message, err), response(res), exit()
function main(argv, delegate) {

    var args = ['tcurl'].concat(argv);
    var cursor = new ShonCursor(args, 1);
    var iterator = new ShonIterator(cursor);
    var shonDelegate = new ShonDelegate({
        cursor: cursor,
        logUsage: help
    });
    var config = shon(command, iterator, shonDelegate);

    if (config === null) {
        return shonDelegate.end();
    }

    if (shonDelegate.trumped === 'help') {
        return help();
    } else if (shonDelegate.trumped === 'man') {
        return man();
    } else if (shonDelegate.trumped === 'version') {
        delegate = delegate || new Logger();
        return delegate.log(packageJson.version);
    } else if (shonDelegate.trumped === 'health') {
        cursor = new ShonCursor(args, 1);
        iterator = new ShonIterator(cursor);
        shonDelegate = new ShonDelegate({
            cursor: cursor,
            logUsage: help
        });
        config = shon(healthCommand, iterator, shonDelegate);
        if (config === null) {
            return shonDelegate.end();
        }
        delegate = delegate || new HealthLogger();
        config.thrift = path.join(__dirname, 'meta.thrift');
        config.endpoint = 'Meta::health';
    }

    config = extend(
        rc('tcurl', {}, config),
        env(),
        config
    );

    config = parseArgs(config);

    var tcurl = new TCurl();

    delegate = delegate || new Logger();

    if (config.rate) {
        var benchmark = new Benchmark({
            tcurl: tcurl,
            cmdOptions: config,
            logger: delegate
        });
        return benchmark.run(function done() {
            tcurl.client.close();
            delegate.exit();
        });
    }

    return tcurl.request(config, delegate);
}

function env() {
    var envConf = rcUtils.env('TCURL_');
    return traverse(envConf).map(camelcaseObjectKeys);

    function camelcaseObjectKeys(value) {
        if (typeof value === 'object') {
            this.update(camelCaseKeys(value));
        }
    }
}

main.exec = function execMain(str, delegate) {
    main(str, delegate);
};

function help() {
    console.log(fs.readFileSync(path.join(__dirname, 'usage.txt').trim(), 'utf8'));
}

function man() {
    var options = {
        cwd: process.cwd(),
        /*eslint no-process-env: [0] */
        env: process.env,
        setsid: false,
        customFds: [0, 1, 2]
    };

    spawn('man', [path.join(__dirname, 'man', 'tcurl.1')], options);
}

function parseArgs(argv) {
    var service = argv.service;
    var endpoint = argv.endpoint;
    var health = argv.health;

    // Prefer peer specified at the command line over peerlist
    var peers;
    if (argv.peers.length) {
        peers = argv.peers;
    } else if (argv.hostlist) {
        peers = parsePeerlist(argv.hostlist);
        if (peers === null) {
            return null;
        }
    } else {
        console.error('Must specify at least one peer with -p|--peer or -P|--peerlist');
        help();
        process.exit(-1);
    }

    var ip;
    function normalizePeer(address) {
        if (!ip) {
            ip = myLocalIp();
        }
        var parsedUri = url.parse('tchannel://' + address);
        if (parsedUri.hostname === 'localhost') {
            parsedUri.hostname = ip;
        }
        assert(parsedUri.hostname, 'host required');
        assert(parsedUri.port, 'port required');
        return parsedUri.hostname + ':' + parsedUri.port;
    }

    peers = peers.map(normalizePeer);

    if (!health && !endpoint) {
        console.error('Please specify an endpoint or --health');
        return null;
    }

    if (!service) {
        console.error('Please specify a service');
        return null;
    }

    var argScheme;
    if (argv.raw) {
        argScheme = 'raw';
    } else if (argv.http) {
        argScheme = 'http';
    } else if (argv.json) {
        argScheme = 'json';
    } else if (argv.thrift || health || endpoint.indexOf('::') >= 0) {
        argScheme = 'thrift';
    } else {
        argScheme = 'json';
    }

    return {
        body: argv.body,
        head: argv.head,
        jsonHead: argv.jsonHead,
        jsonBody: argv.jsonBody,
        shardKey: argv.shardKey,
        service: service,
        endpoint: endpoint,
        peers: peers,
        argScheme: argScheme,
        thrift: argv.thrift,
        strict: argv.strict,
        http: argv.http,
        raw: argv.raw,
        timeout: argv.timeout,
        health: health,
        time: argv.time,
        requests: argv.requests,
        delay: argv.delay,
        rate: argv.rate
    };
}

function parsePeerlist(peerlist) {
    var text;
    try {
        text = fs.readFileSync(peerlist, 'utf-8');
    } catch (err) {
        console.error('Could not read peer list', peerlist);
        console.error(err.message);
        return null;
    }
    var json;
    try {
        json = JSON.parse(text);
    } catch (err) {
        console.error('Could not parse peer list', peerlist);
        console.error(err.message);
        return null;
    }
    return json;
}

function TCurl(opts) {
    if (!(this instanceof TCurl)) {
        return new TCurl(opts);
    }

    var self = this;
    self.subChannel = null;
    self.client = null;
}

TCurl.prototype.parseJsonArgs = function parseJsonArgs(opts, delegate) {
    if (opts.raw) {
        return null;
    }

    var tuple = null;
    if (opts.head) {
        opts.jsonHead = opts.head;
    } if (opts.jsonHead) {
        tuple = safeJsonParse(opts.jsonHead);
        opts.jsonHead = tuple[1] || opts.jsonHead;
    }
    if (tuple && tuple[0]) {
        delegate.error('Failed to parse arg2 (i.e., head) as JSON');
        delegate.error(tuple[0]);
    }

    tuple = null;
    if (opts.body) {
        opts.jsonBody = opts.body;
    } else if (opts.jsonBody) {
        tuple = safeJsonParse(opts.jsonBody);
        opts.jsonBody = tuple[1] || opts.jsonBody;
    }
    if (tuple && tuple[0]) {
        delegate.error('Failed to parse arg3 (i.e., body) as JSON');
        delegate.error(tuple[0]);
    }

    return null;
};

TCurl.prototype.findThriftEntryPoint = function findThriftEntryPoint(opts, delegate) {
    var self = this;
    if (opts.thrift == null) {
        return null;
    }
    opts.thrift = path.resolve(opts.thrift);
    try {
        var files = fs.readdirSync(opts.thrift);
    } catch (err) {
        if (err.code === 'ENOTDIR') {
            return opts.thrift;
        }
    }
    var basename = opts.service + '.thrift';
    if (files.indexOf(basename) >= 0) {
        return path.join(opts.thrift, basename);
    }
    return null;
};

TCurl.prototype.prepare = function prepare(opts, delegate) {
    var self = this;

    // May report errors for arg2, arg3, or both
    self.parseJsonArgs(opts, delegate);
    if (delegate.exitCode) {
        return delegate.exit();
    }

    self.client = TChannel({
        logger: DebugLogtron('tcurl')
    });

    self.subChannel = self.client.makeSubChannel({
        serviceName: opts.service,
        peers: opts.peers,
        requestDefaults: {
            serviceName: opts.service,
            headers: {
                cn: 'tcurl'
            }
        }
    });
};

TCurl.prototype.createRequest = function createRequest(opts) {
    var self = this;
    var headers = opts.shardKey ? {sk: opts.shardKey} : {};
    return self.subChannel.request({
        timeout: opts.timeout || 100,
        hasNoParent: true,
        serviceName: opts.service,
        headers: headers
    });
};

TCurl.prototype.send = function send(opts, request, delegate) {
    var self = this;

    if (opts.argScheme === 'thrift') {
        self.asThrift(opts, request, delegate, done);
    } else if (opts.argScheme === 'http') {
        self.asHTTP(opts, self.client, self.subChannel, delegate, done);
    } else if (opts.argScheme === 'json') {
        self.asJSON(opts, request, delegate, done);
        // TODO fix argument order for each of these
    } else {
        self.asRaw(opts, request, delegate, done);
    }

    function done() {
        if (!opts.rate) {
            self.client.close();
        }
    }
};

TCurl.prototype.request = function tcurlRequest(opts, delegate) {
    var self = this;
    self.prepare(opts, delegate);
    self.send(opts, self.createRequest(opts), delegate);
};

TCurl.prototype.asThrift = function asThrift(opts, request, delegate, done) {
    var self = this;

    var entryPoint = self.findThriftEntryPoint(opts, delegate);

    if (entryPoint === null) {
        delegate.error('Must specify a thrift file with -t|--thrift for Thrift endpoints');
        delegate.error('or specify --json for JSON endpoints that contain ::');
        done();
        return delegate.exit();
    }

    var sender;
    try {
        sender = new TChannelAsThrift({
            entryPoint: entryPoint,
            strict: opts.strict
        });
    } catch (err) {
        if (err.name === 'SyntaxError') {
            // TODO works for now: does not work with include support unless
            // errors are annotated with the source file name.
            delegate.error(opts.thrift + ':' + err.line + ':' + err.column + ': Thrift Syntax Error');
            delegate.error(err.message);
        } else {
            delegate.error('Error parsing Thrift IDL');
            delegate.error(err);
            delegate.error('Consider using --no-strict to bypass mandatory optional/required fields');
        }
        done();
        return delegate.exit();
    }

    // The following is a hack to produce a nice error message when
    // the endpoint does not exist. It is a temporary solution based
    // on the thriftify interface. How the existence of this endpoint
    // is checked and this error thrown will change when we move to
    // the thriftrw rewrite.
    try {
        sender.send(request, opts.endpoint, opts.jsonHead,
            opts.jsonBody, onResponse);
    } catch (err) {
        // TODO untangle this mess
        if (err.message === fmt('type %s_args not found', opts.endpoint)) {
            delegate.error(fmt('%s endpoint does not exist', opts.endpoint));
        } else if (err.message.lastIndexOf('Got unexpected unserializable thrift', 0) === 0) {
            delegate.error('Invalid body for Thrift request');
            delegate.log(err);
        } else {
            delegate.error('Error response received for the as-thrift request.');
            delegate.error(err);
        }
        done();
        return delegate.exit();
    }

    function onResponse(err, res, arg2, arg3) {
        done();
        self.onResponse(err, res, arg2, arg3, opts, delegate);
    }
};

TCurl.prototype.asRaw = function asRaw(opts, request, delegate, done) {
    var self = this;
    request.headers.as = 'raw';
    request.send(opts.endpoint, opts.jsonHead, opts.jsonBody,
        onResponse);

    function onResponse(err, res, arg2, arg3) {
        done();
        self.onResponse(err, res, arg2, arg3, opts, delegate);
    }
};

TCurl.prototype.asHTTP = function asHTTP(opts, client, subChan, delegate, done) {
    var asHttp = TCurlAsHttp({
        channel: client,
        subChannel: subChan,
        method: opts.http,
        endpoint: opts.endpoint,
        headers: opts.jsonHead,
        body: opts.jsonBody,
        done: done,
        logger: delegate
    });
    asHttp.send();
};

TCurl.prototype.asJSON = function asJSON(opts, request, delegate, done) {
    var self = this;
    var sender = new TChannelAsJSON();

    var body = opts.jsonBody == null ? {} : opts.jsonBody;

    sender.send(request, opts.endpoint, opts.jsonHead, body, onResponse);

    function onResponse(err, res, arg2, arg3) {
        done();
        self.onResponse(err, res, arg2, arg3, opts, delegate);
    }
};

TCurl.prototype.onResponse = function onResponse(err, res, arg2, arg3, opts, delegate) {
    if (typeof delegate.handleReponse === 'function') {
        delegate.handleReponse(err, res, arg2, arg3, opts);
    }

    if (err) {
        delegate.error(err);
        return delegate.exit();
    }

    if (arg2 !== undefined && res) {
        res.head = arg2;
    }
    if (arg3 !== undefined && res) {
        res.jsonBody = arg3;
    }

    delegate.response(res, opts);
    return delegate.exit();
};

if (require.main === module) {
    main(process.argv.slice(2));
}
<|endoftext|>


<commit_before>// Copyright 2014 Google Inc. All rights reserved.
//
// 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.

import AxiomError from 'axiom/core/error';

import Path from 'axiom/fs/path';

import FileSystem from 'axiom/fs/base/file_system';

import JsEntry from 'axiom/fs/js/entry';
import JsExecutable from 'axiom/fs/js/executable';
import JsResolveResult from 'axiom/fs/js/resolve_result';

/** @typedef StatResult$$module$axiom$fs$stat_result */
var StatResult;

/** @typedef JsExecuteContext$$module$axiom$fs$js$execute_context */
var JsExecuteContext;

/** @typedef JsFileSystem$$module$axiom$fs$js$file_system */
var JsFileSystem;

/**
 * @constructor @extends {JsEntry}
 * A directory in a JsFileSystem.
 *
 * A directory can contain JsEntry subclasses and/or FileSystems.
 *
 * @param {JsFileSystem} jsfs  The parent file system.
 */
export var JsDirectory = function(jsfs) {
  JsEntry.call(this, jsfs, 'D');

  /** @type {Object<string, (JsEntry|FileSystem)>} */
  this.entries_ = {};
};

export default JsDirectory;

JsDirectory.prototype = Object.create(JsEntry.prototype);

/**
 * Resolve a Path object as far as possible.
 *
 * This may return a partial result which represents the depth to which
 * the path can be resolved.
 *
 * @param {Path} path An object representing the path to resolve.
 * @param {number=} opt_index The optional index into the path elements where
 *   we should start resolving.  Defaults to 0, the first path element.
 * @return {JsResolveResult}
 */
JsDirectory.prototype.resolve = function(path, opt_index) {
  var index = opt_index || 0;

  if (!this.entryExists(path.elements[index])) {
    return new JsResolveResult(
        path.elements.slice(0, index - 1),
        path.elements.slice(index - 1),
        this);
  }

  var entry = this.entries_[path.elements[index]] || null;

  if (index == path.elements.length - 1)
    return new JsResolveResult(path.elements, null, entry);

  if (entry instanceof JsDirectory)
    return entry.resolve(path, index + 1);

  return new JsResolveResult(path.elements.slice(0, index + 1),
                             path.elements.slice(index + 1),
                             entry);
};

/**
 * Return true if the named entry exists in this directory.
 *
 * @param {string} name
 */
JsDirectory.prototype.entryExists = function(name) {
  return this.entries_.hasOwnProperty(name);
};

/**
 * Link the given entry into this directory.
 *
 * This method is not directly reachable through the FileSystem.
 *
 * @param {string} name  A name to give the entry.
 * @param {JsEntry} entry
 */
JsDirectory.prototype.link = function(name, entry) {
  if (!(entry instanceof JsEntry))
    throw new AxiomError.TypeMismatch('instanceof JsEntry', entry);

  if (this.entries_.hasOwnProperty(name))
    throw new AxiomError.Duplicate('directory-name', name);

  this.entries_[name] = entry;
};

/**
 * Link the given FileSystem into this directory.
 *
 * This method is not directly reachable through the FileSystem.
 *
 * @param {string} name  A name to give the file system.
 * @param {FileSystem} fileSystem
 */
JsDirectory.prototype.mount = function(name, fileSystem) {
  if (!(fileSystem instanceof FileSystem)) {
    throw new AxiomError.TypeMismatch('instanceof FileSystem',
                                      fileSystem);
  }

  if (this.entries_.hasOwnProperty(name))
    throw new AxiomError.Duplicate('directory-name', name);

  this.entries_[name] = fileSystem;
};

/**
 * @param {Object<string, function(JsExecuteContext)>} executables
 */
JsDirectory.prototype.install = function(executables) {
  for (var name in executables) {
    var callback = executables[name];
    var sigil;
    var ary = /([^\(]*)\(([^\)]?)\)$/.exec(name);
    if (ary) {
      name = ary[1];
      sigil = ary[2];
      if (sigil && '$@%*'.indexOf(sigil) == -1)
        throw new AxiomError.Invalid('sigil', sigil);
    } else {
      sigil = callback['argSigil'] || '*';
    }

    this.link(name, new JsExecutable(this.jsfs, callback, sigil));
  }
};

/**
 * Make a new, empty directory with the given name.
 *
 * @param {string} name
 */
JsDirectory.prototype.mkdir = function(name) {
  if (this.entryExists(name))
    return Promise.reject(new AxiomError.Duplicate('directory-name', name));

  var dir = new JsDirectory(this.jsfs);
  this.entries_[name] = dir;
  return Promise.resolve(dir);
};

/**
 * Remove the entry with the given name.
 *
 * @param {string} name
 * @return {Promise}
 */
JsDirectory.prototype.unlink = function(name) {
  if (!this.entryExists(name))
    return Promise.reject(new AxiomError.NotFound('name', name));

  delete this.entries_[name];
  return Promise.resolve();
};

/**
 * Return the stat() result for each item in this directory.
 *
 * @return {!Promise<!Object<string, StatResult>>}
 */
JsDirectory.prototype.list = function() {
  var rv = {};
  var promises = [];

  for (var name in this.entries_) {
    var entry = this.entries_[name];
    var promise;

    if (entry instanceof FileSystem) {
      promise = entry.stat('/');
    } else {
      promise = entry.stat();
    }

    promises.push(promise.then(function(name, statResult) {
      rv[name] = statResult;
    }.bind(null, name)));
  }

  return Promise.all(promises).then(function() {
    return rv;
  });
};
<commit_msg>Add return type annotations.<commit_after>// Copyright 2014 Google Inc. All rights reserved.
//
// 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.

import AxiomError from 'axiom/core/error';

import Path from 'axiom/fs/path';

import FileSystem from 'axiom/fs/base/file_system';

import JsEntry from 'axiom/fs/js/entry';
import JsExecutable from 'axiom/fs/js/executable';
import JsResolveResult from 'axiom/fs/js/resolve_result';

/** @typedef StatResult$$module$axiom$fs$stat_result */
var StatResult;

/** @typedef JsExecuteContext$$module$axiom$fs$js$execute_context */
var JsExecuteContext;

/** @typedef JsFileSystem$$module$axiom$fs$js$file_system */
var JsFileSystem;

/**
 * @constructor @extends {JsEntry}
 * A directory in a JsFileSystem.
 *
 * A directory can contain JsEntry subclasses and/or FileSystems.
 *
 * @param {JsFileSystem} jsfs  The parent file system.
 */
export var JsDirectory = function(jsfs) {
  JsEntry.call(this, jsfs, 'D');

  /** @type {Object<string, (JsEntry|FileSystem)>} */
  this.entries_ = {};
};

export default JsDirectory;

JsDirectory.prototype = Object.create(JsEntry.prototype);

/**
 * Resolve a Path object as far as possible.
 *
 * This may return a partial result which represents the depth to which
 * the path can be resolved.
 *
 * @param {Path} path An object representing the path to resolve.
 * @param {number=} opt_index The optional index into the path elements where
 *   we should start resolving.  Defaults to 0, the first path element.
 * @return {!JsResolveResult}
 */
JsDirectory.prototype.resolve = function(path, opt_index) {
  var index = opt_index || 0;

  if (!this.entryExists(path.elements[index])) {
    return new JsResolveResult(
        path.elements.slice(0, index - 1),
        path.elements.slice(index - 1),
        this);
  }

  var entry = this.entries_[path.elements[index]] || null;

  if (index == path.elements.length - 1)
    return new JsResolveResult(path.elements, null, entry);

  if (entry instanceof JsDirectory)
    return entry.resolve(path, index + 1);

  return new JsResolveResult(path.elements.slice(0, index + 1),
                             path.elements.slice(index + 1),
                             entry);
};

/**
 * Return true if the named entry exists in this directory.
 *
 * @param {string} name
 * @return {!boolean}
 */
JsDirectory.prototype.entryExists = function(name) {
  return this.entries_.hasOwnProperty(name);
};

/**
 * Link the given entry into this directory.
 *
 * This method is not directly reachable through the FileSystem.
 *
 * @param {string} name  A name to give the entry.
 * @param {JsEntry} entry
 * @return {void}
 */
JsDirectory.prototype.link = function(name, entry) {
  if (!(entry instanceof JsEntry))
    throw new AxiomError.TypeMismatch('instanceof JsEntry', entry);

  if (this.entries_.hasOwnProperty(name))
    throw new AxiomError.Duplicate('directory-name', name);

  this.entries_[name] = entry;
};

/**
 * Link the given FileSystem into this directory.
 *
 * This method is not directly reachable through the FileSystem.
 *
 * @param {string} name  A name to give the file system.
 * @param {FileSystem} fileSystem
 * @return {void}
 */
JsDirectory.prototype.mount = function(name, fileSystem) {
  if (!(fileSystem instanceof FileSystem)) {
    throw new AxiomError.TypeMismatch('instanceof FileSystem',
                                      fileSystem);
  }

  if (this.entries_.hasOwnProperty(name))
    throw new AxiomError.Duplicate('directory-name', name);

  this.entries_[name] = fileSystem;
};

/**
 * @param {Object<string, function(JsExecuteContext)>} executables
 * @return {void}
 */
JsDirectory.prototype.install = function(executables) {
  for (var name in executables) {
    var callback = executables[name];
    var sigil;
    var ary = /([^\(]*)\(([^\)]?)\)$/.exec(name);
    if (ary) {
      name = ary[1];
      sigil = ary[2];
      if (sigil && '$@%*'.indexOf(sigil) == -1)
        throw new AxiomError.Invalid('sigil', sigil);
    } else {
      sigil = callback['argSigil'] || '*';
    }

    this.link(name, new JsExecutable(this.jsfs, callback, sigil));
  }
};

/**
 * Make a new, empty directory with the given name.
 *
 * @param {string} name
 * @return {!Promise<!JsDirectory>}
 */
JsDirectory.prototype.mkdir = function(name) {
  if (this.entryExists(name))
    return Promise.reject(new AxiomError.Duplicate('directory-name', name));

  var dir = new JsDirectory(this.jsfs);
  this.entries_[name] = dir;
  return Promise.resolve(dir);
};

/**
 * Remove the entry with the given name.
 *
 * @param {string} name
 * @return {!Promise}
 */
JsDirectory.prototype.unlink = function(name) {
  if (!this.entryExists(name))
    return Promise.reject(new AxiomError.NotFound('name', name));

  delete this.entries_[name];
  return Promise.resolve();
};

/**
 * Return the stat() result for each item in this directory.
 *
 * @return {!Promise<!Object<string, StatResult>>}
 */
JsDirectory.prototype.list = function() {
  var rv = {};
  var promises = [];

  for (var name in this.entries_) {
    var entry = this.entries_[name];
    var promise;

    if (entry instanceof FileSystem) {
      promise = entry.stat('/');
    } else {
      promise = entry.stat();
    }

    promises.push(promise.then(function(name, statResult) {
      rv[name] = statResult;
    }.bind(null, name)));
  }

  return Promise.all(promises).then(function() {
    return rv;
  });
};
<|endoftext|>


<commit_before>'use strict'

var cors = require('cors')
const express = require('express')
const router = express.Router({ mergeParams: true })

const path = require('path')

const Repository = require('./repository.model')

function manageError (res, err) {
  res.status(500).json({
    message: err.message,
    stack: err.stack
  })
}

router.use((req, res, next) => {
  const id = `github/${req.params.owner}/${req.params.repo}`
  Repository
    .findById(id)
    .exec()
    .then(repository => {
      if (!repository) {
        return res.status(500).json({
          message: id + ' is not active. Contributions are not possible. Log in to activate and aloow contributions.'
        })
      }

      req.repository = repository
      next()
    })
    .catch(() => {
      res.sendStatus(500)
    })
})

router.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*')
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept')
  next()
})

router.get('/', (req, res) => {
  res.json({ id: req.repository.id })
})

router.get('/tests', (req, res) => {
  res.sendFile(path.join(req.repository.root, 'tests.json'))
})

router.get('/refresh', (req, res) => {
  const start = new Date()
  req.repository.refresh()
    .then(repo => {
      res.json({
        refresh: (new Date()).getTime() - start.getTime(),
        repository: repo.id
      })
    })
    .catch((err) => manageError(res, err))
})

router.use('/suggest', cors())

router.post('/suggest', (req, res) => {
  const suggestion = {
    title: req.body.title,
    body: req.body.body,
    content: req.body.content
  }

  if (typeof suggestion.title === 'undefined' ||
    typeof suggestion.body === 'undefined' ||
    typeof suggestion.content === 'undefined') {
    return res.status(400).json({
      message: Object.keys(suggestion).join(', ') + ' are all required.',
      payload: req.body
    })
  }
  const timestamp = (new Date()).getTime()
  suggestion.headName = `ludwig_${timestamp}`
  suggestion.filePath = path.join(req.repository.testDirectory, `ludwig_test_${timestamp}.yaml`)

  req.repository.suggest(suggestion)
    .then(data => {
      res.json({
        push: (new Date()).getTime() - timestamp,
        data: data
      })
    })
    .catch((err) => manageError(res, err))
})

module.exports = router
<commit_msg>Enable CORS on /suggestion endpoint<commit_after>'use strict'

var cors = require('cors')
const express = require('express')
const router = express.Router({ mergeParams: true })

const path = require('path')

const Repository = require('./repository.model')

function manageError (res, err) {
  res.status(500).json({
    message: err.message,
    stack: err.stack
  })
}

router.use((req, res, next) => {
  const id = `github/${req.params.owner}/${req.params.repo}`
  Repository
    .findById(id)
    .exec()
    .then(repository => {
      if (!repository) {
        return res.status(500).json({
          message: id + ' is not active. Contributions are not possible. Log in to activate and aloow contributions.'
        })
      }

      req.repository = repository
      next()
    })
    .catch(() => {
      res.sendStatus(500)
    })
})

router.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*')
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept')
  next()
})

router.get('/', (req, res) => {
  res.json({ id: req.repository.id })
})

router.get('/tests', (req, res) => {
  res.sendFile(path.join(req.repository.root, 'tests.json'))
})

router.get('/refresh', (req, res) => {
  const start = new Date()
  req.repository.refresh()
    .then(repo => {
      res.json({
        refresh: (new Date()).getTime() - start.getTime(),
        repository: repo.id
      })
    })
    .catch((err) => manageError(res, err))
})

router.options('/suggest', cors())
router.post('/suggest', cors({ origin: '*' }), (req, res) => {
  const suggestion = {
    title: req.body.title,
    body: req.body.body,
    content: req.body.content
  }

  if (typeof suggestion.title === 'undefined' ||
    typeof suggestion.body === 'undefined' ||
    typeof suggestion.content === 'undefined') {
    return res.status(400).json({
      message: Object.keys(suggestion).join(', ') + ' are all required.',
      payload: req.body
    })
  }
  const timestamp = (new Date()).getTime()
  suggestion.headName = `ludwig_${timestamp}`
  suggestion.filePath = path.join(req.repository.testDirectory, `ludwig_test_${timestamp}.yaml`)

  req.repository.suggest(suggestion)
    .then(data => {
      res.json({
        push: (new Date()).getTime() - timestamp,
        data: data
      })
    })
    .catch((err) => manageError(res, err))
})

module.exports = router
<|endoftext|>


<commit_before>var Sf = require('seq-file')

module.exports = function (file, options) {
    options = options||{}

    var sf = new Sf(file, options)
    patchSeq(sf)
    var saveValue = sf.readSync()

    // if seq is 0 strings that start with 0 are always false when compared to it.
    // https://github.com/npm/seq-file/pull/7
    if(sf.seq == 0) sf.seq = ''

    options.savedValue = saveValue||0
    var start = module.exports.starter(function(toSave,cb){
      // save the new sequence via seq-file
      save(sf, toSave, cb)
    },options)

    start.value = saveValue
    return start
}

module.exports.starter = function(persist,options) {

  options = options || {}

  var saveValue = options.savedValue||0
  var delay = options.delay || 1000
  var started = {}
  var dones = {}
  var saving = false
  var saveQ = false

  return function startSequence (seq, opts) {
    started[seq] = seq
    return function (cb) {
      delete started[seq]
      var startedSeq = least(started)

      if (dones[seq]) {
        return cb(new Error("shouldn't 'done' the same sequence id more than once concurrently"))
      }
      dones[seq] = {cb:cb, seq:seq}

      // always save the highest number in the dones that's less than the lowest number in the actives
      var endSeq = ''
      var cbs = []
      // sort
      Object.keys(dones).sort().forEach(function (k) {
        if (!startedSeq || (dones[k].seq < startedSeq && endSeq <= dones[k].seq)) {
          endSeq = dones[k].seq
          cbs.push(dones[k].cb)
          delete dones[k]
        }
      })

      if (!endSeq || endSeq === saveValue) {
        return unroll(false, saveValue, cbs)
      }

      saveValue = endSeq

      if (!saveQ) saveQ = []
      // im either already waiting or my save loop is idle and the implementor has not yet completed the lowest started sequence
      if (saving || !saveValue) {
        return saveQ.push.apply(saveQ, cbs)
      }

      saveLoop(cbs)

      function saveLoop (cbs) {
        saving = true

        var savedValue = saveValue
        persist(savedValue, function (err){
          startSequence.value = savedValue

          unroll(err, savedValue, cbs)
          setTimeout(function () {
            saving = false
            if (saveQ.length) {
              cbs = saveQ
              saveQ = []
              saveLoop(cbs)
            }
          }, delay)
        })
      }
    }
  }
}

function save (sf, seq, cb) {
  sf.savecbs.push(function (err) {
    if (cb) cb(err)
  })
  sf.save(seq)
}

function patchSeq (sf) {
  if (sf.savecbs) return
  sf.savecbs = []
  var ofinish = sf.onFinish
  sf.onFinish = function (err) {
    ofinish.apply(this, arguments)
    var cbs = sf.savecbs
    sf.savecbs = []
    if (cbs) while (cbs.length) cbs.shift()(err)
  }
}

function least (obj) {
  var v = ''
  Object.keys(obj).forEach(function (k) {
    k = obj[k]
    if (!v || v > k) v = k
  })
  return v
}

function unroll (err, data, cbs) {
  var cb
  while (cbs.length) {
    cb = cbs.shift()
    if(cb) cb(err, data)
  }
}

function noop () {}
<commit_msg>warning when there is an error but the user doesnt provide cb<commit_after>var Sf = require('seq-file')

module.exports = function (file, options) {
    options = options||{}

    var sf = new Sf(file, options)
    patchSeq(sf)
    var saveValue = sf.readSync()

    // if seq is 0 strings that start with 0 are always false when compared to it.
    // https://github.com/npm/seq-file/pull/7
    if(sf.seq == 0) sf.seq = ''

    options.savedValue = saveValue||0
    var start = module.exports.starter(function(toSave,cb){
      // save the new sequence via seq-file
      save(sf, toSave, cb)
    },options)

    start.value = saveValue
    return start
}

module.exports.starter = function(persist,options) {

  options = options || {}

  var saveValue = options.savedValue||0
  var delay = options.delay || 1000
  var started = {}
  var dones = {}
  var saving = false
  var saveQ = false

  return function startSequence (seq, opts) {
    started[seq] = seq
    return function (cb) {
      delete started[seq]
      var startedSeq = least(started)

      if (dones[seq]) {
        var msg = "shouldn't 'done' the same sequence id more than once concurrently"
        if(cb) cb(new Error(msg))
        else console.warn(msg)
        return
      }
      dones[seq] = {cb:cb, seq:seq}

      // always save the highest number in the dones that's less than the lowest number in the actives
      var endSeq = ''
      var cbs = []
      // sort
      Object.keys(dones).sort().forEach(function (k) {
        if (!startedSeq || (dones[k].seq < startedSeq && endSeq <= dones[k].seq)) {
          endSeq = dones[k].seq
          cbs.push(dones[k].cb)
          delete dones[k]
        }
      })

      if (!endSeq || endSeq === saveValue) {
        return unroll(false, saveValue, cbs)
      }

      saveValue = endSeq

      if (!saveQ) saveQ = []
      // im either already waiting or my save loop is idle and the implementor has not yet completed the lowest started sequence
      if (saving || !saveValue) {
        return saveQ.push.apply(saveQ, cbs)
      }

      saveLoop(cbs)

      function saveLoop (cbs) {
        saving = true

        var savedValue = saveValue
        persist(savedValue, function (err){
          startSequence.value = savedValue

          unroll(err, savedValue, cbs)
          setTimeout(function () {
            saving = false
            if (saveQ.length) {
              cbs = saveQ
              saveQ = []
              saveLoop(cbs)
            }
          }, delay)
        })
      }
    }
  }
}

function save (sf, seq, cb) {
  sf.savecbs.push(function (err) {
    if (cb) cb(err)
  })
  sf.save(seq)
}

function patchSeq (sf) {
  if (sf.savecbs) return
  sf.savecbs = []
  var ofinish = sf.onFinish
  sf.onFinish = function (err) {
    ofinish.apply(this, arguments)
    var cbs = sf.savecbs
    sf.savecbs = []
    if (cbs) while (cbs.length) cbs.shift()(err)
  }
}

function least (obj) {
  var v = ''
  Object.keys(obj).forEach(function (k) {
    k = obj[k]
    if (!v || v > k) v = k
  })
  return v
}

function unroll (err, data, cbs) {
  var cb
  while (cbs.length) {
    cb = cbs.shift()
    if(cb) cb(err, data)
  }
}

function noop () {}
<|endoftext|>