<commit_before>'use strict';

const { join } = require('path');
const { existsSync } = require('fs-extra');
const _ = require('lodash');
const findPackagePath = require('../load/package-path');
const loadFiles = require('../load/load-files');
const loadConfig = require('../load/load-config-files');

module.exports = async ({ dir, config }) => {
  const localPlugins = await loadLocalPlugins({ dir, config });
  const plugins = await loadPlugins({
    installedPlugins: config.installedPlugins,
    config,
  });

  const pluginsIntersection = _.intersection(Object.keys(localPlugins), Object.keys(plugins));

  if (pluginsIntersection.length > 0) {
    throw new Error(
      `You have some local plugins with the same name as npm installed plugins:\n${pluginsIntersection
        .map(p => `- ${p}`)
        .join('\n')}`
    );
  }

  // check for conflicts
  return _.merge(plugins, localPlugins);
};

const loadLocalPlugins = async ({ dir, config }) => {
  const pluginsDir = join(dir, 'plugins');

  if (!existsSync(pluginsDir)) return {};

  const [files, configs] = await Promise.all([
    loadFiles(pluginsDir, '{*/!(config)/*.*(js|json),*/package.json}'),
    loadConfig(pluginsDir, '*/config/**/*.+(js|json)'),
  ]);
  const userConfigs = Object.keys(files).reduce((acc, plugin) => {
    acc[plugin] = { config: config.get(['plugins', plugin], {}) };
    return acc;
  }, {});
  return _.merge(files, configs, userConfigs);
};

const loadPlugins = async ({ installedPlugins, config }) => {
  let plugins = {};

  for (let plugin of installedPlugins) {
    const pluginPath = findPackagePath(`strapi-plugin-${plugin}`);

    const files = await loadFiles(
      pluginPath,
      '{!(config|node_modules|test)/*.*(js|json),package.json}'
    );

    const { config: pluginConfig } = await loadConfig(pluginPath);

    const userConfig = config.get(['plugins', plugin], {});

    const mergedConfig = _.merge(pluginConfig, userConfig);

    _.set(plugins, plugin, _.assign({}, files, { config: mergedConfig }));
  }

  return plugins;
};
<commit_msg>Fix typo in load-plugins file pattern<commit_after>'use strict';

const { join } = require('path');
const { existsSync } = require('fs-extra');
const _ = require('lodash');
const findPackagePath = require('../load/package-path');
const loadFiles = require('../load/load-files');
const loadConfig = require('../load/load-config-files');

module.exports = async ({ dir, config }) => {
  const localPlugins = await loadLocalPlugins({ dir, config });
  const plugins = await loadPlugins({
    installedPlugins: config.installedPlugins,
    config,
  });

  const pluginsIntersection = _.intersection(Object.keys(localPlugins), Object.keys(plugins));

  if (pluginsIntersection.length > 0) {
    throw new Error(
      `You have some local plugins with the same name as npm installed plugins:\n${pluginsIntersection
        .map(p => `- ${p}`)
        .join('\n')}`
    );
  }

  // check for conflicts
  return _.merge(plugins, localPlugins);
};

const loadLocalPlugins = async ({ dir, config }) => {
  const pluginsDir = join(dir, 'plugins');

  if (!existsSync(pluginsDir)) return {};

  const [files, configs] = await Promise.all([
    loadFiles(pluginsDir, '{*/!(config)/*.*(js|json),*/package.json}'),
    loadConfig(pluginsDir, '*/config/**/*.+(js|json)'),
  ]);
  const userConfigs = Object.keys(files).reduce((acc, plugin) => {
    acc[plugin] = { config: config.get(['plugins', plugin], {}) };
    return acc;
  }, {});
  return _.merge(files, configs, userConfigs);
};

const loadPlugins = async ({ installedPlugins, config }) => {
  let plugins = {};

  for (let plugin of installedPlugins) {
    const pluginPath = findPackagePath(`strapi-plugin-${plugin}`);

    const files = await loadFiles(
      pluginPath,
      '{!(config|node_modules|tests)/*.*(js|json),package.json}'
    );

    const { config: pluginConfig } = await loadConfig(pluginPath);

    const userConfig = config.get(['plugins', plugin], {});

    const mergedConfig = _.merge(pluginConfig, userConfig);

    _.set(plugins, plugin, _.assign({}, files, { config: mergedConfig }));
  }

  return plugins;
};
<|endoftext|>


<commit_before>var url = Npm.require('url');
var stylus = Npm.require('stylus');
var nib = Npm.require('nib');
var Future = Npm.require('fibers/future');
var LRU = Npm.require('lru-cache');

Plugin.registerCompiler({
  extensions: ['styl'],
  archMatchin: 'web'
}, function () {
  return new StylusCompiler();
});

var APP_SYMBOL = '__app__';

var CACHE_SIZE = process.env.METEOR_STYLUS_CACHE_SIZE || 1024*1024*10;

function StylusCompiler () {
  var self = this;

  self._cache = new LRU({
    max: CACHE_SIZE,
    // Cache is measured in bytes (not counting the hashes).
    length: function (value) {
      return value.css.length + sourceMapLength(value.sourceMap);
    }
  });

  self._diskCache = null;
}

StylusCompiler.prototype.processFilesForTarget = function (files) {
  var self = this;

  var currentlyCompiledFile = null;
  var currentlyCompiledPackage = null;
  var currentlyProcessedImports = null;
  var parseImportPath = function (filePath, importerPath) {
    if (! filePath) {
      throw new Error('filePath is undefined');
    }
    if (filePath === currentlyCompiledFile) {
      return {
        packageName: currentlyCompiledPackage,
        pathInPackage: '/' + currentlyCompiledFile
      };
    }
    if (! filePath.match(/^\{.*\}\//)) {
      if (! importerPath) {
        return { packageName: currentlyCompiledPackage, pathInPackage: '/' + filePath };
      }

      // relative path in the same package
      var parsedImporter = parseImportPath(importerPath, null);
      return {
        packageName: parsedImporter.packageName,
        pathInPackage: url.resolve(parsedImporter.pathInPackage, filePath)
      };
    }

    var match = /^(\{.*\})(\/.*)$/.exec(filePath);
    if (! match) { return null; }

    var packageName = match[1];
    if (!packageName || packageName === '{}')
      packageName = APP_SYMBOL;
    else
      packageName = packageName.substr(1, packageName.length - 2);

    var pathInPackage = match[2];

    return {packageName: packageName, pathInPackage: pathInPackage};
  };
  var absoluteImportPath = function (parsed) {
    return '{' + parsed.packageName + '}' + parsed.pathInPackage;
  };

  var filesByAbsoluteImportPath = {};
  files.forEach(function (inputFile) {
    var packageName = inputFile.getPackageName() || APP_SYMBOL;
    var filePath = '/' + inputFile.getPathInPackage();
    filesByAbsoluteImportPath[absoluteImportPath({
      packageName: packageName,
      pathInPackage: filePath
    })] = inputFile;
  });

  var importer = {
    find: function (importPath, paths, importerPath) {
      var parsed = parseImportPath(importPath, importerPath);

      if (! parsed) { return null; }

      var absolutePath = absoluteImportPath(parsed);

      if (! filesByAbsoluteImportPath[absolutePath]) {
        return null;
      }

      return [absolutePath];
    },
    readFile: function (filePath) {
      var parsed = parseImportPath(filePath);
      var absolutePath = absoluteImportPath(parsed);

      currentlyProcessedImports.push(absolutePath);

      if (! filesByAbsoluteImportPath[absolutePath]) throw new Error('Cannot read file ' + absolutePath);

      return filesByAbsoluteImportPath[absolutePath].getContentsAsString();
    }
  };

  function processSourcemap(sourcemap) {
    delete sourcemap.file;
    sourcemap.sourcesContent = sourcemap.sources.map(importer.readFile);
    sourcemap.sources = sourcemap.sources.map(function (filePath) {
      var parsed = parseImportPath(filePath);
      if (parsed.packageName === APP_SYMBOL)
        return parsed.pathInPackage.substr(1);
      return 'packages/' + parsed.packageName + parsed.pathInPackage;
    });

    return sourcemap;
  }

  files.forEach(function (inputFile) {
    var pathInPackage = inputFile.getPathInPackage();
    var fileOptions = inputFile.getFileOptions();

    // The heuristic is that a file is an import (ie, is not itself processed
    // as a root) if it is in a subdirectory named 'import' or if it matches
    // *.import.styl. This can be overridden in either direction via an
    // explicit `isImport` file option in apiaddFiles.
    var filenameSaysImport =
          /\.import\.styl$/.test(pathInPackage) ||
          /(?:^|\/)import\//.test(pathInPackage);
    var isImport = fileOptions.hasOwnProperty('isImport')
          ? fileOptions.isImport : filenameSaysImport;

    if (isImport) {
      return;
    }

    currentlyCompiledFile = pathInPackage;
    currentlyCompiledPackage = inputFile.getPackageName() || APP_SYMBOL;
    currentlyProcessedImports = [];

    var absolutePath = absoluteImportPath({
      packageName: currentlyCompiledPackage,
      filePath: currentlyCompiledFile
    });

    var cacheEntry = self._cache.get(absolutePath);
    if (! (cacheEntry && self._cacheEntryValid(cacheEntry, filesByAbsoluteImportPath))) {
      // the entry in the cache doesn't represent the latest state

      // Append a cache buster because Stylus has a buggy caching
      // based on the contents that produces incorrect sourcemaps (the
      // 'filename' field is not checked into cache)
      var cacheBuster = '/*random cache buster ' + Math.random() + '*/';
      var f = new Future;

      var style = stylus(inputFile.getContentsAsString() + cacheBuster)
        .use(nib())
        .set('filename', pathInPackage)
        .set('sourcemap', { inline: false, comment: false })
        .set('importer', importer);

      style.render(f.resolver());

      try {
        var css = f.wait();
      } catch (e) {
        inputFile.error({
          message: "Stylus compiler error: " + e.message
        });
        return;
      }
      var sourcemap = processSourcemap(style.sourcemap);

      cacheEntry = {
        hashes: {},
        css: css,
        sourceMap: sourcemap
      };
      cacheEntry.hashes[absolutePath] = inputFile.getSourceHash();
      currentlyProcessedImports.forEach(function (path) {
        cacheEntry.hashes[path] =
          filesByAbsoluteImportPath[path].getSourceHash();
      });

      self._cache.set(absolutePath, cacheEntry);
    }

    inputFile.addStylesheet({
      path: inputFile.getPathInPackage() + ".css",
      data: cacheEntry.css,
      sourceMap: cacheEntry.sourceMap
    });
  });

  // Rewrite the cache to disk.
  // XXX #BBPBetterCache we should just write individual entries separately.
  self._writeCache();
};

StylusCompiler.prototype._cacheEntryValid = function (cacheEntry, filesMap) {
  return Object.keys(cacheEntry.hashes).every(function (path) {
    var hash = cacheEntry.hashes[path];
    return filesMap[path] && filesMap[path].getSourceHash() === hash;
  });
};

StylusCompiler.prototype._writeCache = function () {
  // XXX #BBPBetterCache no on-disk caching yet
};

function sourceMapLength(sm) {
  if (! sm) return 0;
  // sum the length of sources and the mappings, the size of
  // metadata is ignored, but it is not a big deal
  return sm.mappings.length
       + (sm.sourcesContent || []).reduce(function (soFar, current) {
         return soFar + (current ? current.length : 0);
       }, 0);
};
<commit_msg>fix archMatching typo<commit_after>var url = Npm.require('url');
var stylus = Npm.require('stylus');
var nib = Npm.require('nib');
var Future = Npm.require('fibers/future');
var LRU = Npm.require('lru-cache');

Plugin.registerCompiler({
  extensions: ['styl'],
  archMatching: 'web'
}, function () {
  return new StylusCompiler();
});

var APP_SYMBOL = '__app__';

var CACHE_SIZE = process.env.METEOR_STYLUS_CACHE_SIZE || 1024*1024*10;

function StylusCompiler () {
  var self = this;

  self._cache = new LRU({
    max: CACHE_SIZE,
    // Cache is measured in bytes (not counting the hashes).
    length: function (value) {
      return value.css.length + sourceMapLength(value.sourceMap);
    }
  });

  self._diskCache = null;
}

StylusCompiler.prototype.processFilesForTarget = function (files) {
  var self = this;

  var currentlyCompiledFile = null;
  var currentlyCompiledPackage = null;
  var currentlyProcessedImports = null;
  var parseImportPath = function (filePath, importerPath) {
    if (! filePath) {
      throw new Error('filePath is undefined');
    }
    if (filePath === currentlyCompiledFile) {
      return {
        packageName: currentlyCompiledPackage,
        pathInPackage: '/' + currentlyCompiledFile
      };
    }
    if (! filePath.match(/^\{.*\}\//)) {
      if (! importerPath) {
        return { packageName: currentlyCompiledPackage, pathInPackage: '/' + filePath };
      }

      // relative path in the same package
      var parsedImporter = parseImportPath(importerPath, null);
      return {
        packageName: parsedImporter.packageName,
        pathInPackage: url.resolve(parsedImporter.pathInPackage, filePath)
      };
    }

    var match = /^(\{.*\})(\/.*)$/.exec(filePath);
    if (! match) { return null; }

    var packageName = match[1];
    if (!packageName || packageName === '{}')
      packageName = APP_SYMBOL;
    else
      packageName = packageName.substr(1, packageName.length - 2);

    var pathInPackage = match[2];

    return {packageName: packageName, pathInPackage: pathInPackage};
  };
  var absoluteImportPath = function (parsed) {
    return '{' + parsed.packageName + '}' + parsed.pathInPackage;
  };

  var filesByAbsoluteImportPath = {};
  files.forEach(function (inputFile) {
    var packageName = inputFile.getPackageName() || APP_SYMBOL;
    var filePath = '/' + inputFile.getPathInPackage();
    filesByAbsoluteImportPath[absoluteImportPath({
      packageName: packageName,
      pathInPackage: filePath
    })] = inputFile;
  });

  var importer = {
    find: function (importPath, paths, importerPath) {
      var parsed = parseImportPath(importPath, importerPath);

      if (! parsed) { return null; }

      var absolutePath = absoluteImportPath(parsed);

      if (! filesByAbsoluteImportPath[absolutePath]) {
        return null;
      }

      return [absolutePath];
    },
    readFile: function (filePath) {
      var parsed = parseImportPath(filePath);
      var absolutePath = absoluteImportPath(parsed);

      currentlyProcessedImports.push(absolutePath);

      if (! filesByAbsoluteImportPath[absolutePath]) throw new Error('Cannot read file ' + absolutePath);

      return filesByAbsoluteImportPath[absolutePath].getContentsAsString();
    }
  };

  function processSourcemap(sourcemap) {
    delete sourcemap.file;
    sourcemap.sourcesContent = sourcemap.sources.map(importer.readFile);
    sourcemap.sources = sourcemap.sources.map(function (filePath) {
      var parsed = parseImportPath(filePath);
      if (parsed.packageName === APP_SYMBOL)
        return parsed.pathInPackage.substr(1);
      return 'packages/' + parsed.packageName + parsed.pathInPackage;
    });

    return sourcemap;
  }

  files.forEach(function (inputFile) {
    var pathInPackage = inputFile.getPathInPackage();
    var fileOptions = inputFile.getFileOptions();

    // The heuristic is that a file is an import (ie, is not itself processed
    // as a root) if it is in a subdirectory named 'import' or if it matches
    // *.import.styl. This can be overridden in either direction via an
    // explicit `isImport` file option in apiaddFiles.
    var filenameSaysImport =
          /\.import\.styl$/.test(pathInPackage) ||
          /(?:^|\/)import\//.test(pathInPackage);
    var isImport = fileOptions.hasOwnProperty('isImport')
          ? fileOptions.isImport : filenameSaysImport;

    if (isImport) {
      return;
    }

    currentlyCompiledFile = pathInPackage;
    currentlyCompiledPackage = inputFile.getPackageName() || APP_SYMBOL;
    currentlyProcessedImports = [];

    var absolutePath = absoluteImportPath({
      packageName: currentlyCompiledPackage,
      filePath: currentlyCompiledFile
    });

    var cacheEntry = self._cache.get(absolutePath);
    if (! (cacheEntry && self._cacheEntryValid(cacheEntry, filesByAbsoluteImportPath))) {
      // the entry in the cache doesn't represent the latest state

      // Append a cache buster because Stylus has a buggy caching
      // based on the contents that produces incorrect sourcemaps (the
      // 'filename' field is not checked into cache)
      var cacheBuster = '/*random cache buster ' + Math.random() + '*/';
      var f = new Future;

      var style = stylus(inputFile.getContentsAsString() + cacheBuster)
        .use(nib())
        .set('filename', pathInPackage)
        .set('sourcemap', { inline: false, comment: false })
        .set('importer', importer);

      style.render(f.resolver());

      try {
        var css = f.wait();
      } catch (e) {
        inputFile.error({
          message: "Stylus compiler error: " + e.message
        });
        return;
      }
      var sourcemap = processSourcemap(style.sourcemap);

      cacheEntry = {
        hashes: {},
        css: css,
        sourceMap: sourcemap
      };
      cacheEntry.hashes[absolutePath] = inputFile.getSourceHash();
      currentlyProcessedImports.forEach(function (path) {
        cacheEntry.hashes[path] =
          filesByAbsoluteImportPath[path].getSourceHash();
      });

      self._cache.set(absolutePath, cacheEntry);
    }

    inputFile.addStylesheet({
      path: inputFile.getPathInPackage() + ".css",
      data: cacheEntry.css,
      sourceMap: cacheEntry.sourceMap
    });
  });

  // Rewrite the cache to disk.
  // XXX #BBPBetterCache we should just write individual entries separately.
  self._writeCache();
};

StylusCompiler.prototype._cacheEntryValid = function (cacheEntry, filesMap) {
  return Object.keys(cacheEntry.hashes).every(function (path) {
    var hash = cacheEntry.hashes[path];
    return filesMap[path] && filesMap[path].getSourceHash() === hash;
  });
};

StylusCompiler.prototype._writeCache = function () {
  // XXX #BBPBetterCache no on-disk caching yet
};

function sourceMapLength(sm) {
  if (! sm) return 0;
  // sum the length of sources and the mappings, the size of
  // metadata is ignored, but it is not a big deal
  return sm.mappings.length
       + (sm.sourcesContent || []).reduce(function (soFar, current) {
         return soFar + (current ? current.length : 0);
       }, 0);
};
<|endoftext|>


<commit_before>'use strict';

const path = require('path');
const fse = require('fs-extra');
const crypto = require('crypto');
const {
    TSError, pDelay, uniq, isString, toString
} = require('@terascope/utils');
const elasticsearchBackend = require('./backends/elasticsearch_store');
const { makeLogger } = require('../workers/helpers/terafoundation');
const { saveAsset } = require('../utils/file_utils');

// Module to manager job states in Elasticsearch.
// All functions in this module return promises that must be resolved to
// get the final result.
module.exports = async function assetsStore(context) {
    const logger = makeLogger(context, 'assets_storage');
    const config = context.sysconfig.teraslice;
    const assetsPath = config.assets_directory;
    const indexName = `${config.name}__assets`;

    const backendConfig = {
        context,
        indexName,
        recordType: 'asset',
        idField: 'id',
        fullResponse: true,
        logRecord: false,
        storageName: 'assets'
    };

    await ensureAssetDir();
    const backend = await elasticsearchBackend(backendConfig);

    async function _assetExistsInFS(id) {
        try {
            // eslint-disable-next-line no-bitwise
            const access = fse.constants.F_OK | fse.constants.R_OK | fse.constants.W_OK;
            await fse.access(path.join(assetsPath, id), access);
            return true;
        } catch (err) {
            return false;
        }
    }

    async function _assetExistsInES(id) {
        try {
            const result = await backend.get(id, null, ['id', 'name']);
            return result != null;
        } catch (err) {
            if (err.statusCode === 404) {
                return false;
            }
            throw new TSError(err, {
                reason: `Failure checking asset index, could not get asset with id: ${id}`
            });
        }
    }

    async function _assetExists(id) {
        const readable = await _assetExistsInFS(id);
        const exists = await _assetExistsInES(id);
        return readable && exists;
    }

    async function save(data) {
        try {
            const esData = data.toString('base64');
            const id = crypto.createHash('sha1').update(esData).digest('hex');

            const exists = await _assetExists(id);
            if (exists) {
                logger.info(`asset id: ${id} already exists`);
            } else {
                const metaData = await saveAsset(logger, assetsPath, id, data, _metaIsUnqiue);

                const assetRecord = Object.assign({
                    blob: esData,
                    _created: new Date().toISOString()
                }, metaData);

                await backend.indexWithId(id, assetRecord);

                logger.info(`assets: ${metaData.name}, id: ${id} has been saved to assets_directory and elasticsearch`);
            }

            return {
                assetId: id,
                created: !exists,
            };
        } catch (err) {
            return err;
        }
    }

    async function search(query, from, size, sort, fields) {
        return backend.search(query, from, size, sort, fields);
    }

    async function getAsset(id) {
        return backend.get(id);
    }

    async function _getAssetId(assetIdentifier) {
        // is full _id
        if (assetIdentifier.length === 40) {
            // need to return a promise
            return assetIdentifier;
        }

        const metaData = assetIdentifier.split(':');
        const sort = '_created:desc';
        const fields = ['version'];

        // if no version specified get latest
        if (metaData.length === 1 || metaData[1] === 'latest') {
            const assetRecord = await search(`name:"${metaData[0]}"`, null, 1, sort, fields);
            const record = assetRecord.hits.hits[0];
            if (!record) {
                throw new Error(`asset: ${metaData.join(' ')} was not found`);
            }
            return record._id;
        }

        // has wildcard in version
        const assetRecords = await search(`name:"${metaData[0]}" AND version:"${metaData[1]}"`, null, 10000, sort, fields);
        const records = assetRecords.hits.hits.map((doc) => ({
            id: doc._id,
            version: doc._source.version
        }));
        const versionID = metaData[1];
        const wildcardPlacement = versionID.indexOf('*') - 1;
        const versionTransform = versionID.split('.');
        const versionWithWildcard = versionTransform.indexOf('*');
        const versionSlice = versionTransform.filter((chars) => chars !== '*').join('.');
        if (records.length === 0) {
            throw new Error(`No asset with the provided name and version could be located, asset: ${metaData.join(':')}`);
        }

        return records.reduce((prev, curr) => _compareVersions(
            prev, curr, wildcardPlacement, versionSlice, versionWithWildcard
        )).id;
    }

    function parseAssetsArray(assetsArray) {
        return Promise.all(uniq(assetsArray).map(_getAssetId));
    }

    function _compareVersions(prev, curr, wildcardPlacement, versionSlice, versionWithWildcard) {
        const prevBool = prev.version.slice(0, wildcardPlacement) === versionSlice;
        const currBool = curr.version.slice(0, wildcardPlacement) === versionSlice;

        // if they both match up to wildcard
        if (prevBool && currBool) {
            const prevVersion = prev.version.split('.');
            const currVersion = curr.version.split('.');
            const prevParsedNumber = Number(prevVersion[versionWithWildcard]);
            const currParsedNumber = Number(currVersion[versionWithWildcard]);

            if (prevParsedNumber < currParsedNumber) {
                return curr;
            }
            return prev;
        }

        if (prevBool && !currBool) {
            return prev;
        }

        return curr;
    }

    async function _metaIsUnqiue(meta) {
        const results = await search(`name:${meta.name} AND version:${meta.version}`, null, 10000);
        if (results.hits.hits.length === 0) {
            return meta;
        }

        const error = new TSError(`asset name:${meta.name} and version:${meta.version} already exists, please increment the version and send again`, {
            statusCode: 409
        });
        error.code = 409;
        error.alreadyExists = true;
        throw error;
    }

    async function shutdown(forceShutdown) {
        logger.info('shutting asset store down.');
        return backend.shutdown(forceShutdown);
    }

    async function remove(assetId) {
        try {
            await backend.get(assetId, null, ['name']);
        } catch (err) {
            if (toString(err).indexOf('Not Found')) {
                const error = new TSError(`Unable to find asset ${assetId}`, {
                    statusCode: 404
                });
                error.code = 404;
                throw error;
            }
            throw err;
        }
        await backend.remove(assetId);
        await fse.remove(path.join(assetsPath, assetId));
    }

    async function ensureAssetDir() {
        if (!assetsPath || !isString(assetsPath)) {
            throw new Error('Asset Store requires a valid assetsPath');
        }

        try {
            return await fse.ensureDir(assetsPath);
        } catch (err) {
            throw new Error(`Failure to the ensure assets directory ${assetsPath}, for reason ${err.message}`);
        }
    }

    async function findAssetsToAutoload(autoloadDir) {
        const files = await fse.readdir(autoloadDir);

        return files.filter((fileName) => {
            const ext = path.extname(fileName);
            return ext === '.zip';
        });
    }

    async function autoload() {
        const autoloadDir = context.sysconfig.teraslice.autoload_directory;
        if (!autoloadDir || !fse.existsSync(autoloadDir)) return;

        const assets = await findAssetsToAutoload(autoloadDir);
        if (!assets || !assets.length) return;

        const promises = assets.map(async (asset, i) => {
            await pDelay(i * 100);

            logger.info(`autoloading asset ${asset}...`);
            const assetPath = path.join(autoloadDir, asset);
            try {
                const result = await save(await fse.readFile(assetPath));
                if (result.created) {
                    logger.debug(`autoloaded asset ${asset}`);
                } else {
                    logger.debug(`autoloaded asset ${asset} already exists`);
                }
            } catch (err) {
                if (err.alreadyExists) {
                    logger.debug(`autoloaded asset ${asset} already exists`);
                } else {
                    throw err;
                }
            }
        });

        await Promise.all(promises);

        logger.info('done autoloading assets');
    }

    function verifyClient() {
        return backend.verifyClient();
    }

    async function waitForClient() {
        return backend.waitForClient();
    }

    logger.info('assets storage initialized');
    return {
        save,
        search,
        get: getAsset,
        remove,
        autoload,
        parseAssetsArray,
        shutdown,
        waitForClient,
        verifyClient,
    };
};
<commit_msg>Fix an issue where the assets save function would return the error instead of throwing it<commit_after>'use strict';

const path = require('path');
const fse = require('fs-extra');
const crypto = require('crypto');
const {
    TSError, pDelay, uniq, isString, toString
} = require('@terascope/utils');
const elasticsearchBackend = require('./backends/elasticsearch_store');
const { makeLogger } = require('../workers/helpers/terafoundation');
const { saveAsset } = require('../utils/file_utils');

// Module to manager job states in Elasticsearch.
// All functions in this module return promises that must be resolved to
// get the final result.
module.exports = async function assetsStore(context) {
    const logger = makeLogger(context, 'assets_storage');
    const config = context.sysconfig.teraslice;
    const assetsPath = config.assets_directory;
    const indexName = `${config.name}__assets`;

    const backendConfig = {
        context,
        indexName,
        recordType: 'asset',
        idField: 'id',
        fullResponse: true,
        logRecord: false,
        storageName: 'assets'
    };

    await ensureAssetDir();
    const backend = await elasticsearchBackend(backendConfig);

    async function _assetExistsInFS(id) {
        try {
            // eslint-disable-next-line no-bitwise
            const access = fse.constants.F_OK | fse.constants.R_OK | fse.constants.W_OK;
            await fse.access(path.join(assetsPath, id), access);
            return true;
        } catch (err) {
            return false;
        }
    }

    async function _assetExistsInES(id) {
        try {
            const result = await backend.get(id, null, ['id', 'name']);
            return result != null;
        } catch (err) {
            if (err.statusCode === 404) {
                return false;
            }
            throw new TSError(err, {
                reason: `Failure checking asset index, could not get asset with id: ${id}`
            });
        }
    }

    async function _assetExists(id) {
        const readable = await _assetExistsInFS(id);
        const exists = await _assetExistsInES(id);
        return readable && exists;
    }

    async function save(data) {
        const esData = data.toString('base64');
        const id = crypto.createHash('sha1').update(esData).digest('hex');

        const exists = await _assetExists(id);
        if (exists) {
            logger.info(`asset id: ${id} already exists`);
        } else {
            const metaData = await saveAsset(logger, assetsPath, id, data, _metaIsUnqiue);

            const assetRecord = Object.assign({
                blob: esData,
                _created: new Date().toISOString()
            }, metaData);

            await backend.indexWithId(id, assetRecord);

            logger.info(`assets: ${metaData.name}, id: ${id} has been saved to assets_directory and elasticsearch`);
        }

        return {
            assetId: id,
            created: !exists,
        };
    }

    async function search(query, from, size, sort, fields) {
        return backend.search(query, from, size, sort, fields);
    }

    async function getAsset(id) {
        return backend.get(id);
    }

    async function _getAssetId(assetIdentifier) {
        // is full _id
        if (assetIdentifier.length === 40) {
            // need to return a promise
            return assetIdentifier;
        }

        const metaData = assetIdentifier.split(':');
        const sort = '_created:desc';
        const fields = ['version'];

        // if no version specified get latest
        if (metaData.length === 1 || metaData[1] === 'latest') {
            const assetRecord = await search(`name:"${metaData[0]}"`, null, 1, sort, fields);
            const record = assetRecord.hits.hits[0];
            if (!record) {
                throw new Error(`asset: ${metaData.join(' ')} was not found`);
            }
            return record._id;
        }

        // has wildcard in version
        const assetRecords = await search(`name:"${metaData[0]}" AND version:"${metaData[1]}"`, null, 10000, sort, fields);
        const records = assetRecords.hits.hits.map((doc) => ({
            id: doc._id,
            version: doc._source.version
        }));
        const versionID = metaData[1];
        const wildcardPlacement = versionID.indexOf('*') - 1;
        const versionTransform = versionID.split('.');
        const versionWithWildcard = versionTransform.indexOf('*');
        const versionSlice = versionTransform.filter((chars) => chars !== '*').join('.');
        if (records.length === 0) {
            throw new Error(`No asset with the provided name and version could be located, asset: ${metaData.join(':')}`);
        }

        return records.reduce((prev, curr) => _compareVersions(
            prev, curr, wildcardPlacement, versionSlice, versionWithWildcard
        )).id;
    }

    function parseAssetsArray(assetsArray) {
        return Promise.all(uniq(assetsArray).map(_getAssetId));
    }

    function _compareVersions(prev, curr, wildcardPlacement, versionSlice, versionWithWildcard) {
        const prevBool = prev.version.slice(0, wildcardPlacement) === versionSlice;
        const currBool = curr.version.slice(0, wildcardPlacement) === versionSlice;

        // if they both match up to wildcard
        if (prevBool && currBool) {
            const prevVersion = prev.version.split('.');
            const currVersion = curr.version.split('.');
            const prevParsedNumber = Number(prevVersion[versionWithWildcard]);
            const currParsedNumber = Number(currVersion[versionWithWildcard]);

            if (prevParsedNumber < currParsedNumber) {
                return curr;
            }
            return prev;
        }

        if (prevBool && !currBool) {
            return prev;
        }

        return curr;
    }

    async function _metaIsUnqiue(meta) {
        const results = await search(`name:${meta.name} AND version:${meta.version}`, null, 10000);
        if (results.hits.hits.length === 0) {
            return meta;
        }

        const error = new TSError(`asset name:${meta.name} and version:${meta.version} already exists, please increment the version and send again`, {
            statusCode: 409
        });
        error.code = 409;
        error.alreadyExists = true;
        throw error;
    }

    async function shutdown(forceShutdown) {
        logger.info('shutting asset store down.');
        return backend.shutdown(forceShutdown);
    }

    async function remove(assetId) {
        try {
            await backend.get(assetId, null, ['name']);
        } catch (err) {
            if (toString(err).indexOf('Not Found')) {
                const error = new TSError(`Unable to find asset ${assetId}`, {
                    statusCode: 404
                });
                error.code = 404;
                throw error;
            }
            throw err;
        }
        await backend.remove(assetId);
        await fse.remove(path.join(assetsPath, assetId));
    }

    async function ensureAssetDir() {
        if (!assetsPath || !isString(assetsPath)) {
            throw new Error('Asset Store requires a valid assetsPath');
        }

        try {
            return await fse.ensureDir(assetsPath);
        } catch (err) {
            throw new Error(`Failure to the ensure assets directory ${assetsPath}, for reason ${err.message}`);
        }
    }

    async function findAssetsToAutoload(autoloadDir) {
        const files = await fse.readdir(autoloadDir);

        return files.filter((fileName) => {
            const ext = path.extname(fileName);
            return ext === '.zip';
        });
    }

    async function autoload() {
        const autoloadDir = context.sysconfig.teraslice.autoload_directory;
        if (!autoloadDir || !fse.existsSync(autoloadDir)) return;

        const assets = await findAssetsToAutoload(autoloadDir);
        if (!assets || !assets.length) return;

        const promises = assets.map(async (asset, i) => {
            await pDelay(i * 100);

            logger.info(`autoloading asset ${asset}...`);
            const assetPath = path.join(autoloadDir, asset);
            try {
                const result = await save(await fse.readFile(assetPath));
                if (result.created) {
                    logger.debug(`autoloaded asset ${asset}`);
                } else {
                    logger.debug(`autoloaded asset ${asset} already exists`);
                }
            } catch (err) {
                if (err.alreadyExists) {
                    logger.debug(`autoloaded asset ${asset} already exists`);
                } else {
                    throw err;
                }
            }
        });

        await Promise.all(promises);

        logger.info('done autoloading assets');
    }

    function verifyClient() {
        return backend.verifyClient();
    }

    async function waitForClient() {
        return backend.waitForClient();
    }

    logger.info('assets storage initialized');
    return {
        save,
        search,
        get: getAsset,
        remove,
        autoload,
        parseAssetsArray,
        shutdown,
        waitForClient,
        verifyClient,
    };
};
<|endoftext|>


<commit_before>module.exports = require('../lib/kite-server-as-promised/kite-server.js');
<commit_msg>remove obsolete file<commit_after><|endoftext|>


<commit_before>/*
 * ESUI (Enterprise Simple UI)
 * Copyright 2010 Baidu Inc. All rights reserved.
 *
 * path:    esui/InputControl.js
 * desc:    输入控件基类
 * author:  erik
 */

///import esui.Control;
///import baidu.lang.inherits;

/**
 * 输入控件基类
 *
 * @class
 * @param {Object} options 初始化参数
 */
esui.InputControl = function ( options ) {
    esui.Control.call( this, options );
};

esui.InputControl.prototype = {
    /**
     * 渲染控件
     *
     * @public
     */
    render: function () {
        this.name = this.main.getAttribute( 'name' );
        esui.Control.prototype.render.call( this );
    },

    /**
     * 获取控件的值
     *
     * @public
     * @return {string}
     */
    getValue: function () {
        return this.value;
    },

    /**
     * 设置控件的值
     *
     * @public
     * @param {string} value 控件的值
     */
    setValue: function ( value ) {
        this.value = value;
    },

    /**
     * 创建Input元素
     *
     * @protected
     * @return {HTMLInputElement}
     */
    __createInput: function ( options ) {
        var tagName = options.tagName;
        var name    = options.name;
        var type    = options.type;
        var creater = tagName;
        var input;

        name && ( creater = '<' + tagName + ' name="' + this.name + '">' );
        input = document.createElement( creater );

        // 非IE浏览器不认createElement( '<input name=...' )
        if ( !input ) {
            input = document.createElement( tagName );
            name && ( input.name = name );
        }

        type && ( input.type = type );
        return input;
    }
};

baidu.inherits( esui.InputControl, esui.Control );
<commit_msg>add validate functioin<commit_after>/*
 * ESUI (Enterprise Simple UI)
 * Copyright 2010 Baidu Inc. All rights reserved.
 *
 * path:    esui/InputControl.js
 * desc:    输入控件基类
 * author:  erik
 */

///import esui.Control;
///import baidu.lang.inherits;
///import esui.validator.Rule;
///import esui.validator.Validity;
///import esui.validator.ValidityState;

/**
 * 输入控件基类
 *
 * @class
 * @param {Object} options 初始化参数
 */
esui.InputControl = function ( options ) {
    esui.Control.call( this, options );

    this._validatorMessageClass = 'ui-validator-message';

    /**
     * @inner
     */
    function addRule( ruleObj ) {
        if ( !ruleObj ) {
            return;
        }

        if ( typeof ruleObj == 'string' ) {
            rules.push( esui.validator.Rule.get( ruleObj ) );
        } else if ( ruleObj instanceof esui.validator.Rule ) {
            rules.push( ruleObj );
        } else if ( typeof ruleObj == 'object' ) {
            rules.push( new esui.validator.Rule( {
                name            : ruleObj.name,
                errorMessage    : ruleObj.errorMessage,
                check           : ruleObj.check
            } ) );
        }
    }

    // 验证规则初始化
    var rule = this.rule;
    var rules = [];
    this._rules = rules;
    if ( typeof rule == 'string' ) {
        rule = rule.split( ',' );
    }

    if ( rule instanceof Array ) {
        var ruleLen = rule.length;
        var i;

        for ( i = 0; i < ruleLen; i++ ) {
            addRule( rule[ i ] );
        }
    } else {
        addRule( rule );
    }
};

esui.InputControl.prototype = {
    /**
     * 渲染控件
     *
     * @public
     */
    render: function () {
        this.name = this.main.getAttribute( 'name' );
        esui.Control.prototype.render.call( this );
    },

    /**
     * 获取控件的值
     *
     * @public
     * @return {string}
     */
    getValue: function () {
        return this.value;
    },

    /**
     * 设置控件的值
     *
     * @public
     * @param {string} value 控件的值
     */
    setValue: function ( value ) {
        this.value = value;
    },

    /**
     * 创建Input元素
     *
     * @protected
     * @return {HTMLInputElement}
     */
    __createInput: function ( options ) {
        var tagName = options.tagName;
        var name    = options.name;
        var type    = options.type;
        var creater = tagName;
        var input;

        name && ( creater = '<' + tagName + ' name="' + this.name + '">' );
        input = document.createElement( creater );

        // 非IE浏览器不认createElement( '<input name=...' )
        if ( !input ) {
            input = document.createElement( tagName );
            name && ( input.name = name );
        }

        type && ( input.type = type );
        return input;
    },

    onbeforevalidate    : new Function(),
    onaftervalidate     : new Function(),
    oninvalid           : new Function(),

    /**
     * 验证控件
     *
     * @protected
     * @param {boolean} 是否仅验证
     * @return {boolean} 是否验证通过
     */
    __validate: function ( justCheck ) {
        var i, len, rule;
        var rules = this._rules;
        var isValid;
        var validity = new esui.validator.Validity();

        // 开始验证前事件触发
        !justCheck && this.onbeforevalidate( validity );

        // 开始验证
        for ( i = 0, len = rules.length; i < len; i++ ) {
            rule = rules[ i ];
            validity.addState( rule.getName(), rule.checkValidity( this ) );
        }

        // 验证完成后事件触发
        !justCheck && this.onaftervalidate( validity );

        // 验证失败事件触发
        isValid = validity.isValid();
        if ( !isValid ) {
            this.oninvalid( validity );
        }

        // 验证信息显示
        !justCheck && this.showValidity( validity );

        return isValid;
    },

    /**
     * 验证控件，仅返回是否验证通过
     *
     * @public
     * @return {boolean} 是否验证通过
     */
    checkValidity: function () {
        return this.__validate( true );
    },

    /**
     * 验证控件，当值不合法时显示错误信息
     *
     * @public
     * @return {boolean} 是否验证通过
     */
    validate: function () {
        return this.__validate();
    },

    /**
     * 显示验证信息
     *
     * @public
     * @param {validator.Validity} 验证信息
     */
    showValidity: function ( validity ) {
        var isValid         = validity.isValid();
        var dom             = this.__getValidMsgDom();
        var states          = validity.getStateList();
        var customMessage   = validity.getCustomMessage();
        var msg             = [];
        var i, len, state;

        if ( isValid ) {
            dom.innerHTML = '';
            baidu.hide( dom );
        } else {
            if ( customMessage ) {
                dom.innerHTML = customMessage;
            } else {
                for ( i = 0, len = states.length; i < len - 1; i++ ) {
                    state = states[ i ];
                    !state.getState() && msg.push( state.getMessage() );
                }

                dom.innerHTML = msg.join( ',' );
            }

            baidu.show( dom );
        }
    },

    /**
     * 获取显示验证信息的容器
     *
     * @public
     * @return {HTMLElement}
     */
    __getValidMsgDom: function () {
        var id = this.__getId( 'validatemessage' );
        var dom = baidu.g( id );
        var father;

        if ( !dom ) {
            dom = document.createElement( 'span' );
            dom.id = id;
            dom.className = this._validatorMessageClass;
            father = this.main.parentNode;
            father && father.insertBefore( dom, this.main.nextSibling );
        }

        return dom;
    }
};

baidu.inherits( esui.InputControl, esui.Control );
<|endoftext|>


<commit_before>METEOR_VERSION = "0.3.5";

Meteor.startup(function () {
  // XXX this is broken by the new multi-page layout.  Also, it was
  // broken before the multi-page layout because it had illegible
  // colors. Just turn it off for now. We'll fix it and turn it on
  // later.
  // prettyPrint();

  // returns a jQuery object suitable for setting scrollTop to
  // scroll the page, either directly for via animate()
  var scroller = function() {
    return $("html, body").stop();
  };

  var sections = [];
  _.each($('#main h1, #main h2, #main h3'), function (elt) {
    var classes = (elt.getAttribute('class') || '').split(/\s+/);
    if (_.indexOf(classes, "nosection") === -1)
      sections.push(elt);
  });

  for (var i = 0; i < sections.length; i++) {
    var classes = (sections[i].getAttribute('class') || '').split(/\s+/);
    if (_.indexOf(classes, "nosection") !== -1)
      continue;
    sections[i].prev = sections[i-1] || sections[i];
    sections[i].next = sections[i+1] || sections[i];
    $(sections[i]).waypoint({offset: 30});
  }
  var section = document.location.hash.substr(1) || sections[0].id;
  Session.set('section', section);
  if (section) {
    // WebKit will scroll down to the #id in the URL asynchronously
    // after the page is rendered, but Firefox won't.
    Meteor.setTimeout(function() {
      var elem = $('#'+section);
      if (elem.length)
        scroller().scrollTop(elem.offset().top);
    }, 0);
  }

  var ignore_waypoints = false;
  $('body').delegate('h1, h2, h3', 'waypoint.reached', function (evt, dir) {
    if (!ignore_waypoints) {
      var active = (dir === "up") ? this.prev : this;
      Session.set("section", active.id);
    }
  });

  $('#main, #nav').delegate("a[href^='#']", 'click', function (evt) {
    evt.preventDefault();
    var sel = $(this).attr('href');
    ignore_waypoints = true;
    Session.set("section", sel.substr(1));
    scroller().animate({
      scrollTop: $(sel).offset().top
    }, 500, 'swing', function () {
      window.location.hash = sel;
      ignore_waypoints = false;
    });
  });
});

var toc = [
  {name: "Meteor " + METEOR_VERSION, id: "top"}, [
    "Quick start",
    "Seven principles",
    "Resources"
  ],
  "Concepts", [
    "Structuring your app",
    "Data",
    "Reactivity",
    "Live HTML",
    "Templates",
    "Smart Packages",
    "Deploying"
  ],

  "API", [
    "Core", [
      "Meteor.is_client",
      "Meteor.is_server",
      "Meteor.startup"
    ],

    "Publish and subscribe", [
      "Meteor.publish", [
        {instance: "this", name: "set", id: "publish_set"},
        {instance: "this", name: "unset", id: "publish_unset"},
        {instance: "this", name: "complete", id: "publish_complete"},
        {instance: "this", name: "flush", id: "publish_flush"},
        {instance: "this", name: "onStop", id: "publish_onstop"},
        {instance: "this", name: "stop", id: "publish_stop"}
      ],
      "Meteor.subscribe",
      "Meteor.autosubscribe"
    ],

    {name: "Methods", id: "methods_header"}, [
      "Meteor.methods", [
        {instance: "this", name: "is_simulation", id: "method_is_simulation"},
        {instance: "this", name: "unblock", id: "method_unblock"}
      ],
      "Meteor.Error",
      "Meteor.call",
      "Meteor.apply"
    ],

    {name: "Server connections", id: "connections"}, [
      "Meteor.status",
      "Meteor.reconnect",
      "Meteor.connect"
    ],

    {name: "Collections", id: "collections"}, [
      "Meteor.Collection", [
        {instance: "collection", name: "find"},
        {instance: "collection", name: "findOne"},
        {instance: "collection", name: "insert"},
        {instance: "collection", name: "update"},
        {instance: "collection", name: "remove"}
      ],

      "Meteor.Collection.Cursor", [
        {instance: "cursor", name: "forEach"},
        {instance: "cursor", name: "map"},
        {instance: "cursor", name: "fetch"},
        {instance: "cursor", name: "count"},
        {instance: "cursor", name: "rewind"},
        {instance: "cursor", name: "observe"}
      ],
      {type: "spacer"},
      {name: "Selectors", style: "noncode"},
      {name: "Modifiers", style: "noncode"},
      {name: "Sort specifiers", style: "noncode"}
    ],

    "Session", [
      "Session.set",
      "Session.get",
      "Session.equals"
    ],

    "Meteor.ui", [
      "Meteor.ui.render",
      "Meteor.ui.chunk",
      "Meteor.ui.listChunk",
      "Meteor.flush",
      {type: "spacer"},
      {name: "Event maps", style: "noncode"}
    ],

    "Timers", [
      "Meteor.setTimeout",
      "Meteor.setInterval",
      "Meteor.clearTimeout",
      "Meteor.clearInterval"
    ],

    "Meteor.deps", [
      {name: "Meteor.deps.Context", id: "context"}, [
        {instance: "context", name: "run"},
        {instance: "context", name: "on_invalidate"},
        {instance: "context", name: "invalidate"}
      ],
      {name: "Meteor.deps.Context.current", id: "current"}
    // ],

    // "Environment Variables", [
    //   "Meteor.EnvironmentVariable", [
    //     {instance: "env_var", name: "get", id: "env_var_get"},
    //     {instance: "env_var", name: "withValue", id: "env_var_withvalue"},
    //     {instance: "env_var", name: "bindEnvironment", id: "env_var_bindenvironment"}
    //   ]
    ],

    "Meteor.http", [
      "Meteor.http.call",
      {name: "Meteor.http.get", id: "meteor_http_get"},
      {name: "Meteor.http.post", id: "meteor_http_post"},
      {name: "Meteor.http.put", id: "meteor_http_put"},
      {name: "Meteor.http.del", id: "meteor_http_del"}
    ]
  ],

  "Packages", [ [
    "amplify",
    "backbone",
    "bootstrap",
    "coffeescript",
    "jquery",
    "less",
    "sass",
    "stylus",
    "showdown",
    "underscore"
  ] ],

  "Command line", [ [
    "meteor help",
    "meteor run",
    "meteor create",
    "meteor deploy",
    "meteor logs",
    "meteor update",
    "meteor add",
    "meteor remove",
    "meteor list",
    "meteor mongo",
    "meteor reset",
    "meteor bundle"
  ] ]
];

var name_to_id = function (name) {
  var x = name.toLowerCase().replace(/[^a-z0-9_,.]/g, '').replace(/[,.]/g, '_');
  return x;
};

Template.nav.sections = function () {
  var ret = [];
  var walk = function (items, depth) {
    _.each(items, function (item) {
      if (item instanceof Array)
        walk(item, depth + 1);
      else {
        if (typeof(item) === "string")
          item = {name: item};
        ret.push(_.extend({
          type: "section",
          id: item.name && name_to_id(item.name) || undefined,
          depth: depth,
          style: ''
        }, item));
      }
    });
  };

  walk(toc, 1);
  return ret;
};

Template.nav.type = function (what) {
  return this.type === what;
}

Template.nav.maybe_current = function () {
  return Session.equals("section", this.id) ? "current" : "";
};

Handlebars.registerHelper('warning', function(fn) {
  return Template.warning_helper(fn(this));
});

Handlebars.registerHelper('note', function(fn) {
  return Template.note_helper(fn(this));
});

Handlebars.registerHelper('dtdd', function(name, optType, fn) {
  var type = null;
  // handle optional positional argument (messy)
  if (! fn)
    fn = optType; // two arguments
  else
    type = optType; // three arguments

  return Template.dtdd_helper(
    {descr: fn(this), name:name, type:type}, true);
});

Handlebars.registerHelper('better_markdown', function(fn) {
  var converter = new Showdown.converter();
  var input = fn(this);

  ///////
  // Make Markdown *actually* skip over block-level elements when
  // processing a string.
  //
  // Official Markdown doesn't descend into
  // block elements written out as HTML (divs, tables, etc.), BUT
  // it doesn't skip them properly either.  It assumes they are
  // either pretty-printed with their contents indented, or, failing
  // that, it just scans for a close tag with the same name, and takes
  // it regardless of whether it is the right one.  As a hack to work
  // around Markdown's hacks, we find the block-level elements
  // using a proper recursive method and rewrite them to be indented
  // with the final close tag on its own line.
  ///////

  // Open-block tag should be at beginning of line,
  // and not, say, in a string literal in example code, or in a pre block.
  // Tag must be followed by a non-word-char so that we match whole tag, not
  // eg P for PRE.  All regexes we wish to use when scanning must have
  // 'g' flag so that they respect (and set) lastIndex.
  // Assume all tags are lowercase.
  var rOpenBlockTag = /^\s{0,2}<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)(?=\W)/mg;
  var rTag = /<(\/?\w+)/g;
  var idx = 0;
  var newParts = [];
  var blockBuf = [];
  // helper function to execute regex `r` starting at idx and putting
  // the end index back into idx; accumulate the intervening string
  // into an array; and return the regex's first capturing group.
  var rcall = function(r, inBlock) {
    var lastIndex = idx;
    r.lastIndex = lastIndex;
    var match = r.exec(input);
    var result = null;
    if (! match) {
      idx = input.length;
    } else {
      idx = r.lastIndex;
      result = match[1];
    }
    (inBlock ? blockBuf : newParts).push(input.substring(lastIndex, idx));
    return result;
  };

  input = input.replace(/<!--.*?-->/g, '\n$&\n');

  var hashedBlocks = {};
  var numHashedBlocks = 0;

  var nestedTags = [];
  while (idx < input.length) {
    var blockTag = rcall(rOpenBlockTag, false);
    if (blockTag) {
      nestedTags.push(blockTag);
      while (nestedTags.length) {
        var tag = rcall(rTag, true);
        if (! tag) {
          throw new Error("Expected </"+nestedTags[nestedTags.length-1]+
                          "> but found end of string");
        } else if (tag.charAt(0) === '/') {
          // close tag
          var tagToPop = tag.substring(1);
          var tagPopped = nestedTags.pop();
          if (tagPopped !== tagToPop)
            throw new Error(("Mismatched close tag, expected </"+tagPopped+
                             "> but found </"+tagToPop+">: "+
                             input.substr(idx-50,50)+"{HERE}"+
                             input.substr(idx,50)).replace(/\n/g,'\\n'));
        } else {
          // open tag
          nestedTags.push(tag);
        }
      }
      var newBlock = blockBuf.join('');
      var openTagFinish = newBlock.indexOf('>') + 1;
      var closeTagLoc = newBlock.lastIndexOf('<');

      var key = ++numHashedBlocks;
      hashedBlocks[key] = newBlock.slice(openTagFinish, closeTagLoc);
      newParts.push(newBlock.slice(0, openTagFinish),
                    '!!!!HTML:'+key+'!!!!',
                    newBlock.slice(closeTagLoc));
      blockBuf.length = 0;
    }
  }

  var newInput = newParts.join('');
  var output = converter.makeHtml(newInput);

  output = output.replace(/!!!!HTML:(.*?)!!!!/g, function(z, a) {
    return hashedBlocks[a];
  });

  return output;
});

Handlebars.registerHelper('dstache', function() {
  return '{{';
});

Handlebars.registerHelper('tstache', function() {
  return '{{{';
});

Handlebars.registerHelper('api_section', function(id, nameFn) {
  return Template.api_section_helper(
    {name: nameFn(this), id:id}, true);
});

Handlebars.registerHelper('api_box_inline', function(box, fn) {
  return Template.api_box(_.extend(box, {body: fn(this)}), true);
});

Template.api_box.bare = function() {
  return ((this.descr && this.descr.length) ||
          (this.args && this.args.length) ||
          (this.options && this.options.length)) ? "" : "bareapi";
};

var check_links = function() {
  var body = document.body.innerHTML;

  var id_set = {};

  body.replace(/id\s*=\s*"(.*?)"/g, function(match, id) {
    if (! id) return;
    if (id_set['$'+id]) {
      console.log("ERROR: Duplicate id: "+id);
    } else {
      id_set['$'+id] = true;
    }
  });

  body.replace(/"#(.*?)"/g, function(match, frag) {
    if (! frag) return;
    if (! id_set['$'+frag]) {
      var suggestions = [];
      _.each(_.keys(id_set), function(id) {
        id = id.slice(1);
        if (id.slice(-frag.length) === frag ||
            frag.slice(-id.length) === id) {
          suggestions.push(id);
        }
      });
      var msg = "ERROR: id not found: "+frag;
      if (suggestions.length > 0) {
        msg += " -- suggest "+suggestions.join(', ');
      }
      console.log(msg);
    }
  });

  return "DONE";
};
<commit_msg>fix docs markdown again (link regression)<commit_after>METEOR_VERSION = "0.3.5";

Meteor.startup(function () {
  // XXX this is broken by the new multi-page layout.  Also, it was
  // broken before the multi-page layout because it had illegible
  // colors. Just turn it off for now. We'll fix it and turn it on
  // later.
  // prettyPrint();

  // returns a jQuery object suitable for setting scrollTop to
  // scroll the page, either directly for via animate()
  var scroller = function() {
    return $("html, body").stop();
  };

  var sections = [];
  _.each($('#main h1, #main h2, #main h3'), function (elt) {
    var classes = (elt.getAttribute('class') || '').split(/\s+/);
    if (_.indexOf(classes, "nosection") === -1)
      sections.push(elt);
  });

  for (var i = 0; i < sections.length; i++) {
    var classes = (sections[i].getAttribute('class') || '').split(/\s+/);
    if (_.indexOf(classes, "nosection") !== -1)
      continue;
    sections[i].prev = sections[i-1] || sections[i];
    sections[i].next = sections[i+1] || sections[i];
    $(sections[i]).waypoint({offset: 30});
  }
  var section = document.location.hash.substr(1) || sections[0].id;
  Session.set('section', section);
  if (section) {
    // WebKit will scroll down to the #id in the URL asynchronously
    // after the page is rendered, but Firefox won't.
    Meteor.setTimeout(function() {
      var elem = $('#'+section);
      if (elem.length)
        scroller().scrollTop(elem.offset().top);
    }, 0);
  }

  var ignore_waypoints = false;
  $('body').delegate('h1, h2, h3', 'waypoint.reached', function (evt, dir) {
    if (!ignore_waypoints) {
      var active = (dir === "up") ? this.prev : this;
      Session.set("section", active.id);
    }
  });

  $('#main, #nav').delegate("a[href^='#']", 'click', function (evt) {
    evt.preventDefault();
    var sel = $(this).attr('href');
    ignore_waypoints = true;
    Session.set("section", sel.substr(1));
    scroller().animate({
      scrollTop: $(sel).offset().top
    }, 500, 'swing', function () {
      window.location.hash = sel;
      ignore_waypoints = false;
    });
  });
});

var toc = [
  {name: "Meteor " + METEOR_VERSION, id: "top"}, [
    "Quick start",
    "Seven principles",
    "Resources"
  ],
  "Concepts", [
    "Structuring your app",
    "Data",
    "Reactivity",
    "Live HTML",
    "Templates",
    "Smart Packages",
    "Deploying"
  ],

  "API", [
    "Core", [
      "Meteor.is_client",
      "Meteor.is_server",
      "Meteor.startup"
    ],

    "Publish and subscribe", [
      "Meteor.publish", [
        {instance: "this", name: "set", id: "publish_set"},
        {instance: "this", name: "unset", id: "publish_unset"},
        {instance: "this", name: "complete", id: "publish_complete"},
        {instance: "this", name: "flush", id: "publish_flush"},
        {instance: "this", name: "onStop", id: "publish_onstop"},
        {instance: "this", name: "stop", id: "publish_stop"}
      ],
      "Meteor.subscribe",
      "Meteor.autosubscribe"
    ],

    {name: "Methods", id: "methods_header"}, [
      "Meteor.methods", [
        {instance: "this", name: "is_simulation", id: "method_is_simulation"},
        {instance: "this", name: "unblock", id: "method_unblock"}
      ],
      "Meteor.Error",
      "Meteor.call",
      "Meteor.apply"
    ],

    {name: "Server connections", id: "connections"}, [
      "Meteor.status",
      "Meteor.reconnect",
      "Meteor.connect"
    ],

    {name: "Collections", id: "collections"}, [
      "Meteor.Collection", [
        {instance: "collection", name: "find"},
        {instance: "collection", name: "findOne"},
        {instance: "collection", name: "insert"},
        {instance: "collection", name: "update"},
        {instance: "collection", name: "remove"}
      ],

      "Meteor.Collection.Cursor", [
        {instance: "cursor", name: "forEach"},
        {instance: "cursor", name: "map"},
        {instance: "cursor", name: "fetch"},
        {instance: "cursor", name: "count"},
        {instance: "cursor", name: "rewind"},
        {instance: "cursor", name: "observe"}
      ],
      {type: "spacer"},
      {name: "Selectors", style: "noncode"},
      {name: "Modifiers", style: "noncode"},
      {name: "Sort specifiers", style: "noncode"}
    ],

    "Session", [
      "Session.set",
      "Session.get",
      "Session.equals"
    ],

    "Meteor.ui", [
      "Meteor.ui.render",
      "Meteor.ui.chunk",
      "Meteor.ui.listChunk",
      "Meteor.flush",
      {type: "spacer"},
      {name: "Event maps", style: "noncode"}
    ],

    "Timers", [
      "Meteor.setTimeout",
      "Meteor.setInterval",
      "Meteor.clearTimeout",
      "Meteor.clearInterval"
    ],

    "Meteor.deps", [
      {name: "Meteor.deps.Context", id: "context"}, [
        {instance: "context", name: "run"},
        {instance: "context", name: "on_invalidate"},
        {instance: "context", name: "invalidate"}
      ],
      {name: "Meteor.deps.Context.current", id: "current"}
    // ],

    // "Environment Variables", [
    //   "Meteor.EnvironmentVariable", [
    //     {instance: "env_var", name: "get", id: "env_var_get"},
    //     {instance: "env_var", name: "withValue", id: "env_var_withvalue"},
    //     {instance: "env_var", name: "bindEnvironment", id: "env_var_bindenvironment"}
    //   ]
    ],

    "Meteor.http", [
      "Meteor.http.call",
      {name: "Meteor.http.get", id: "meteor_http_get"},
      {name: "Meteor.http.post", id: "meteor_http_post"},
      {name: "Meteor.http.put", id: "meteor_http_put"},
      {name: "Meteor.http.del", id: "meteor_http_del"}
    ]
  ],

  "Packages", [ [
    "amplify",
    "backbone",
    "bootstrap",
    "coffeescript",
    "jquery",
    "less",
    "sass",
    "stylus",
    "showdown",
    "underscore"
  ] ],

  "Command line", [ [
    "meteor help",
    "meteor run",
    "meteor create",
    "meteor deploy",
    "meteor logs",
    "meteor update",
    "meteor add",
    "meteor remove",
    "meteor list",
    "meteor mongo",
    "meteor reset",
    "meteor bundle"
  ] ]
];

var name_to_id = function (name) {
  var x = name.toLowerCase().replace(/[^a-z0-9_,.]/g, '').replace(/[,.]/g, '_');
  return x;
};

Template.nav.sections = function () {
  var ret = [];
  var walk = function (items, depth) {
    _.each(items, function (item) {
      if (item instanceof Array)
        walk(item, depth + 1);
      else {
        if (typeof(item) === "string")
          item = {name: item};
        ret.push(_.extend({
          type: "section",
          id: item.name && name_to_id(item.name) || undefined,
          depth: depth,
          style: ''
        }, item));
      }
    });
  };

  walk(toc, 1);
  return ret;
};

Template.nav.type = function (what) {
  return this.type === what;
}

Template.nav.maybe_current = function () {
  return Session.equals("section", this.id) ? "current" : "";
};

Handlebars.registerHelper('warning', function(fn) {
  return Template.warning_helper(fn(this));
});

Handlebars.registerHelper('note', function(fn) {
  return Template.note_helper(fn(this));
});

Handlebars.registerHelper('dtdd', function(name, optType, fn) {
  var type = null;
  // handle optional positional argument (messy)
  if (! fn)
    fn = optType; // two arguments
  else
    type = optType; // three arguments

  return Template.dtdd_helper(
    {descr: fn(this), name:name, type:type}, true);
});

Handlebars.registerHelper('better_markdown', function(fn) {
  var converter = new Showdown.converter();
  var input = fn(this);

  ///////
  // Make Markdown *actually* skip over block-level elements when
  // processing a string.
  //
  // Official Markdown doesn't descend into
  // block elements written out as HTML (divs, tables, etc.), BUT
  // it doesn't skip them properly either.  It assumes they are
  // either pretty-printed with their contents indented, or, failing
  // that, it just scans for a close tag with the same name, and takes
  // it regardless of whether it is the right one.  As a hack to work
  // around Markdown's hacks, we find the block-level elements
  // using a proper recursive method and rewrite them to be indented
  // with the final close tag on its own line.
  ///////

  // Open-block tag should be at beginning of line,
  // and not, say, in a string literal in example code, or in a pre block.
  // Tag must be followed by a non-word-char so that we match whole tag, not
  // eg P for PRE.  All regexes we wish to use when scanning must have
  // 'g' flag so that they respect (and set) lastIndex.
  // Assume all tags are lowercase.
  var rOpenBlockTag = /^\s{0,2}<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)(?=\W)/mg;
  var rTag = /<(\/?\w+)/g;
  var idx = 0;
  var newParts = [];
  var blockBuf = [];
  // helper function to execute regex `r` starting at idx and putting
  // the end index back into idx; accumulate the intervening string
  // into an array; and return the regex's first capturing group.
  var rcall = function(r, inBlock) {
    var lastIndex = idx;
    r.lastIndex = lastIndex;
    var match = r.exec(input);
    var result = null;
    if (! match) {
      idx = input.length;
    } else {
      idx = r.lastIndex;
      result = match[1];
    }
    (inBlock ? blockBuf : newParts).push(input.substring(lastIndex, idx));
    return result;
  };

  input = input.replace(/<!--.*?-->/g, '\n\n$&\n\n');

  var hashedBlocks = {};
  var numHashedBlocks = 0;

  var nestedTags = [];
  while (idx < input.length) {
    var blockTag = rcall(rOpenBlockTag, false);
    if (blockTag) {
      nestedTags.push(blockTag);
      while (nestedTags.length) {
        var tag = rcall(rTag, true);
        if (! tag) {
          throw new Error("Expected </"+nestedTags[nestedTags.length-1]+
                          "> but found end of string");
        } else if (tag.charAt(0) === '/') {
          // close tag
          var tagToPop = tag.substring(1);
          var tagPopped = nestedTags.pop();
          if (tagPopped !== tagToPop)
            throw new Error(("Mismatched close tag, expected </"+tagPopped+
                             "> but found </"+tagToPop+">: "+
                             input.substr(idx-50,50)+"{HERE}"+
                             input.substr(idx,50)).replace(/\n/g,'\\n'));
        } else {
          // open tag
          nestedTags.push(tag);
        }
      }
      var newBlock = blockBuf.join('');
      var openTagFinish = newBlock.indexOf('>') + 1;
      var closeTagLoc = newBlock.lastIndexOf('<');

      var key = ++numHashedBlocks;
      hashedBlocks[key] = newBlock.slice(openTagFinish, closeTagLoc);
      newParts.push(newBlock.slice(0, openTagFinish),
                    '!!!!HTML:'+key+'!!!!',
                    newBlock.slice(closeTagLoc));
      blockBuf.length = 0;
    }
  }

  var newInput = newParts.join('');
  var output = converter.makeHtml(newInput);

  output = output.replace(/!!!!HTML:(.*?)!!!!/g, function(z, a) {
    return hashedBlocks[a];
  });

  return output;
});

Handlebars.registerHelper('dstache', function() {
  return '{{';
});

Handlebars.registerHelper('tstache', function() {
  return '{{{';
});

Handlebars.registerHelper('api_section', function(id, nameFn) {
  return Template.api_section_helper(
    {name: nameFn(this), id:id}, true);
});

Handlebars.registerHelper('api_box_inline', function(box, fn) {
  return Template.api_box(_.extend(box, {body: fn(this)}), true);
});

Template.api_box.bare = function() {
  return ((this.descr && this.descr.length) ||
          (this.args && this.args.length) ||
          (this.options && this.options.length)) ? "" : "bareapi";
};

var check_links = function() {
  var body = document.body.innerHTML;

  var id_set = {};

  body.replace(/id\s*=\s*"(.*?)"/g, function(match, id) {
    if (! id) return;
    if (id_set['$'+id]) {
      console.log("ERROR: Duplicate id: "+id);
    } else {
      id_set['$'+id] = true;
    }
  });

  body.replace(/"#(.*?)"/g, function(match, frag) {
    if (! frag) return;
    if (! id_set['$'+frag]) {
      var suggestions = [];
      _.each(_.keys(id_set), function(id) {
        id = id.slice(1);
        if (id.slice(-frag.length) === frag ||
            frag.slice(-id.length) === id) {
          suggestions.push(id);
        }
      });
      var msg = "ERROR: id not found: "+frag;
      if (suggestions.length > 0) {
        msg += " -- suggest "+suggestions.join(', ');
      }
      console.log(msg);
    }
  });

  return "DONE";
};
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Switch } from 'react-router-dom';
import { IndexRoute, Route } from 'react-router';
// Styling
import 'materialize-css/bin/materialize.css';
import 'jquery/dist/jquery';
import './scss/style.scss'; // Custom styling
import './js/creategroup';
import './js/materialize';

// Routes
import App from './components/App.jsx';
import Home from './components/views/Index.jsx';
import CreateGroup from './components/views/CreateGroup.jsx';
import MessageBoard from './components/views/MessageBoard.jsx';
import PostMessage from './components/views/PostMessage.jsx';
import SignUp from './components/views/SignUp.jsx';

$(document).ready(() => {
  $('.button-collapse').sideNav();
});

ReactDOM.render(<Router>
    <Switch>
        <Route path='/' component={PostMessage}/>
        <Route path='signup' component={SignUp}/>
        <Route path='creategroup' component={SignUp}/>
        <Route path='messageboard' component={MessageBoard}/>
        <Route path='postmessage' component={PostMessage}/>
    </Switch>
  </Router>, document.getElementById('app'));

<commit_msg>change default page, for testing purposes<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Switch } from 'react-router-dom';
import { IndexRoute, Route } from 'react-router';
// Styling
import 'materialize-css/bin/materialize.css';
import 'jquery/dist/jquery';
import './scss/style.scss'; // Custom styling
import './js/creategroup';
import './js/materialize';

// Routes
import App from './components/App.jsx';
import Home from './components/views/Index.jsx';
import CreateGroup from './components/views/CreateGroup.jsx';
import MessageBoard from './components/views/MessageBoard.jsx';
import PostMessage from './components/views/PostMessage.jsx';
import SignUp from './components/views/SignUp.jsx';

$(document).ready(() => {
  $('.button-collapse').sideNav();
});

ReactDOM.render(<Router>
    <Switch>
        <Route path='/' component={CreateGroup}/>
        <Route path='signup' component={SignUp}/>
        <Route path='creategroup' component={SignUp}/>
        <Route path='messageboard' component={MessageBoard}/>
        <Route path='postmessage' component={PostMessage}/>
    </Switch>
  </Router>, document.getElementById('app'));

<|endoftext|>


<commit_before>var SECONDS_FOR_INTRO_SNIPPET = 3.;
var SECONDS_FOR_MIDDLE_SNIPPET = 3.;

var currentSound = null;
var nextSound = null;

Meteor.startup(function() {
  Session.set("isPlaying", false);          // Because there's no autoplay until a user event
  Session.set("isHoldingPlay", false);

  SC.initialize({
    client_id: "c77badb5b68bb339edd72aeb1048266c",
    redirect_uri: Meteor.absoluteUrl("server/soundcloud-callback.html")
  });

  // Set up the first track to play
  SC.stream("/tracks/293", function(sound){
    currentSound = sound;
    Session.set("currentTrack.url", sound.url);
    // Set up the next track to play
    SC.stream("/tracks/294", function(sound){
      nextSound = sound;
    });
  });
});

startTrack = function() {
/*
  // Wait until currentSound is ready
  // TODO: Don't wait indefinitely
  while(currentSound == null) { }
*/

  currentSound.options.whileplaying =
    function() {
      if (!Session.get("isHoldingPlay")) {
        if (this.position > SECONDS_FOR_INTRO_SNIPPET) {
        } else {
          // We're still at the beginning of the track
        }
      } else {
        // if end of track ..
      }
//    if (this.position > SECONDS_FOR_INTRO_SNIPPET && !Session.get("isHoldingPlay"))
//    console.log(this.position + " " + Session.get("isHoldingPlay"));
    };
  currentSound.play();
}
<commit_msg>Start finding second snippet<commit_after>var SECONDS_FOR_INTRO_SNIPPET = 3.;
var SECONDS_FOR_SECOND_SNIPPET = 3.;

var currentSound = null;
var nextSound = null;

Meteor.startup(function() {
  Session.set("isPlaying", false);          // Because there's no autoplay until a user event
  Session.set("isHoldingPlay", false);

  SC.initialize({
    client_id: "c77badb5b68bb339edd72aeb1048266c",
    redirect_uri: Meteor.absoluteUrl("server/soundcloud-callback.html")
  });

  // Set up the first track to play
  SC.stream("/tracks/293", function(sound){
    currentSound = sound;
    Session.set("currentTrack.url", sound.url);
    // Set up the next track to play
    SC.stream("/tracks/294", function(sound){
      nextSound = sound;
    });
  });
});

startTrack = function() {
/*
  // Wait until currentSound is ready
  // TODO: Don't wait indefinitely
  while(currentSound == null) { }
*/

  secondSnippetStart = null;
  currentSound.options.whileplaying =
    function() {
      if (!Session.get("isHoldingPlay")) {
        if (this.position > SECONDS_FOR_INTRO_SNIPPET) {
          if (secondSnippetStart == null) {
            // Second snippet starts at halfway into the track
            // todo: Get the duration from the soundcloud API against the track URL?
            // todo: Pick the most commented portion of the song?
            secondSnippetStart = currentSound.durationEstimate / 1000. / 2;
            secondSnippetEnd = secondSnippetStart + SECONDS_FOR_SECOND_SNIPPET
            console.log(secondSnippetStart);
          }

/*
          if (this.position < secondSnippetStart) {
            sound.seek(secondSnippetStart * 1000.);
          }
          */
        } else {
          // We're still at the beginning of the track
        }
      } else {
        // if end of track ..
      }
//    if (this.position > SECONDS_FOR_INTRO_SNIPPET && !Session.get("isHoldingPlay"))
//    console.log(this.position + " " + Session.get("isHoldingPlay"));
    };
  currentSound.play();
}
<|endoftext|>


<commit_before>var express = require('express'),
       yelp = require('yelp-fusion');
var router = express.Router();

var client;

const token = yelp.accessToken(process.env.YELP_KEY, process.env.YELP_SECRET).then(response =>{
    client = yelp.client(response.jsonBody.access_token);
  }).catch(e => {
    console.log(e);
  });

function randomGenerator (numBus) {
  return Math.floor(Math.random() * numBus);
}

function yelpS (query, lat, lon, rad, res, times) {
  client.search({
    term: query,
    latitude: lat ,
    longitude: lon ,
    radius: rad,
    categories: ("coffee"),
    limit: 50
  }).then(response => {
    const resJson = response.jsonBody;
    // Variable to check when response value found
    // Generates a random business number upto 50
    let count = resJson.businesses.length;
    if (count == 0 && times < 6) {
      console.log("expanding search radius to: " + rad);
      rad *= 2;
      times += 1;

      yelpS(query, lat, lon, rad, res, times);
    }

    let randBus = randomGenerator(count);

    for (var c = 0; c < count; c++) {
      console.log("looping: " + c);
      let randBusiness = resJson.businesses[randBus]
      // Only marks cafes with a 4 or higher rating
      if (randBusiness.rating >= 4) {
        // Returns the selected business name
        resVal = resJson.businesses[randBus].name;
        return res.status(200).json(resJson.businesses[randBus]);
      } else {
        // Loops with another randomly generated business number
        randBus = randomGenerator(count);
      }
    }
  }).catch(e => {
    // console.log(e);
    if (times < 6) {
      console.log("times run: " + times + " rad: " + rad);
      rad *= 2;
      times += 1;

      yelpS(query, lat, lon, rad, res, times);
    } else {
      return res.status(200).json({name: "Could not find :("});
    }
  });
}

router.post('/yelpSearch', (req, res) => {
  let query = req.body.data.query;
  let coords = req.body.data.coords.split(',');
  // Splits the coordinates into latitude and longitude values
  let lat = coords[0], lon = coords[1];
  // Radius of search in meters
  let rad = 9000;
  let times = 0;
  // If stay, shows radius of 500m, otherwise 6 miles
  if (req.body.data.stay) {
    rad = 250;
  } else {
    rad = 9000;
  }
  // Check to make sure query and coords got passed through
  if (query || coords === undefined) {
    yelpS(query, lat, lon, rad, res, times);
  }
})

module.exports = router;
<commit_msg>FIXED: Error handling for expanding radius<commit_after>var express = require('express'),
       yelp = require('yelp-fusion');
var router = express.Router();

var client;

const token = yelp.accessToken(process.env.YELP_KEY, process.env.YELP_SECRET).then(response =>{
    client = yelp.client(response.jsonBody.access_token);
  }).catch(e => {
    console.log(e);
  });

function randomGenerator (numBus) {
  return Math.floor(Math.random() * numBus);
}

function yelpS (query, lat, lon, rad, res, times) {
  client.search({
    term: query,
    latitude: lat ,
    longitude: lon ,
    radius: rad,
    categories: ("coffee"),
    limit: 50
  }).then(response => {
    const resJson = response.jsonBody;
    // Variable to check when response value found
    // Generates a random business number upto 50
    let count = resJson.businesses.length;
    if (count == 0 && times < 6) {
      console.log("expanding search radius to: " + rad);
      rad *= 2;
      times += 1;

      yelpS(query, lat, lon, rad, res, times);
    } else {
      return res.status(200).json({name: "Could not find :("});
    }

    let randBus = randomGenerator(count);

    for (var c = 0; c < count; c++) {
      // console.log("looping: " + c);
      let randBusiness = resJson.businesses[randBus]
      // Only marks cafes with a 4 or higher rating
      if (randBusiness.rating >= 4) {
        // Returns the selected business name
        resVal = resJson.businesses[randBus].name;
        return res.status(200).json(resJson.businesses[randBus]);
      } else {
        // Loops with another randomly generated business number
        randBus = randomGenerator(count);
      }
    }
  }).catch(e => {
    // console.log(e);
    if (times < 6) {
      // console.log("times run: " + times + " rad: " + rad);
      rad *= 2;
      times += 1;

      yelpS(query, lat, lon, rad, res, times);
    } else {
      return res.status(200).json({name: "Could not find :("});
    }
  });
}

router.post('/yelpSearch', (req, res) => {
  let query = req.body.data.query;
  let coords = req.body.data.coords.split(',');
  // Splits the coordinates into latitude and longitude values
  let lat = coords[0], lon = coords[1];
  // Radius of search in meters
  let rad = 9000;
  let times = 0;
  // If stay, shows radius of 500m, otherwise 6 miles
  if (req.body.data.stay) {
    rad = 250;
  } else {
    rad = 9000;
  }
  // Check to make sure query and coords got passed through
  if (query || coords === undefined) {
    yelpS(query, lat, lon, rad, res, times);
  }
})

module.exports = router;
<|endoftext|>


<commit_before>export let serviceName = 'navigation';
export default /*@ngInject*/ function navigation(
  $ionicHistory,
  $ionicModal,
  $q,
  $rootScope,
  $state,
  $timeout,
  R,
  state
) {
  const routes = {
    public: {
      welcome: 'public.welcome',
      cloud: 'public.cloud',
      signin: 'public.signin',
      signout: 'public.signin'
    },
    private: {
      home: 'private.home',
      cloud: 'private.cloud',
      channel: 'private.channel'
    }
  };

  const DEFAULT_PUBLIC_STATE = routes.public.welcome;
  const DEFAULT_PRIVATE_STATE = routes.private.home;

  let go = function go(stateName, parameters) {
    return $state.go(stateName, parameters);
  };

  let navigate = function navigate(viewId) {
    if (isActiveView(viewId)) {
      return $q.when();
    }

    let toHome = viewId === 'home';

    if (!toHome) {
      let channelExists = R.pipe(
        R.keys,
        R.contains(viewId)
      )(state.cloud.channels.get() || {});

      if (!channelExists) {
        return $q.when();
      }
    }

    let destination = toHome ?
      routes.private.home : routes.private.channel;
    let destinationParams = toHome ?
      undefined : { channelId: viewId };

    $ionicHistory.nextViewOptions({
      disableBack: true,
      disableAnimate: false
    });

    return go(destination, destinationParams)
      .then(() => state.save(
        state.cloud.navigation,
        ['activeViewId'],
        viewId
      ));
  };

  let isActiveView = function isActiveView(viewId) {
    return state.cloud.navigation.get('activeViewId') === viewId;
  };

  let at = function at(stateName, parameters) {
    return $state.is(stateName, parameters);
  };

  let showModal = function showModal(modalName, template, controller, scope) {
    //clean up existing modal if it was hidden instead of removed
    if (controller[modalName]) {
      controller[modalName].remove();
    }

    controller[modalName] = $ionicModal.fromTemplate(template, { scope });
    return controller[modalName].show();
  };

  let setupRedirect = function setupRedirect() {
    // redirect to routes.welcome if identity has not been initialized
    $rootScope.$on('$stateChangeStart', function(event, toState) {
      let doRedirect;
      let redirectStateName;

      if (state.cloud.identity && state.cloud.identity.get()) {
        doRedirect = !isPrivateState(toState.name);
        redirectStateName = DEFAULT_PRIVATE_STATE;
      } else {
        doRedirect = isPrivateState(toState.name);
        redirectStateName = DEFAULT_PUBLIC_STATE;
      }

      if (!doRedirect) {
        return;
      }

      event.preventDefault();
      return go(redirectStateName);
    });

    return $q.when();
  };

  let clearCache = function clearCache() {
    return $ionicHistory.clearCache();
  };

  let isPrivateState = function isPrivateState(stateName) {
    if (stateName) {
      return stateName.startsWith('private');
    }

    return $state.includes('private');
  };

  let resetHistory = function resetHistory(options = {disableAnimate: false}) {
    $ionicHistory.nextViewOptions({
      historyRoot: true,
      disableBack: true,
      disableAnimate: options.disableAnimate
    });
    return $q.when();
  };

  let initializePublic = function initializePublic() {
    let prepareNavigate = !at(routes.public.welcome) ?
      resetHistory({disableAnimate: true}) :
      $q.when();

    return prepareNavigate
      .then(() => go(routes.public.welcome))
      //workaround for too early initialization
      .then(() => $timeout(() => clearCache(), 0, false));
  };

  let initialize =
    function initializeNavigation() {
      let activeViewId = state.cloud.navigation.get('activeViewId');

      if (activeViewId === undefined) {
        return resetHistory()
          .then(() => go(DEFAULT_PRIVATE_STATE))
          .then(() => state.save(
            state.cloud.navigation,
            ['activeViewId'],
            'home'
          ));
      }

      if (activeViewId.startsWith('toc-')) {
        return resetHistory()
          .then(() => go(
            routes.private.channel,
            {channelId: activeViewId}
          ));
      }

      return resetHistory()
        .then(() => go(DEFAULT_PRIVATE_STATE));
    };

  return {
    routes,
    go,
    at,
    navigate,
    isActiveView,
    isPrivateState,
    showModal,
    clearCache,
    setupRedirect,
    resetHistory,
    initializePublic,
    initialize
  };
}
<commit_msg>Avoid growing the browser history stack in app<commit_after>export let serviceName = 'navigation';
export default /*@ngInject*/ function navigation(
  $ionicHistory,
  $ionicModal,
  $q,
  $rootScope,
  $state,
  $timeout,
  R,
  state
) {
  const routes = {
    public: {
      welcome: 'public.welcome',
      cloud: 'public.cloud',
      signin: 'public.signin',
      signout: 'public.signin'
    },
    private: {
      home: 'private.home',
      cloud: 'private.cloud',
      channel: 'private.channel'
    }
  };

  const DEFAULT_PUBLIC_STATE = routes.public.welcome;
  const DEFAULT_PRIVATE_STATE = routes.private.home;

  let go = function go(stateName, parameters) {
    let options = { location: 'replace' };
    return $state.go(stateName, parameters, options);
  };

  let navigate = function navigate(viewId) {
    if (isActiveView(viewId)) {
      return $q.when();
    }

    let toHome = viewId === 'home';

    if (!toHome) {
      let channelExists = R.pipe(
        R.keys,
        R.contains(viewId)
      )(state.cloud.channels.get() || {});

      if (!channelExists) {
        return $q.when();
      }
    }

    let destination = toHome ?
      routes.private.home : routes.private.channel;
    let destinationParams = toHome ?
      undefined : { channelId: viewId };

    $ionicHistory.nextViewOptions({
      disableBack: true,
      disableAnimate: false,
      historyRoot: true
    });

    return go(destination, destinationParams)
      .then(() => state.save(
        state.cloud.navigation,
        ['activeViewId'],
        viewId
      ));
  };

  let isActiveView = function isActiveView(viewId) {
    return state.cloud.navigation.get('activeViewId') === viewId;
  };

  let at = function at(stateName, parameters) {
    return $state.is(stateName, parameters);
  };

  let showModal = function showModal(modalName, template, controller, scope) {
    //clean up existing modal if it was hidden instead of removed
    if (controller[modalName]) {
      controller[modalName].remove();
    }

    controller[modalName] = $ionicModal.fromTemplate(template, { scope });
    return controller[modalName].show();
  };

  let setupRedirect = function setupRedirect() {
    // redirect to routes.welcome if identity has not been initialized
    $rootScope.$on('$stateChangeStart', function(event, toState) {
      let doRedirect;
      let redirectStateName;

      if (state.cloud.identity && state.cloud.identity.get()) {
        doRedirect = !isPrivateState(toState.name);
        redirectStateName = DEFAULT_PRIVATE_STATE;
      } else {
        doRedirect = isPrivateState(toState.name);
        redirectStateName = DEFAULT_PUBLIC_STATE;
      }

      if (!doRedirect) {
        return;
      }

      event.preventDefault();
      return go(redirectStateName);
    });

    return $q.when();
  };

  let clearCache = function clearCache() {
    return $ionicHistory.clearCache();
  };

  let isPrivateState = function isPrivateState(stateName) {
    if (stateName) {
      return stateName.startsWith('private');
    }

    return $state.includes('private');
  };

  let resetHistory = function resetHistory(options = {disableAnimate: false}) {
    $ionicHistory.nextViewOptions({
      historyRoot: true,
      disableBack: true,
      disableAnimate: options.disableAnimate
    });
    return $q.when();
  };

  let initializePublic = function initializePublic() {
    let prepareNavigate = !at(routes.public.welcome) ?
      resetHistory({disableAnimate: true}) :
      $q.when();

    return prepareNavigate
      .then(() => go(routes.public.welcome))
      //workaround for too early initialization
      .then(() => $timeout(() => clearCache(), 0, false));
  };

  let initialize =
    function initializeNavigation() {
      let activeViewId = state.cloud.navigation.get('activeViewId');

      if (activeViewId === undefined) {
        return resetHistory()
          .then(() => go(DEFAULT_PRIVATE_STATE))
          .then(() => state.save(
            state.cloud.navigation,
            ['activeViewId'],
            'home'
          ));
      }

      if (activeViewId.startsWith('toc-')) {
        return resetHistory()
          .then(() => go(
            routes.private.channel,
            {channelId: activeViewId}
          ));
      }

      return resetHistory()
        .then(() => go(DEFAULT_PRIVATE_STATE));
    };

  return {
    routes,
    go,
    at,
    navigate,
    isActiveView,
    isPrivateState,
    showModal,
    clearCache,
    setupRedirect,
    resetHistory,
    initializePublic,
    initialize
  };
}
<|endoftext|>


<commit_before>(function ( $ ) {

    $.fn.laravelDeleteLink = function( options ) {

        var settings = $.extend({

        }, $.fn.positive.defaults, options);

        // Setting some private variables
        var methodSpoofFieldName = '_method';
        var csrfTokenFieldName = '_token';
        var csrfToken = $('meta[name="csrf-token"]').attr('content');

        this.each(function() {
            var $deleteLink = $(this);

            // Handling click on the delete button
            $deleteLink.bind('click', function (event) {
                if ($('#deleteConfirmation').length > 0) {
                    $('#deleteConfirmation').remove();
                }

                event.preventDefault();

                var modalTitle = 'Do you want to delete this item?';
                if ($deleteLink.data('title')) {
                    modalTitle = $deleteLink.data('title');
                }

                var modalContent = 'This action can\'t be reversed!';
                if ($deleteLink.data('content')) {
                    modalContent = $deleteLink.data('content');
                }

                var methodSpoof = 'DELETE';
                if ($deleteLink.data('method')) {
                    methodSpoof = $deleteLink.data('method');
                }

                var targetUrl = $deleteLink.data('target-url');
                var $formModal = buildForm(targetUrl, modalTitle, modalContent, methodSpoof);

                $('body').append($formModal);
                $formModal.modal();
            });
        });

        function buildForm(targetUrl, modalTitle, modalContent, methodSpoof)
        {
            var $csrfField = $('<input/>')
                .attr('name', csrfTokenFieldName)
                .attr('type', 'hidden')
                .attr('value', csrfToken);
            var $methodSpoofField = $('<input/>')
                .attr('name', methodSpoofFieldName)
                .attr('type', 'hidden')
                .attr('value', methodSpoof);

            var $submitButton = $('<button></button>')
                .addClass('btn btn-danger')
                .attr('type', 'submit')
                .text('Yes, delete');
            var $cancelButton = $('<button></button>')
                .addClass('btn btn-default')
                .attr('type', 'button')
                .attr('data-dismiss', 'modal')
                .text('No, cancel');

            var $form = $('<form></form>')
                .attr('action', targetUrl)
                .attr('method', 'post')
                .append($csrfField)
                .append($methodSpoofField)
                .append($cancelButton)
                .append($submitButton);

            var $modal = buildModal($form, modalTitle, modalContent);

            return $modal;
        }

        function buildModal($form, title, content)
        {
            var $modal = $('\

 \

 \

 \

 \

' + title + '
 \

 \

 \
                                ' + content + ' \

 \

 \

 \

 \

 \
            ');

            $('.modal-footer', $modal).append($form);

            return $modal;
        }

        return this;
    };

}( jQuery ));<commit_msg>Few change in the confirm button change<commit_after>(function ( $ ) {

    $.fn.laravelDeleteLink = function( options ) {

        var settings = $.extend({

        }, $.fn.positive.defaults, options);

        // Setting some private variables
        var methodSpoofFieldName = '_method';
        var csrfTokenFieldName = '_token';
        var csrfToken = $('meta[name="csrf-token"]').attr('content');

        this.each(function() {
            var $deleteLink = $(this);

            // Handling click on the delete button
            $deleteLink.bind('click', function (event) {
                if ($('#deleteConfirmation').length > 0) {
                    $('#deleteConfirmation').remove();
                }

                event.preventDefault();

                var modalTitle = 'Do you want to delete this item?';
                if ($deleteLink.data('title')) {
                    modalTitle = $deleteLink.data('title');
                }

                var modalContent = 'This action can\'t be reversed!';
                if ($deleteLink.data('content')) {
                    modalContent = $deleteLink.data('content');
                }

                var methodSpoof = 'DELETE';
                if ($deleteLink.data('method')) {
                    methodSpoof = $deleteLink.data('method');
                }

                var targetUrl = $deleteLink.data('target-url');
                var $formModal = buildForm(targetUrl, modalTitle, modalContent, methodSpoof);

                $('body').append($formModal);
                $formModal.modal();
            });
        });

        function buildForm(targetUrl, modalTitle, modalContent, methodSpoof)
        {
            var $csrfField = $('<input/>')
                .attr('name', csrfTokenFieldName)
                .attr('type', 'hidden')
                .attr('value', csrfToken);
            var $methodSpoofField = $('<input/>')
                .attr('name', methodSpoofFieldName)
                .attr('type', 'hidden')
                .attr('value', methodSpoof);

            var $submitButton = $('<button></button>')
                .addClass('btn btn-danger')
                .attr('type', 'submit')
                .text('Yes');
            var $cancelButton = $('<button></button>')
                .addClass('btn btn-default')
                .attr('type', 'button')
                .attr('data-dismiss', 'modal')
                .text('No, cancel');

            var $form = $('<form></form>')
                .attr('action', targetUrl)
                .attr('method', 'post')
                .append($csrfField)
                .append($methodSpoofField)
                .append($cancelButton)
                .append($submitButton);

            var $modal = buildModal($form, modalTitle, modalContent);

            return $modal;
        }

        function buildModal($form, title, content)
        {
            var $modal = $('\

 \

 \

 \

 \

' + title + '
 \

 \

 \
                                ' + content + ' \

 \

 \

 \

 \

 \
            ');

            $('.modal-footer', $modal).append($form);

            return $modal;
        }

        return this;
    };

}( jQuery ));<|endoftext|>


<commit_before>/* global fixture hexToRgb assertCssPropertiesAreEqual getElementById */
describe('checkbox', () => {
  afterEach(() => {
    fixture.cleanup();
  });

  beforeEach(() => {
    fixture.load('inputs/checkbox.html');
  });

  describe('pe-checkbox-checked', () => {
    it('should match the design spec for checked', () => {
      assertCssPropertiesAreEqual(getElementById('chk-input-checked'), [
        ['height', '15px']
      ]);
    });
  });

  describe('pe-checkbox-unchecked', () => {
    it('should match the design spec for unchecked', () => {
      assertCssPropertiesAreEqual(getElementById('chk-input-unchecked'), [
        ['height', '15px']
      ]);
    });
  });

  describe('pe-checkbox-disabled', () => {
    it('should match the design spec for disabled', () => {
      assertCssPropertiesAreEqual(getElementById('chk-input-disabled'), [
        ['height', '15px']
      ]);
    });
  });

  describe('pe-checkbox-disabled-checked', () => {
    it('should match the design spec for disabled', () => {
      assertCssPropertiesAreEqual(getElementById('chk-input-disabled-checked'), [
        ['height', '22px']
      ]);
    });
  });
});

<commit_msg>Fixing unit tests<commit_after>/* global fixture hexToRgb assertCssPropertiesAreEqual getElementById */
describe('checkbox', () => {
  afterEach(() => {
    fixture.cleanup();
  });

  beforeEach(() => {
    fixture.load('inputs/checkbox.html');
  });

  describe('pe-checkbox-checked', () => {
    it('should match the design spec for checked', () => {
      assertCssPropertiesAreEqual(getElementById('chk-input-checked'), [
        ['height', '13px']
      ]);
    });
  });

  describe('pe-checkbox-unchecked', () => {
    it('should match the design spec for unchecked', () => {
      assertCssPropertiesAreEqual(getElementById('chk-input-unchecked'), [
        ['height', '13px']
      ]);
    });
  });

  describe('pe-checkbox-disabled', () => {
    it('should match the design spec for disabled', () => {
      assertCssPropertiesAreEqual(getElementById('chk-input-disabled'), [
        ['height', '13px']
      ]);
    });
  });

  describe('pe-checkbox-disabled-checked', () => {
    it('should match the design spec for disabled', () => {
      assertCssPropertiesAreEqual(getElementById('chk-input-disabled-checked'), [
        ['height', '23px']
      ]);
    });
  });
});

<|endoftext|>