<commit_before>module.exports = {
  'env': {
    'es6': true
  },
  'parserOptions': {
    'ecmaVersion': 6,
    'sourceType': 'module',
    'ecmaFeatures': {
      'generators': false,
      'objectLiteralDuplicateProperties': false
    }
  },
  'plugins': [
    'import'
  ],
  'rules': {
    // enforces no braces where they can be omitted
    // http://eslint.org/docs/rules/arrow-body-style
    'arrow-body-style': [2, 'as-needed'],
    // require parens in arrow function arguments
    'arrow-parens': 0,
    // require space before/after arrow function's arrow
    // http://eslint.org/docs/rules/arrow-spacing
    'arrow-spacing': [2, { 'before': true, 'after': true }],
    // require trailing commas in multiline object literals
    'comma-dangle': [2, 'always-multiline'],
    // verify super() callings in constructors
    'constructor-super': 0,
    // enforce the spacing around the * in generator functions
    'generator-star-spacing': 0,
    // disallow modifying variables of class declarations
    // http://eslint.org/docs/rules/no-class-assign
    'no-class-assign': 2,
    // disallow arrow functions where they could be confused with comparisons
    // http://eslint.org/docs/rules/no-confusing-arrow
    'no-confusing-arrow': [2, {
      'allowParens': true,
    }],
    // disallow modifying variables that are declared using const
    'no-const-assign': 2,
    // disallow duplicate class members
    // http://eslint.org/docs/rules/no-dupe-class-members
    'no-dupe-class-members': 2,
    // disallow importing from the same path more than once
    // http://eslint.org/docs/rules/no-duplicate-imports
    'no-duplicate-imports': 2,
    // disallow symbol constructor
    // http://eslint.org/docs/rules/no-new-symbol
    'no-new-symbol': 2,
    // disallow specific globals
    'no-restricted-globals': 0,
    // disallow specific imports
    // http://eslint.org/docs/rules/no-restricted-imports
    'no-restricted-imports': 0,
    // disallow to use this/super before super() calling in constructors.
    'no-this-before-super': 0,
    // require let or const instead of var
    'no-var': 2,
    // disallow useless computed property keys
    // http://eslint.org/docs/rules/no-useless-computed-key
    'no-useless-computed-key': 2,
    // disallow unnecessary constructor
    // http://eslint.org/docs/rules/no-useless-constructor
    'no-useless-constructor': 2,
    // require method and property shorthand syntax for object literals
    // http://eslint.org/docs/rules/object-shorthand
    'object-shorthand': [2, 'always'],
    // suggest using arrow functions as callbacks
    'prefer-arrow-callback': [2, {
      'allowNamedFunctions': false,
      'allowUnboundThis': true,
    }],
    // suggest using of const declaration for variables that are never modified after declared
    'prefer-const': 2,
    // suggest using the spread operator instead of .apply()
    'prefer-spread': 0,
    // suggest using Reflect methods where applicable
    'prefer-reflect': 0,
    // use rest parameters instead of arguments
    // http://eslint.org/docs/rules/prefer-rest-params
    'prefer-rest-params': 2,
    // suggest using template literals instead of string concatenation
    // http://eslint.org/docs/rules/prefer-template
    'prefer-template': 2,
    // disallow generator functions that do not have yield
    'require-yield': 0,
    // import sorting
    // http://eslint.org/docs/rules/sort-imports
    'sort-imports': 0,
    // enforce usage of spacing in template strings
    // http://eslint.org/docs/rules/template-curly-spacing
    'template-curly-spacing': 2,
    // enforce spacing around the * in yield* expressions
    // http://eslint.org/docs/rules/yield-star-spacing
    'yield-star-spacing': [2, 'after'],
    // disallow invalid exports, e.g. multiple defaults
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/export.md
    'import/export': 2,
    // ensure default import coupled with default export
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/default.md#when-not-to-use-it
    'import/default': 0,
    // Ensure consistent use of file extension within the import path
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/extensions.md
    // TODO: enable
    'import/extensions': [0, 'never'],
    // ensure named imports coupled with named exports
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/named.md#when-not-to-use-it
    'import/named': 0,
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/namespace.md
    'import/namespace': 0,
    // Forbid the use of extraneous packages
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-extraneous-dependencies.md
    // TODO: enable
    'import/no-extraneous-dependencies': [0, {
      'devDependencies': false,
      'optionalDependencies': false,
    }],
    // ensure imports point to files/modules that can be resolved
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unresolved.md
    'import/no-unresolved': [2, { 'commonjs': true }],
    // do not allow a default import name to match a named export
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-named-as-default.md
    // TODO: enable
    'import/no-named-as-default': 0,
    // disallow require()
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-commonjs.md
    'import/no-commonjs': 0,
    // disallow AMD require/define
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-amd.md
    // TODO: enable
    'import/no-amd': 0,
    // disallow non-import statements appearing before import statements
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/imports-first.md
    // TODO: enable?
    'import/imports-first': [0, 'absolute-first'],
    // disallow duplicate imports
    // TODO: enable
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-duplicates.md
    'import/no-duplicates': 0,
    // disallow use of jsdoc-marked-deprecated imports
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-deprecated.md
    'import/no-deprecated': 0,
    // disallow namespace imports
    // TODO: enable?
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-namespace.md
    'import/no-namespace': 0,
    // warn on accessing default export property names that are also named exports
    // TODO: enable?
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-named-as-default-member.md
    'import/no-named-as-default-member': 0,
    // No Node.js builtin modules
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-nodejs-modules.md
    'import/no-nodejs-modules': 0,
    // Enforce a convention in module import order
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/order.md
    // TODO: enable?
    'import/order': [0, {
      'groups': ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
      'newlines-between': 'never',
    }],
    // Require a newline after the last import/require in a group
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/newline-after-import.md
    // TODO: enable
    'import/newline-after-import': 0,
    // Forbid mutable exports
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-mutable-exports.md
    // TODO: enable
    'import/no-mutable-exports': 0,
  },
  'settings': {
    'import/resolver': {
      'node': {
        'extensions': ['.js', '.json']
      }
    }
  }
};
<commit_msg>[eslint config] [base] [minor] enable `import/no-amd`<commit_after>module.exports = {
  'env': {
    'es6': true
  },
  'parserOptions': {
    'ecmaVersion': 6,
    'sourceType': 'module',
    'ecmaFeatures': {
      'generators': false,
      'objectLiteralDuplicateProperties': false
    }
  },
  'plugins': [
    'import'
  ],
  'rules': {
    // enforces no braces where they can be omitted
    // http://eslint.org/docs/rules/arrow-body-style
    'arrow-body-style': [2, 'as-needed'],
    // require parens in arrow function arguments
    'arrow-parens': 0,
    // require space before/after arrow function's arrow
    // http://eslint.org/docs/rules/arrow-spacing
    'arrow-spacing': [2, { 'before': true, 'after': true }],
    // require trailing commas in multiline object literals
    'comma-dangle': [2, 'always-multiline'],
    // verify super() callings in constructors
    'constructor-super': 0,
    // enforce the spacing around the * in generator functions
    'generator-star-spacing': 0,
    // disallow modifying variables of class declarations
    // http://eslint.org/docs/rules/no-class-assign
    'no-class-assign': 2,
    // disallow arrow functions where they could be confused with comparisons
    // http://eslint.org/docs/rules/no-confusing-arrow
    'no-confusing-arrow': [2, {
      'allowParens': true,
    }],
    // disallow modifying variables that are declared using const
    'no-const-assign': 2,
    // disallow duplicate class members
    // http://eslint.org/docs/rules/no-dupe-class-members
    'no-dupe-class-members': 2,
    // disallow importing from the same path more than once
    // http://eslint.org/docs/rules/no-duplicate-imports
    'no-duplicate-imports': 2,
    // disallow symbol constructor
    // http://eslint.org/docs/rules/no-new-symbol
    'no-new-symbol': 2,
    // disallow specific globals
    'no-restricted-globals': 0,
    // disallow specific imports
    // http://eslint.org/docs/rules/no-restricted-imports
    'no-restricted-imports': 0,
    // disallow to use this/super before super() calling in constructors.
    'no-this-before-super': 0,
    // require let or const instead of var
    'no-var': 2,
    // disallow useless computed property keys
    // http://eslint.org/docs/rules/no-useless-computed-key
    'no-useless-computed-key': 2,
    // disallow unnecessary constructor
    // http://eslint.org/docs/rules/no-useless-constructor
    'no-useless-constructor': 2,
    // require method and property shorthand syntax for object literals
    // http://eslint.org/docs/rules/object-shorthand
    'object-shorthand': [2, 'always'],
    // suggest using arrow functions as callbacks
    'prefer-arrow-callback': [2, {
      'allowNamedFunctions': false,
      'allowUnboundThis': true,
    }],
    // suggest using of const declaration for variables that are never modified after declared
    'prefer-const': 2,
    // suggest using the spread operator instead of .apply()
    'prefer-spread': 0,
    // suggest using Reflect methods where applicable
    'prefer-reflect': 0,
    // use rest parameters instead of arguments
    // http://eslint.org/docs/rules/prefer-rest-params
    'prefer-rest-params': 2,
    // suggest using template literals instead of string concatenation
    // http://eslint.org/docs/rules/prefer-template
    'prefer-template': 2,
    // disallow generator functions that do not have yield
    'require-yield': 0,
    // import sorting
    // http://eslint.org/docs/rules/sort-imports
    'sort-imports': 0,
    // enforce usage of spacing in template strings
    // http://eslint.org/docs/rules/template-curly-spacing
    'template-curly-spacing': 2,
    // enforce spacing around the * in yield* expressions
    // http://eslint.org/docs/rules/yield-star-spacing
    'yield-star-spacing': [2, 'after'],
    // disallow invalid exports, e.g. multiple defaults
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/export.md
    'import/export': 2,
    // ensure default import coupled with default export
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/default.md#when-not-to-use-it
    'import/default': 0,
    // Ensure consistent use of file extension within the import path
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/extensions.md
    // TODO: enable
    'import/extensions': [0, 'never'],
    // ensure named imports coupled with named exports
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/named.md#when-not-to-use-it
    'import/named': 0,
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/namespace.md
    'import/namespace': 0,
    // Forbid the use of extraneous packages
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-extraneous-dependencies.md
    // TODO: enable
    'import/no-extraneous-dependencies': [0, {
      'devDependencies': false,
      'optionalDependencies': false,
    }],
    // ensure imports point to files/modules that can be resolved
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unresolved.md
    'import/no-unresolved': [2, { 'commonjs': true }],
    // do not allow a default import name to match a named export
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-named-as-default.md
    // TODO: enable
    'import/no-named-as-default': 0,
    // disallow require()
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-commonjs.md
    'import/no-commonjs': 0,
    // disallow AMD require/define
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-amd.md
    'import/no-amd': 2,
    // disallow non-import statements appearing before import statements
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/imports-first.md
    // TODO: enable?
    'import/imports-first': [0, 'absolute-first'],
    // disallow duplicate imports
    // TODO: enable
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-duplicates.md
    'import/no-duplicates': 0,
    // disallow use of jsdoc-marked-deprecated imports
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-deprecated.md
    'import/no-deprecated': 0,
    // disallow namespace imports
    // TODO: enable?
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-namespace.md
    'import/no-namespace': 0,
    // warn on accessing default export property names that are also named exports
    // TODO: enable?
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-named-as-default-member.md
    'import/no-named-as-default-member': 0,
    // No Node.js builtin modules
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-nodejs-modules.md
    'import/no-nodejs-modules': 0,
    // Enforce a convention in module import order
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/order.md
    // TODO: enable?
    'import/order': [0, {
      'groups': ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
      'newlines-between': 'never',
    }],
    // Require a newline after the last import/require in a group
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/newline-after-import.md
    // TODO: enable
    'import/newline-after-import': 0,
    // Forbid mutable exports
    // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-mutable-exports.md
    // TODO: enable
    'import/no-mutable-exports': 0,
  },
  'settings': {
    'import/resolver': {
      'node': {
        'extensions': ['.js', '.json']
      }
    }
  }
};
<|endoftext|>


<commit_before>import React from 'react';
import styled from 'styled-components';
import {theme, breakpoints} from '../../theme';
import {Image, Flex, Box} from 'rebass';
import brain from '../../images/brain.gif';
import batteries from '../../images/batteries.gif';
import separator from '../../images/separator.svg';
import {ButtonLink} from '../links';

const OuterContainer = styled.section`
  background-color: ${theme.colors.white};
  box-shadow: 0 0px 11px 5px #33333312;
  padding: 40px 20px;

  @media screen and (min-width: ${breakpoints.TABLET}) {
    padding: 70px 20px;
  }
`;

const Content = styled(Flex)`
  max-width: 900px;
  margin: auto;
  flex-direction: column;
`;

const FeatureImage = styled(Image)`
  width: 150px;
  margin: auto;
`;

const Code = styled.code`
  background-color: #ebe7e7;
`;

const Separator = styled(Image)`
  width: 18px;
  margin: 0 10px;
  transform: rotate(90deg);
  margin: auto;

  @media screen and (min-width: ${breakpoints.TABLET}) {
    transform: rotate(0deg);
    margin: ${theme.space[7]}px ${theme.space[3]}px 0;
  }
`;

const TextBox = styled(Box)`
  max-width: 500px;
`;

const Features = () => {
  return(
    <OuterContainer>
      <Content>
        <Box alignSelf="center">
Node-Tap Features
</Box>
        <Flex pb={4} flexDirection={['column', 'column', 'row']} alignItems="center">
          <Flex px={4} flexDirection="column">
            <FeatureImage pb={[0, 3]} src={brain}/>
            <Box alignSelf="center">
No Fancy DSL to Learn
</Box>
            <TextBox p={2}>

                The whole API is very small, even though it's a powerful framework. t.test(), t.end(), and a handful of assertion methods. This results in having to write and remember less than describe('foo', () => it('is a string or null', () => expect(foo).to.be.a.string().or.null())))

            </TextBox>
          </Flex>
          <Separator src={separator}/>
          <Flex px={4} flexDirection="column">
            <FeatureImage pb={[0, 3]} src={batteries}/>
            <Box alignSelf="center">
Batteries Included
</Box>
            <TextBox p={2}>

                Code coverage, test reporting, error handling, parallel tests, support for JSX/TypeScript/ESM, and a full-featured assertion set are all baked in.  No need to choose any other stuff. Just write some tests.

            </TextBox>
          </Flex>
        </Flex>
        <ButtonLink to="/docs/">Get Started</ButtonLink>
      </Content>
    </OuterContainer>
  );
};

export default Features;
<commit_msg>more noodling<commit_after>import React from 'react';
import styled from 'styled-components';
import {theme, breakpoints} from '../../theme';
import {Image, Flex, Box} from 'rebass';
import brain from '../../images/brain.gif';
import batteries from '../../images/batteries.gif';
import separator from '../../images/separator.svg';
import {ButtonLink} from '../links';

const OuterContainer = styled.section`
  background-color: ${theme.colors.white};
  box-shadow: 0 0px 11px 5px #33333312;
  padding: 40px 20px;

  @media screen and (min-width: ${breakpoints.TABLET}) {
    padding: 70px 20px;
  }
`;

const Content = styled(Flex)`
  max-width: 900px;
  margin: auto;
  flex-direction: column;
`;

const FeatureImage = styled(Image)`
  width: 150px;
  margin: auto;
`;

const Code = styled.code`
  background-color: #ebe7e7;
  font-size: 14px;
`;

const Separator = styled(Image)`
  width: 18px;
  margin: 0 10px;
  transform: rotate(90deg);
  margin: auto;

  @media screen and (min-width: ${breakpoints.TABLET}) {
    transform: rotate(0deg);
    margin: ${theme.space[7]}px ${theme.space[3]}px 0;
  }
`;

const TextBox = styled(Box)`
  max-width: 500px;
`;

const Features = () => {
  return(
    <OuterContainer>
      <Content>
        <Box alignSelf="center">
Node-Tap Features
</Box>
        <Flex pb={4} flexDirection={['column', 'column', 'row']} alignItems="center">
          <Flex px={4} flexDirection="column">
            <FeatureImage pb={[0, 3]} src={brain}/>
            <Box alignSelf="center">
No Fancy DSL to Learn
</Box>
            <TextBox p={2}>

                The whole API is very small, even though it's a powerful framework. t.test(), t.end(), and a handful of assertion methods. This results in having to write and remember less than describe('foo', () => it('is a string or null', () => expect(foo).to.be.a.string().or.null())))

            </TextBox>
          </Flex>
          <Separator src={separator}/>
          <Flex px={4} flexDirection="column">
            <FeatureImage pb={[0, 3]} src={batteries}/>
            <Box alignSelf="center">
Batteries Included
</Box>
            <TextBox p={2}>

                Code coverage, test reporting, error handling, parallel tests, support for JSX/TypeScript/ESM, and a full-featured assertion set are all baked in. No need to choose any other stuff. Just write some tests.

            </TextBox>
          </Flex>
        </Flex>
        <ButtonLink to="/docs/">Get Started</ButtonLink>
      </Content>
    </OuterContainer>
  );
};

export default Features;
<|endoftext|>


<commit_before>//----------------------------------------------------------------------------------
// Microsoft Developer & Platform Evangelism
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
//----------------------------------------------------------------------------------
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//----------------------------------------------------------------------------------

var fs = require('fs');
var guid = require('node-uuid');
var storage = require('azure-storage');
var config = require('./config.js');

var entityGen;
var tableService;
var tableName;

function AdvancedAzureTableSamples() {
  entityGen = storage.TableUtilities.entityGenerator;
  tableService = storage.createTableService(config.connectionString);
  tableName = "Customers" + guid.v1().replace(/-/g, '');

  return scenarios = [
    {
      action: listAllTables,
      message: 'Azure Table Advanced Sample\n'
    },
    {
      action: tableOperationsWithSas,
      message: 'Azure Table Operations with SAS\n'
    }
  ];
}

function listAllTables(callback) {
  tableService.createTableIfNotExists("Advanced" + guid.v1().replace(/-/g, ''), function (error, created) {
    if (error) return callback(error);

    tableService.createTableIfNotExists("Advanced" + guid.v1().replace(/-/g, ''), function (error, created) {
      if (error) return callback(error);

      listTables('Advanced', tableService, null, { maxResults: 100 }, null, function (error, tables) {
        if (error) return callback(error);

        tables.forEach(function (table) {
          console.log("Table: " + table);

          tableService.deleteTable(table, null, function (error) {
            if (!error) console.log('Table ' + table + ' deleted.');

            return callback(error);
          })
        })
      })
    })
  })
};

function tableOperationsWithSas(callback) {
  // Create or reference an existing table
  tableService.createTableIfNotExists(tableName, function tableCreated(error, createResult) {
    if (error) return callback(error);

    if (createResult.isSuccessful) {
      console.log("   Create Table operation executed successfuly for: ", tableName);
    }

    var startDate = new Date();
    var expiryDate = new Date(startDate);

    startDate.setMinutes(startDate.getMinutes() - 5);
    expiryDate.setMinutes(startDate.getMinutes() + 30);

    var sharedAccessPolicy = {
      AccessPolicy: {
        Permissions: storage.TableUtilities.SharedAccessPermissions.QUERY
        + storage.TableUtilities.SharedAccessPermissions.ADD
        + storage.TableUtilities.SharedAccessPermissions.UPDATE
        + storage.TableUtilities.SharedAccessPermissions.DELETE,
        Start: startDate,
        Expiry: expiryDate
      },
    };

    var sas = tableService.generateSharedAccessSignature(tableName, sharedAccessPolicy);

    var sharedTableService = storage.createTableServiceWithSas(tableService.host, sas);

    console.log("2. Inserting or updating an entity with Shared Access Signature.");
    var customer = createCustomerEntityDescriptor("Harp", "Walter", "Walter@contoso.com", "425-555-0101");

    sharedTableService.insertOrMergeEntity(tableName, customer, function (error, result, response) {
      if (error) return callback(error);

      console.log("   insertOrMergeEntity succeeded.");

      console.log("3. Reading the updated entity with Shared Access Signature.");

      // Demonstrate the most efficient storage query - the point query - where both partition key and row key are specified.
      sharedTableService.retrieveEntity(tableName, customer.PartitionKey._, customer.RowKey._, function (error, result) {
        if (error) return callback(error);

        console.log("   retrieveEntity succeeded: ", result.PartitionKey._, result.RowKey._, result.email._, result.phone._);

        console.log("4. Deleting the entity with Shared Access Signature. ");

        sharedTableService.deleteEntity(tableName, customer, function entitiesQueried(error, result) {
          if (error) return callback(error);

          console.log("   deleteEntity succeeded.");

          console.log('5. Deleting table');
          tableService.deleteTable(tableName, function (error) {
            callback(error);
          });
        });
      });
    });
  });
};

/**
* Lists tables in the container.
* @ignore
*
* @param {string}             prefix                              The prefix of the table name.
* @param {TableService}       tableService                        The table service client.
* @param {object}             token                               A continuation token returned by a previous listing operation.
*                                                                 Please use 'null' or 'undefined' if this is the first operation.
* @param {object}             [options]                           The request options.
* @param {int}                [options.maxResults]                Specifies the maximum number of tables to return per call to Azure ServiceClient.
*                                                                 This does NOT affect list size returned by this function. (maximum: 5000)
* @param {errorOrResult}      callback                            `error` will contain information
*                                                                 if an error occurs; otherwise `result` will contain `entries` and `continuationToken`.
*                                                                 `entries`  gives a list of tables and the `continuationToken` is used for the next listing operation.
*                                                                 `response` will contain information related to this operation.
*/
function listTables(prefix, tableService, token, options, tables, callback) {
  tables = tables || [];

  tableService.listTablesSegmentedWithPrefix(prefix, token, options, function (error, result) {

    if (error) return callback(error, null);

    tables.push.apply(tables, result.entries);

    var token = result.continuationToken;

    if (token) {
      console.log('   Received a segment of results. There are ' + result.entries.length + ' tables on this segment.');
      listTables(prefix, tableService, token, options, callback);
    } else {
      console.log('   Completed listing. There are ' + tables.length + ' tables.');
      callback(null, tables);
    }
  })
}

/**
* Creates a customer entity to be used in library calls based on provided parameters
* @ignore
*
* @param {string}  partitionKey     Last name of the customer
* @param {string}  rowKey           Name of the customer
* @param {string}  email            Email of the customer
* @param {string}  phone            Phone number of the customer
* @return {Object}
*/
function createCustomerEntityDescriptor(partitionKey, rowKey, email, phone) {
  var customerEntity = {
    PartitionKey: entityGen.String(partitionKey),
    RowKey: entityGen.String(rowKey),
    email: entityGen.String(email),
    phone: entityGen.String(phone)
  };
  return customerEntity;
}

module.exports = AdvancedAzureTableSamples();<commit_msg>Removed start date from SAS<commit_after>//----------------------------------------------------------------------------------
// Microsoft Developer & Platform Evangelism
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
//----------------------------------------------------------------------------------
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//----------------------------------------------------------------------------------

var fs = require('fs');
var guid = require('node-uuid');
var storage = require('azure-storage');
var config = require('./config.js');

var entityGen;
var tableService;
var tableName;

function AdvancedAzureTableSamples() {
  entityGen = storage.TableUtilities.entityGenerator;
  tableService = storage.createTableService(config.connectionString);
  tableName = "Customers" + guid.v1().replace(/-/g, '');

  return scenarios = [
    {
      action: listAllTables,
      message: 'Azure Table Advanced Sample\n'
    },
    {
      action: tableOperationsWithSas,
      message: 'Azure Table Operations with SAS\n'
    }
  ];
}

function listAllTables(callback) {
  tableService.createTableIfNotExists("Advanced" + guid.v1().replace(/-/g, ''), function (error, created) {
    if (error) return callback(error);

    tableService.createTableIfNotExists("Advanced" + guid.v1().replace(/-/g, ''), function (error, created) {
      if (error) return callback(error);

      listTables('Advanced', tableService, null, { maxResults: 100 }, null, function (error, tables) {
        if (error) return callback(error);

        tables.forEach(function (table) {
          console.log("Table: " + table);

          tableService.deleteTable(table, null, function (error) {
            if (!error) console.log('Table ' + table + ' deleted.');

            return callback(error);
          })
        })
      })
    })
  })
};

function tableOperationsWithSas(callback) {
  // Create or reference an existing table
  tableService.createTableIfNotExists(tableName, function tableCreated(error, createResult) {
    if (error) return callback(error);

    if (createResult.isSuccessful) {
      console.log("   Create Table operation executed successfuly for: ", tableName);
    }

    var expiryDate = new Date();

    expiryDate.setMinutes(expiryDate.getMinutes() + 30);

    var sharedAccessPolicy = {
      AccessPolicy: {
        Permissions: storage.TableUtilities.SharedAccessPermissions.QUERY
        + storage.TableUtilities.SharedAccessPermissions.ADD
        + storage.TableUtilities.SharedAccessPermissions.UPDATE
        + storage.TableUtilities.SharedAccessPermissions.DELETE,
        Expiry: expiryDate
      },
    };

    var sas = tableService.generateSharedAccessSignature(tableName, sharedAccessPolicy);

    var sharedTableService = storage.createTableServiceWithSas(tableService.host, sas);

    console.log("2. Inserting or updating an entity with Shared Access Signature.");
    var customer = createCustomerEntityDescriptor("Harp", "Walter", "Walter@contoso.com", "425-555-0101");

    sharedTableService.insertOrMergeEntity(tableName, customer, function (error, result, response) {
      if (error) return callback(error);

      console.log("   insertOrMergeEntity succeeded.");

      console.log("3. Reading the updated entity with Shared Access Signature.");

      // Demonstrate the most efficient storage query - the point query - where both partition key and row key are specified.
      sharedTableService.retrieveEntity(tableName, customer.PartitionKey._, customer.RowKey._, function (error, result) {
        if (error) return callback(error);

        console.log("   retrieveEntity succeeded: ", result.PartitionKey._, result.RowKey._, result.email._, result.phone._);

        console.log("4. Deleting the entity with Shared Access Signature. ");

        sharedTableService.deleteEntity(tableName, customer, function entitiesQueried(error, result) {
          if (error) return callback(error);

          console.log("   deleteEntity succeeded.");

          console.log('5. Deleting table');
          tableService.deleteTable(tableName, function (error) {
            callback(error);
          });
        });
      });
    });
  });
};

/**
* Lists tables in the container.
* @ignore
*
* @param {string}             prefix                              The prefix of the table name.
* @param {TableService}       tableService                        The table service client.
* @param {object}             token                               A continuation token returned by a previous listing operation.
*                                                                 Please use 'null' or 'undefined' if this is the first operation.
* @param {object}             [options]                           The request options.
* @param {int}                [options.maxResults]                Specifies the maximum number of tables to return per call to Azure ServiceClient.
*                                                                 This does NOT affect list size returned by this function. (maximum: 5000)
* @param {errorOrResult}      callback                            `error` will contain information
*                                                                 if an error occurs; otherwise `result` will contain `entries` and `continuationToken`.
*                                                                 `entries`  gives a list of tables and the `continuationToken` is used for the next listing operation.
*                                                                 `response` will contain information related to this operation.
*/
function listTables(prefix, tableService, token, options, tables, callback) {
  tables = tables || [];

  tableService.listTablesSegmentedWithPrefix(prefix, token, options, function (error, result) {

    if (error) return callback(error, null);

    tables.push.apply(tables, result.entries);

    var token = result.continuationToken;

    if (token) {
      console.log('   Received a segment of results. There are ' + result.entries.length + ' tables on this segment.');
      listTables(prefix, tableService, token, options, callback);
    } else {
      console.log('   Completed listing. There are ' + tables.length + ' tables.');
      callback(null, tables);
    }
  })
}

/**
* Creates a customer entity to be used in library calls based on provided parameters
* @ignore
*
* @param {string}  partitionKey     Last name of the customer
* @param {string}  rowKey           Name of the customer
* @param {string}  email            Email of the customer
* @param {string}  phone            Phone number of the customer
* @return {Object}
*/
function createCustomerEntityDescriptor(partitionKey, rowKey, email, phone) {
  var customerEntity = {
    PartitionKey: entityGen.String(partitionKey),
    RowKey: entityGen.String(rowKey),
    email: entityGen.String(email),
    phone: entityGen.String(phone)
  };
  return customerEntity;
}

module.exports = AdvancedAzureTableSamples();<|endoftext|>


<commit_before>/* Copyright 2015, Yahoo Inc.
   Copyrights licensed under the MIT License.
   See the accompanying LICENSE file for terms. */

var path = require('path');
var xtend = require('xtend');
var Module = require('module');
var pathToRegexp = require('path-to-regexp');
var browserify = require('browserify');
var watchify = require('watchify');
var treenherit = require('mendel-treenherit');
var requirify = require('mendel-requirify');
var parseConfig = require('mendel-config');
var validVariations = require('mendel-config/variations');
var applyExtraOptions = require('mendel-development/apply-extra-options');
var resolveVariations = require('mendel-development/resolve-variations');
var variationMatches = require('mendel-development/variation-matches');
var CachedStreamCollection = require('./cached-stream-collection');
var MendelLoader = require('mendel-development-loader');

module.exports = MendelMiddleware;

function MendelMiddleware(opts) {
    var config = parseConfig(opts);
    var existingVariations = validVariations(config);
    var base = config.base || 'base';

    existingVariations = existingVariations.concat({
        id: base,
        chain: [config.basetree || 'base'],
    });

    var route = config.variationsroute || '/mendel/:variations/:bundle\.js';
    var getPath = pathToRegexp.compile(route);
    var keys = [];
    var bundleRoute = pathToRegexp(route, keys);
    var bundles = config.bundles.reduce(function(acc, bundle) {
        acc[bundle.id] = bundle;
        return acc;
    }, {});

    var allDirs = existingVariations.reduce(function(allDirs, variation) {
        variation.chain.forEach(function(path) {
            if (-1 === allDirs.indexOf(path)) allDirs.push(path);
        });
        return allDirs;
    }, []);

    var loader = new MendelLoader(existingVariations, config, module.parent);

    return function(req, res, next) {
        req.mendel = req.mendel || {};

        req.mendel.getBundleEntries = function() {
            return Object.keys(bundles).reduce(

                function(outputBundles, id) {
                    var bundle = bundles[id];
                    var outputEntries = [];

                    [].concat(bundle.entries, bundle.require)
                    .filter(Boolean)
                    .forEach(
                        function(entry) {
                            var match = variationMatches(existingVariations, entry);
                            if (match) entry = match.file;
                            allDirs.forEach(function(dirPath) {
                                var absolutePath = path.resolve(
                                    config.basedir, dirPath, entry
                                );
                                if (-1 === outputEntries
                                    .indexOf(absolutePath)
                                ){
                                    outputEntries.push(absolutePath);
                                }
                            });
                        }
                    );

                    outputBundles[id] = outputEntries;
                    return outputBundles;
                },

                {} // outputBundles
            );
        };

        req.mendel.getURL = function(bundle, variations) {
            var vars = variations.join(',') || config.base;
            return getPath({bundle: bundle, variations: vars});
        };

        req.mendel.resolver = loader.resolver.bind(loader);
        req.mendel.isSsrReady = loader.isSsrReady.bind(loader);

        // Match bundle route
        var reqParams = bundleRoute.exec(req.url);
        if (!reqParams) {
            return next();
        }
        var params = namedParams(keys, reqParams);
        if (!(
            params.bundle &&
            params.variations &&
            bundles[params.bundle]
        )) {
            return next();
        }
        var bundleConfig = bundles[params.bundle];
        var dirs = params.variations.split(/(,|%2C)/i);
        dirs = resolveVariations(existingVariations, dirs);
        if (!dirs.length || !bundleConfig) {
            return next();
        }

        // Serve bundle
        res.header('content-type', 'application/javascript');

        bundleConfig = xtend(config, bundleConfig, {
            debug: true,
            cache: {},
            packageCache: {}
        });

        cachedStreamBundle(bundleConfig, dirs, function(bundleStream) {
            bundleStream.on('error', function(e) {
                console.error(e.stack);
                res.send('console.error( "Error compiling client bundle", ' +
                    JSON.stringify({ stack: e.stack }) + ')').end();
            });
            bundleStream.pipe(res);
        });
    };
}

function namedParams(keys, reqParams) {
    return keys.reduce(function(params, param, index) {
        params[param.name] = reqParams[index+1];
        return params;
    }, {});
}

var streamCache = new CachedStreamCollection();
function cachedStreamBundle(bundleConfig, dirs, cb) {
    var id = [bundleConfig.id].concat(dirs).join('/');
    if (streamCache.hasItem(id)) {
        return cb(streamCache.outputPipe(id));
    }

    getCachedWatchfy(id, bundleConfig, dirs, function(err, watchBundle) {
        // multiple kinds of error handling start
        function boundError(e) {
            streamCache.sendError(id, e);
        }
        if (err) return cb(boundError(err));

        function makeBundle() {
            var bundle = watchBundle.bundle();
            // multiple kinds of error handling end
            bundle.on('error', boundError);
            bundle.on('transform', function(tr) {
                tr.on('error', boundError);
            });

            streamCache.createItem(id);
            streamCache.inputPipe(id, bundle);
        }

        watchBundle.on('update', function(srcFiles) {
            streamCache.invalidateItem(id);
            invalidateNodeCache(dirs, srcFiles, bundleConfig.serveroutdir);
            makeBundle();
        });

        makeBundle();

        cb(streamCache.outputPipe(id));
    });
}

var watchfyCache = {};
function getCachedWatchfy(id, bundleConfig, dirs, cb) {
    if (watchfyCache[id]) {
        return cb(null, watchfyCache[id]);
    }

    // TODO: async lookup of entries
    bundleConfig.entries = (bundleConfig.entries||[]).map(function(entry) {
        return path.join(bundleConfig.basetree, entry);
    });

    var bundler = browserify(bundleConfig);
    applyExtraOptions(bundler, bundleConfig);
    bundler.transform(treenherit, { dirs: dirs });
    bundler.plugin(watchify);

    if (bundleConfig.serveroutdir && bundleConfig.entries.length) {
        bundler.plugin(requirify, {
            dirs: dirs,
            outdir: bundleConfig.serveroutdir
        });
    }

    watchfyCache[id] = bundler;
    cb(null, watchfyCache[id]);
}

function invalidateNodeCache(dirs, files, serveroutdir) {
    files.forEach(function(file) {
        var match = variationMatches([{chain: dirs}], file);
        if (match) {
            var fullPath = path.join(serveroutdir, match.dir, match.file);
            delete Module._cache[fullPath];
        }
    });
}
<commit_msg>Normalize entries on mendel-development<commit_after>/* Copyright 2015, Yahoo Inc.
   Copyrights licensed under the MIT License.
   See the accompanying LICENSE file for terms. */

var fs = require('fs');
var path = require('path');
var xtend = require('xtend');
var Module = require('module');
var pathToRegexp = require('path-to-regexp');
var browserify = require('browserify');
var watchify = require('watchify');
var treenherit = require('mendel-treenherit');
var requirify = require('mendel-requirify');
var parseConfig = require('mendel-config');
var validVariations = require('mendel-config/variations');
var applyExtraOptions = require('mendel-development/apply-extra-options');
var resolveVariations = require('mendel-development/resolve-variations');
var variationMatches = require('mendel-development/variation-matches');
var CachedStreamCollection = require('./cached-stream-collection');
var MendelLoader = require('mendel-development-loader');

module.exports = MendelMiddleware;

function MendelMiddleware(opts) {
    var config = parseConfig(opts);
    var existingVariations = validVariations(config);
    var base = config.base || 'base';

    existingVariations = existingVariations.concat({
        id: base,
        chain: [config.basetree || 'base'],
    });

    var route = config.variationsroute || '/mendel/:variations/:bundle\.js';
    var getPath = pathToRegexp.compile(route);
    var keys = [];
    var bundleRoute = pathToRegexp(route, keys);
    var bundles = config.bundles.reduce(function(acc, bundle) {
        acc[bundle.id] = bundle;
        return acc;
    }, {});

    var allDirs = existingVariations.reduce(function(allDirs, variation) {
        variation.chain.forEach(function(path) {
            if (-1 === allDirs.indexOf(path)) allDirs.push(path);
        });
        return allDirs;
    }, []);

    var loader = new MendelLoader(existingVariations, config, module.parent);

    return function(req, res, next) {
        req.mendel = req.mendel || {};

        req.mendel.getBundleEntries = function() {
            return Object.keys(bundles).reduce(

                function(outputBundles, id) {
                    var bundle = bundles[id];
                    var outputEntries = [];

                    [].concat(bundle.entries, bundle.require)
                    .filter(Boolean)
                    .forEach(
                        function(entry) {
                            var match = variationMatches(existingVariations, entry);
                            if (match) entry = match.file;
                            allDirs.forEach(function(dirPath) {
                                var absolutePath = path.resolve(
                                    config.basedir, dirPath, entry
                                );
                                if (-1 === outputEntries
                                    .indexOf(absolutePath)
                                ){
                                    outputEntries.push(absolutePath);
                                }
                            });
                        }
                    );

                    outputBundles[id] = outputEntries;
                    return outputBundles;
                },

                {} // outputBundles
            );
        };

        req.mendel.getURL = function(bundle, variations) {
            var vars = variations.join(',') || config.base;
            return getPath({bundle: bundle, variations: vars});
        };

        req.mendel.resolver = loader.resolver.bind(loader);
        req.mendel.isSsrReady = loader.isSsrReady.bind(loader);

        // Match bundle route
        var reqParams = bundleRoute.exec(req.url);
        if (!reqParams) {
            return next();
        }
        var params = namedParams(keys, reqParams);
        if (!(
            params.bundle &&
            params.variations &&
            bundles[params.bundle]
        )) {
            return next();
        }
        var bundleConfig = bundles[params.bundle];
        var dirs = params.variations.split(/(,|%2C)/i);
        dirs = resolveVariations(existingVariations, dirs);
        if (!dirs.length || !bundleConfig) {
            return next();
        }

        // Serve bundle
        res.header('content-type', 'application/javascript');

        bundleConfig = xtend(config, bundleConfig, {
            debug: true,
            cache: {},
            packageCache: {}
        });

        cachedStreamBundle(bundleConfig, dirs, function(bundleStream) {
            bundleStream.on('error', function(e) {
                console.error(e.stack);
                res.send('console.error( "Error compiling client bundle", ' +
                    JSON.stringify({ stack: e.stack }) + ')').end();
            });
            bundleStream.pipe(res);
        });
    };
}

function namedParams(keys, reqParams) {
    return keys.reduce(function(params, param, index) {
        params[param.name] = reqParams[index+1];
        return params;
    }, {});
}

var streamCache = new CachedStreamCollection();
function cachedStreamBundle(bundleConfig, dirs, cb) {
    var id = [bundleConfig.id].concat(dirs).join('/');
    if (streamCache.hasItem(id)) {
        return cb(streamCache.outputPipe(id));
    }

    getCachedWatchfy(id, bundleConfig, dirs, function(err, watchBundle) {
        // multiple kinds of error handling start
        function boundError(e) {
            streamCache.sendError(id, e);
        }
        if (err) return cb(boundError(err));

        function makeBundle() {
            var bundle = watchBundle.bundle();
            // multiple kinds of error handling end
            bundle.on('error', boundError);
            bundle.on('transform', function(tr) {
                tr.on('error', boundError);
            });

            streamCache.createItem(id);
            streamCache.inputPipe(id, bundle);
        }

        watchBundle.on('update', function(srcFiles) {
            streamCache.invalidateItem(id);
            invalidateNodeCache(dirs, srcFiles, bundleConfig.serveroutdir);
            makeBundle();
        });

        makeBundle();

        cb(streamCache.outputPipe(id));
    });
}

var watchfyCache = {};
function getCachedWatchfy(id, bundleConfig, dirs, cb) {
    if (watchfyCache[id]) {
        return cb(null, watchfyCache[id]);
    }

    // TODO: async lookup of entries
    bundleConfig.entries = normalizeEntries(bundleConfig.entries||[], bundleConfig);

    var bundler = browserify(bundleConfig);
    applyExtraOptions(bundler, bundleConfig);
    bundler.transform(treenherit, { dirs: dirs });
    bundler.plugin(watchify);

    if (bundleConfig.serveroutdir && bundleConfig.entries.length) {
        bundler.plugin(requirify, {
            dirs: dirs,
            outdir: bundleConfig.serveroutdir
        });
    }

    watchfyCache[id] = bundler;
    cb(null, watchfyCache[id]);
}

function normalizeEntries(entries, config) {
    return [].concat(entries).filter(Boolean)
    .map(function(entry) {
        if (typeof entry === 'string') {
            if(!fs.existsSync(path.join(config.basedir, entry))) {
                var messages = [
                    '[warn] paths relative to variation are deprecated',
                    'you can fix this by changing',
                    entry,
                    'in your configuration'
                ];
                console.log(messages.join(' '));
                entry = path.join(config.basedir, config.basetree, entry);
            }
        }
        return entry;
    });
}

function invalidateNodeCache(dirs, files, serveroutdir) {
    files.forEach(function(file) {
        var match = variationMatches([{chain: dirs}], file);
        if (match) {
            var fullPath = path.join(serveroutdir, match.dir, match.file);
            delete Module._cache[fullPath];
        }
    });
}
<|endoftext|>


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

'use strict';

require('babel-polyfill');

const RelayCodegenRunner = require('RelayCodegenRunner');
const RelayConsoleReporter = require('RelayConsoleReporter');
const RelayFileIRParser = require('RelayFileIRParser');
const RelayFileWriter = require('RelayFileWriter');
const RelayIRTransforms = require('RelayIRTransforms');

const formatGeneratedModule = require('formatGeneratedModule');
const fs = require('fs');
const path = require('path');
const yargs = require('yargs');

const {
  buildASTSchema,
  buildClientSchema,
  parse,
  printSchema,
} = require('graphql');

const {
  codegenTransforms,
  fragmentTransforms,
  printTransforms,
  queryTransforms,
  schemaExtensions,
} = RelayIRTransforms;

import type {GraphQLSchema} from 'graphql';

function buildWatchExpression(options: {extensions: Array<string>}) {
  return [
    'allof',
    ['type', 'f'],
    ['anyof', ...options.extensions.map(ext => ['suffix', ext])],
    ['not', ['match', '**/node_modules/**', 'wholename']],
    ['not', ['match', '**/__mocks__/**', 'wholename']],
    ['not', ['match', '**/__tests__/**', 'wholename']],
    ['not', ['match', '**/__generated__/**', 'wholename']],
  ];
}

/* eslint-disable no-console-disallow */

async function run(options: {
  schema: string,
  src: string,
  extensions: Array<string>,
  verbose: boolean,
  watch?: ?boolean,
}) {
  const schemaPath = path.resolve(process.cwd(), options.schema);
  if (!fs.existsSync(schemaPath)) {
    throw new Error(`--schema path does not exist: ${schemaPath}.`);
  }
  const srcDir = path.resolve(process.cwd(), options.src);
  if (!fs.existsSync(srcDir)) {
    throw new Error(`--source path does not exist: ${srcDir}.`);
  }
  if (options.watch && !hasWatchmanRootFile(srcDir)) {
    throw new Error(
      `
--watch requires that the src directory have a valid watchman "root" file.

Root files can include:
- A .git/ Git folder
- A .hg/ Mercurial folder
- A .watchmanconfig file

Ensure that one such file exists in ${srcDir} or its parents.
    `.trim(),
    );
  }

  const reporter = new RelayConsoleReporter({verbose: options.verbose});

  const parserConfigs = {
    default: {
      baseDir: srcDir,
      getFileFilter: RelayFileIRParser.getFileFilter,
      getParser: RelayFileIRParser.getParser,
      getSchema: () => getSchema(schemaPath),
      watchmanExpression: buildWatchExpression(options),
    },
  };
  const writerConfigs = {
    default: {
      getWriter: getRelayFileWriter(srcDir),
      isGeneratedFile: (filePath: string) =>
        filePath.endsWith('.js') && filePath.includes('__generated__'),
      parser: 'default',
    },
  };
  const codegenRunner = new RelayCodegenRunner({
    reporter,
    parserConfigs,
    writerConfigs,
    onlyValidate: false,
    skipPersist: true,
  });
  if (options.watch) {
    await codegenRunner.watchAll();
  } else {
    console.log('HINT: pass --watch to keep watching for changes.');
    await codegenRunner.compileAll();
  }
}

function getRelayFileWriter(baseDir: string) {
  return (onlyValidate, schema, documents, baseDocuments) =>
    new RelayFileWriter({
      config: {
        formatModule: formatGeneratedModule,
        compilerTransforms: {
          codegenTransforms,
          fragmentTransforms,
          printTransforms,
          queryTransforms,
        },
        baseDir,
        schemaExtensions,
      },
      onlyValidate,
      schema,
      baseDocuments,
      documents,
    });
}

function getSchema(schemaPath: string): GraphQLSchema {
  try {
    let source = fs.readFileSync(schemaPath, 'utf8');
    if (path.extname(schemaPath) === '.json') {
      source = printSchema(buildClientSchema(JSON.parse(source).data));
    }
    source = `
  directive @include(if: Boolean) on FRAGMENT | FIELD
  directive @skip(if: Boolean) on FRAGMENT | FIELD

  ${source}
  `;
    return buildASTSchema(parse(source));
  } catch (error) {
    throw new Error(
      `
Error loading schema. Expected the schema to be a .graphql or a .json
file, describing your GraphQL server's API. Error detail:

${error.stack}
    `.trim(),
    );
  }
}

// Ensure that a watchman "root" file exists in the given directory
// or a parent so that it can be watched
const WATCHMAN_ROOT_FILES = ['.git', '.hg', '.watchmanconfig'];
function hasWatchmanRootFile(testPath) {
  while (path.dirname(testPath) !== testPath) {
    if (
      WATCHMAN_ROOT_FILES.some(file => {
        return fs.existsSync(path.join(testPath, file));
      })
    ) {
      return true;
    }
    testPath = path.dirname(testPath);
  }
  return false;
}

// Collect args
const argv = yargs
  .usage(
    'Create Relay generated files\n\n' +
      '$0 --schema <path> --src <path> [--watch]',
  )
  .options({
    schema: {
      describe: 'Path to schema.graphql or schema.json',
      demandOption: true,
      type: 'string',
    },
    src: {
      describe: 'Root directory of application code',
      demandOption: true,
      type: 'string',
    },
    extensions: {
      array: true,
      default: ['js'],
      describe: 'File extensions to compile (--extensions js jsx)',
      type: 'string',
    },
    verbose: {
      describe: 'More verbose logging',
      type: 'boolean',
    },
    watch: {
      describe: 'If specified, watches files and regenerates on changes',
      type: 'boolean',
    },
  })
  .help().argv;

// Run script with args
run(argv).catch(error => {
  console.error(String(error.stack || error));
  process.exit(1);
});
<commit_msg>add include/exclude options to compiler<commit_after>/**
 * Copyright (c) 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @flow
 * @providesModule RelayCompilerBin
 * @format
 */

'use strict';

require('babel-polyfill');

const RelayCodegenRunner = require('RelayCodegenRunner');
const RelayConsoleReporter = require('RelayConsoleReporter');
const RelayFileIRParser = require('RelayFileIRParser');
const RelayFileWriter = require('RelayFileWriter');
const RelayIRTransforms = require('RelayIRTransforms');

const formatGeneratedModule = require('formatGeneratedModule');
const fs = require('fs');
const path = require('path');
const yargs = require('yargs');

const {
  buildASTSchema,
  buildClientSchema,
  parse,
  printSchema,
} = require('graphql');

const {
  codegenTransforms,
  fragmentTransforms,
  printTransforms,
  queryTransforms,
  schemaExtensions,
} = RelayIRTransforms;

import type {GraphQLSchema} from 'graphql';

function buildWatchExpression(options: {
  extensions: Array<string>,
  include: Array<string>,
  exclude: Array<string>,
}) {
  return [
    'allof',
    ['type', 'f'],
    ['anyof', ...options.extensions.map(ext => ['suffix', ext])],
    [
      'anyof',
      ...options.include.map(include => ['match', include, 'wholename']),
    ],
    ...options.exclude.map(exclude => ['not', ['match', exclude, 'wholename']]),
  ];
}

/* eslint-disable no-console-disallow */

async function run(options: {
  schema: string,
  src: string,
  extensions: Array<string>,
  include: Array<string>,
  exclude: Array<string>,
  verbose: boolean,
  watch?: ?boolean,
}) {
  const schemaPath = path.resolve(process.cwd(), options.schema);
  if (!fs.existsSync(schemaPath)) {
    throw new Error(`--schema path does not exist: ${schemaPath}.`);
  }
  const srcDir = path.resolve(process.cwd(), options.src);
  if (!fs.existsSync(srcDir)) {
    throw new Error(`--source path does not exist: ${srcDir}.`);
  }
  if (options.watch && !hasWatchmanRootFile(srcDir)) {
    throw new Error(
      `
--watch requires that the src directory have a valid watchman "root" file.

Root files can include:
- A .git/ Git folder
- A .hg/ Mercurial folder
- A .watchmanconfig file

Ensure that one such file exists in ${srcDir} or its parents.
    `.trim(),
    );
  }

  const reporter = new RelayConsoleReporter({verbose: options.verbose});

  const parserConfigs = {
    default: {
      baseDir: srcDir,
      getFileFilter: RelayFileIRParser.getFileFilter,
      getParser: RelayFileIRParser.getParser,
      getSchema: () => getSchema(schemaPath),
      watchmanExpression: buildWatchExpression(options),
    },
  };
  const writerConfigs = {
    default: {
      getWriter: getRelayFileWriter(srcDir),
      isGeneratedFile: (filePath: string) =>
        filePath.endsWith('.js') && filePath.includes('__generated__'),
      parser: 'default',
    },
  };
  const codegenRunner = new RelayCodegenRunner({
    reporter,
    parserConfigs,
    writerConfigs,
    onlyValidate: false,
    skipPersist: true,
  });
  if (options.watch) {
    await codegenRunner.watchAll();
  } else {
    console.log('HINT: pass --watch to keep watching for changes.');
    await codegenRunner.compileAll();
  }
}

function getRelayFileWriter(baseDir: string) {
  return (onlyValidate, schema, documents, baseDocuments) =>
    new RelayFileWriter({
      config: {
        formatModule: formatGeneratedModule,
        compilerTransforms: {
          codegenTransforms,
          fragmentTransforms,
          printTransforms,
          queryTransforms,
        },
        baseDir,
        schemaExtensions,
      },
      onlyValidate,
      schema,
      baseDocuments,
      documents,
    });
}

function getSchema(schemaPath: string): GraphQLSchema {
  try {
    let source = fs.readFileSync(schemaPath, 'utf8');
    if (path.extname(schemaPath) === '.json') {
      source = printSchema(buildClientSchema(JSON.parse(source).data));
    }
    source = `
  directive @include(if: Boolean) on FRAGMENT | FIELD
  directive @skip(if: Boolean) on FRAGMENT | FIELD

  ${source}
  `;
    return buildASTSchema(parse(source));
  } catch (error) {
    throw new Error(
      `
Error loading schema. Expected the schema to be a .graphql or a .json
file, describing your GraphQL server's API. Error detail:

${error.stack}
    `.trim(),
    );
  }
}

// Ensure that a watchman "root" file exists in the given directory
// or a parent so that it can be watched
const WATCHMAN_ROOT_FILES = ['.git', '.hg', '.watchmanconfig'];
function hasWatchmanRootFile(testPath) {
  while (path.dirname(testPath) !== testPath) {
    if (
      WATCHMAN_ROOT_FILES.some(file => {
        return fs.existsSync(path.join(testPath, file));
      })
    ) {
      return true;
    }
    testPath = path.dirname(testPath);
  }
  return false;
}

// Collect args
const argv = yargs
  .usage(
    'Create Relay generated files\n\n' +
      '$0 --schema <path> --src <path> [--watch]',
  )
  .options({
    schema: {
      describe: 'Path to schema.graphql or schema.json',
      demandOption: true,
      type: 'string',
    },
    src: {
      describe: 'Root directory of application code',
      demandOption: true,
      type: 'string',
    },
    include: {
      array: true,
      default: ['**'],
      describe: 'Directories to include under src',
      type: 'string',
    },
    exclude: {
      array: true,
      default: [
        '**/node_modules/**',
        '**/__mocks__/**',
        '**/__tests__/**',
        '**/__generated__/**',
      ],
      describe: 'Directories to ignore under src',
      type: 'string',
    },
    extensions: {
      array: true,
      default: ['js'],
      describe: 'File extensions to compile (--extensions js jsx)',
      type: 'string',
    },
    verbose: {
      describe: 'More verbose logging',
      type: 'boolean',
    },
    watch: {
      describe: 'If specified, watches files and regenerates on changes',
      type: 'boolean',
    },
  })
  .help().argv;

// Run script with args
run(argv).catch(error => {
  console.error(String(error.stack || error));
  process.exit(1);
});
<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var R = require('request-promise');
var P = require("bluebird");

var RETRY_TIMEOUT     = 0;          // the time to wait for retrying a request
var LIMIT_PER_SECOND  = 0;          // how many requests are available per second
var SLOT_RESPAWN      = 0;          // Time in miliseconds for respawning the slots
var TOO_MANY_REQUESTS = 0;          // The return Status from the Server if there are too many request sent to it. If applicable.
var INFLIGHT          = 'not set';  // Status while the request call is active
var FULFILLED         = 'not set';  // Status when the request was successfull
var THROTTLED         = 'not set';  // Status when the request gets throttled
var ERRORED           = 'not set';  // Status when the request has thrown an internal error
var RETRY_ERRORED     = false;      // whether to retry a request if it throws an internal error or not
var RETRY_FAILED      = false;      // whether to retry a request if it returns an http error code
var LOGGER            = null        // Logger function
var NAME              = 'not set';  // The Baboon name for log identification

function CapeBaboon(options) {
  options = options || {};
  RETRY_TIMEOUT     = options.RETRY_TIMEOUT     || 1000;
  LIMIT_PER_SECOND  = options.LIMIT_PER_SECOND  || 10;
  SLOT_RESPAWN      = options.SLOT_RESPAWN      || 4.0 * 1000/LIMIT_PER_SECOND;
  TOO_MANY_REQUESTS = options.TOO_MANY_REQUESTS || 429;
  INFLIGHT          = options.INFLIGHT          || 'inflight';
  FULFILLED         = options.FULFILLED         || 'fulfilled';
  THROTTLED         = options.THROTTLED         || 'throttled';
  ERRORED           = options.FAILED            || 'errored';
  RETRY_FAILED      = options.RETRY_FAILED      || false;
  RETRY_ERRORED     = options.RETRY_ERRORED     || false;
  LOGGER            = options.LOGGER            || function(text){console.log(text);};
  NAME              = options.NAME              || 'Funky Baboon';
  this._pending     = [];
  this._inflight    = [];
  this._reset();
}

var logger = function(string){
  LOGGER('|'+NAME+'|'+string);
};

CapeBaboon.prototype.push = function (call) {
  var self = this;
  var promise = new P(function(resolve, reject){
    var requestObject = {
      call: call,
      resolve: resolve,
      reject: reject,
      status: null,
      throttle: function(){
        this.status = THROTTLED;
        self._proceed();
      }
    };
    self._pending.push(requestObject);
  });
  this._proceed();
  return promise;
};

CapeBaboon.prototype.request = function(options) {
  var call = function(){
    return R(options)
  };
  return this.push(call);
};

CapeBaboon.prototype._proceed = function(){
  this._removeFulfilled();
  this._removeThrottled();
  this._startPending();
};

CapeBaboon.prototype._removeFulfilled = function(){
  _.remove(this._inflight, {status: FULFILLED});
};

CapeBaboon.prototype._removeThrottled = function(){
  var throttled = _.remove(this._inflight, {status: THROTTLED});
  if (throttled.length > 0) this._retry(throttled);
};

CapeBaboon.prototype._retry = function(requests){
  var self = this;
  this._pending.unshift.apply(this._pending, requests);
  this._retryTimeout = setTimeout(function(){
    self._reset();
    self._proceed();
  }, RETRY_TIMEOUT);
  self._numSlots = 0;
};

CapeBaboon.prototype._startPending = function(){
  var self = this;
  var startRequests = Math.min(this._numSlots, this._pending.length);

  _.times(startRequests, function () {
    var request = self._pending.shift();
    request.status = INFLIGHT;
    try {
      request.call()
      .then(successHandler, errorHandler);
    } catch (e){
      //when the synchronous call() fails
      //should never happen unless _performRequest throws
      //TODO not quite happy with this. I want this to appear in the
      //     console with the original stacktrace (call to adapter.request)
      if(RETRY_ERRORED){
        logger('ERROR THROTTLED'+e);
        request.status = THROTTLED;
        self._proceed();
      }else{
        request.status = ERRORED;
        request.reject(e);
      }
      return;
    }
    self._takeSlot();
    self._inflight.push(request);

    function successHandler(result){
      if (result.status === TOO_MANY_REQUESTS) {
        logger('MESSAGE THROTTLED: '+result.status);
        request.status = THROTTLED;
      } else {
        request.status = FULFILLED;
        request.resolve(result);
      }
      self._proceed();
    }

    function errorHandler(error){
      if(RETRY_FAILED){
        logger('FAIL THROTTLED: '+error);
        request.status = THROTTLED;
      }else{
        request.status = FULFILLED;
        request.reject(error);
      }
      self._proceed();
    }
  });
};

CapeBaboon.prototype._takeSlot = function(){
  if (this._numSlots > 0) {
    this._numSlots--;
    setTimeout(respawnSlot, SLOT_RESPAWN);
  } else {
    throw new Error('No slots available');
  }

  var self = this;
  function respawnSlot(){
    if (self._isWaitingForRetry()) return;
    if (self._numSlots < LIMIT_PER_SECOND) {
      self._numSlots++;
      self._proceed();
    }
  }
};

CapeBaboon.prototype._reset = function(){
  this._numSlots = LIMIT_PER_SECOND;
  this._retryTimeout = null;
};

CapeBaboon.prototype._isWaitingForRetry = function(){
  return this._retryTimeout !== null && this._retryTimeout !== undefined;
};

module.exports = CapeBaboon;
<commit_msg>make Config publicly available but instance variables<commit_after>'use strict';

var _ = require('lodash');
var R = require('request-promise');
var P = require("bluebird");

function CapeBaboon(options) {
  options = options || {};
  this.RETRY_TIMEOUT     = options.RETRY_TIMEOUT     || 1000;                         // the time to wait for retrying a request
  this.LIMIT_PER_SECOND  = options.LIMIT_PER_SECOND  || 10;                           // the time to wait for retrying a request
  this.SLOT_RESPAWN      = options.SLOT_RESPAWN      || 4.0 * 1000/LIMIT_PER_SECOND;  // Time in miliseconds for respawning the slots
  this.TOO_MANY_REQUESTS = options.TOO_MANY_REQUESTS || 429;                          // The return Status from the Server if there are too many request sent to it. If applicable.
  this.INFLIGHT          = options.INFLIGHT          || 'inflight';                   // Status while the request call is active
  this.FULFILLED         = options.FULFILLED         || 'fulfilled';                  // Status when the request was successfull
  this.THROTTLED         = options.THROTTLED         || 'throttled';                  // Status when the request gets throttled
  this.ERRORED           = options.FAILED            || 'errored';                    // Status when the request has thrown an internal error
  this.RETRY_FAILED      = options.RETRY_FAILED      || false;                        // whether to retry a request if it throws an internal error or not
  this.RETRY_ERRORED     = options.RETRY_ERRORED     || false;                        // whether to retry a request if it returns an http error code
  this.LOGGER            = options.LOGGER            || function(text){console.log(text);}; // Logger function
  this.NAME              = options.NAME              || 'Funky Baboon';               // The Baboon name for log identification
  this._pending     = [];
  this._inflight    = [];
  this._reset();
}

CapeBaboon.prototype.push = function (call) {
  var self = this;
  var promise = new P(function(resolve, reject){
    var requestObject = {
      call: call,
      resolve: resolve,
      reject: reject,
      status: null,
      throttle: function(){
        this.status = self.THROTTLED;
        self._proceed();
      }
    };
    self._pending.push(requestObject);
  });
  this._proceed();
  return promise;
};

CapeBaboon.prototype.request = function(options) {
  var call = function(){
    return R(options)
  };
  return this.push(call);
};

CapeBaboon.prototype._proceed = function(){
  this._removeFulfilled();
  this._removeThrottled();
  this._startPending();
};

CapeBaboon.prototype._removeFulfilled = function(){
  _.remove(this._inflight, {status: self.FULFILLED});
};

CapeBaboon.prototype._removeThrottled = function(){
  var throttled = _.remove(this._inflight, {status: self.THROTTLED});
  if (throttled.length > 0) this._retry(throttled);
};

CapeBaboon.prototype._retry = function(requests){
  var self = this;
  this._pending.unshift.apply(this._pending, requests);
  this._retryTimeout = setTimeout(function(){
    self._reset();
    self._proceed();
  }, self.RETRY_TIMEOUT);
  self._numSlots = 0;
};

CapeBaboon.prototype._startPending = function(){
  var self = this;
  var startRequests = Math.min(this._numSlots, this._pending.length);

  _.times(startRequests, function () {
    var request = self._pending.shift();
    request.status = self.INFLIGHT;
    try {
      request.call()
      .then(successHandler, errorHandler);
    } catch (e){
      if(self.RETRY_ERRORED){
        logger('ERROR THROTTLED'+e);
        request.status = self.THROTTLED;
        self._proceed();
      }else{
        request.status = self.ERRORED;
        request.reject(e);
      }
      return;
    }
    self._takeSlot();
    self._inflight.push(request);

    function successHandler(result){
      if (result.status === self.TOO_MANY_REQUESTS) {
        logger('MESSAGE THROTTLED: '+result.status);
        request.status = self.THROTTLED;
      } else {
        request.status = self.FULFILLED;
        request.resolve(result);
      }
      self._proceed();
    }

    function errorHandler(error){
      if(self.RETRY_FAILED){
        logger('FAIL THROTTLED: '+error);
        request.status = self.THROTTLED;
      }else{
        request.status = self.FULFILLED;
        request.reject(error);
      }
      self._proceed();
    }
  });
};

CapeBaboon.prototype._takeSlot = function(){
  if (this._numSlots > 0) {
    this._numSlots--;
    setTimeout(respawnSlot, self.SLOT_RESPAWN);
  } else {
    throw new Error('No slots available');
  }

  var self = this;
  function respawnSlot(){
    if (self._isWaitingForRetry()) return;
    if (self._numSlots < self.LIMIT_PER_SECOND) {
      self._numSlots++;
      self._proceed();
    }
  }
};

CapeBaboon.prototype._reset = function(){
  this._numSlots = self.LIMIT_PER_SECOND;
  this._retryTimeout = null;
};

CapeBaboon.prototype._isWaitingForRetry = function(){
  return this._retryTimeout !== null && this._retryTimeout !== undefined;
};

module.exports = CapeBaboon;
<|endoftext|>


<commit_before>import pify from 'pify'
import { createTransport } from 'nodemailer'
import { markdown as nodemailerMarkdown } from 'nodemailer-markdown'

// ===================================================================

const markdownCompiler = nodemailerMarkdown()

// ===================================================================

export const configurationSchema = {
  type: 'object',

  properties: {
    from: {
      type: 'object',

      properties: {
        name: {
          type: 'string'
        },
        address: {
          type: 'string'
        }
      },

      additionalProperties: false,
      required: ['address']
    },

    transport: {
      type: 'object',

      properties: {
        host: {
          type: 'string',
          description: 'hostname or IP address of the SMTP server'
        },
        port: {
          type: 'integer',
          description: 'port of the SMTP server (defaults to 25 or 465)'
        },
        secure: {
          type: 'boolean',
          description: 'whether the connection should use SSL'
        },

        // FIXME: xo-web does not support edition of too nested
        user: {
          type: 'string',
          description: 'name to use to authenticate'
        },
        password: {
          type: 'string',
          description: 'password to use to authenticate'
        }
        // properties.
        // auth: {
        //   type: 'object',

        //   properties: {
        //     user: {
        //       type: 'string',
        //       description: 'name to use to authenticate'
        //     },
        //     pass: {
        //       type: 'string',
        //       description: 'password to use to authenticate'
        //     }
        //   },

        //   additionalProperties: false,
        //   required: ['user', 'pass']
        // }
      },

      additionalProperties: false,
      required: ['host', 'user', 'pass']
    }
  },

  additionalProperties: false,
  required: ['from', 'transport']
}

// ===================================================================

class TransportEmailPlugin {
  constructor (xo) {
    this._sendEmail = ::this._sendEmail
    this._set = ::xo.defineProperty
    this._unset = null

    // Defined in configure().
    this._conf = null
    this._send = null
  }

  configure ({
    transport: {
      user,
      password,
      ...transportConf
    },
    ...conf
  }) {
    transportConf.auth = { user, pass: password }

    const transport = createTransport(transportConf)
    transport.use('compile', markdownCompiler)

    this._conf = conf
    this._send = pify(::transport.sendMail, Promise)
  }

  load () {
    this._unset = this._set('sendEmail', this._sendEmail)
  }

  unload () {
    this._unset()
  }

  async _sendEmail ({
    from,
    to, cc, bcc,
    subject,
    markdown
  }) {
    await this._send({
      from: from || this._conf.from,
      to, cc, bcc,
      subject,
      markdown
    })
  }
}

// ===================================================================

export default ({ xo }) => new TransportEmailPlugin(xo)
<commit_msg>Fix required field, changed from pass to password<commit_after>import pify from 'pify'
import { createTransport } from 'nodemailer'
import { markdown as nodemailerMarkdown } from 'nodemailer-markdown'

// ===================================================================

const markdownCompiler = nodemailerMarkdown()

// ===================================================================

export const configurationSchema = {
  type: 'object',

  properties: {
    from: {
      type: 'object',

      properties: {
        name: {
          type: 'string'
        },
        address: {
          type: 'string'
        }
      },

      additionalProperties: false,
      required: ['address']
    },

    transport: {
      type: 'object',

      properties: {
        host: {
          type: 'string',
          description: 'hostname or IP address of the SMTP server'
        },
        port: {
          type: 'integer',
          description: 'port of the SMTP server (defaults to 25 or 465)'
        },
        secure: {
          type: 'boolean',
          description: 'whether the connection should use SSL'
        },

        // FIXME: xo-web does not support edition of too nested
        user: {
          type: 'string',
          description: 'name to use to authenticate'
        },
        password: {
          type: 'string',
          description: 'password to use to authenticate'
        }
        // properties.
        // auth: {
        //   type: 'object',

        //   properties: {
        //     user: {
        //       type: 'string',
        //       description: 'name to use to authenticate'
        //     },
        //     pass: {
        //       type: 'string',
        //       description: 'password to use to authenticate'
        //     }
        //   },

        //   additionalProperties: false,
        //   required: ['user', 'pass']
        // }
      },

      additionalProperties: false,
      required: ['host', 'user', 'password']
    }
  },

  additionalProperties: false,
  required: ['from', 'transport']
}

// ===================================================================

class TransportEmailPlugin {
  constructor (xo) {
    this._sendEmail = ::this._sendEmail
    this._set = ::xo.defineProperty
    this._unset = null

    // Defined in configure().
    this._conf = null
    this._send = null
  }

  configure ({
    transport: {
      user,
      password,
      ...transportConf
    },
    ...conf
  }) {
    transportConf.auth = { user, pass: password }

    const transport = createTransport(transportConf)
    transport.use('compile', markdownCompiler)

    this._conf = conf
    this._send = pify(::transport.sendMail, Promise)
  }

  load () {
    this._unset = this._set('sendEmail', this._sendEmail)
  }

  unload () {
    this._unset()
  }

  async _sendEmail ({
    from,
    to, cc, bcc,
    subject,
    markdown
  }) {
    await this._send({
      from: from || this._conf.from,
      to, cc, bcc,
      subject,
      markdown
    })
  }
}

// ===================================================================

export default ({ xo }) => new TransportEmailPlugin(xo)
<|endoftext|>


<commit_before>/**
 * Interface for evaluating revisions
 *
 * @author: Helder (https://github.com/he7d3r)
 * @license: CC BY-SA 3.0 <https://creativecommons.org/licenses/by-sa/3.0/>
 * Based on mockups by Aaron Halfaker
 * https://meta.wikimedia.org/wiki/Research_talk:Revision_scoring_as_a_service?oldid=10266386#Revision_handcoding_.28mockups.29
 */
( function ( mw, $ ) {
	'use strict';
	var fields, tasks, curTaskIdx;

	function lookup( k ) {
		return mw.msg( 'rvc-' + k );
	}
	// Applying a translation to any level of a form description doc
	function applyTranslation( value, lookup ) {
		var i, l, transList, obj, transObj, key, str;
		if ( typeof value === 'string' ) {
			// If a string, look to see if we need to translate it.
			str = value;
			if ( str.charAt( 0 ) === '<' && str.charAt( str.length - 1 ) === '>' ) {
				// Lookup translation
				return lookup( str.substr( 1, str.length - 2 ) );
			} else {
				// No translation necessary
				return str;
			}
		} else if ( $.isArray( value ) ) {
			// Going to have to recurse for each item
			l = value;
			transList = [];
			for ( i in l ) {
				if ( l.hasOwnProperty( i ) ) {
					transList.push( applyTranslation( l[i], lookup ) );
				}
			}
			return transList;
		} else if ( typeof value === 'object' ) {
			// Going to have to recurse for each value
			obj = value;
			transObj = {};
			for ( key in obj ) {
				if ( obj.hasOwnProperty( key ) ) {
					transObj[ key ] = applyTranslation( obj[key], lookup );
				}
			}
			return transObj;
		} else {
			// bool or numeric == A-OK
			return value;
		}
	}

	function toggleSelection( e ) {
		var $target = $( e.target ),
			wasSelected = $target.hasClass( 'rvc-selected' );
		$target
			.parent()
				.find( '.rvc-selected' )
					.removeClass( 'rvc-selected' )
					.end()
				.end();
		if ( !wasSelected ) {
			$target.addClass( 'rvc-selected' );
		}
		// The user must select one value for each field
		$( '#rvc-submit' ).prop(
			'disabled',
			$( '.mw-ui-button.rvc-selected' ).length !== fields.length ||
				curTaskIdx >= tasks.length
		);
	}

	function getWorkSet( campId, wsId ) {
		campId = campId || 345;
		wsId = wsId || 222;
		return $.ajax( {
			url: '//ores-test.wmflabs.org/coder/campaigns/' +
				mw.config.get( 'wgDBname' ) + '/' + campId + '/' + wsId + '/',
			dataType: 'jsonp'
		} );
	}

	function showWorkSet( data ) {
		var i, j, field, $icon, className, tooltip, value,
			$bar = $( '.rvc-progress' ).empty();
		tasks = ( data && data.workset.tasks ) || tasks;
		for ( i = 0; i < tasks.length; i++ ) {
			$icon = $( '
' );
			tooltip = mw.msg( 'rvc-revision-title', tasks[i].data.rev_id );
			for ( j = 0; j < fields.length; j++ ) {
				field = fields[j].id;
				// FIXME: how to get the labels (values) without doing an API request for each task in this workset?
				// FIXME: type of label values are inconsistent (boolean vs integers):
				// * true/false: https://ores-test.wmflabs.org/coder/campaigns/enwiki/111/222/333/
				// * 1/0: https://ores-test.wmflabs.org/coder/forms/damaging_and_goodfaith
				//
				// idx = tasks[i].fields[ field ];
				// value = fields[j].options[ idx ] && fields[j].options[ idx ].value;
				// tooltip += '\n' + fields[j].label + ' ' + value;
				className = 'rvc-' + field + '-' + value;
				$icon.append( $( '
' ).addClass( className ) );
			}
			$icon.attr(
				'title',
				tooltip
			);
			$bar.append( $icon );
		}
		$( '.rvc-progress > div' ).css( 'width', ( 100 / tasks.length ) + '%' );
		$( '.mw-ui-button.rvc-selected' ).removeClass( 'rvc-selected' );
		$( '#rvc-submit' ).prop( 'disabled', true );
		if ( curTaskIdx < tasks.length ) {
			$bar.find( '> div' ).eq( curTaskIdx ).addClass( 'rvc-selected' );
			showDiff( tasks[curTaskIdx].data.rev_id );
		}
	}

	function showDiff( revid ) {
		new mw.Api().get( {
			action: 'query',
			prop: 'revisions',
			rvdiffto: 'prev',
			revids: revid,
			indexpageids: true
		} ).done( function ( data ) {
			var page, pageids = data.query.pageids;
			if ( pageids && pageids[0] ) {
				page = data.query.pages[ pageids[0] ];
				// $( '#firstHeading' ).text( page.title );
				$( '#rvc-diff' ).empty().append(
					page.revisions[0].diff['*']
				);
			} else {
				$( '#rvc-diff' ).empty().text( mw.msg( 'rvc-badpageid' ) );
			}
		} );
	}

	function submit() {
		var campId = 123,
			wsId = 456,
			taskId = 789;
		$( '.mw-ui-button.rvc-selected' ).each( function () {
			var $this = $( this ),
				idxValue = $this.data( 'rvc-value' ),
				field = $this.parent().data( 'rvc-field' );
			if ( field !== undefined && idxValue !== undefined ) {
				if ( !tasks[ curTaskIdx ].fields ) {
					tasks[ curTaskIdx ].fields = {};
				}
				tasks[ curTaskIdx ].fields[ field ] = idxValue;
			}
		} );
		$( '#rvc-submit' ).injectSpinner( 'rvc-submit-spinner' );
		$.ajax( {
			url: '//ores-test.wmflabs.org/coder/campaigns/' +
				mw.config.get( 'wgDBname' ) + '/' + campId + '/' + wsId + '/' + taskId + '/',
			data: {
				label: JSON.stringify( {
					// TODO: use integers consistently for storing labels?
					goodfaith: true,
					damaging: false
				} )
			},
			dataType: 'jsonp'
		} ).always( function () {
			$.removeSpinner( 'rvc-submit-spinner' );
		} ).fail( function () {
			alert( 'An errror occurred! Check the console...' );
		} );
		curTaskIdx++;
		showWorkSet();
		if ( curTaskIdx >= tasks.length ) {
			alert( mw.msg( 'rvc-dataset-completed' ) );
			$( '#rvc-submit' ).prop( 'disabled', true );
		}
	}

	function load( data ) {
		var $ui = $( '#rvc-ui' ).empty(),
			// FIXME: Migrate to OOjs UI (http://livingstyleguide.wmflabs.org/wiki/OOjs_UI)
			$submit = $( '<input id="rvc-submit" class="mw-ui-button mw-ui-constructive" type="submit">' )
				.prop( 'disabled', true )
				.click( submit ),
			field, i, j, id, val, $feature, $group, key, messages, prefixedMsgs;
		// Reads in messages and sets a prefix for mw.msg to do lookups
		messages = data.i18n[ mw.config.get( 'wgUserLanguage' ) ] || data.i18n.en;
		prefixedMsgs = {};
		for ( key in messages ) {
			if ( messages.hasOwnProperty( key ) ) {
				prefixedMsgs[ 'rvc-' + key ] = messages[ key ];
			}
		}
		mw.messages.set( prefixedMsgs );
		fields = applyTranslation( data.fields, lookup );

		$submit.val( mw.msg( 'rvc-submit' ) );
		$ui.append(
			$( '
' )
				.text( mw.msg( 'rvc-work-set' ) ),
			$( '
' )
				.addClass( 'rvc-progress' )
		);
		for ( i = 0; i < fields.length; i++ ) {
			field = fields[i];
			id = field.id;
			$group = $( '
' )
				.data( 'rvc-field', id )
				// .addClass( 'mw-ui-radio');
				.addClass( 'mw-ui-button-group' );
			for ( j = 0; j < field.options.length; j++ ) {
				val = field.options[j].value;
				$group.append(
					$( '
' )
						.addClass( 'mw-ui-button' )
						.attr( 'id', 'rvc-' + field.id + '-' + val )
						.attr( 'title', field.options[j].tooltip )
						.text( field.options[j].label )
						.data( 'rvc-value', j )
						.click( toggleSelection )
// 					$( '<input type="radio">' )
// 						.attr( 'name', 'rvc-' + field.id )
// 						.attr( 'id', 'rvc-' + field.id + '-' + val )
// 						.attr( 'title', field.options[j].tooltip ),
// 					$( '' )
// 						.text( field.options[j].label )
// 						.attr( 'for', 'rvc-' + field.id + '-' + val )
// 						.data( 'rvc-value', j )
// 						.click( toggleSelection )
				);
			}
			$feature = $( '
' )
				.attr( 'title', field.help )
				.append(
					$( '
' )
						.text( field.label ),
					$group
				);
			$ui.append( $feature, '

' );
		}
		$ui.append( $submit )
			.append(
				'
' +
				'<colgroup><col class="diff-marker">' +
				'<col class="diff-content">' +
				'<col class="diff-marker">' +
				'<col class="diff-content">' +
				'</colgroup>

'
			);
		curTaskIdx = 0;
		getWorkSet()
			.done( showWorkSet );
	}

	if ( $.inArray( mw.config.get( 'wgAction' ), [ 'view', 'purge' ] ) !== -1 ) {
		$( function () {
			if ( $( '#rvc-ui' ).length !== 0 ) {
				mw.loader.using( [
					'mediawiki.api',
					'jquery.spinner',
					// TODO: Load this only when necessary
					// (e.g. if the user will be required to click on some button before the first diff appears)
					'mediawiki.action.history.diff'
				] ).done( function () {
					$.ajax(
					{
						url: '//ores-test.wmflabs.org/coder/forms/damaging_and_goodfaith',
						dataType: 'jsonp'
					} )
					.done( load );
				} );
			}
		} );
	}

}( mediaWiki, jQuery ) );
<commit_msg>Add more error handling and timeout after 3 seconds<commit_after>/**
 * Interface for evaluating revisions
 *
 * @author: Helder (https://github.com/he7d3r)
 * @license: CC BY-SA 3.0 <https://creativecommons.org/licenses/by-sa/3.0/>
 * Based on mockups by Aaron Halfaker
 * https://meta.wikimedia.org/wiki/Research_talk:Revision_scoring_as_a_service?oldid=10266386#Revision_handcoding_.28mockups.29
 */
( function ( mw, $ ) {
	'use strict';
	var fields, tasks, curTaskIdx;

	function lookup( k ) {
		return mw.msg( 'rvc-' + k );
	}
	// Applying a translation to any level of a form description doc
	function applyTranslation( value, lookup ) {
		var i, l, transList, obj, transObj, key, str;
		if ( typeof value === 'string' ) {
			// If a string, look to see if we need to translate it.
			str = value;
			if ( str.charAt( 0 ) === '<' && str.charAt( str.length - 1 ) === '>' ) {
				// Lookup translation
				return lookup( str.substr( 1, str.length - 2 ) );
			} else {
				// No translation necessary
				return str;
			}
		} else if ( $.isArray( value ) ) {
			// Going to have to recurse for each item
			l = value;
			transList = [];
			for ( i in l ) {
				if ( l.hasOwnProperty( i ) ) {
					transList.push( applyTranslation( l[i], lookup ) );
				}
			}
			return transList;
		} else if ( typeof value === 'object' ) {
			// Going to have to recurse for each value
			obj = value;
			transObj = {};
			for ( key in obj ) {
				if ( obj.hasOwnProperty( key ) ) {
					transObj[ key ] = applyTranslation( obj[key], lookup );
				}
			}
			return transObj;
		} else {
			// bool or numeric == A-OK
			return value;
		}
	}

	function toggleSelection( e ) {
		var $target = $( e.target ),
			wasSelected = $target.hasClass( 'rvc-selected' );
		$target
			.parent()
				.find( '.rvc-selected' )
					.removeClass( 'rvc-selected' )
					.end()
				.end();
		if ( !wasSelected ) {
			$target.addClass( 'rvc-selected' );
		}
		// The user must select one value for each field
		$( '#rvc-submit' ).prop(
			'disabled',
			$( '.mw-ui-button.rvc-selected' ).length !== fields.length ||
				curTaskIdx >= tasks.length
		);
	}

	function getWorkSet( campId, wsId ) {
		// FIXME: Remove these hardcoded values
		campId = campId || 1;
		wsId = wsId || 1;
		return $.ajax( {
			url: '//ores-test.wmflabs.org/coder/campaigns/' +
				mw.config.get( 'wgDBname' ) + '/' + campId + '/' + wsId + '/',
			data: {
				tasks: ''
			},
			dataType: 'jsonp',
			timeout: 3000
		} ).fail( function ( jqXHR, textStatus ) {
			alert( 'An errror occurred: ' + textStatus );
		} );
	}

	function showWorkSet( data ) {
		var i, j, field, $icon, className, tooltip, value,
			$bar = $( '.rvc-progress' ).empty();
		tasks = ( data && data.tasks ) || tasks;
		for ( i = 0; i < tasks.length; i++ ) {
			$icon = $( '
' );
			tooltip = mw.msg( 'rvc-revision-title', tasks[i].data.rev_id );
			for ( j = 0; j < fields.length; j++ ) {
				field = fields[j].id;
				// FIXME: how to get the labels (values) without doing an API request for each task in this workset?
				// FIXME: type of label values are inconsistent (boolean vs integers):
				// * true/false: https://ores-test.wmflabs.org/coder/campaigns/enwiki/111/222/333/
				// * 1/0: https://ores-test.wmflabs.org/coder/forms/damaging_and_goodfaith
				//
				// idx = tasks[i].fields[ field ];
				// value = fields[j].options[ idx ] && fields[j].options[ idx ].value;
				// tooltip += '\n' + fields[j].label + ' ' + value;
				className = 'rvc-' + field + '-' + value;
				$icon.append( $( '
' ).addClass( className ) );
			}
			$icon.attr(
				'title',
				tooltip
			);
			$bar.append( $icon );
		}
		$( '.rvc-progress > div' ).css( 'width', ( 100 / tasks.length ) + '%' );
		$( '.mw-ui-button.rvc-selected' ).removeClass( 'rvc-selected' );
		$( '#rvc-submit' ).prop( 'disabled', true );
		if ( curTaskIdx < tasks.length ) {
			$bar.find( '> div' ).eq( curTaskIdx ).addClass( 'rvc-selected' );
			showDiff( tasks[curTaskIdx].data.rev_id );
		}
	}

	function showDiff( revid ) {
		new mw.Api().get( {
			action: 'query',
			prop: 'revisions',
			rvdiffto: 'prev',
			revids: revid,
			indexpageids: true
		} ).done( function ( data ) {
			var page, pageids = data.query.pageids;
			if ( pageids && pageids[0] ) {
				page = data.query.pages[ pageids[0] ];
				if ( page.missing !== '' ) {
					// $( '#firstHeading' ).text( page.title );
					$( '#rvc-diff' ).empty().append(
						page.revisions[0].diff['*']
					);
				} else {
					$( '#rvc-diff' ).empty().text( mw.msg( 'rvc-page-missing' ) );
				}
			} else {
				$( '#rvc-diff' ).empty().text( mw.msg( 'rvc-badpageid' ) );
			}
		} );
	}

	function submit() {
		var campId = 1,
			wsId = 1,
			taskId = 1;
		$( '.mw-ui-button.rvc-selected' ).each( function () {
			var $this = $( this ),
				idxValue = $this.data( 'rvc-value' ),
				field = $this.parent().data( 'rvc-field' );
			if ( field !== undefined && idxValue !== undefined ) {
				if ( !tasks[ curTaskIdx ].fields ) {
					tasks[ curTaskIdx ].fields = {};
				}
				tasks[ curTaskIdx ].fields[ field ] = idxValue;
			}
		} );
		$( '#rvc-submit' ).injectSpinner( 'rvc-submit-spinner' );
		$.ajax( {
			url: '//ores-test.wmflabs.org/coder/campaigns/' +
				mw.config.get( 'wgDBname' ) + '/' + campId + '/' + wsId + '/' + taskId + '/',
			data: {
				label: JSON.stringify( {
					// TODO: use integers consistently for storing labels?
					goodfaith: true,
					damaging: false
				} )
			},
			dataType: 'jsonp',
			timeout: 3000
		} ).always( function () {
			$.removeSpinner( 'rvc-submit-spinner' );
		} ).fail( function ( jqXHR, textStatus ) {
			alert( 'An errror occurred: ' + textStatus );
		} );
		curTaskIdx++;
		showWorkSet();
		if ( curTaskIdx >= tasks.length ) {
			alert( mw.msg( 'rvc-dataset-completed' ) );
			$( '#rvc-submit' ).prop( 'disabled', true );
		}
	}

	function load( data ) {
		var $ui = $( '#rvc-ui' ).empty(),
			// FIXME: Migrate to OOjs UI (http://livingstyleguide.wmflabs.org/wiki/OOjs_UI)
			$submit = $( '<input id="rvc-submit" class="mw-ui-button mw-ui-constructive" type="submit">' )
				.prop( 'disabled', true )
				.click( submit ),
			field, i, j, id, val, $feature, $group, key, messages, prefixedMsgs;
		// Reads in messages and sets a prefix for mw.msg to do lookups
		messages = data.i18n[ mw.config.get( 'wgUserLanguage' ) ] || data.i18n.en;
		prefixedMsgs = {};
		for ( key in messages ) {
			if ( messages.hasOwnProperty( key ) ) {
				prefixedMsgs[ 'rvc-' + key ] = messages[ key ];
			}
		}
		mw.messages.set( prefixedMsgs );
		fields = applyTranslation( data.fields, lookup );

		$submit.val( mw.msg( 'rvc-submit' ) );
		$ui.append(
			$( '
' )
				.text( mw.msg( 'rvc-work-set' ) ),
			$( '
' )
				.addClass( 'rvc-progress' )
		);
		for ( i = 0; i < fields.length; i++ ) {
			field = fields[i];
			id = field.id;
			$group = $( '
' )
				.data( 'rvc-field', id )
				// .addClass( 'mw-ui-radio');
				.addClass( 'mw-ui-button-group' );
			for ( j = 0; j < field.options.length; j++ ) {
				val = field.options[j].value;
				$group.append(
					$( '
' )
						.addClass( 'mw-ui-button' )
						.attr( 'id', 'rvc-' + field.id + '-' + val )
						.attr( 'title', field.options[j].tooltip )
						.text( field.options[j].label )
						.data( 'rvc-value', j )
						.click( toggleSelection )
// 					$( '<input type="radio">' )
// 						.attr( 'name', 'rvc-' + field.id )
// 						.attr( 'id', 'rvc-' + field.id + '-' + val )
// 						.attr( 'title', field.options[j].tooltip ),
// 					$( '' )
// 						.text( field.options[j].label )
// 						.attr( 'for', 'rvc-' + field.id + '-' + val )
// 						.data( 'rvc-value', j )
// 						.click( toggleSelection )
				);
			}
			$feature = $( '
' )
				.attr( 'title', field.help )
				.append(
					$( '
' )
						.text( field.label ),
					$group
				);
			$ui.append( $feature, '

' );
		}
		$ui.append( $submit )
			.append(
				'
' +
				'<colgroup><col class="diff-marker">' +
				'<col class="diff-content">' +
				'<col class="diff-marker">' +
				'<col class="diff-content">' +
				'</colgroup>

'
			);
		curTaskIdx = 0;
		getWorkSet()
			.done( showWorkSet );
	}

	if ( $.inArray( mw.config.get( 'wgAction' ), [ 'view', 'purge' ] ) !== -1 ) {
		$( function () {
			if ( $( '#rvc-ui' ).length !== 0 ) {
				mw.loader.using( [
					'mediawiki.api',
					'jquery.spinner',
					// TODO: Load this only when necessary
					// (e.g. if the user will be required to click on some button before the first diff appears)
					'mediawiki.action.history.diff'
				] ).done( function () {
					$.ajax( {
						url: '//ores-test.wmflabs.org/coder/forms/damaging_and_goodfaith',
						dataType: 'jsonp',
						timeout: 3000
					} )
					.done( load )
					.fail( function ( jqXHR, textStatus ) {
						alert( 'An errror occurred: ' + textStatus );
					} );
				} );
			}
		} );
	}

}( mediaWiki, jQuery ) );
<|endoftext|>