<commit_before>/** @typedef {import('./index').Logger} Logger */

import path from 'path'

import { dim } from 'colorette'
import debug from 'debug'
import { Listr } from 'listr2'
import normalize from 'normalize-path'

import { chunkFiles } from './chunkFiles.js'
import { execGit } from './execGit.js'
import { generateTasks } from './generateTasks.js'
import { getConfigGroups } from './getConfigGroups.js'
import { getRenderer } from './getRenderer.js'
import { getStagedFiles } from './getStagedFiles.js'
import { GitWorkflow } from './gitWorkflow.js'
import { makeCmdTasks } from './makeCmdTasks.js'
import {
  DEPRECATED_GIT_ADD,
  FAILED_GET_STAGED_FILES,
  NOT_GIT_REPO,
  NO_STAGED_FILES,
  NO_TASKS,
  SKIPPED_GIT_ERROR,
  skippingBackup,
} from './messages.js'
import { resolveGitRepo } from './resolveGitRepo.js'
import {
  applyModificationsSkipped,
  cleanupEnabled,
  cleanupSkipped,
  getInitialState,
  hasPartiallyStagedFiles,
  restoreOriginalStateEnabled,
  restoreOriginalStateSkipped,
  restoreUnstagedChangesSkipped,
} from './state.js'
import { GitRepoError, GetStagedFilesError, GitError } from './symbols.js'

const debugLog = debug('lint-staged:runAll')

const createError = (ctx) => Object.assign(new Error('lint-staged failed'), { ctx })

/**
 * Executes all tasks and either resolves or rejects the promise
 *
 * @param {object} options
 * @param {boolean} [options.allowEmpty] - Allow empty commits when tasks revert all staged changes
 * @param {boolean | number} [options.concurrent] - The number of tasks to run concurrently, or false to run tasks serially
 * @param {Object} [options.configObject] - Explicit config object from the js API
 * @param {string} [options.configPath] - Explicit path to a config file
 * @param {string} [options.cwd] - Current working directory
 * @param {boolean} [options.debug] - Enable debug mode
 * @param {number} [options.maxArgLength] - Maximum argument string length
 * @param {boolean} [options.quiet] - Disable lint-staged’s own console output
 * @param {boolean} [options.relative] - Pass relative filepaths to tasks
 * @param {boolean} [options.shell] - Skip parsing of tasks for better shell support
 * @param {boolean} [options.stash] - Enable the backup stash, and revert in case of errors
 * @param {boolean} [options.verbose] - Show task output even when tasks succeed; by default only failed output is shown
 * @param {Logger} logger
 * @returns {Promise}
 */
export const runAll = async (
  {
    allowEmpty = false,
    concurrent = true,
    configObject,
    configPath,
    cwd = process.cwd(),
    debug = false,
    maxArgLength,
    quiet = false,
    relative = false,
    shell = false,
    stash = true,
    verbose = false,
  },
  logger = console
) => {
  debugLog('Running all linter scripts')

  const ctx = getInitialState({ quiet })

  const { gitDir, gitConfigDir } = await resolveGitRepo(cwd)
  if (!gitDir) {
    if (!quiet) ctx.output.push(NOT_GIT_REPO)
    ctx.errors.add(GitRepoError)
    throw createError(ctx)
  }

  // Test whether we have any commits or not.
  // Stashing must be disabled with no initial commit.
  const hasInitialCommit = await execGit(['log', '-1'], { cwd: gitDir })
    .then(() => true)
    .catch(() => false)

  // Lint-staged should create a backup stash only when there's an initial commit
  ctx.shouldBackup = hasInitialCommit && stash
  if (!ctx.shouldBackup) {
    logger.warn(skippingBackup(hasInitialCommit))
  }

  const files = await getStagedFiles({ cwd: gitDir })
  if (!files) {
    if (!quiet) ctx.output.push(FAILED_GET_STAGED_FILES)
    ctx.errors.add(GetStagedFilesError)
    throw createError(ctx, GetStagedFilesError)
  }
  debugLog('Loaded list of staged files in git:\n%O', files)

  // If there are no files avoid executing any lint-staged logic
  if (files.length === 0) {
    if (!quiet) ctx.output.push(NO_STAGED_FILES)
    return ctx
  }

  const configGroups = await getConfigGroups({ configObject, configPath, files }, logger)

  // lint-staged 10 will automatically add modifications to index
  // Warn user when their command includes `git add`
  let hasDeprecatedGitAdd = false

  const listrOptions = {
    ctx,
    exitOnError: false,
    nonTTYRenderer: 'verbose',
    registerSignalListeners: false,
    ...getRenderer({ debug, quiet }),
  }

  const listrTasks = []

  // Set of all staged files that matched a task glob. Values in a set are unique.
  const matchedFiles = new Set()

  for (const [configPath, { config, files }] of Object.entries(configGroups)) {
    const stagedFileChunks = chunkFiles({ baseDir: gitDir, files, maxArgLength, relative })

    const chunkCount = stagedFileChunks.length
    if (chunkCount > 1) {
      debugLog('Chunked staged files from `%s` into %d part', configPath, chunkCount)
    }

    for (const [index, files] of stagedFileChunks.entries()) {
      const chunkTasks = generateTasks({ config, cwd, files, relative })
      const chunkListrTasks = []

      for (const task of chunkTasks) {
        const subTasks = await makeCmdTasks({
          commands: task.commands,
          cwd,
          files: task.fileList,
          gitDir,
          renderer: listrOptions.renderer,
          shell,
          verbose,
        })

        // Add files from task to match set
        task.fileList.forEach((file) => {
          matchedFiles.add(file)
        })

        hasDeprecatedGitAdd =
          hasDeprecatedGitAdd || subTasks.some((subTask) => subTask.command === 'git add')

        const fileCount = task.fileList.length

        chunkListrTasks.push({
          title: `${task.pattern}${dim(` — ${fileCount} ${fileCount > 1 ? 'files' : 'file'}`)}`,
          task: async () =>
            new Listr(subTasks, {
              // In sub-tasks we don't want to run concurrently
              // and we want to abort on errors
              ...listrOptions,
              concurrent: false,
              exitOnError: true,
            }),
          skip: () => {
            // Skip task when no files matched
            if (fileCount === 0) {
              return `${task.pattern}${dim(' — no files')}`
            }
            return false
          },
        })
      }

      const relativeConfig = normalize(path.relative(cwd, configPath))

      listrTasks.push({
        title:
          `${relativeConfig}${dim(` — ${files.length} ${files.length > 1 ? 'files' : 'file'}`)}` +
          (chunkCount > 1 ? dim(` (chunk ${index + 1}/${chunkCount})...`) : ''),
        task: () => new Listr(chunkListrTasks, { ...listrOptions, concurrent, exitOnError: true }),
        skip: () => {
          // Skip if the first step (backup) failed
          if (ctx.errors.has(GitError)) return SKIPPED_GIT_ERROR
          // Skip chunk when no every task is skipped (due to no matches)
          if (chunkListrTasks.every((task) => task.skip())) {
            return `${relativeConfig}${dim(' — no tasks to run')}`
          }
          return false
        },
      })
    }
  }

  if (hasDeprecatedGitAdd) {
    logger.warn(DEPRECATED_GIT_ADD)
  }

  // If all of the configured tasks should be skipped
  // avoid executing any lint-staged logic
  if (listrTasks.every((task) => task.skip())) {
    if (!quiet) ctx.output.push(NO_TASKS)
    return ctx
  }

  // Chunk matched files for better Windows compatibility
  const matchedFileChunks = chunkFiles({
    // matched files are relative to `cwd`, not `gitDir`, when `relative` is used
    baseDir: cwd,
    files: Array.from(matchedFiles),
    maxArgLength,
    relative: false,
  })

  const git = new GitWorkflow({ allowEmpty, gitConfigDir, gitDir, matchedFileChunks })

  const runner = new Listr(
    [
      {
        title: 'Preparing lint-staged...',
        task: (ctx) => git.prepare(ctx),
      },
      {
        title: 'Hiding unstaged changes to partially staged files...',
        task: (ctx) => git.hideUnstagedChanges(ctx),
        enabled: hasPartiallyStagedFiles,
      },
      {
        title: `Running tasks for staged files...`,
        task: () => new Listr(listrTasks, { ...listrOptions, concurrent }),
        skip: () => listrTasks.every((task) => task.skip()),
      },
      {
        title: 'Applying modifications from tasks...',
        task: (ctx) => git.applyModifications(ctx),
        skip: applyModificationsSkipped,
      },
      {
        title: 'Restoring unstaged changes to partially staged files...',
        task: (ctx) => git.restoreUnstagedChanges(ctx),
        enabled: hasPartiallyStagedFiles,
        skip: restoreUnstagedChangesSkipped,
      },
      {
        title: 'Reverting to original state because of errors...',
        task: (ctx) => git.restoreOriginalState(ctx),
        enabled: restoreOriginalStateEnabled,
        skip: restoreOriginalStateSkipped,
      },
      {
        title: 'Cleaning up temporary files...',
        task: (ctx) => git.cleanup(ctx),
        enabled: cleanupEnabled,
        skip: cleanupSkipped,
      },
    ],
    listrOptions
  )

  await runner.run()

  if (ctx.errors.size > 0) {
    throw createError(ctx)
  }

  return ctx
}
<commit_msg>refactor: replace "for...of" with "await Promise.all()"<commit_after>/** @typedef {import('./index').Logger} Logger */

import path from 'path'

import { dim } from 'colorette'
import debug from 'debug'
import { Listr } from 'listr2'
import normalize from 'normalize-path'

import { chunkFiles } from './chunkFiles.js'
import { execGit } from './execGit.js'
import { generateTasks } from './generateTasks.js'
import { getConfigGroups } from './getConfigGroups.js'
import { getRenderer } from './getRenderer.js'
import { getStagedFiles } from './getStagedFiles.js'
import { GitWorkflow } from './gitWorkflow.js'
import { makeCmdTasks } from './makeCmdTasks.js'
import {
  DEPRECATED_GIT_ADD,
  FAILED_GET_STAGED_FILES,
  NOT_GIT_REPO,
  NO_STAGED_FILES,
  NO_TASKS,
  SKIPPED_GIT_ERROR,
  skippingBackup,
} from './messages.js'
import { resolveGitRepo } from './resolveGitRepo.js'
import {
  applyModificationsSkipped,
  cleanupEnabled,
  cleanupSkipped,
  getInitialState,
  hasPartiallyStagedFiles,
  restoreOriginalStateEnabled,
  restoreOriginalStateSkipped,
  restoreUnstagedChangesSkipped,
} from './state.js'
import { GitRepoError, GetStagedFilesError, GitError } from './symbols.js'

const debugLog = debug('lint-staged:runAll')

const createError = (ctx) => Object.assign(new Error('lint-staged failed'), { ctx })

/**
 * Executes all tasks and either resolves or rejects the promise
 *
 * @param {object} options
 * @param {boolean} [options.allowEmpty] - Allow empty commits when tasks revert all staged changes
 * @param {boolean | number} [options.concurrent] - The number of tasks to run concurrently, or false to run tasks serially
 * @param {Object} [options.configObject] - Explicit config object from the js API
 * @param {string} [options.configPath] - Explicit path to a config file
 * @param {string} [options.cwd] - Current working directory
 * @param {boolean} [options.debug] - Enable debug mode
 * @param {number} [options.maxArgLength] - Maximum argument string length
 * @param {boolean} [options.quiet] - Disable lint-staged’s own console output
 * @param {boolean} [options.relative] - Pass relative filepaths to tasks
 * @param {boolean} [options.shell] - Skip parsing of tasks for better shell support
 * @param {boolean} [options.stash] - Enable the backup stash, and revert in case of errors
 * @param {boolean} [options.verbose] - Show task output even when tasks succeed; by default only failed output is shown
 * @param {Logger} logger
 * @returns {Promise}
 */
export const runAll = async (
  {
    allowEmpty = false,
    concurrent = true,
    configObject,
    configPath,
    cwd = process.cwd(),
    debug = false,
    maxArgLength,
    quiet = false,
    relative = false,
    shell = false,
    stash = true,
    verbose = false,
  },
  logger = console
) => {
  debugLog('Running all linter scripts')

  const ctx = getInitialState({ quiet })

  const { gitDir, gitConfigDir } = await resolveGitRepo(cwd)
  if (!gitDir) {
    if (!quiet) ctx.output.push(NOT_GIT_REPO)
    ctx.errors.add(GitRepoError)
    throw createError(ctx)
  }

  // Test whether we have any commits or not.
  // Stashing must be disabled with no initial commit.
  const hasInitialCommit = await execGit(['log', '-1'], { cwd: gitDir })
    .then(() => true)
    .catch(() => false)

  // Lint-staged should create a backup stash only when there's an initial commit
  ctx.shouldBackup = hasInitialCommit && stash
  if (!ctx.shouldBackup) {
    logger.warn(skippingBackup(hasInitialCommit))
  }

  const files = await getStagedFiles({ cwd: gitDir })
  if (!files) {
    if (!quiet) ctx.output.push(FAILED_GET_STAGED_FILES)
    ctx.errors.add(GetStagedFilesError)
    throw createError(ctx, GetStagedFilesError)
  }
  debugLog('Loaded list of staged files in git:\n%O', files)

  // If there are no files avoid executing any lint-staged logic
  if (files.length === 0) {
    if (!quiet) ctx.output.push(NO_STAGED_FILES)
    return ctx
  }

  const configGroups = await getConfigGroups({ configObject, configPath, files }, logger)

  // lint-staged 10 will automatically add modifications to index
  // Warn user when their command includes `git add`
  let hasDeprecatedGitAdd = false

  const listrOptions = {
    ctx,
    exitOnError: false,
    nonTTYRenderer: 'verbose',
    registerSignalListeners: false,
    ...getRenderer({ debug, quiet }),
  }

  const listrTasks = []

  // Set of all staged files that matched a task glob. Values in a set are unique.
  const matchedFiles = new Set()

  for (const [configPath, { config, files }] of Object.entries(configGroups)) {
    const stagedFileChunks = chunkFiles({ baseDir: gitDir, files, maxArgLength, relative })

    const chunkCount = stagedFileChunks.length
    if (chunkCount > 1) {
      debugLog('Chunked staged files from `%s` into %d part', configPath, chunkCount)
    }

    for (const [index, files] of stagedFileChunks.entries()) {
      const relativeConfig = normalize(path.relative(cwd, configPath))

      const chunkListrTasks = await Promise.all(
        generateTasks({ config, cwd, files, relative }).map((task) =>
          makeCmdTasks({
            commands: task.commands,
            cwd,
            files: task.fileList,
            gitDir,
            renderer: listrOptions.renderer,
            shell,
            verbose,
          }).then((subTasks) => {
            // Add files from task to match set
            task.fileList.forEach((file) => {
              matchedFiles.add(file)
            })

            hasDeprecatedGitAdd =
              hasDeprecatedGitAdd || subTasks.some((subTask) => subTask.command === 'git add')

            const fileCount = task.fileList.length

            return {
              title: `${task.pattern}${dim(` — ${fileCount} ${fileCount > 1 ? 'files' : 'file'}`)}`,
              task: async () =>
                new Listr(subTasks, {
                  // In sub-tasks we don't want to run concurrently
                  // and we want to abort on errors
                  ...listrOptions,
                  concurrent: false,
                  exitOnError: true,
                }),
              skip: () => {
                // Skip task when no files matched
                if (fileCount === 0) {
                  return `${task.pattern}${dim(' — no files')}`
                }
                return false
              },
            }
          })
        )
      )

      listrTasks.push({
        title:
          `${relativeConfig}${dim(` — ${files.length} ${files.length > 1 ? 'files' : 'file'}`)}` +
          (chunkCount > 1 ? dim(` (chunk ${index + 1}/${chunkCount})...`) : ''),
        task: () => new Listr(chunkListrTasks, { ...listrOptions, concurrent, exitOnError: true }),
        skip: () => {
          // Skip if the first step (backup) failed
          if (ctx.errors.has(GitError)) return SKIPPED_GIT_ERROR
          // Skip chunk when no every task is skipped (due to no matches)
          if (chunkListrTasks.every((task) => task.skip())) {
            return `${relativeConfig}${dim(' — no tasks to run')}`
          }
          return false
        },
      })
    }
  }

  if (hasDeprecatedGitAdd) {
    logger.warn(DEPRECATED_GIT_ADD)
  }

  // If all of the configured tasks should be skipped
  // avoid executing any lint-staged logic
  if (listrTasks.every((task) => task.skip())) {
    if (!quiet) ctx.output.push(NO_TASKS)
    return ctx
  }

  // Chunk matched files for better Windows compatibility
  const matchedFileChunks = chunkFiles({
    // matched files are relative to `cwd`, not `gitDir`, when `relative` is used
    baseDir: cwd,
    files: Array.from(matchedFiles),
    maxArgLength,
    relative: false,
  })

  const git = new GitWorkflow({ allowEmpty, gitConfigDir, gitDir, matchedFileChunks })

  const runner = new Listr(
    [
      {
        title: 'Preparing lint-staged...',
        task: (ctx) => git.prepare(ctx),
      },
      {
        title: 'Hiding unstaged changes to partially staged files...',
        task: (ctx) => git.hideUnstagedChanges(ctx),
        enabled: hasPartiallyStagedFiles,
      },
      {
        title: `Running tasks for staged files...`,
        task: () => new Listr(listrTasks, { ...listrOptions, concurrent }),
        skip: () => listrTasks.every((task) => task.skip()),
      },
      {
        title: 'Applying modifications from tasks...',
        task: (ctx) => git.applyModifications(ctx),
        skip: applyModificationsSkipped,
      },
      {
        title: 'Restoring unstaged changes to partially staged files...',
        task: (ctx) => git.restoreUnstagedChanges(ctx),
        enabled: hasPartiallyStagedFiles,
        skip: restoreUnstagedChangesSkipped,
      },
      {
        title: 'Reverting to original state because of errors...',
        task: (ctx) => git.restoreOriginalState(ctx),
        enabled: restoreOriginalStateEnabled,
        skip: restoreOriginalStateSkipped,
      },
      {
        title: 'Cleaning up temporary files...',
        task: (ctx) => git.cleanup(ctx),
        enabled: cleanupEnabled,
        skip: cleanupSkipped,
      },
    ],
    listrOptions
  )

  await runner.run()

  if (ctx.errors.size > 0) {
    throw createError(ctx)
  }

  return ctx
}
<|endoftext|>


<commit_before>'use strict';

var EE = require('events').EventEmitter;
var _ = require('lodash');
var async = require('async');
var debug = require('debug')('runner');
var arrivals = require('./arrivals');
var request = require('request');
var Measured = require('measured');
var mustache = require('mustache');
var traverse = require('traverse');

module.exports = function runner(script, payload, options) {

  var opts = _.assign({
    periodicStats: 10
  },
  options);

  if (payload) {
    script.config.payload.data = payload;
  }

  var ee = new EE();
  ee.run = function() {

    run(script, ee, opts);
  };

  return ee;
};

var INITIAL_CONTEXT = {
  vars: {
  }
};

var Stats = {
  pendingRequests: new Measured.Counter(),
  pendingScenarios: new Measured.Counter(),

  completedRequests: new Measured.Counter(), // request_count - successful requests only
  generatedScenarios: new Measured.Counter(), // generated_users_total
  completedScenarios: new Measured.Counter(), // finished_users_total - succesful only
  //collection: Measured.createCollection(),
  rps: new Measured.Meter({
    rateUnit: 1 * 1000,
    tickInterval: 1 * 1000
  }),
  latency: new Measured.Histogram(), //
  errors: new Measured.Counter(),
  codes: { // code_NNN_total
  }
};

var PeriodicStats = {
  generatedScenarios: new Measured.Counter(), // generated_users_last10
  completedScenarios: new Measured.Counter(), // finished_users_last10
  completedRequests: new Measured.Counter(), // request_10sec_count
  errors: new Measured.Counter(),
  codes: { // code_NNN_last10
  }
};

function run(script, ee, options) {

  var phases = _.map(script.config.phases, function(phaseSpec, i) {

    var task = function(callback) {

      ee.emit('phaseStarted', {
        index: i,
        name: phaseSpec.name,
        duration: phaseSpec.duration
      });
      var ar = 1000 / phaseSpec.arrivalRate;
      debug('ar = %s', ar);
      var ppStartedAt = process.hrtime();
      var pp = arrivals.poisson.process(ar, function() {

        launchScenario(script);
      });
      pp.start();
      setTimeout(function() {

        ee.emit('phaseCompleted', {
          index: i,
          name: phaseSpec.name,
          duration: phaseSpec.duration
        });
        var ppStoppedAt = process.hrtime(ppStartedAt);
        var ppRanFor = (ppStoppedAt[0] * 1e9) + ppStoppedAt[1];
        debug('PoissonProcess ran for %s', ppRanFor / 1e6);
        pp.stop();
        return callback(null);
      }, phaseSpec.duration * 1000);
    };

    return task;
  });

  var periodicStatsTimer = setInterval(function() {
    ee.emit('stats', PeriodicStats);
    PeriodicStats.generatedScenarios.reset();
    PeriodicStats.completedScenarios.reset();
    PeriodicStats.completedRequests.reset();
    PeriodicStats.errors.reset();
    PeriodicStats.codes = {};
  }, options.periodicStats * 1000);

  async.series(phases, function(err) {

    if (err) {
      debug(err);
    }

    debug('All phases launched');

    var doneYet = setInterval(function() {
      if (Stats.pendingScenarios.toJSON() === 0) {
        if (Stats.pendingRequests.toJSON() !== 0) {
          debug('DONE. Pending requests: %s', Stats.pendingRequests.toJSON());
        }
        clearInterval(doneYet);
        clearInterval(periodicStatsTimer);
        Stats.rps.unref();
        return ee.emit('done', Stats);
      } else {
        debug('Pending requests: %s', Stats.pendingRequests.toJSON());
        debug('Pending scenarios: %s', Stats.pendingScenarios.toJSON());
      }
    }, 3 * 1000);
  });
}

function launchScenario(script) {

  var i = _.random(0, script.scenarios.length - 1);
  var spec = script.scenarios[i].flow;
  var scenario = createScenarioTask(spec, script.config);
  Stats.generatedScenarios.inc();
  PeriodicStats.generatedScenarios.inc();
  scenario(function(err, context) {

    if (err) {
      debug(err);
      debug('Scenario aborted due to error');
    } else {
      //debug('Scenario completed');
      //debug(context);
      Stats.completedScenarios.inc();
      PeriodicStats.completedScenarios.inc();
    }
  });

}

//
// This needs to be fixed up.
//
function maybePrependBase(uri, config) {

  if (_.startsWith(uri, '/')) {
    return config.target + uri;
  } else {
    return uri;
  }
}

function createRequestTask(requestSpec, config) {

  Stats.pendingRequests.inc();

  if (typeof requestSpec.think === 'number') {
    return function(context, callback) {

      debug('thinking for ' + requestSpec.think + ' seconds');
      setTimeout(function() {

        callback(null, context);
      }, requestSpec.think * 1000);
    };
  }

  var f = function(context, callback) {

    var method = _.keys(requestSpec)[0].toUpperCase();
    var params = requestSpec[method.toLowerCase()];
    var uri = maybePrependBase(template(params.url, context), config);
    var requestParams = {
      uri: uri,
      method: method,
      headers: {},
      timeout: 10 * 1000
    };

    if (params.json) {
      requestParams.json = template(params.json, context);
      //debug('json', requestParams.json);
    } else if (params.body) {
      requestParams.body = template(params.body, context);
      //debug('body', requestParams.body);
    }

    // Assign default headers then overwrite as needed
    if (config.defaults && config.defaults.headers) {
      requestParams.headers = _.extend(
        _.cloneDeep(config.defaults.headers || {}),
        params.headers || {});
    }

    request(requestParams, function requestCallback(err, res, body) {
      Stats.pendingRequests.dec();

      if (err) {
        Stats.errors.inc();
        PeriodicStats.errors.inc();
        debug(err);
        // this aborts the scenario
        return callback(err, context);
      } else {
        Stats.completedRequests.inc();
        PeriodicStats.completedRequests.inc();

        var code = res.statusCode;
        if (Stats.codes[code]) {
          Stats.codes[code].inc();
        } else {
          Stats.codes[code] = new Measured.Counter();
        }
        if (PeriodicStats.codes[code]) {
          PeriodicStats.codes[code].inc();
        } else {
          PeriodicStats.codes[code] = new Measured.Counter();
        }

        return callback(null, context);
      }
    })
    .on('request', function(req) {
      Stats.rps.mark();

      var startedAt = process.hrtime();

      req.on('response', function updateLatency(_resp) {
        var endedAt = process.hrtime(startedAt);
        var delta = (endedAt[0] * 1e9) + endedAt[1];
        Stats.latency.update(delta / 1e6);
      });
    }).on('end', function() {
    });
  };

  return f;
}

function createScenarioTask(scenarioSpec, config) {

  var zeroth = function(callback) {

    var initialContext = _.cloneDeep(INITIAL_CONTEXT);
    if (config.payload && config.payload.data) {
      var i = _.random(0, config.payload.data.length - 1);
      var row = config.payload.data[i];
      _.each(config.payload.fields, function(fieldName, j) {

        initialContext.vars[fieldName] = row[j];
      });
    }
    callback(null, initialContext);
  };

  var tasks = _.foldl(scenarioSpec, function(acc, rs) {

    acc.push(createRequestTask(rs, config));
    return acc;
  }, [zeroth]);

  var scenarioTask = function(callback) {

    async.waterfall(tasks, function(err, scenarioContext) {

      Stats.pendingScenarios.dec();
      if (err) {
        debug(err);
      }
      return callback(null, scenarioContext);
    });
  };

  Stats.pendingScenarios.inc();
  return scenarioTask;
}

function template(o, context) {

  var result;
  if (typeof o === 'object') {
    result = traverse(o).map(function(x) {

      if (typeof x === 'string') {
        this.update(template(x, context));
      } else {
        return x;
      }
    });
  } else {
    result = mustache.render(o, context.vars);
  }
  return result;
}
<commit_msg>Don't need to init Stats and PeriodicStats on require<commit_after>'use strict';

var EE = require('events').EventEmitter;
var _ = require('lodash');
var async = require('async');
var debug = require('debug')('runner');
var arrivals = require('./arrivals');
var request = require('request');
var Measured = require('measured');
var mustache = require('mustache');
var traverse = require('traverse');

module.exports = runner;

var Stats;
var PeriodicStats;
var INITIAL_CONTEXT = {
  vars: {
  }
};

function runner(script, payload, options) {

  var opts = _.assign({
    periodicStats: 10
  },
  options);

  if (payload) {
    script.config.payload.data = payload;
  }

  var ee = new EE();
  ee.run = function() {

    run(script, ee, opts);
  };

  return ee;
};

function run(script, ee, options) {

  Stats = {
    pendingRequests: new Measured.Counter(),
    pendingScenarios: new Measured.Counter(),

    generatedScenarios: new Measured.Counter(), // generated_users_total
    completedScenarios: new Measured.Counter(), // finished_users_total - succesful only
    completedRequests: new Measured.Counter(), // request_count - successful requests only
    rps: new Measured.Meter({
      rateUnit: 1 * 1000,
      tickInterval: 1 * 1000
    }),
    latency: new Measured.Histogram(),
    errors: new Measured.Counter(),
    codes: { // code_NNN_total
    }
  };

  PeriodicStats = {
    generatedScenarios: new Measured.Counter(), // generated_users_last10
    completedScenarios: new Measured.Counter(), // finished_users_last10
    completedRequests: new Measured.Counter(), // request_10sec_count
    rps: new Measured.Meter({
      rateUnit: 1 * 1000,
      tickInterval: 1 * 1000
    }),
    latency: new Measured.Histogram(),
    errors: new Measured.Counter(),
    codes: { // code_NNN_last10
    }
  };

  var phases = _.map(script.config.phases, function(phaseSpec, i) {

    var task = function(callback) {

      ee.emit('phaseStarted', {
        index: i,
        name: phaseSpec.name,
        duration: phaseSpec.duration
      });
      var ar = 1000 / phaseSpec.arrivalRate;
      debug('ar = %s', ar);
      var ppStartedAt = process.hrtime();
      var pp = arrivals.poisson.process(ar, function() {

        launchScenario(script);
      });
      pp.start();
      setTimeout(function() {

        ee.emit('phaseCompleted', {
          index: i,
          name: phaseSpec.name,
          duration: phaseSpec.duration
        });
        var ppStoppedAt = process.hrtime(ppStartedAt);
        var ppRanFor = (ppStoppedAt[0] * 1e9) + ppStoppedAt[1];
        debug('PoissonProcess ran for %s', ppRanFor / 1e6);
        pp.stop();
        return callback(null);
      }, phaseSpec.duration * 1000);
    };

    return task;
  });

  var periodicStatsTimer = setInterval(function() {
    ee.emit('stats', PeriodicStats);
    PeriodicStats.generatedScenarios.reset();
    PeriodicStats.completedScenarios.reset();
    PeriodicStats.completedRequests.reset();
    PeriodicStats.rps = new Measured.Meter({
      rateUnit: 1 * 1000,
      tickInterval: 1 * 1000
    });
    PeriodicStats.latency.reset();
    PeriodicStats.errors.reset();
    PeriodicStats.codes = {};
  }, options.periodicStats * 1000);

  async.series(phases, function(err) {

    if (err) {
      debug(err);
    }

    debug('All phases launched');

    var doneYet = setInterval(function() {
      if (Stats.pendingScenarios.toJSON() === 0) {
        if (Stats.pendingRequests.toJSON() !== 0) {
          debug('DONE. Pending requests: %s', Stats.pendingRequests.toJSON());
        }
        clearInterval(doneYet);
        clearInterval(periodicStatsTimer);
        Stats.rps.unref();
        return ee.emit('done', Stats);
      } else {
        debug('Pending requests: %s', Stats.pendingRequests.toJSON());
        debug('Pending scenarios: %s', Stats.pendingScenarios.toJSON());
      }
    }, 3 * 1000);
  });
}

function launchScenario(script) {

  var i = _.random(0, script.scenarios.length - 1);
  var spec = script.scenarios[i].flow;
  var scenario = createScenarioTask(spec, script.config);
  Stats.generatedScenarios.inc();
  PeriodicStats.generatedScenarios.inc();
  scenario(function(err, context) {

    if (err) {
      debug(err);
      debug('Scenario aborted due to error');
    } else {
      //debug('Scenario completed');
      //debug(context);
      Stats.completedScenarios.inc();
      PeriodicStats.completedScenarios.inc();
    }
  });

}

//
// This needs to be fixed up.
//
function maybePrependBase(uri, config) {

  if (_.startsWith(uri, '/')) {
    return config.target + uri;
  } else {
    return uri;
  }
}

function createRequestTask(requestSpec, config) {

  Stats.pendingRequests.inc();

  if (typeof requestSpec.think === 'number') {
    return function(context, callback) {

      debug('thinking for ' + requestSpec.think + ' seconds');
      setTimeout(function() {

        callback(null, context);
      }, requestSpec.think * 1000);
    };
  }

  var f = function(context, callback) {

    var method = _.keys(requestSpec)[0].toUpperCase();
    var params = requestSpec[method.toLowerCase()];
    var uri = maybePrependBase(template(params.url, context), config);
    var requestParams = {
      uri: uri,
      method: method,
      headers: {},
      timeout: 10 * 1000
    };

    if (params.json) {
      requestParams.json = template(params.json, context);
      //debug('json', requestParams.json);
    } else if (params.body) {
      requestParams.body = template(params.body, context);
      //debug('body', requestParams.body);
    }

    // Assign default headers then overwrite as needed
    if (config.defaults && config.defaults.headers) {
      requestParams.headers = _.extend(
        _.cloneDeep(config.defaults.headers || {}),
        params.headers || {});
    }

    request(requestParams, function requestCallback(err, res, body) {
      Stats.pendingRequests.dec();

      if (err) {
        Stats.errors.inc();
        PeriodicStats.errors.inc();
        debug(err);
        // this aborts the scenario
        return callback(err, context);
      } else {
        Stats.completedRequests.inc();
        PeriodicStats.completedRequests.inc();

        var code = res.statusCode;
        if (Stats.codes[code]) {
          Stats.codes[code].inc();
        } else {
          Stats.codes[code] = new Measured.Counter();
        }
        if (PeriodicStats.codes[code]) {
          PeriodicStats.codes[code].inc();
        } else {
          PeriodicStats.codes[code] = new Measured.Counter();
        }

        return callback(null, context);
      }
    })
    .on('request', function(req) {
      Stats.rps.mark();
      PeriodicStats.rps.mark();

      var startedAt = process.hrtime();

      req.on('response', function updateLatency(_resp) {
        var endedAt = process.hrtime(startedAt);
        var delta = (endedAt[0] * 1e9) + endedAt[1];
        Stats.latency.update(delta / 1e6);
        PeriodicStats.latency.update(delta / 1e6);
      });
    }).on('end', function() {
    });
  };

  return f;
}

function createScenarioTask(scenarioSpec, config) {

  var zeroth = function(callback) {

    var initialContext = _.cloneDeep(INITIAL_CONTEXT);
    if (config.payload && config.payload.data) {
      var i = _.random(0, config.payload.data.length - 1);
      var row = config.payload.data[i];
      _.each(config.payload.fields, function(fieldName, j) {

        initialContext.vars[fieldName] = row[j];
      });
    }
    callback(null, initialContext);
  };

  var tasks = _.foldl(scenarioSpec, function(acc, rs) {

    acc.push(createRequestTask(rs, config));
    return acc;
  }, [zeroth]);

  var scenarioTask = function(callback) {

    async.waterfall(tasks, function(err, scenarioContext) {

      Stats.pendingScenarios.dec();
      if (err) {
        debug(err);
      }
      return callback(null, scenarioContext);
    });
  };

  Stats.pendingScenarios.inc();
  return scenarioTask;
}

function template(o, context) {

  var result;
  if (typeof o === 'object') {
    result = traverse(o).map(function(x) {

      if (typeof x === 'string') {
        this.update(template(x, context));
      } else {
        return x;
      }
    });
  } else {
    result = mustache.render(o, context.vars);
  }
  return result;
}
<|endoftext|>


<commit_before>// const fs = require('fs');
// const binpath = './node_modules/nightwatch/bin/';
const seleniumServer = require('selenium-server');
const chromedriver = require('chromedriver');
const TRAVIS_JOB_NUMBER = process.env.TRAVIS_JOB_NUMBER;
const SELENIUM_PORT = process.env.NW_ENV === 'travis' ? 4445 : 4444;

module.exports = {
  src_folders: ['test/client'],
  output_folder: 'reports',
  custom_commands_path: '',
  custom_assertions_path: '',
  page_objects_path: '',
  globals_path: '',

  selenium: {
    start_process: true,
    server_path: seleniumServer.path,
    log_path: '',
    host: '127.0.0.1',
    port: SELENIUM_PORT,
    cli_args: {
      'webdriver.chrome.driver': chromedriver.path
    }
  },

  test_settings: {
    travis: {
      launch_url: 'ondemand.saucelabs.com:80',
      selenium_port: 80,
      selenium_host: 'ondemand.saucelabs.com',
      silent: true,
      username: process.env.SAUCE_USERNAME,
      access_key: process.env.SAUCE_ACCESS_KEY,
      screenshots: {
        enabled: false,
        path: ''
      },
      globals: {
        waitForConditionTimeout: 10000
      },
      desiredCapabilities: {
        browserName: 'chrome',
        chromeOptions: {
          w3c: false,
          args: ['--disable-dev-shm-usage']
        },
        javascriptEnabled: true,
        acceptSslCerts: true,
        build: `build-${TRAVIS_JOB_NUMBER}`,
        'tunnel-identifier': TRAVIS_JOB_NUMBER
      }
    },

    default: {
      launch_url: 'http://localhost',
      selenium_port: 4444,
      selenium_host: 'localhost',
      silent: true,
      screenshots: {
        enabled: false,
        path: ''
      },
      globals: {
        waitForConditionTimeout: 10000
      },
      desiredCapabilities: {
        browserName: 'chrome',
        chromeOptions: {
          w3c: false,
          args: ['--disable-dev-shm-usage']
        },
        javascriptEnabled: true,
        acceptSslCerts: true
      }
    },

    chrome: {
      desiredCapabilities: {
        browserName: 'chrome',
        chromeOptions: {
          w3c: false,
          args: ['--disable-dev-shm-usage']
        },
        javascriptEnabled: true,
        acceptSslCerts: true
      }
    }
  }
};

// fs.stat(binpath + 'selenium.jar', function (err, stat) {
//   if (err || !stat || stat.size < 1) {
//     require('selenium-download').ensure(binpath, function (error) {
//       if (error) throw new Error(error);
//       console.log('✔ Selenium & Chromedriver downloaded to:', binpath);
//     });
//   }
// });

<commit_msg>update to nightwatch selenium download<commit_after>const fs = require('fs');
const binpath = './node_modules/nightwatch/bin/';
const seleniumServer = require('selenium-server');
const chromedriver = require('chromedriver');
const TRAVIS_JOB_NUMBER = process.env.TRAVIS_JOB_NUMBER;
const SELENIUM_PORT = process.env.NW_ENV === 'travis' ? 4445 : 4444;

module.exports = {
  src_folders: ['test/client'],
  output_folder: 'reports',
  custom_commands_path: '',
  custom_assertions_path: '',
  page_objects_path: '',
  globals_path: '',

  selenium: {
    start_process: true,
    server_path: seleniumServer.path,
    log_path: '',
    host: '127.0.0.1',
    port: SELENIUM_PORT,
    cli_args: {
      'webdriver.chrome.driver': chromedriver.path
    }
  },

  test_settings: {
    travis: {
      launch_url: 'ondemand.saucelabs.com:80',
      selenium_port: 80,
      selenium_host: 'ondemand.saucelabs.com',
      silent: true,
      username: process.env.SAUCE_USERNAME,
      access_key: process.env.SAUCE_ACCESS_KEY,
      screenshots: {
        enabled: false,
        path: ''
      },
      globals: {
        waitForConditionTimeout: 10000
      },
      desiredCapabilities: {
        browserName: 'chrome',
        chromeOptions: {
          w3c: false,
          args: ['--disable-dev-shm-usage']
        },
        javascriptEnabled: true,
        acceptSslCerts: true,
        build: `build-${TRAVIS_JOB_NUMBER}`,
        'tunnel-identifier': TRAVIS_JOB_NUMBER
      }
    },

    default: {
      launch_url: 'http://localhost',
      selenium_port: 4444,
      selenium_host: 'localhost',
      silent: true,
      screenshots: {
        enabled: false,
        path: ''
      },
      globals: {
        waitForConditionTimeout: 10000
      },
      desiredCapabilities: {
        browserName: 'chrome',
        chromeOptions: {
          w3c: false,
          args: ['--disable-dev-shm-usage']
        },
        javascriptEnabled: true,
        acceptSslCerts: true
      }
    },

    chrome: {
      desiredCapabilities: {
        browserName: 'chrome',
        chromeOptions: {
          w3c: false,
          args: ['--disable-dev-shm-usage']
        },
        javascriptEnabled: true,
        acceptSslCerts: true
      }
    }
  }
};

fs.stat(binpath + 'selenium.jar', function (err, stat) {
  // if (err || !stat || stat.size < 1) {
  //   require('selenium-download').ensure(binpath, function (error) {
  //     if (error) throw new Error(error);
  //     console.log('✔ Selenium & Chromedriver downloaded to:', binpath);
  //   });
  // }
});

<|endoftext|>


<commit_before>/* eslint-disable import/no-extraneous-dependencies */
const seleniumSever = require('selenium-server');
const geckoDriver = require('geckodriver');
const chromeDriver = require('chromedriver');
/* eslint-disable import/no-extraneous-dependencies */

const testSettings = {
  chrome: {
    desiredCapabilities: {
      browserName: 'chrome'
    }
  },

  'chrome-headless': {
    desiredCapabilities: {
      browserName: 'chrome',
      chromeOptions: {
        args: ['headless']
      }
    }
  },

  firefox: {
    desiredCapabilities: {
      browserName: 'firefox'
    }
  }
};

module.exports = {
  src_folders: ['e2e/tests'],
  output_folder: 'e2e/reports',
  globals_path: 'e2e/global.js',
  page_objects_path: 'e2e/pages/',
  custom_assertions_path: 'e2e/custom_assertions/',
  custom_commands_path: 'e2e/custom_commands/',

  selenium: {
    start_process: true,
    server_path: seleniumSever.path,
    cli_args: {
      'webdriver.gecko.driver': geckoDriver.path,
      'webdriver.chrome.driver': chromeDriver.path
    }
  },

  test_settings: {
    default: {
      silent: true,
      launch_url: 'http://localhost:8888',
      desiredCapabilities: testSettings.chrome.desiredCapabilities
    },

    chrome: testSettings.chrome,
    'chrome-headless': testSettings['chrome-headless'],
    firefox: testSettings.firefox
  }
};
<commit_msg>add window-size args in nightwatch.conf.js<commit_after>/* eslint-disable import/no-extraneous-dependencies */
const seleniumSever = require('selenium-server');
const geckoDriver = require('geckodriver');
const chromeDriver = require('chromedriver');
/* eslint-disable import/no-extraneous-dependencies */

const testSettings = {
  chrome: {
    desiredCapabilities: {
      browserName: 'chrome',
      chromeOptions: {
        args: ['window-size=1280,800']
      }
    }
  },

  'chrome-headless': {
    desiredCapabilities: {
      browserName: 'chrome',
      chromeOptions: {
        args: ['headless', 'window-size=1280,800']
      }
    }
  },

  firefox: {
    desiredCapabilities: {
      browserName: 'firefox'
    }
  }
};

module.exports = {
  src_folders: ['e2e/tests'],
  output_folder: 'e2e/reports',
  globals_path: 'e2e/global.js',
  page_objects_path: 'e2e/pages/',
  custom_assertions_path: 'e2e/custom_assertions/',
  custom_commands_path: 'e2e/custom_commands/',

  selenium: {
    start_process: true,
    server_path: seleniumSever.path,
    cli_args: {
      'webdriver.gecko.driver': geckoDriver.path,
      'webdriver.chrome.driver': chromeDriver.path
    }
  },

  test_settings: {
    default: {
      silent: true,
      launch_url: 'http://localhost:8888',
      desiredCapabilities: testSettings.chrome.desiredCapabilities
    },

    chrome: testSettings.chrome,
    'chrome-headless': testSettings['chrome-headless'],
    firefox: testSettings.firefox
  }
};
<|endoftext|>


<commit_before>//A small but powerful library to solve sudokus

var SelectedIndex=0;
var board=[],alternatives=[],checkGrid=[0,1,2,9,10,11,18,19,20];
var changedStuff=true,time;

//Library-specific variables
var allSolved=[],validSolution=[];
var solveNo,solveCount;

//for backtrack solving
var savedBoards=[],insertAt=[],possibleValues=[],checked=[];
for (var i=0;i<80;i++){savedBoards.push(0); insertAt.push(0); possibleValues.push(0); checked.push(0);}
var level;

var sudoku={
	solve: function(array,no){
	 	solveNo=no;
		if (no<1||no==null||isNaN(no)){solveNo=1;}
		var success=coreSolve(array);
		return {
			solved: success,
			solution: validSolution,
			allSolutions: allSolved,
			solutionNo: solveCount,
			time: (new Date().getTime()-time)
		}
	}
};

function setAndReset(){
  solveCount=0;
  allSolved=[];
	validSolution=[];

  savedBoards=[];
  insertAt=[];
  possibleValues=[];
  checked=[];
  for (var i=0;i<80;i++){savedBoards.push(0); insertAt.push(0); possibleValues.push(0); checked.push(0);}
}

//All solving algorithms
function coreSolve(input){
  setAndReset();
  board=[];
  for (var i=0;i<input.length;i++){
    board.push(input[i]);
  }

  //Check if input is valid
  if (!isValid(false)){
    return false;
  }

  time=new Date().getTime();
  if (logicSolve() && !isFull()){
    level=0;
    var tmpBoard=[];
    for (var i=0;i<81;i++){tmpBoard.push(board[i]);}
    savedBoards[0]=tmpBoard;
    var firstBox=getBox();
    insertAt[0]=firstBox;
    checked[0]=0;
    possibleValues[0]=alternatives[firstBox];
    backtrackSolve();
  }

  if (!isFull()||!isValid(true)){
    return false;
  }
  return true;
}

function getBox(){
  for (var i=2;i<10;i++){
    for (var n=0;n<81;n++){
      if (alternatives[n].length==i){
        return n;
      }
    }
  }
}

function isFull(){
  for (var i=0;i<81;i++){
    if (board[i]==0){return false;}
  }
  return true;
}

//Solve as far as possible using only logic
function logicSolve(){
  changedStuff=true;
  while (changedStuff){
    changedStuff=false;
    getAlternatives();
    exclusionSolve();
    alienationSolve();
  }
  for (var i=0;i<81;i++){
    if (alternatives[i].length<=1&&board[i]==0){return false;}
  }
  return true;
}

function exclusionSolve(){
  for (var i=0;i<81;i++){
    if (alternatives[i].length==1&&canPut(alternatives[i][0],i)){
      board[i]=alternatives[i][0];
      changedStuff=true;
    }
  }
}

function alienationSolve(){
  //check rows
  var outArr=[0,1,2,3,4,5,6,7,8];
  for (var i=0;i<81;i+=9){
    alienationHelper(i,outArr);
  }

  //check columns
  outArr=[0,9,18,27,36,45,54,63,72];
  for (var i=0;i<9;i++){
    alienationHelper(i,outArr);
  }

  //check boxes
  outArr=[0,1,2,9,10,11,18,19,20];
  for (var h=0;h<81;h+=27){
    for (var w=0;w<9;w+=3){
      alienationHelper(h+w,outArr);
    }
  }
}

function alienationHelper(startAt,inArr){
  var oneToNine=[0,0,0,0,0,0,0,0,0];
  var foundAt=[0,0,0,0,0,0,0,0,0];
  var active,actIndex;
  for (var m=0;m<9;m++){
    actIndex=startAt+inArr[m];
    active=alternatives[actIndex];
    for (var i=0;i<active.length;i++){
      if (board[actIndex]==0&&board[actIndex]!=active[i]){
        oneToNine[active[i]-1]++;
        foundAt[active[i]-1]=actIndex;
      }else{
        oneToNine[board[actIndex]-1]=2;
      }
    }
  }
  for (var c=0;c<9;c++){
    if (oneToNine[c]==1){
      board[foundAt[c]]=c+1;
      changedStuff=true;
    }
  }
}

function backtrackSolve(){
  while(true){
    var tmpArr=[];
    try{
      for (var i=0;i<81;i++){tmpArr.push(savedBoards[level][i]);}
    }catch(e){
      return false;
    }
    board=tmpArr;
    board[insertAt[level]]=possibleValues[level][checked[level]];
    level++;
    if (logicSolve()){
      var isF=isFull(),isV=isValid(true);
      if (isF && isV){
        solveCount++;
        allSolved.push(board);
				validSolution=new Array(board);
        if (solveCount==solveNo){break;}
      }
      else if (isF && !isV){
        goBack();
      }else{
        tmpArr=[];
        for (var i=0;i<81;i++){tmpArr.push(board[i]);}
        savedBoards[level]=tmpArr;
        var firstBox=getBox();
        insertAt[level]=firstBox;
        possibleValues[level]=alternatives[firstBox];
      }
    }else{
      goBack();
    }
  }
}

function goBack(){
  while(true){
    checked[level]=0;
    level--;
    checked[level]++;
    if (level<0){break;}
    if (checked[level]<possibleValues[level].length){break;}
  }
}

function getAlternatives(){
  alternatives=[];
  var alts=[];

  var counter=0;
  var match;
  for (var h=0;h<9;h++){
    for (var w=0;w<9;w++){
      alts=[];
      if (board[counter]==0){
        for (var val=1;val<10;val++){
          match=false;
          //check rows
          var startAt=h*9;
          for (var c=startAt;c<startAt+9;c++){
            if (board[c]==val){match=true; break;}
          }

          //check columns
          if (!match){
            startAt=w;
            for (var c=startAt;c<startAt+81;c+=9){
              if (board[c]==val){match=true; break;}
            }
          }

          //check boxes
          if (!match){
            startAt=27*Math.floor(counter/27)+3*Math.floor(w/3);
            //console.log(startAt);
            for (var c=0;c<9;c++){
              if (board[startAt+checkGrid[c]]==val){match=true; break;}
            }
          }

          if (!match){
            alts.push(val);
          }
        }
      }
      alternatives.push(alts);
      counter++;
    }
  }
}

function isValid(aggr){
  for (var i=0;i<81;i++){
    if (aggr){
      if (!canPut(board[i],i)||board[i]==0){return false;}
    }else{
      if (!canPut(board[i],i)&&board[i]!=0){return false;}
    }
  }
  return true;
}

function canPut(input,location){
  var outArr=[0,1,2,3,4,5,6,7,8];
  var i=Math.floor(location/9)*9;
  for (var n=0;n<9;n++){
    if (board[i+outArr[n]]==input&&i+outArr[n]!=location){return false;}  //alert(location);
  }

  //check columns
  outArr=[0,9,18,27,36,45,54,63,72];
  var i=location%9;
  for (var n=0;n<9;n++){
    if (board[i+outArr[n]]==input&&i+outArr[n]!=location){return false;}
  }

  //check boxes
  outArr=[0,1,2,9,10,11,18,19,20];
  var h=Math.floor(location/27)*27,w=Math.floor((location%9)/3)*3;
  for (var n=0;n<9;n++){
    if (board[h+w+outArr[n]]==input&&h+w+outArr[n]!=location){return false;}
  }
  return true;
}
<commit_msg>Update sudokuSolver.js<commit_after>//A small but powerful library to solve sudokus

var SelectedIndex=0;
var board=[],alternatives=[],checkGrid=[0,1,2,9,10,11,18,19,20];
var changedStuff=true,time;

//Library-specific variables
var allSolved=[],validSolution=[];
var solveNo,solveCount;

//for backtrack solving
var savedBoards=[],insertAt=[],possibleValues=[],checked=[];
for (var i=0;i<80;i++){savedBoards.push(0); insertAt.push(0); possibleValues.push(0); checked.push(0);}
var level;

var sudoku={
	solve: function(array,no){
	 	solveNo=no;
		if (no<1||no==null||isNaN(no)){solveNo=1;}
		coreSolve(array);
		return {
			solved: (validSolution!=[]),
			solution: validSolution,
			allSolutions: allSolved,
			solutionNo: solveCount,
			time: (new Date().getTime()-time)
		}
	}
};

function setAndReset(){
  solveCount=0;
  allSolved=[];
	validSolution=[];

  savedBoards=[];
  insertAt=[];
  possibleValues=[];
  checked=[];
  for (var i=0;i<80;i++){savedBoards.push(0); insertAt.push(0); possibleValues.push(0); checked.push(0);}
}

//All solving algorithms
function coreSolve(input){
  setAndReset();
  board=[];
  for (var i=0;i<input.length;i++){
    board.push(input[i]);
  }

  //Check if input is valid
  if (!isValid(false)){
    return false;
  }

  time=new Date().getTime();
  if (logicSolve() && !isFull()){
    level=0;
    var tmpBoard=[];
    for (var i=0;i<81;i++){tmpBoard.push(board[i]);}
    savedBoards[0]=tmpBoard;
    var firstBox=getBox();
    insertAt[0]=firstBox;
    checked[0]=0;
    possibleValues[0]=alternatives[firstBox];
    backtrackSolve();
  }

  if (!isFull()||!isValid(true)){
    return false;
  }
  return true;
}

function getBox(){
  for (var i=2;i<10;i++){
    for (var n=0;n<81;n++){
      if (alternatives[n].length==i){
        return n;
      }
    }
  }
}

function isFull(){
  for (var i=0;i<81;i++){
    if (board[i]==0){return false;}
  }
  return true;
}

//Solve as far as possible using only logic
function logicSolve(){
  changedStuff=true;
  while (changedStuff){
    changedStuff=false;
    getAlternatives();
    exclusionSolve();
    alienationSolve();
  }
  for (var i=0;i<81;i++){
    if (alternatives[i].length<=1&&board[i]==0){return false;}
  }
  return true;
}

function exclusionSolve(){
  for (var i=0;i<81;i++){
    if (alternatives[i].length==1&&canPut(alternatives[i][0],i)){
      board[i]=alternatives[i][0];
      changedStuff=true;
    }
  }
}

function alienationSolve(){
  //check rows
  var outArr=[0,1,2,3,4,5,6,7,8];
  for (var i=0;i<81;i+=9){
    alienationHelper(i,outArr);
  }

  //check columns
  outArr=[0,9,18,27,36,45,54,63,72];
  for (var i=0;i<9;i++){
    alienationHelper(i,outArr);
  }

  //check boxes
  outArr=[0,1,2,9,10,11,18,19,20];
  for (var h=0;h<81;h+=27){
    for (var w=0;w<9;w+=3){
      alienationHelper(h+w,outArr);
    }
  }
}

function alienationHelper(startAt,inArr){
  var oneToNine=[0,0,0,0,0,0,0,0,0];
  var foundAt=[0,0,0,0,0,0,0,0,0];
  var active,actIndex;
  for (var m=0;m<9;m++){
    actIndex=startAt+inArr[m];
    active=alternatives[actIndex];
    for (var i=0;i<active.length;i++){
      if (board[actIndex]==0&&board[actIndex]!=active[i]){
        oneToNine[active[i]-1]++;
        foundAt[active[i]-1]=actIndex;
      }else{
        oneToNine[board[actIndex]-1]=2;
      }
    }
  }
  for (var c=0;c<9;c++){
    if (oneToNine[c]==1){
      board[foundAt[c]]=c+1;
      changedStuff=true;
    }
  }
}

function backtrackSolve(){
  while(true){
    var tmpArr=[];
    try{
      for (var i=0;i<81;i++){tmpArr.push(savedBoards[level][i]);}
    }catch(e){
      return false;
    }
    board=tmpArr;
    board[insertAt[level]]=possibleValues[level][checked[level]];
    level++;
    if (logicSolve()){
      var isF=isFull(),isV=isValid(true);
      if (isF && isV){
        solveCount++;
        allSolved.push(board);
				validSolution=new Array(board);
        if (solveCount==solveNo){break;}
      }
      else if (isF && !isV){
        goBack();
      }else{
        tmpArr=[];
        for (var i=0;i<81;i++){tmpArr.push(board[i]);}
        savedBoards[level]=tmpArr;
        var firstBox=getBox();
        insertAt[level]=firstBox;
        possibleValues[level]=alternatives[firstBox];
      }
    }else{
      goBack();
    }
  }
}

function goBack(){
  while(true){
    checked[level]=0;
    level--;
    checked[level]++;
    if (level<0){break;}
    if (checked[level]<possibleValues[level].length){break;}
  }
}

function getAlternatives(){
  alternatives=[];
  var alts=[];

  var counter=0;
  var match;
  for (var h=0;h<9;h++){
    for (var w=0;w<9;w++){
      alts=[];
      if (board[counter]==0){
        for (var val=1;val<10;val++){
          match=false;
          //check rows
          var startAt=h*9;
          for (var c=startAt;c<startAt+9;c++){
            if (board[c]==val){match=true; break;}
          }

          //check columns
          if (!match){
            startAt=w;
            for (var c=startAt;c<startAt+81;c+=9){
              if (board[c]==val){match=true; break;}
            }
          }

          //check boxes
          if (!match){
            startAt=27*Math.floor(counter/27)+3*Math.floor(w/3);
            //console.log(startAt);
            for (var c=0;c<9;c++){
              if (board[startAt+checkGrid[c]]==val){match=true; break;}
            }
          }

          if (!match){
            alts.push(val);
          }
        }
      }
      alternatives.push(alts);
      counter++;
    }
  }
}

function isValid(aggr){
  for (var i=0;i<81;i++){
    if (aggr){
      if (!canPut(board[i],i)||board[i]==0){return false;}
    }else{
      if (!canPut(board[i],i)&&board[i]!=0){return false;}
    }
  }
  return true;
}

function canPut(input,location){
  var outArr=[0,1,2,3,4,5,6,7,8];
  var i=Math.floor(location/9)*9;
  for (var n=0;n<9;n++){
    if (board[i+outArr[n]]==input&&i+outArr[n]!=location){return false;}  //alert(location);
  }

  //check columns
  outArr=[0,9,18,27,36,45,54,63,72];
  var i=location%9;
  for (var n=0;n<9;n++){
    if (board[i+outArr[n]]==input&&i+outArr[n]!=location){return false;}
  }

  //check boxes
  outArr=[0,1,2,9,10,11,18,19,20];
  var h=Math.floor(location/27)*27,w=Math.floor((location%9)/3)*3;
  for (var n=0;n<9;n++){
    if (board[h+w+outArr[n]]==input&&h+w+outArr[n]!=location){return false;}
  }
  return true;
}
<|endoftext|>


<commit_before>/** @jsx React.DOM */

var _ = require('underscore'),
	React = require('react');

var noop = function() {};

var logEvent = function(msg) {
	console.log(msg);
};

// comment out this line to debug the control state
logEvent = noop;

var classes = function() {
	var rtn = [];
	for (var i = 0; i < arguments.length; i++) {
		if ('string' === typeof arguments[i]) {
			rtn.push(arguments[i]);
		} else if (_.isObject(arguments[i])) {
			_.each(arguments[i], function(val, key) {
				if (val) {
					rtn.push(key);
				}
			});
		}
	}
	return rtn.join(' ') || undefined;
}

var Option = React.createClass({

	select: function() {
		logEvent('select: option');
		this.props.onSelect({
			value: this.props.value,
			label: this.props.label
		});
	},

	render: function() {

		var optionClass = classes({
			'Select-option': true,
			'focused': this.props.focused
		});

		return
{this.props.label}
;

	}

});

var Select = React.createClass({

	getInitialState: function() {
		return {
			value: this.props.value,
			inputValue: '',
			placeholder: '',
			focusedOption: null,
			isFocused: false,
			isOpen: false
		};
	},

	componentWillMount: function() {
		this.setState(this.getStateFromValue(this.state.value));
	},

	getStateFromValue: function(value) {
		var selectedOption = ('string' === typeof value) ? _.findWhere(this.props.options, { value: value }) : value;
		return selectedOption ? {
			value: value,
			inputValue: selectedOption.label,
			placeholder: selectedOption.label,
			focusedOption: selectedOption
		} : {
			value: '',
			inputValue: '',
			placeholder: this.props.placeholder || 'Select...',
			focusedOption: null
		};
	},

	keyboardActions: {
		13: 'selectFocusedOption',
		27: 'closeOnEscape',
		38: 'focusPreviousOption',
		40: 'focusNextOption'
	},

	handleKeyDown: function(event) {
		logEvent('------');
		logEvent(event);
		var action = this.keyboardActions[event.keyCode];
		if (!action) {
			return;
		}
		event.preventDefault();
		this[action].call(this);
	},

	handleMouseDown: function() {
		logEvent('click: control');
		if (this.state.isOpen) {
			this.setState({
				isOpen: false
			});
			this._controlIsFocused = true;
			this.refs.control.getDOMNode().focus();
			clearTimeout(this.blurTimer);
		} else {
			this.setState({
				isOpen: true,
				inputValue: ''
			});
			if (!this._inputIsFocused) {
				this.refs.input.getDOMNode().focus();
			}
		}
	},

	handleFocus: function() {
		if (this._controlIsFocused) return;
		logEvent('focus: control');
		this._controlIsFocused = true;
		clearTimeout(this.blurTimer);
		setTimeout(function() {
			if (!this._inputIsFocused) {
				this.refs.input.getDOMNode().focus();
			}
		}.bind(this), 0);
		this.setState({
			isFocused: true
		});
	},

	handleBlur: function(event) {
		if (!this._controlIsFocused) return;
		this._controlIsFocused = false;
		clearTimeout(this.blurTimer);
		this.blurTimer = setTimeout(function() {
			logEvent('blur: control');
			var blurState = this.getStateFromValue(this.state.value);
			blurState.isFocused = false;
			blurState.isOpen = false;
			this.setState(blurState);
		}.bind(this), 100);
	},

	handleInputMouseDown: function(event) {
		if (this._inputIsFocused) {
			logEvent('click: input');
			event.stopPropagation();
		}
	},

	handleInputFocus: function(event) {
		logEvent('focus: input');
		clearTimeout(this.blurTimer);
		this._inputIsFocused = true;
	},

	handleInputBlur: function(event) {
		logEvent('blur: input');
		this._inputIsFocused = false;
	},

	handleInputChange: function(event) {
		this.setState({
			isOpen: true,
			inputValue: event.target.value
		});
	},

	selectOption: function(option) {
		this.setValue(option);
		this.refs.control.getDOMNode().focus();
	},

	setValue: function(option) {
		var newState = this.getStateFromValue(option);
		newState.isOpen = false;
		this.setState(newState);
	},

	selectFocusedOption: function() {
		return this.setValue(this.state.focusedOption);
	},

	clearValue: function(event) {
		logEvent('clear value');
		this.setValue(null);
	},

	closeOnEscape: function() {
		this.setValue(this.state.value);
	},

	focusOption: function(op) {
		this.setState({
			focusedOption: op
		});
	},

	unfocusOption: function(op) {
		if (this.state.focusedOption === op) {
			this.setState({
				focusedOption: null
			});
		}
	},

	focusNextOption: function() {
		this.focusAdjacentOption('next');
	},

	focusPreviousOption: function() {
		this.focusAdjacentOption('previous');
	},

	focusAdjacentOption: function(dir) {

		if (!this.state.isOpen) {
			this.setState({
				isOpen: true,
				inputValue: ''
			});
			return;
		}

		var ops = this.filterOptions();

		if (!ops.length) {
			return;
		}

		var focusedIndex = -1;

		for (var i = 0; i < ops.length; i++) {
			if (this.state.focusedOption === ops[i]) {
				focusedIndex = i;
				break;
			}
		}

		var focusedOption = ops[0];

		if (dir === 'next' && focusedIndex > -1 && focusedIndex < ops.length - 1) {
			focusedOption = ops[focusedIndex + 1];
		} else if (dir === 'previous') {
			if (focusedIndex > 0) {
				focusedOption = ops[focusedIndex - 1];
			} else {
				focusedOption = ops[ops.length - 1];
			}
		}

		this.setState({
			focusedOption: focusedOption
		});

	},

	filterOptions: function() {
		return _.filter(this.props.options, this.filterOption, this);
	},

	filterOption: function(op) {
		return (
			!this.state.inputValue
			|| op.value.toLowerCase().indexOf(this.state.inputValue.toLowerCase()) >= 0
			|| op.label.toLowerCase().indexOf(this.state.inputValue.toLowerCase()) >= 0
		);
	},

	getOptions: function() {

		var ops = {};

		_.each(this.filterOptions(), function(op) {

			var optionClass = classes({
				'Select-option': true,
				'is-focused': this.state.focusedOption === op
			});

			var mouseEnter = this.focusOption.bind(this, op),
				mouseLeave = this.unfocusOption.bind(this, op),
				mouseDown = this.selectOption.bind(this, op);

			ops[op.value] =
{op.label}
;

		}, this);

		if (_.isEmpty(ops)) {
			ops._no_ops =
No results found
;
		}

		return ops;

	},

	render: function() {

		logEvent('render');
		// console.log(this.state);

		var menu = this.state.isOpen ?
{this.getOptions()}
 : null;
		var clear = this.state.value ? × : null;

		var selectClass = classes('Select', {
			'is-open': this.state.isOpen,
			'is-focused': this.state.isFocused
		});

		return

			<input type="hidden" ref="value" name={this.props.name} value={this.state.value} />

				<input className="Select-input" placeholder={this.state.placeholder} ref="input" onMouseDown={this.handleInputMouseDown} value={this.state.inputValue} onFocus={this.handleInputFocus} onBlur={this.handleInputBlur} onChange={this.handleInputChange} />
				{clear}

			{menu}

;
	}

});

module.exports = Select;
<commit_msg>Removing unused Option class<commit_after>/** @jsx React.DOM */

var _ = require('underscore'),
	React = require('react');

var noop = function() {};

var logEvent = function(msg) {
	console.log(msg);
};

// comment out this line to debug the control state
logEvent = noop;

var classes = function() {
	var rtn = [];
	for (var i = 0; i < arguments.length; i++) {
		if ('string' === typeof arguments[i]) {
			rtn.push(arguments[i]);
		} else if (_.isObject(arguments[i])) {
			_.each(arguments[i], function(val, key) {
				if (val) {
					rtn.push(key);
				}
			});
		}
	}
	return rtn.join(' ') || undefined;
}

var Select = React.createClass({

	getInitialState: function() {
		return {
			value: this.props.value,
			inputValue: '',
			placeholder: '',
			focusedOption: null,
			isFocused: false,
			isOpen: false
		};
	},

	componentWillMount: function() {
		this.setState(this.getStateFromValue(this.state.value));
	},

	getStateFromValue: function(value) {
		var selectedOption = ('string' === typeof value) ? _.findWhere(this.props.options, { value: value }) : value;
		return selectedOption ? {
			value: value,
			inputValue: selectedOption.label,
			placeholder: selectedOption.label,
			focusedOption: selectedOption
		} : {
			value: '',
			inputValue: '',
			placeholder: this.props.placeholder || 'Select...',
			focusedOption: null
		};
	},

	keyboardActions: {
		13: 'selectFocusedOption',
		27: 'closeOnEscape',
		38: 'focusPreviousOption',
		40: 'focusNextOption'
	},

	handleKeyDown: function(event) {
		logEvent('------');
		logEvent(event);
		var action = this.keyboardActions[event.keyCode];
		if (!action) {
			return;
		}
		event.preventDefault();
		this[action].call(this);
	},

	handleMouseDown: function() {
		logEvent('click: control');
		if (this.state.isOpen) {
			this.setState({
				isOpen: false
			});
			this._controlIsFocused = true;
			this.refs.control.getDOMNode().focus();
			clearTimeout(this.blurTimer);
		} else {
			this.setState({
				isOpen: true,
				inputValue: ''
			});
			if (!this._inputIsFocused) {
				this.refs.input.getDOMNode().focus();
			}
		}
	},

	handleFocus: function() {
		if (this._controlIsFocused) return;
		logEvent('focus: control');
		this._controlIsFocused = true;
		clearTimeout(this.blurTimer);
		setTimeout(function() {
			if (!this._inputIsFocused) {
				this.refs.input.getDOMNode().focus();
			}
		}.bind(this), 0);
		this.setState({
			isFocused: true
		});
	},

	handleBlur: function(event) {
		if (!this._controlIsFocused) return;
		this._controlIsFocused = false;
		clearTimeout(this.blurTimer);
		this.blurTimer = setTimeout(function() {
			logEvent('blur: control');
			var blurState = this.getStateFromValue(this.state.value);
			blurState.isFocused = false;
			blurState.isOpen = false;
			this.setState(blurState);
		}.bind(this), 100);
	},

	handleInputMouseDown: function(event) {
		if (this._inputIsFocused) {
			logEvent('click: input');
			event.stopPropagation();
		}
	},

	handleInputFocus: function(event) {
		logEvent('focus: input');
		clearTimeout(this.blurTimer);
		this._inputIsFocused = true;
	},

	handleInputBlur: function(event) {
		logEvent('blur: input');
		this._inputIsFocused = false;
	},

	handleInputChange: function(event) {
		this.setState({
			isOpen: true,
			inputValue: event.target.value
		});
	},

	selectOption: function(option) {
		this.setValue(option);
		this.refs.control.getDOMNode().focus();
	},

	setValue: function(option) {
		var newState = this.getStateFromValue(option);
		newState.isOpen = false;
		this.setState(newState);
	},

	selectFocusedOption: function() {
		return this.setValue(this.state.focusedOption);
	},

	clearValue: function(event) {
		logEvent('clear value');
		this.setValue(null);
	},

	closeOnEscape: function() {
		this.setValue(this.state.value);
	},

	focusOption: function(op) {
		this.setState({
			focusedOption: op
		});
	},

	unfocusOption: function(op) {
		if (this.state.focusedOption === op) {
			this.setState({
				focusedOption: null
			});
		}
	},

	focusNextOption: function() {
		this.focusAdjacentOption('next');
	},

	focusPreviousOption: function() {
		this.focusAdjacentOption('previous');
	},

	focusAdjacentOption: function(dir) {

		if (!this.state.isOpen) {
			this.setState({
				isOpen: true,
				inputValue: ''
			});
			return;
		}

		var ops = this.filterOptions();

		if (!ops.length) {
			return;
		}

		var focusedIndex = -1;

		for (var i = 0; i < ops.length; i++) {
			if (this.state.focusedOption === ops[i]) {
				focusedIndex = i;
				break;
			}
		}

		var focusedOption = ops[0];

		if (dir === 'next' && focusedIndex > -1 && focusedIndex < ops.length - 1) {
			focusedOption = ops[focusedIndex + 1];
		} else if (dir === 'previous') {
			if (focusedIndex > 0) {
				focusedOption = ops[focusedIndex - 1];
			} else {
				focusedOption = ops[ops.length - 1];
			}
		}

		this.setState({
			focusedOption: focusedOption
		});

	},

	filterOptions: function() {
		return _.filter(this.props.options, this.filterOption, this);
	},

	filterOption: function(op) {
		return (
			!this.state.inputValue
			|| op.value.toLowerCase().indexOf(this.state.inputValue.toLowerCase()) >= 0
			|| op.label.toLowerCase().indexOf(this.state.inputValue.toLowerCase()) >= 0
		);
	},

	getOptions: function() {

		var ops = {};

		_.each(this.filterOptions(), function(op) {

			var optionClass = classes({
				'Select-option': true,
				'is-focused': this.state.focusedOption === op
			});

			var mouseEnter = this.focusOption.bind(this, op),
				mouseLeave = this.unfocusOption.bind(this, op),
				mouseDown = this.selectOption.bind(this, op);

			ops[op.value] =
{op.label}
;

		}, this);

		if (_.isEmpty(ops)) {
			ops._no_ops =
No results found
;
		}

		return ops;

	},

	render: function() {

		logEvent('render');
		// console.log(this.state);

		var menu = this.state.isOpen ?
{this.getOptions()}
 : null;
		var clear = this.state.value ? × : null;

		var selectClass = classes('Select', {
			'is-open': this.state.isOpen,
			'is-focused': this.state.isFocused
		});

		return

			<input type="hidden" ref="value" name={this.props.name} value={this.state.value} />

				<input className="Select-input" placeholder={this.state.placeholder} ref="input" onMouseDown={this.handleInputMouseDown} value={this.state.inputValue} onFocus={this.handleInputFocus} onBlur={this.handleInputBlur} onChange={this.handleInputChange} />
				{clear}

			{menu}

;
	}

});

module.exports = Select;
<|endoftext|>


<commit_before>var st = require('st')
  , http = require('http')
  , js = require('atomify-js')
  , css = require('atomify-css')
  , open = require('open')

module.exports = function (args) {

  var mount = st(args.server.st || process.cwd())
    , port = args.server.port || 1337
    , launch = args.server.open
    , path = args.server.path || ''
    , url = args.server.url || 'http://localhost:' + port + path

  http.createServer(function(req, res) {

    switch (req.url) {
      case args.js.alias || args.js.entry:
        js(args.js, responder('javascript', res))
        break

      case args.css.alias || args.css.entry:
        css(args.css, responder('css', res))
        break

      default:
        mount(req, res)
        break
    }

  }).listen(port)

  if (launch) open(url)
}

function responder (type, res) {
  return function (err, src) {
    if (!res.headersSent) res.setHeader('Content-Type', 'text/' + type)
    res.end(src)
  }
}
<commit_msg>Add leading slash to path if not provided<commit_after>var st = require('st')
  , http = require('http')
  , js = require('atomify-js')
  , css = require('atomify-css')
  , open = require('open')

module.exports = function (args) {

  var mount = st(args.server.st || process.cwd())
    , port = args.server.port || 1337
    , launch = args.server.open
    , path = args.server.path || '/'
    , url

  if (path.charAt(0) !== '/') path = '/' + path

  url = args.server.url || 'http://localhost:' + port + path

  http.createServer(function (req, res) {

    switch (req.url) {
      case args.js.alias || args.js.entry:
        js(args.js, responder('javascript', res))
        break

      case args.css.alias || args.css.entry:
        css(args.css, responder('css', res))
        break

      default:
        mount(req, res)
        break
    }

  }).listen(port)

  if (launch) open(url)
}

function responder (type, res) {
  return function (err, src) {
    if (!res.headersSent) res.setHeader('Content-Type', 'text/' + type)
    res.end(src)
  }
}
<|endoftext|>


<commit_before>var _ = require('lodash'),
  express = require('express'),
  consolidate = require('consolidate'),
  fs = require('fs'),
  utils = require('./utils');

var app = express();

function findHTML(file, path, cb) {
  file = file || 'index';
  fs.exists(path + file + '.html', function (exists) {
    if (!exists && (/index$/).test(file)) {
      cb('File not found: ' + path + file);
      return;
    }

    if (!exists) {
      findHTML(file + '/index', path, cb);
      return;
    }

    file = file + '.html';

    fs.stat(path + file, function (err, stats) {
      cb(null, file, stats);
    });
  });
}

exports.run = function (argv) {
  var path = argv._[0],
    engine = argv.e,
    encoding = argv.encoding,
    port = argv.p,
    __swig;

  app.use(express.logger('dev'));
  app.use(app.router);

  if (!consolidate[engine]) {
    utils.error('Template engine', engine, 'does not exist');
    process.exit(1);
  }

  if (engine === 'swig') {
    // Swig requires some extra setup
    __swig = require('swig');
    __swig.init({
      root: path,
      allowErrors: true,
      cache: false
    });
  }

  app.engine('.html', consolidate[engine]);
  app.set('view engine', 'html');
  app.set('views', path);

  app.get('/*', function (req, res) {
    var view = _.first(req.params).replace(/\/$/, '');

    findHTML(view, path, function (err, tpl, stat) {
      if (err) {
        utils.error('View not found for', view);
        return;
      }

      var dataFile = tpl.replace(/\.html$/, '.json');

      fs.readFile(path + dataFile, encoding, function (err, jsonData) {
        var data = {};

        if (err) {
          utils.warn('No data for file', tpl);
        } else {
          try {
            data = _.extend(stat, JSON.parse(jsonData));
          } catch (e) {
            utils.warn('Data not proper JSON', dataFile);
          }
        }

        res.render(tpl, data);
      });

    });
  });

  app.listen(port);
  utils.log('Server listening on port', port);
};
<commit_msg>DEV var and better static file handling<commit_after>var _ = require('lodash'),
  express = require('express'),
  consolidate = require('consolidate'),
  fs = require('fs'),
  utils = require('./utils');

var app = express();

function findHTML(file, path, cb) {
  file = file || 'index';
  fs.exists(path + file + '.html', function (exists) {
    if (!exists && (/index$/).test(file)) {
      cb('File not found: ' + path + file);
      return;
    }

    if (!exists) {
      findHTML(file + '/index', path, cb);
      return;
    }

    file = file + '.html';

    fs.stat(path + file, function (err, stats) {
      cb(null, file, stats);
    });
  });
}

exports.run = function (argv) {
  var path = argv._[0],
    engine = argv.e,
    encoding = argv.encoding,
    port = argv.p,
    __swig;

  app.use(express.logger('dev'));
  app.use(app.router);

  if (!consolidate[engine]) {
    utils.error('Template engine', engine, 'does not exist');
    process.exit(1);
  }

  if (engine === 'swig') {
    // Swig requires some extra setup
    __swig = require('swig');
    __swig.init({
      root: path,
      allowErrors: true,
      cache: false
    });
  }

  app.engine('.html', consolidate[engine]);
  app.set('view engine', 'html');
  app.set('views', path);

  app.get('/*', function (req, res) {
    var view = _.first(req.params).replace(/\/$/, '');

    findHTML(view, path, function (err, tpl, stat) {
      if (err) {
        try {
          res.sendfile(path + view);
        } catch (e) {
          utils.error('View not found for', view);
        }
        return;
      }

      var dataFile = tpl.replace(/\.html$/, '.json');

      fs.readFile(path + dataFile, encoding, function (err, jsonData) {
        var data = {};

        if (err) {
          utils.warn('No data for file', tpl);
        } else {
          try {
            data = _.extend({ DEV: true }, stat, JSON.parse(jsonData));
          } catch (e) {
            utils.warn('Data not proper JSON', dataFile);
          }
        }

        res.render(tpl, data);
      });

    });
  });

  app.listen(port);
  utils.log('Server listening on port', port);
};
<|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var path = require('path')
var Asset = require('./web/asset')
var debug = require('debug')('micromono:server')
var Router = require('./web/router')
var argv = require('./argv').parse(process.argv)
var ServiceManager = require('./service/manager')

var PORT = argv.port
var HOST = argv.host
var SERVICE = argv.service
var SERVICE_DIR = argv.serviceDir
var ALLOW_PENDING = argv.allowPending

/**
 * Constructor for MicroMonoServer class
 *
 * @return {MicroMonoServer} Instance of MicroMonoServer class
 */
var MicroMonoServer = module.exports = function(options) {
  this.options = this.getDefaultOptions(options)
  this.parsePackageInfo(this.options.packagePath)
  Router.prototype.setFramework.call(this, this.options.framework)

  this.manager = new ServiceManager({
    allowPending: ALLOW_PENDING,
    serviceDir: SERVICE_DIR
  })
}

/**
 * Get default options for server.
 * @param {Object} [options] Optional options, it could have following values:
 * {
 *   packagePath: '/path/to/the/package', // Where your package.json is.
 *   framework: 'express', // Name or instance of your web framework.
 * }
 *
 * @type {Object}
 */
MicroMonoServer.prototype.getDefaultOptions = function(options) {
  options = options || {}

  if (!options.packagePath) {
    var parentFile = module.parent.parent.filename
    options.packagePath = path.dirname(parentFile)
  }

  if (!options.framework) {
    options.framework = 'express'
  }

  return options
}

/**
 * Parse and create asset instance for this server.
 *
 * @param  {String} packagePath Path to the package.
 */
MicroMonoServer.prototype.parsePackageInfo = function(packagePath) {
  this.asset = new Asset(packagePath)

  try {
    this.asset.parseJSPM()
  } catch (e) {
    debug('failed to parse package info', e)
  }
}

/**
 * Require a service.
 *
 * @param  {String} name Name of the service to require.
 * @return {Service}     The service constructor.
 */
MicroMonoServer.prototype.require = function(name) {
  return this.manager.require(name)
}

/**
 * Start the service with a standalone internal server.
 *
 * @param  {Service} ServiceClass Service class.
 * @return {Promise}              Instance of promise.
 */
MicroMonoServer.prototype.startService = function(ServiceClass) {
  var manager = this.manager
  debug('start service')
  return manager.startService(ServiceClass).then(function() {
    // Listen for new providers for existing or pending services.
    manager.listenProviders()
  })
}

/**
 * Start the server as a balancer.
 *
 * @param  {Object} [app] The instance provided by external web framework.
 * @return {Promise}      An instance of promise.
 */
MicroMonoServer.prototype.startBalancer = function(app) {
  var self = this
  var asset = this.asset
  var manager = this.manager
  var framework = this.framework
  manager.name = 'MicroMonoServiceManager'

  if (SERVICE) {
    var services = SERVICE.split(',')
    // Load services required from command line.
    services.forEach(function(name) {
      self.require(name)
    })
  }

  if (app) {
    PORT = app
    framework.setApp(app)
  }

  var promise = manager.runServices(self)
    .then(function() {
      return asset.configJSPM()
    })
    .then(function() {
      // Serve local asset files.
      framework.serveAsset(asset)
    })

  return promise
    .then(function() {
      return framework.startServer(PORT, HOST, manager).then(function(server) {
        if (server) {
          var address = server.address()
          debug('balancer started at %s:%s', address.address, address.port)
        }
      })
    })
    .then(function() {
      // Listen for new providers for existing or pending services.
      manager.listenProviders(self)
    })
    .catch(function(e) {
      debug('started with error:', e.stack)
    })
}
<commit_msg>Bundle asset for balancer if we have any.<commit_after>/**
 * Module dependencies
 */

var path = require('path')
var Asset = require('./web/asset')
var debug = require('debug')('micromono:server')
var Router = require('./web/router')
var argv = require('./argv').parse(process.argv)
var ServiceManager = require('./service/manager')

var PORT = argv.port
var HOST = argv.host
var SERVICE = argv.service
var SERVICE_DIR = argv.serviceDir
var ALLOW_PENDING = argv.allowPending

/**
 * Constructor for MicroMonoServer class
 *
 * @return {MicroMonoServer} Instance of MicroMonoServer class
 */
var MicroMonoServer = module.exports = function(options) {
  this.options = this.getDefaultOptions(options)
  this.parsePackageInfo(this.options.packagePath)
  Router.prototype.setFramework.call(this, this.options.framework)

  this.manager = new ServiceManager({
    allowPending: ALLOW_PENDING,
    serviceDir: SERVICE_DIR
  })
}

/**
 * Get default options for server.
 * @param {Object} [options] Optional options, it could have following values:
 * {
 *   packagePath: '/path/to/the/package', // Where your package.json is.
 *   framework: 'express', // Name or instance of your web framework.
 * }
 *
 * @type {Object}
 */
MicroMonoServer.prototype.getDefaultOptions = function(options) {
  options = options || {}

  if (!options.packagePath) {
    var parentFile = module.parent.parent.filename
    options.packagePath = path.dirname(parentFile)
  }

  if (!options.framework) {
    options.framework = 'express'
  }

  return options
}

/**
 * Parse and create asset instance for this server.
 *
 * @param  {String} packagePath Path to the package.
 */
MicroMonoServer.prototype.parsePackageInfo = function(packagePath) {
  this.asset = new Asset(packagePath)

  try {
    this.asset.parseJSPM()
  } catch (e) {
    debug('failed to parse package info', e)
  }
}

/**
 * Require a service.
 *
 * @param  {String} name Name of the service to require.
 * @return {Service}     The service constructor.
 */
MicroMonoServer.prototype.require = function(name) {
  return this.manager.require(name)
}

/**
 * Start the service with a standalone internal server.
 *
 * @param  {Service} ServiceClass Service class.
 * @return {Promise}              Instance of promise.
 */
MicroMonoServer.prototype.startService = function(ServiceClass) {
  var manager = this.manager
  debug('start service')
  return manager.startService(ServiceClass).then(function() {
    // Listen for new providers for existing or pending services.
    manager.listenProviders()
  })
}

/**
 * Start the server as a balancer.
 *
 * @param  {Object} [app] The instance provided by external web framework.
 * @return {Promise}      An instance of promise.
 */
MicroMonoServer.prototype.startBalancer = function(app) {
  var self = this
  var asset = this.asset
  var manager = this.manager
  var framework = this.framework
  manager.name = 'MicroMonoServiceManager'

  if (SERVICE) {
    var services = SERVICE.split(',')
    // Load services required from command line.
    services.forEach(function(name) {
      self.require(name)
    })
  }

  if (app) {
    PORT = app
    framework.setApp(app)
  }

  var promise = manager.runServices(self)
    .then(function() {
      return asset.configJSPM()
    })
    .then(function() {
      if (argv.bundleAsset && asset.jspmInfo && asset.jspmInfo.main) {
        return asset.bundle(null, process.env.NODE_ENV)
      }
    })
    .then(function() {
      // Serve local asset files.
      framework.serveAsset(asset)
    })

  return promise
    .then(function() {
      return framework.startServer(PORT, HOST, manager).then(function(server) {
        if (server) {
          var address = server.address()
          debug('balancer started at %s:%s', address.address, address.port)
        }
      })
    })
    .then(function() {
      // Listen for new providers for existing or pending services.
      manager.listenProviders(self)
    })
    .catch(function(e) {
      debug('started with error:', e.stack)
    })
}
<|endoftext|>


<commit_before>var http     = require('http')
  , fs       = require('fs')
  , path     = require('path')
  , url      = require('url')
  , check    = require('./check')
  , parser   = require('./parser')
  , template = require('./template');

exports.startAt = (function() {
  var server = http.createServer(handler)
  return function(port, fn) {
    http
      .get('http://localhost:' + port, fn)
      .on('error', function(){
        server.listen(port);
        fn();
      });
  };
}());

function handler(req, res) {
  var filename = url.parse(req.url).path.substr(1)
    , basename = path.basename(filename);

  if (req.url == '/close') {
    process.exit(1);
  }

  check(filename, function(ok) {
    if (ok) {
      fs.readFile(filename, 'utf-8', function(err, input) {
        res.writeHead(200, {'Content-Type':'text/html;charset=utf-8'});
        res.end(
          template.render({
              title: basename
            , body: parser.parse(input)
          })
        );
      });
    } else {
      res.writeHead(404, {'Content-Type':'text/plain;charset=utf-8'});
      res.end('Cannot open file ' + basename);
    }
  });
}
<commit_msg>add decodeURI<commit_after>var http     = require('http')
  , fs       = require('fs')
  , path     = require('path')
  , url      = require('url')
  , check    = require('./check')
  , parser   = require('./parser')
  , template = require('./template');

exports.startAt = (function() {
  var server = http.createServer(handler)
  return function(port, fn) {
    http
      .get('http://localhost:' + port, fn)
      .on('error', function(){
        server.listen(port);
        fn();
      });
  };
}());

function handler(req, res) {
  var filename = decodeURI(url.parse(req.url).path.substr(1))
    , basename = path.basename(filename);

  if (req.url == '/close') {
    process.exit(1);
  }

  check(filename, function(ok) {
    if (ok) {
      fs.readFile(filename, 'utf-8', function(err, input) {
        res.writeHead(200, {'Content-Type':'text/html;charset=utf-8'});
        res.end(
          template.render({
              title: basename
            , body: parser.parse(input)
          })
        );
      });
    } else {
      res.writeHead(404, {'Content-Type':'text/plain;charset=utf-8'});
      res.end('Cannot open file ' + basename);
    }
  });
}
<|endoftext|>


<commit_before>'use strict';

var express    = require('express');
var path       = require('path');
var fs         = require('fs');
var morgan     = require('morgan');
var bodyParser = require('body-parser');
var session    = require('express-session');

var pkg       = require('../package.json');
var helper    = require('./backend/common/helper');
var multipart = require('./backend/common/multipart');

var server = module.exports = express();

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
initExpressServer(server); function initExpressServer(server) {
    //console.log('initExpressServer');
    var engineDirPath  = __dirname;
    var backendDirPath = path.join(engineDirPath, 'backend');

    // environment
    server.set('appsDirPath', path.join(helper.getCommandLineParams().appsDirPath || pkg.config.appsDirPath));
    if (!fs.existsSync(server.get('appsDirPath'))) {
        console.log("Application folder '{appsDirPath}' doesn't exist".template({
            appsDirPath: path.resolve(server.get('appsDirPath'))
        }));
        process.exit(1);
    }

    // vars
    server.set('version'        , pkg.version);
    server.set('handleException', helper.getCommandLineParams().handleException || true);
    server.set('view engine'    , 'ejs');
    server.set('views'          , path.join(backendDirPath, 'routes'));
    server.set('public'         , path.join(engineDirPath,  'frontend'));
    server.set('runtime'        , path.join(engineDirPath,  'runtime'));
    server.set('temp'           , path.join(engineDirPath,  'runtime/temp'));
    server.set('applications'   , {});
    server.set('commonClassCss' , helper.getFilePathsSync(server.get('public'), 'common/class', 'css'));
    server.set('commonClassJs'  , helper.getFilePathsSync(server.get('public'), 'common/class', 'js' ));
    server.set('homeClassCss'   , helper.getFilePathsSync(server.get('public'), 'home/class'  , 'css'));
    server.set('homeClassJs'    , helper.getFilePathsSync(server.get('public'), 'home/class'  , 'js' ));
    server.set('viewerClassCss' , helper.getFilePathsSync(server.get('public'), 'viewer/class', 'css'));
    server.set('viewerClassJs'  , helper.getFilePathsSync(server.get('public'), 'viewer/class', 'js' ));
    server.set('editorClassCss' , helper.getFilePathsSync(server.get('public'), 'editor/class', 'css'));
    server.set('editorClassJs'  , helper.getFilePathsSync(server.get('public'), 'editor/class', 'js' ));

    server.enable('strict routing');

    // production by default to disable editor
    if (!process.env.NODE_ENV) {
        server.set('env', 'production');
    }

    // middlewares
    //server.use(morgan('dev'));
    server.use(function (req, res, next) {
        //console.log(req.originalUrl);
        next();
    });
    server.use(bodyParser.json());
    server.use(bodyParser.urlencoded({ extended: false }));
    server.use(multipart);
    server.use(session({
        secret            : 'qforms',
        key               : 'sid',
        resave            : false,
        saveUninitialized : false
    }));

    // routes
    var home   = require(path.join(backendDirPath, 'routes/home'));
    var viewer = require(path.join(backendDirPath, 'routes/viewer'));
    var editor = require(path.join(backendDirPath, 'routes/editor'));
    var file   = require(path.join(backendDirPath, 'routes/viewer/file'));
    var error  = require(path.join(backendDirPath, 'routes/error'));

    // home
    server.get('/' , home);
    server.post('/', home);

    // view
    server.get('/view/:appDirName/:appFileName/' , viewer);
    server.get('/view/:appDirName/:appFileName/*', function (req, res, next) {
        file(req, res, function () {
            //console.log('file not found: ', req.originalUrl);
            var url = req.originalUrl.replace('/view/' + req.params.appDirName + '/' + req.params.appFileName, '');
            res.redirect(url);
        });
    });
    server.post('/view/:appDirName/:appFileName/', viewer);

    // editor
    server.get('/edit/:appDirName/:appFileName/' , editor);
    server.get('/edit/:appDirName/:appFileName/*', function (req, res, next) {
        file(req, res, function () {
            //console.log('file not found: ', req.originalUrl);
            var url = req.originalUrl.replace('/edit/' + req.params.appDirName + '/' + req.params.appFileName, '');
            res.redirect(url);
        });
    });
    server.post('/edit/:appDirName/:appFileName/', editor);

    // /favicon.ico
    server.get('/favicon.ico', function (req, res, next) {
        console.log('/favicon.ico');
        res.end();
    });
    server.use(express.static(server.get('public')));

    // catch 404 and forward to error handler
    server.use(error.e404);
    server.use(error.e500);

    // runtime & temp
    helper.createDirIfNotExistsSync(server.get('runtime'));
    helper.createDirIfNotExistsSync(server.get('temp'));
}<commit_msg>redirect replaced by sendFile<commit_after>'use strict';

var express    = require('express');
var path       = require('path');
var fs         = require('fs');
var morgan     = require('morgan');
var bodyParser = require('body-parser');
var session    = require('express-session');

var pkg       = require('../package.json');
var helper    = require('./backend/common/helper');
var multipart = require('./backend/common/multipart');

var server = module.exports = express();

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
initExpressServer(server); function initExpressServer(server) {
    //console.log('initExpressServer');
    var engineDirPath  = __dirname;
    var backendDirPath = path.join(engineDirPath, 'backend');

    // environment
    server.set('appsDirPath', path.join(helper.getCommandLineParams().appsDirPath || pkg.config.appsDirPath));
    if (!fs.existsSync(server.get('appsDirPath'))) {
        console.log("Application folder '{appsDirPath}' doesn't exist".template({
            appsDirPath: path.resolve(server.get('appsDirPath'))
        }));
        process.exit(1);
    }

    // vars
    server.set('version'        , pkg.version);
    server.set('handleException', helper.getCommandLineParams().handleException || true);
    server.set('view engine'    , 'ejs');
    server.set('views'          , path.join(backendDirPath, 'routes'));
    server.set('public'         , path.join(engineDirPath,  'frontend'));
    server.set('runtime'        , path.join(engineDirPath,  'runtime'));
    server.set('temp'           , path.join(engineDirPath,  'runtime/temp'));
    server.set('applications'   , {});
    server.set('commonClassCss' , helper.getFilePathsSync(server.get('public'), 'common/class', 'css'));
    server.set('commonClassJs'  , helper.getFilePathsSync(server.get('public'), 'common/class', 'js' ));
    server.set('homeClassCss'   , helper.getFilePathsSync(server.get('public'), 'home/class'  , 'css'));
    server.set('homeClassJs'    , helper.getFilePathsSync(server.get('public'), 'home/class'  , 'js' ));
    server.set('viewerClassCss' , helper.getFilePathsSync(server.get('public'), 'viewer/class', 'css'));
    server.set('viewerClassJs'  , helper.getFilePathsSync(server.get('public'), 'viewer/class', 'js' ));
    server.set('editorClassCss' , helper.getFilePathsSync(server.get('public'), 'editor/class', 'css'));
    server.set('editorClassJs'  , helper.getFilePathsSync(server.get('public'), 'editor/class', 'js' ));

    server.enable('strict routing');

    // production by default to disable editor
    if (!process.env.NODE_ENV) {
        server.set('env', 'production');
    }

    // middlewares
    //server.use(morgan('dev'));
    server.use(function (req, res, next) {
        //console.log(req.originalUrl);
        next();
    });
    server.use(bodyParser.json());
    server.use(bodyParser.urlencoded({ extended: false }));
    server.use(multipart);
    server.use(session({
        secret            : 'qforms',
        key               : 'sid',
        resave            : false,
        saveUninitialized : false
    }));

    // routes
    var home   = require(path.join(backendDirPath, 'routes/home'));
    var viewer = require(path.join(backendDirPath, 'routes/viewer'));
    var editor = require(path.join(backendDirPath, 'routes/editor'));
    var file   = require(path.join(backendDirPath, 'routes/viewer/file'));
    var error  = require(path.join(backendDirPath, 'routes/error'));

    // home
    server.get('/' , home);
    server.post('/', home);

    // view
    server.get('/view/:appDirName/:appFileName/' , viewer);
    server.get('/view/:appDirName/:appFileName/*', function (req, res, next) {
        file(req, res, function () {
            //console.log('file not found: ', req.originalUrl);
            var uri = req.originalUrl.replace('/view/' + req.params.appDirName + '/' + req.params.appFileName, '');
            var filePath = path.join(server.get('public'), uri);
            res.sendFile(filePath);
        });
    });
    server.post('/view/:appDirName/:appFileName/', viewer);

    // editor
    server.get('/edit/:appDirName/:appFileName/' , editor);
    server.get('/edit/:appDirName/:appFileName/*', function (req, res, next) {
        file(req, res, function () {
            //console.log('file not found: ', req.originalUrl);
            var uri = req.originalUrl.replace('/edit/' + req.params.appDirName + '/' + req.params.appFileName, '');
            var filePath = path.join(server.get('public'), uri);
            res.sendFile(filePath);
        });
    });
    server.post('/edit/:appDirName/:appFileName/', editor);

    // /favicon.ico
    server.get('/favicon.ico', function (req, res, next) {
        console.log('/favicon.ico');
        res.end();
    });
    server.use(express.static(server.get('public')));

    // catch 404 and forward to error handler
    server.use(error.e404);
    server.use(error.e500);

    // runtime & temp
    helper.createDirIfNotExistsSync(server.get('runtime'));
    helper.createDirIfNotExistsSync(server.get('temp'));
}<|endoftext|>