<commit_before>'use strict';

var net = require('net');

var port = 11311;

var cache = {};

var server = net.createServer(function(connection) {
	console.log('Connection open');
	connection.on('data', function(data) {
		var line = String(data).trim();
		var words = line.split(' ');
		if (words.length < 2) {
			return error(connection);
		}
		var command = words[0];
		var key = words[1];
		if (command == 'get') {
			if (words.length != 2) {
				return error(connection);
			}
			if (key in cache) {
				write(connection, 'VALUE ' + key + ' ' + cache[key]);
			}
			return write(connection, 'END');
		}
		if (command == 'set') {
			if (words.length != 3)
			{
				return error(connection);
			}
			cache[key] = words[2];
			return write(connection, 'STORED');
		}
		if (command == 'delete') {
			if (key in cache) {
				delete cache[key];
				return write(connection, 'DELETED');
			}
			return write(connection, 'NOT_FOUND');
		}
	});
});

server.listen(port);
console.log('Server listening on port %s', port);

/**
 * Show an error on the given connection.
 */
function error(connection) {
	write(connection, 'ERROR');
}

function write(connection, message) {
	connection.write(message + '\r\n');
}

<commit_msg>Added command quit.<commit_after>'use strict';

var net = require('net');

var port = 11311;

var cache = {};

var server = net.createServer(function(connection) {
	console.log('Connection open');
	connection.on('data', function(data) {
		var line = String(data).trim();
		var words = line.split(' ');
		var command = words[0];
		if (command == 'quit' && words.length == 1) {
			console.log('Closing connection');
			return connection.end();
		}
		if (words.length < 2) {
			return error(connection);
		}
		var key = words[1];
		if (command == 'get') {
			if (words.length != 2) {
				return error(connection);
			}
			if (key in cache) {
				write(connection, 'VALUE ' + key + ' ' + cache[key]);
			}
			return write(connection, 'END');
		}
		if (command == 'set') {
			if (words.length != 3)
			{
				return error(connection);
			}
			cache[key] = words[2];
			return write(connection, 'STORED');
		}
		if (command == 'delete') {
			if (key in cache) {
				delete cache[key];
				return write(connection, 'DELETED');
			}
			return write(connection, 'NOT_FOUND');
		}
	});
});

server.listen(port);
console.log('Server listening on port %s', port);

/**
 * Show an error on the given connection.
 */
function error(connection) {
	write(connection, 'ERROR');
}

function write(connection, message) {
	connection.write(message + '\r\n');
}

<|endoftext|>


<commit_before>// Karma configuration
// http://karma-runner.github.io/0.12/config/configuration-file.html
// Generated on 2015-05-22 using
// generator-karma 1.0.0

module.exports = function(config) {
  'use strict';

  config.set({
    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // base path, that will be used to resolve files and exclude
    basePath: '../',

    // testing framework to use (jasmine/mocha/qunit/...)
    // as well as any additional frameworks (requirejs/chai/sinon/...)
    frameworks: [
      "jasmine",
      "sinon"
    ],

    // list of files / patterns to load in the browser
    files: [
      // bower:js
      'bower_components/es5-shim/es5-shim.js',
      'bower_components/jquery/dist/jquery.js',
      'bower_components/angular/angular.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap.js',
      'bower_components/angular-animate/angular-animate.js',
      'bower_components/angular-aria/angular-aria.js',
      'bower_components/angular-cookies/angular-cookies.js',
      'bower_components/angular-messages/angular-messages.js',
      'bower_components/angular-resource/angular-resource.js',
      'bower_components/angular-sanitize/angular-sanitize.js',
      'bower_components/angular-touch/angular-touch.js',
      'bower_components/lodash/lodash.js',
      'bower_components/restangular/dist/restangular.js',
      'bower_components/angular-ui-router/release/angular-ui-router.js',
      'bower_components/angular-jwt/dist/angular-jwt.js',
      'bower_components/angular-mocks/angular-mocks.js',
      // endbower
      "app/scripts/**/*.js",
      "test/mock/**/*.js",
      "test/spec/**/*.js"
    ],

    // list of files / patterns to exclude
    exclude: [
    ],

    // web server port
    port: 8080,

    // Start these browsers, currently available:
    // - Chrome
    // - ChromeCanary
    // - Firefox
    // - Opera
    // - Safari (only Mac)
    // - PhantomJS
    // - IE (only Windows)
    browsers: [
      "PhantomJS"
    ],

    // Which plugins to enable
    plugins: [
      "karma-phantomjs-launcher",
      "karma-chrome-launcher",
      "karma-jasmine",
      "karma-sinon"
    ],

    // Continuous Integration mode
    // if true, it capture browsers, run tests and exit
    singleRun: false,

    colors: true,

    // level of logging
    // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
    logLevel: config.LOG_INFO,

    // Uncomment the following lines if you are using grunt's server to run the tests
    // proxies: {
    //   '/': 'http://localhost:9000/'
    // },
    // URL root prevent conflicts with the site root
    // urlRoot: '_karma_'
  });
};
<commit_msg>Fixed quotes<commit_after>// Karma configuration
// http://karma-runner.github.io/0.12/config/configuration-file.html
// Generated on 2015-05-22 using
// generator-karma 1.0.0

module.exports = function(config) {
  'use strict';

  config.set({
    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // base path, that will be used to resolve files and exclude
    basePath: '../',

    // testing framework to use (jasmine/mocha/qunit/...)
    // as well as any additional frameworks (requirejs/chai/sinon/...)
    frameworks: [
      'jasmine',
      'sinon'
    ],

    // list of files / patterns to load in the browser
    files: [
      // bower:js
      'bower_components/es5-shim/es5-shim.js',
      'bower_components/jquery/dist/jquery.js',
      'bower_components/angular/angular.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap.js',
      'bower_components/angular-animate/angular-animate.js',
      'bower_components/angular-aria/angular-aria.js',
      'bower_components/angular-cookies/angular-cookies.js',
      'bower_components/angular-messages/angular-messages.js',
      'bower_components/angular-resource/angular-resource.js',
      'bower_components/angular-sanitize/angular-sanitize.js',
      'bower_components/angular-touch/angular-touch.js',
      'bower_components/lodash/lodash.js',
      'bower_components/restangular/dist/restangular.js',
      'bower_components/angular-ui-router/release/angular-ui-router.js',
      'bower_components/angular-jwt/dist/angular-jwt.js',
      'bower_components/angular-mocks/angular-mocks.js',
      // endbower
      'app/scripts/**/*.js',
      'test/mock/**/*.js',
      'test/spec/**/*.js'
    ],

    // list of files / patterns to exclude
    exclude: [
    ],

    // web server port
    port: 8080,

    // Start these browsers, currently available:
    // - Chrome
    // - ChromeCanary
    // - Firefox
    // - Opera
    // - Safari (only Mac)
    // - PhantomJS
    // - IE (only Windows)
    browsers: [
      'PhantomJS'
    ],

    // Which plugins to enable
    plugins: [
      'karma-phantomjs-launcher',
      'karma-chrome-launcher',
      'karma-jasmine',
      'karma-sinon',
      'karma-spec-reporter'
    ],

    // Continuous Integration mode
    // if true, it capture browsers, run tests and exit
    singleRun: false,

    colors: true,

    // level of logging
    // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
    logLevel: config.LOG_INFO,

    // Uncomment the following lines if you are using grunt's server to run the tests
    // proxies: {
    //   '/': 'http://localhost:9000/'
    // },
    // URL root prevent conflicts with the site root
    // urlRoot: '_karma_'
  });
};
<|endoftext|>


<commit_before>const path = require('path');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const pkg = require('../package.json');
const { findPages } = require('./src/modules/utils/find');
const { LANGUAGES, LANGUAGES_SSR } = require('./src/modules/constants');

const workspaceRoot = path.join(__dirname, '../');

const reactStrictMode = true;
if (reactStrictMode) {
  // eslint-disable-next-line no-console
  console.log(`Using React.StrictMode.`);
}
const l10nPRInNetlify = /^l10n_/.test(process.env.HEAD) && process.env.NETLIFY === 'true';
const vercelDeploy = Boolean(process.env.VERCEL);

const staging =
  process.env.REPOSITORY_URL === undefined ||
  /mui-org\/material-ui$/.test(process.env.REPOSITORY_URL);
if (staging) {
  // eslint-disable-next-line no-console
  console.log(`Staging deploy of ${process.env.REPOSITORY_URL || 'local repository'}`);
}

module.exports = {
  eslint: {
    // TODO: https://github.com/mui-org/material-ui/issues/25966
    ignoreDuringBuilds: true,
  },
  typescript: {
    // Motivated by https://github.com/zeit/next.js/issues/7687
    ignoreDevErrors: true,
    ignoreBuildErrors: true,
  },
  webpack5: true,
  webpack: (config, options) => {
    const plugins = config.plugins.slice();

    if (process.env.DOCS_STATS_ENABLED) {
      plugins.push(
        // For all options see https://github.com/th0r/webpack-bundle-analyzer#as-plugin
        new BundleAnalyzerPlugin({
          analyzerMode: 'server',
          generateStatsFile: true,
          analyzerPort: options.isServer ? 8888 : 8889,
          // Will be available at `.next/stats.json`
          statsFilename: 'stats.json',
        }),
      );
    }

    // next includes node_modules in webpack externals. Some of those have dependencies
    // on the aliases defined above. If a module is an external those aliases won't be used.
    // We need tell webpack to not consider those packages as externals.
    if (options.isServer) {
      const [nextExternals, ...externals] = config.externals;

      if (externals.length > 0) {
        // currently not the case but other next plugins might introduce additional
        // rules for externals. We would need to handle those in the callback
        throw new Error('There are other externals in the webpack config.');
      }

      config.externals = [
        (ctx, callback) => {
          const { request } = ctx;
          const hasDependencyOnRepoPackages = ['notistack', '@material-ui/data-grid'].includes(
            request,
          );

          if (hasDependencyOnRepoPackages) {
            return callback(null);
          }
          return nextExternals(ctx, callback);
        },
      ];
    }

    return {
      ...config,
      plugins,
      resolve: {
        ...config.resolve,
        // resolve .tsx first
        extensions: [
          '.tsx',
          ...config.resolve.extensions.filter((extension) => extension !== '.tsx'),
        ],
      },
      module: {
        ...config.module,
        rules: config.module.rules.concat([
          {
            test: /\.md$/,
            oneOf: [
              {
                resourceQuery: /@mui\/markdown/,
                use: require.resolve('@mui/markdown/loader'),
              },
              {
                // used in some /getting-started/templates
                type: 'asset/source',
              },
            ],
          },
          // transpile 3rd party packages with dependencies in this repository
          {
            test: /\.(js|mjs|jsx)$/,
            include: /node_modules(\/|\\)(notistack|@material-ui(\/|\\)data-grid)/,
            use: {
              loader: 'babel-loader',
              options: {
                // on the server we use the transpiled commonJS build, on client ES6 modules
                // babel needs to figure out in what context to parse the file
                sourceType: 'unambiguous',
                plugins: [
                  [
                    'babel-plugin-module-resolver',
                    {
                      alias: {
                        // all packages in this monorepo
                        '@mui/material': '../packages/mui-material/src',
                        '@mui/docs': '../packages/mui-docs/src',
                        '@mui/icons-material': '../packages/mui-icons-material/lib',
                        '@mui/lab': '../packages/mui-lab/src',
                        '@mui/styled-engine': '../packages/mui-styled-engine/src',
                        '@mui/styles': '../packages/mui-styles/src',
                        '@mui/system': '../packages/mui-system/src',
                        '@mui/private-theming': '../packages/mui-private-theming/src',
                        '@mui/utils': '../packages/mui-utils/src',
                        '@mui/core': '../packages/mui-core/src',
                        // all legacy package names in this monorepo
                        '@material-ui/core': '../packages/mui-material/src',
                        '@material-ui/docs': '../packages/mui-docs/src',
                        '@material-ui/icons': '../packages/mui-icons-material/lib',
                        '@material-ui/lab': '../packages/mui-lab/src',
                        '@material-ui/styled-engine': '../packages/mui-styled-engine/src',
                        '@material-ui/styles': '../packages/mui-styles/src',
                        '@material-ui/system': '../packages/mui-system/src',
                        '@material-ui/private-theming': '../packages/mui-private-theming/src',
                        '@material-ui/utils': '../packages/mui-utils/src',
                        '@material-ui/unstyled': '../packages/mui-core/src',
                        '@material-ui/core/*': '../packages/mui-material/src/*',
                      },
                      transformFunctions: ['require'],
                    },
                  ],
                ],
              },
            },
          },
          // required to transpile ../packages/
          {
            test: /\.(js|mjs|tsx|ts)$/,
            include: [workspaceRoot],
            exclude: /(node_modules|mui-icons-material)/,
            use: options.defaultLoaders.babel,
          },
        ]),
      },
    };
  },
  trailingSlash: true,
  env: {
    COMMIT_REF: process.env.COMMIT_REF,
    ENABLE_AD: process.env.ENABLE_AD,
    GITHUB_AUTH: process.env.GITHUB_AUTH,
    GIT_REVIEW_ID: process.env.REVIEW_ID,
    LIB_VERSION: pkg.version,
    NETLIFY_DEPLOY_URL: process.env.DEPLOY_URL || 'http://localhost:3000',
    NETLIFY_SITE_NAME: process.env.SITE_NAME || 'material-ui',
    PULL_REQUEST: process.env.PULL_REQUEST === 'true',
    REACT_STRICT_MODE: reactStrictMode,
    FEEDBACK_URL: process.env.FEEDBACK_URL,
    // #default-branch-switch
    SOURCE_CODE_ROOT_URL: 'https://github.com/mui-org/material-ui/blob/next',
    SOURCE_CODE_REPO: 'https://github.com/mui-org/material-ui',
    STAGING: staging,
  },
  // Next.js provides a `defaultPathMap` argument, we could simplify the logic.
  // However, we don't in order to prevent any regression in the `findPages()` method.
  exportPathMap: () => {
    const pages = findPages();
    const map = {};

    function traverse(pages2, userLanguage) {
      const prefix = userLanguage === 'en' ? '' : `/${userLanguage}`;

      pages2.forEach((page) => {
        if (!page.children) {
          map[`${prefix}${page.pathname.replace(/^\/api-docs\/(.*)/, '/api/$1')}`] = {
            page: page.pathname,
            query: {
              userLanguage,
            },
          };
          return;
        }

        traverse(page.children, userLanguage);
      });
    }

    // We want to speed-up the build of pull requests.
    // For crowdin PRs we want to build all locales for testing.
    if (process.env.PULL_REQUEST === 'true' && !l10nPRInNetlify && !vercelDeploy) {
      // eslint-disable-next-line no-console
      console.log('Considering only English for SSR');
      traverse(pages, 'en');
    } else {
      // eslint-disable-next-line no-console
      console.log('Considering various locales for SSR');
      LANGUAGES_SSR.forEach((userLanguage) => {
        traverse(pages, userLanguage);
      });
    }

    return map;
  },
  reactStrictMode,
  async rewrites() {
    return [{ source: `/:lang(${LANGUAGES.join('|')})?/:rest*`, destination: '/:rest*' }];
  },
};
<commit_msg>[website] Disable Next.js font optimization (#28128)<commit_after>const path = require('path');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const pkg = require('../package.json');
const { findPages } = require('./src/modules/utils/find');
const { LANGUAGES, LANGUAGES_SSR } = require('./src/modules/constants');

const workspaceRoot = path.join(__dirname, '../');

const reactStrictMode = true;
if (reactStrictMode) {
  // eslint-disable-next-line no-console
  console.log(`Using React.StrictMode.`);
}
const l10nPRInNetlify = /^l10n_/.test(process.env.HEAD) && process.env.NETLIFY === 'true';
const vercelDeploy = Boolean(process.env.VERCEL);

const staging =
  process.env.REPOSITORY_URL === undefined ||
  /mui-org\/material-ui$/.test(process.env.REPOSITORY_URL);
if (staging) {
  // eslint-disable-next-line no-console
  console.log(`Staging deploy of ${process.env.REPOSITORY_URL || 'local repository'}`);
}

module.exports = {
  eslint: {
    // TODO: https://github.com/mui-org/material-ui/issues/25966
    ignoreDuringBuilds: true,
  },
  typescript: {
    // Motivated by https://github.com/zeit/next.js/issues/7687
    ignoreDevErrors: true,
    ignoreBuildErrors: true,
  },
  webpack5: true,
  webpack: (config, options) => {
    const plugins = config.plugins.slice();

    if (process.env.DOCS_STATS_ENABLED) {
      plugins.push(
        // For all options see https://github.com/th0r/webpack-bundle-analyzer#as-plugin
        new BundleAnalyzerPlugin({
          analyzerMode: 'server',
          generateStatsFile: true,
          analyzerPort: options.isServer ? 8888 : 8889,
          // Will be available at `.next/stats.json`
          statsFilename: 'stats.json',
        }),
      );
    }

    // next includes node_modules in webpack externals. Some of those have dependencies
    // on the aliases defined above. If a module is an external those aliases won't be used.
    // We need tell webpack to not consider those packages as externals.
    if (options.isServer) {
      const [nextExternals, ...externals] = config.externals;

      if (externals.length > 0) {
        // currently not the case but other next plugins might introduce additional
        // rules for externals. We would need to handle those in the callback
        throw new Error('There are other externals in the webpack config.');
      }

      config.externals = [
        (ctx, callback) => {
          const { request } = ctx;
          const hasDependencyOnRepoPackages = ['notistack', '@material-ui/data-grid'].includes(
            request,
          );

          if (hasDependencyOnRepoPackages) {
            return callback(null);
          }
          return nextExternals(ctx, callback);
        },
      ];
    }

    return {
      ...config,
      plugins,
      resolve: {
        ...config.resolve,
        // resolve .tsx first
        extensions: [
          '.tsx',
          ...config.resolve.extensions.filter((extension) => extension !== '.tsx'),
        ],
      },
      module: {
        ...config.module,
        rules: config.module.rules.concat([
          {
            test: /\.md$/,
            oneOf: [
              {
                resourceQuery: /@mui\/markdown/,
                use: require.resolve('@mui/markdown/loader'),
              },
              {
                // used in some /getting-started/templates
                type: 'asset/source',
              },
            ],
          },
          // transpile 3rd party packages with dependencies in this repository
          {
            test: /\.(js|mjs|jsx)$/,
            include: /node_modules(\/|\\)(notistack|@material-ui(\/|\\)data-grid)/,
            use: {
              loader: 'babel-loader',
              options: {
                // on the server we use the transpiled commonJS build, on client ES6 modules
                // babel needs to figure out in what context to parse the file
                sourceType: 'unambiguous',
                plugins: [
                  [
                    'babel-plugin-module-resolver',
                    {
                      alias: {
                        // all packages in this monorepo
                        '@mui/material': '../packages/mui-material/src',
                        '@mui/docs': '../packages/mui-docs/src',
                        '@mui/icons-material': '../packages/mui-icons-material/lib',
                        '@mui/lab': '../packages/mui-lab/src',
                        '@mui/styled-engine': '../packages/mui-styled-engine/src',
                        '@mui/styles': '../packages/mui-styles/src',
                        '@mui/system': '../packages/mui-system/src',
                        '@mui/private-theming': '../packages/mui-private-theming/src',
                        '@mui/utils': '../packages/mui-utils/src',
                        '@mui/core': '../packages/mui-core/src',
                        // all legacy package names in this monorepo
                        '@material-ui/core': '../packages/mui-material/src',
                        '@material-ui/docs': '../packages/mui-docs/src',
                        '@material-ui/icons': '../packages/mui-icons-material/lib',
                        '@material-ui/lab': '../packages/mui-lab/src',
                        '@material-ui/styled-engine': '../packages/mui-styled-engine/src',
                        '@material-ui/styles': '../packages/mui-styles/src',
                        '@material-ui/system': '../packages/mui-system/src',
                        '@material-ui/private-theming': '../packages/mui-private-theming/src',
                        '@material-ui/utils': '../packages/mui-utils/src',
                        '@material-ui/unstyled': '../packages/mui-core/src',
                        '@material-ui/core/*': '../packages/mui-material/src/*',
                      },
                      transformFunctions: ['require'],
                    },
                  ],
                ],
              },
            },
          },
          // required to transpile ../packages/
          {
            test: /\.(js|mjs|tsx|ts)$/,
            include: [workspaceRoot],
            exclude: /(node_modules|mui-icons-material)/,
            use: options.defaultLoaders.babel,
          },
        ]),
      },
    };
  },
  trailingSlash: true,
  env: {
    COMMIT_REF: process.env.COMMIT_REF,
    ENABLE_AD: process.env.ENABLE_AD,
    GITHUB_AUTH: process.env.GITHUB_AUTH,
    GIT_REVIEW_ID: process.env.REVIEW_ID,
    LIB_VERSION: pkg.version,
    NETLIFY_DEPLOY_URL: process.env.DEPLOY_URL || 'http://localhost:3000',
    NETLIFY_SITE_NAME: process.env.SITE_NAME || 'material-ui',
    PULL_REQUEST: process.env.PULL_REQUEST === 'true',
    REACT_STRICT_MODE: reactStrictMode,
    FEEDBACK_URL: process.env.FEEDBACK_URL,
    // #default-branch-switch
    SOURCE_CODE_ROOT_URL: 'https://github.com/mui-org/material-ui/blob/next',
    SOURCE_CODE_REPO: 'https://github.com/mui-org/material-ui',
    STAGING: staging,
  },
  // Next.js provides a `defaultPathMap` argument, we could simplify the logic.
  // However, we don't in order to prevent any regression in the `findPages()` method.
  exportPathMap: () => {
    const pages = findPages();
    const map = {};

    function traverse(pages2, userLanguage) {
      const prefix = userLanguage === 'en' ? '' : `/${userLanguage}`;

      pages2.forEach((page) => {
        if (!page.children) {
          map[`${prefix}${page.pathname.replace(/^\/api-docs\/(.*)/, '/api/$1')}`] = {
            page: page.pathname,
            query: {
              userLanguage,
            },
          };
          return;
        }

        traverse(page.children, userLanguage);
      });
    }

    // We want to speed-up the build of pull requests.
    // For crowdin PRs we want to build all locales for testing.
    if (process.env.PULL_REQUEST === 'true' && !l10nPRInNetlify && !vercelDeploy) {
      // eslint-disable-next-line no-console
      console.log('Considering only English for SSR');
      traverse(pages, 'en');
    } else {
      // eslint-disable-next-line no-console
      console.log('Considering various locales for SSR');
      LANGUAGES_SSR.forEach((userLanguage) => {
        traverse(pages, userLanguage);
      });
    }

    return map;
  },
  reactStrictMode,
  async rewrites() {
    return [{ source: `/:lang(${LANGUAGES.join('|')})?/:rest*`, destination: '/:rest*' }];
  },
  // Can be turned on when https://github.com/vercel/next.js/issues/24640 is fixed
  optimizeFonts: false,
};
<|endoftext|>


<commit_before>import { NotFoundError, isDefined } from 'kinvey-node-sdk/dist/export';
import map from 'lodash/map';
import forEach from 'lodash/forEach';
import isArray from 'lodash/isArray';
import isFunction from 'lodash/isFunction';
import isString from 'lodash/isString';
const idAttribute = process.env.KINVEY_ID_ATTRIBUTE || '_id';
const masterCollectionName = 'sqlite_master';
const size = 5 * 1000 * 1000; // Database size in bytes
let dbCache = {};
let isSupported;

class WebSQL {
  constructor(name = 'kinvey') {
    if (isDefined(name) === false) {
      throw new Error('A name is required to use the IndexedDB adapter.', name);
    }

    if (isString(name) === false) {
      throw new Error('The name must be a string to use the IndexedDB adapter', name);
    }

    this.name = name;
  }

  openDatabase() {
    let db = dbCache[this.name];

    if (!db) {
      db = global.openDatabase(this.name, 1, 'Kinvey Cache', size);
      dbCache[this.name] = db;
    }

    return db;
  }

  openTransaction(collection, query, parameters, write = false) {
    const db = this.openDatabase();
    const escapedCollection = `"${collection}"`;
    const isMaster = collection === masterCollectionName;
    const isMulti = isArray(query);
    query = isMulti ? query : [[query, parameters]];

    const promise = new Promise((resolve, reject) => {
      const writeTxn = write || !isFunction(db.readTransaction);
      db[writeTxn ? 'transaction' : 'readTransaction']((tx) => {
        if (write && !isMaster) {
          tx.executeSql(`CREATE TABLE IF NOT EXISTS ${escapedCollection} ` +
            '(key BLOB PRIMARY KEY NOT NULL, value BLOB NOT NULL)');
        }

        let pending = query.length;
        const responses = [];

        if (pending === 0) {
          resolve(isMulti ? responses : responses.shift());
        } else {
          forEach(query, (parts) => {
            const sql = parts[0].replace('#{collection}', escapedCollection);

            tx.executeSql(sql, parts[1], (_, resultSet) => {
              const response = {
                rowCount: resultSet.rowsAffected,
                result: []
              };

              if (resultSet.rows.length) {
                for (let i = 0, len = resultSet.rows.length; i < len; i += 1) {
                  try {
                    const value = resultSet.rows.item(i).value;
                    const entity = isMaster ? value : JSON.parse(value);
                    response.result.push(entity);
                  } catch (error) {
                    // Catch the error
                  }
                }
              }

              responses.push(response);
              pending -= 1;

              if (pending === 0) {
                resolve(isMulti ? responses : responses.shift());
              }
            });
          });
        }
      }, (error) => {
        error = isString(error) ? error : error.message;

        if (error && error.indexOf('no such table') === -1) {
          return reject(new NotFoundError(`The ${collection} collection was not found on`
            + ` the ${this.name} WebSQL database.`));
        }

        const query = 'SELECT name AS value from #{collection} WHERE type = ? AND name = ?';
        const parameters = ['table', collection];

        return this.openTransaction(masterCollectionName, query, parameters).then((response) => {
          if (response.result.length === 0) {
            return reject(new NotFoundError(`The ${collection} collection was not found on`
              + ` the ${this.name} WebSQL database.`));
          }

          return reject(new Error(`Unable to open a transaction for the ${collection}`
            + ` collection on the ${this.name} WebSQL database.`));
        }).catch((error) => {
          reject(new Error(`Unable to open a transaction for the ${collection}`
            + ` collection on the ${this.name} WebSQL database.`, error));
        });
      });
    });

    return promise;
  }

  find(collection) {
    const sql = 'SELECT value FROM #{collection}';
    return this.openTransaction(collection, sql, [])
      .then(response => response.result);
  }

  findById(collection, id) {
    const sql = 'SELECT value FROM #{collection} WHERE key = ?';
    return this.openTransaction(collection, sql, [id])
      .then(response => response.result)
      .then((entities) => {
        if (entities.length === 0) {
          throw new NotFoundError(`An entity with _id = ${id} was not found in the ${collection}`
            + ` collection on the ${this.name} WebSQL database.`);
        }

        return entities[0];
      });
  }

  save(collection, entities) {
    const queries = [];
    let singular = false;

    if (!isArray(entities)) {
      singular = true;
      entities = [entities];
    }

    if (entities.length === 0) {
      return Promise.resolve(null);
    }

    entities = map(entities, (entity) => {
      queries.push([
        'REPLACE INTO #{collection} (key, value) VALUES (?, ?)',
        [entity[idAttribute], JSON.stringify(entity)]
      ]);

      return entity;
    });

    return this.openTransaction(collection, queries, null, true)
      .then(() => (singular ? entities[0] : entities));
  }

  removeById(collection, id) {
    const queries = [
      ['SELECT value FROM #{collection} WHERE key = ?', [id]],
      ['DELETE FROM #{collection} WHERE key = ?', [id]],
    ];
    return this.openTransaction(collection, queries, null, true)
      .then((response) => {
        const entities = response[0].result;
        let count = response[1].rowCount;
        count = count || entities.length;

        if (count === 0) {
          throw new NotFoundError(`An entity with _id = ${id} was not found in the ${collection}`
            + ` collection on the ${this.name} WebSQL database.`);
        }

        return entities[0];
      });
  }

  clear() {
    return this.openTransaction(
      masterCollectionName,
      'SELECT name AS value FROM #{collection} WHERE type = ?',
      ['table'],
      false
    )
      .then(response => response.result)
      .then((tables) => {
        // If there are no tables, return.
        if (tables.length === 0) {
          return null;
        }

        // Drop all tables. Filter tables first to avoid attempting to delete
        // system tables (which will fail).
        const queries = tables
          .filter(table => (/^[a-zA-Z0-9-]{1,128}/).test(table))
          .map(table => [`DROP TABLE IF EXISTS '${table}'`]);
        return this.openTransaction(masterCollectionName, queries, null, true);
      })
      .then(() => {
        dbCache = {};
        return null;
      });
  }
}

export default {
  load(name) {
    const db = new WebSQL(name);

    if (isDefined(global.openDatabase) === false) {
      return Promise.resolve(undefined);
    }

    if (isDefined(isSupported)) {
      if (isSupported) {
        return Promise.resolve(db);
      }

      return Promise.resolve(undefined);
    }

    return db.save('__testSupport', { _id: '1' })
      .then(() => {
        isSupported = true;
        return db;
      })
      .catch(() => {
        isSupported = false;
        return undefined;
      });
  }
};
<commit_msg>Replace IndexedDB with WebSQL in error message<commit_after>import { NotFoundError, isDefined } from 'kinvey-node-sdk/dist/export';
import map from 'lodash/map';
import forEach from 'lodash/forEach';
import isArray from 'lodash/isArray';
import isFunction from 'lodash/isFunction';
import isString from 'lodash/isString';
const idAttribute = process.env.KINVEY_ID_ATTRIBUTE || '_id';
const masterCollectionName = 'sqlite_master';
const size = 5 * 1000 * 1000; // Database size in bytes
let dbCache = {};
let isSupported;

class WebSQL {
  constructor(name = 'kinvey') {
    if (isDefined(name) === false) {
      throw new Error('A name is required to use the WebSQL adapter.', name);
    }

    if (isString(name) === false) {
      throw new Error('The name must be a string to use the WebSQL adapter', name);
    }

    this.name = name;
  }

  openDatabase() {
    let db = dbCache[this.name];

    if (!db) {
      db = global.openDatabase(this.name, 1, 'Kinvey Cache', size);
      dbCache[this.name] = db;
    }

    return db;
  }

  openTransaction(collection, query, parameters, write = false) {
    const db = this.openDatabase();
    const escapedCollection = `"${collection}"`;
    const isMaster = collection === masterCollectionName;
    const isMulti = isArray(query);
    query = isMulti ? query : [[query, parameters]];

    const promise = new Promise((resolve, reject) => {
      const writeTxn = write || !isFunction(db.readTransaction);
      db[writeTxn ? 'transaction' : 'readTransaction']((tx) => {
        if (write && !isMaster) {
          tx.executeSql(`CREATE TABLE IF NOT EXISTS ${escapedCollection} ` +
            '(key BLOB PRIMARY KEY NOT NULL, value BLOB NOT NULL)');
        }

        let pending = query.length;
        const responses = [];

        if (pending === 0) {
          resolve(isMulti ? responses : responses.shift());
        } else {
          forEach(query, (parts) => {
            const sql = parts[0].replace('#{collection}', escapedCollection);

            tx.executeSql(sql, parts[1], (_, resultSet) => {
              const response = {
                rowCount: resultSet.rowsAffected,
                result: []
              };

              if (resultSet.rows.length) {
                for (let i = 0, len = resultSet.rows.length; i < len; i += 1) {
                  try {
                    const value = resultSet.rows.item(i).value;
                    const entity = isMaster ? value : JSON.parse(value);
                    response.result.push(entity);
                  } catch (error) {
                    // Catch the error
                  }
                }
              }

              responses.push(response);
              pending -= 1;

              if (pending === 0) {
                resolve(isMulti ? responses : responses.shift());
              }
            });
          });
        }
      }, (error) => {
        error = isString(error) ? error : error.message;

        if (error && error.indexOf('no such table') === -1) {
          return reject(new NotFoundError(`The ${collection} collection was not found on`
            + ` the ${this.name} WebSQL database.`));
        }

        const query = 'SELECT name AS value from #{collection} WHERE type = ? AND name = ?';
        const parameters = ['table', collection];

        return this.openTransaction(masterCollectionName, query, parameters).then((response) => {
          if (response.result.length === 0) {
            return reject(new NotFoundError(`The ${collection} collection was not found on`
              + ` the ${this.name} WebSQL database.`));
          }

          return reject(new Error(`Unable to open a transaction for the ${collection}`
            + ` collection on the ${this.name} WebSQL database.`));
        }).catch((error) => {
          reject(new Error(`Unable to open a transaction for the ${collection}`
            + ` collection on the ${this.name} WebSQL database.`, error));
        });
      });
    });

    return promise;
  }

  find(collection) {
    const sql = 'SELECT value FROM #{collection}';
    return this.openTransaction(collection, sql, [])
      .then(response => response.result);
  }

  findById(collection, id) {
    const sql = 'SELECT value FROM #{collection} WHERE key = ?';
    return this.openTransaction(collection, sql, [id])
      .then(response => response.result)
      .then((entities) => {
        if (entities.length === 0) {
          throw new NotFoundError(`An entity with _id = ${id} was not found in the ${collection}`
            + ` collection on the ${this.name} WebSQL database.`);
        }

        return entities[0];
      });
  }

  save(collection, entities) {
    const queries = [];
    let singular = false;

    if (!isArray(entities)) {
      singular = true;
      entities = [entities];
    }

    if (entities.length === 0) {
      return Promise.resolve(null);
    }

    entities = map(entities, (entity) => {
      queries.push([
        'REPLACE INTO #{collection} (key, value) VALUES (?, ?)',
        [entity[idAttribute], JSON.stringify(entity)]
      ]);

      return entity;
    });

    return this.openTransaction(collection, queries, null, true)
      .then(() => (singular ? entities[0] : entities));
  }

  removeById(collection, id) {
    const queries = [
      ['SELECT value FROM #{collection} WHERE key = ?', [id]],
      ['DELETE FROM #{collection} WHERE key = ?', [id]],
    ];
    return this.openTransaction(collection, queries, null, true)
      .then((response) => {
        const entities = response[0].result;
        let count = response[1].rowCount;
        count = count || entities.length;

        if (count === 0) {
          throw new NotFoundError(`An entity with _id = ${id} was not found in the ${collection}`
            + ` collection on the ${this.name} WebSQL database.`);
        }

        return entities[0];
      });
  }

  clear() {
    return this.openTransaction(
      masterCollectionName,
      'SELECT name AS value FROM #{collection} WHERE type = ?',
      ['table'],
      false
    )
      .then(response => response.result)
      .then((tables) => {
        // If there are no tables, return.
        if (tables.length === 0) {
          return null;
        }

        // Drop all tables. Filter tables first to avoid attempting to delete
        // system tables (which will fail).
        const queries = tables
          .filter(table => (/^[a-zA-Z0-9-]{1,128}/).test(table))
          .map(table => [`DROP TABLE IF EXISTS '${table}'`]);
        return this.openTransaction(masterCollectionName, queries, null, true);
      })
      .then(() => {
        dbCache = {};
        return null;
      });
  }
}

export default {
  load(name) {
    const db = new WebSQL(name);

    if (isDefined(global.openDatabase) === false) {
      return Promise.resolve(undefined);
    }

    if (isDefined(isSupported)) {
      if (isSupported) {
        return Promise.resolve(db);
      }

      return Promise.resolve(undefined);
    }

    return db.save('__testSupport', { _id: '1' })
      .then(() => {
        isSupported = true;
        return db;
      })
      .catch(() => {
        isSupported = false;
        return undefined;
      });
  }
};
<|endoftext|>


<commit_before>var kafka = require('kafka-node')
  , redis = require('redis')
  , xxhash = require('xxhashjs')
  , path = require('path')
  , WebSocketServer = require('ws').Server
  , env = process.env.NODE_ENV || 'dev'
  , config = require('../config')[env];

var redisClient = redis.createClient(
  config.redis.port,
  config.redis.host);

var connString = config.zookeeper.host + ':' + config.zookeeper.port;
var kafkaClient = new kafka.Client(connString);

// read messages for topic
exports.consume = function (topic, cb) {
  var options = {
    autoCommit: false,
    fromBeginning: false,
    fetchMaxWaitMs: 1000,
    fetchMaxBytes: 1024*1024
  };

  // use default partitions
  var topics = [
    { topic: topic, partition: 0 },
    { topic: topic, partition: 1 }
  ];

  var consumer = new kafka.Consumer(kafkaClient, topics, options);
  var offset = new kafka.Offset(kafkaClient);

  consumer.on('message', cb);

  consumer.on('error', function (err) {
    throw err;
  });

  // recompute offset
  consumer.on('offsetOutOfRange', function (topic) {
    topic.maxNum = 2;

    offset.fetch([topic], function (err, offsets) {
      var min = Math.min.apply(null, offsets[topic.topic][topic.partition]);
      consumer.setOffset(topic.topic, topic.partition, min);
    });
  });

  return consumer;
};

exports.produce = function (topic, message, cb) {
  var producer = new kafka.Producer(kafkaClient);

  producer.send([{ messages: [message], topic: topic, parition: 0 }], cb);
};

// regsiter a query as a new kafka topic
exports.register = function (topic, cb) {
  var producer = new kafka.Producer(kafkaClient);

  producer.createTopics([topic], false, cb);
};

exports.initialize = function (app, server) {

  // web socket setup
  var wss = new WebSocketServer({
    server: server,
    clientTracking: true,
    path: '/alert'
  });

  // alerts are stored in database 0
  redisClient.select(0, function () {
    // TODO: read saved topics / Dashboards from Redis / Elasticsearch
    exports.register('opensoc', function () {
      console.log('Registered topic: opensoc');

      exports.consume('opensoc', function (message) {
        // each alert needs a unique identifier to determine if we've read it
        var toHash = message.topic + ':' +
          message.offset + ':' +
          message.partition + ':' +
          message.value;
        var key = xxhash(toHash, 1).toString(16);
        var countKey = 'alert-count';
        var timestampKey = 'alert-timestamp';
        var valueKey = 'alert-value';

        // don't re-read alerts from kafka
        var op = redisClient.hexists(countKey, key, function (err, result) {
          // increment alert count
          redisClient.hincrby(countKey, key, 1, redisClient.print);

          // set timestamp
          var timestamp = (new Date()).getTime();
          redisClient.hset(timestampKey, key, timestamp, redisClient.print);

          if (!result) {
            // store message value in separate hash
            redisClient.hset(valueKey, key, message.value, redisClient.print);
          }
        });
      });
    });
  });

  wss.on('connection', function (ws) {
    // read new messages from redis buffer

    // ws.send(message.value, function () { });

    ws.on('close', function () {
      console.log('ws client disconnected');
    });

    ws.on('error', function (err) {
      console.log('WebSockets ERROR:');
      console.log(err);
    });
  });

  // Register realtime search
  app.post('/alerts', function (req, res) {
    res.send(null);
  });

  // Read realtime search
  app.get('/alerts', function (req, res) {
    res.render('alerts', { flash: req.flash() });
  });

};
<commit_msg>construct alert from redis buffer<commit_after>/* global _:true */

var kafka = require('kafka-node')
  , redis = require('redis')
  , xxhash = require('xxhashjs')
  , _ = require('lodash')
  , path = require('path')
  , WebSocketServer = require('ws').Server
  , env = process.env.NODE_ENV || 'dev'
  , config = require('../config')[env];

var redisClient = redis.createClient(
  config.redis.port,
  config.redis.host);

var connString = config.zookeeper.host + ':' + config.zookeeper.port;
var kafkaClient = new kafka.Client(connString);

// read messages for topic
exports.consume = function (topic, cb) {
  var options = {
    autoCommit: false,
    fromBeginning: false,
    fetchMaxWaitMs: 1000,
    fetchMaxBytes: 1024*1024
  };

  // use default partitions
  var topics = [
    { topic: topic, partition: 0 },
    { topic: topic, partition: 1 }
  ];

  var consumer = new kafka.Consumer(kafkaClient, topics, options);
  var offset = new kafka.Offset(kafkaClient);

  consumer.on('message', cb);

  consumer.on('error', function (err) {
    throw err;
  });

  // recompute offset
  consumer.on('offsetOutOfRange', function (topic) {
    topic.maxNum = 2;

    offset.fetch([topic], function (err, offsets) {
      var min = Math.min.apply(null, offsets[topic.topic][topic.partition]);
      consumer.setOffset(topic.topic, topic.partition, min);
    });
  });

  return consumer;
};

exports.produce = function (topic, message, cb) {
  var producer = new kafka.Producer(kafkaClient);

  producer.send([{ messages: [message], topic: topic, parition: 0 }], cb);
};

// regsiter a query as a new kafka topic
exports.register = function (topic, cb) {
  var producer = new kafka.Producer(kafkaClient);

  producer.createTopics([topic], false, cb);
};

exports.initialize = function (app, server) {
  var countKey = 'alert-count';
  var timestampKey = 'alert-timestamp';
  var valueKey = 'alert-value';

  // web socket setup
  var wss = new WebSocketServer({
    server: server,
    clientTracking: true,
    path: '/alert'
  });

  // alerts are stored in database 0
  redisClient.select(0, function () {
    // TODO: read saved topics / Dashboards from Redis / Elasticsearch
    exports.register('opensoc', function () {
      console.log('Registered topic: opensoc');

      exports.consume('opensoc', function (message) {
        // each alert needs a unique identifier to determine if we've read it
        var toHash = message.topic + ':' +
          message.offset + ':' +
          message.partition + ':' +
          message.value;
        var key = xxhash(toHash, 1).toString(16);

        // don't re-read alerts from kafka
        var op = redisClient.hexists(countKey, key, function (err, result) {
          // increment alert count
          redisClient.hincrby(countKey, key, 1, redisClient.print);

          // set timestamp
          var timestamp = (new Date()).getTime();
          redisClient.hset(timestampKey, key, timestamp, redisClient.print);

          if (!result) {
            // store message value in separate hash
            redisClient.hset(valueKey, key, message.value, redisClient.print);
          }
        });
      });
    });
  });

  wss.on('connection', function (ws) {
    // read new messages from redis buffer
    redisClient.hkeys(countKey, function (err, keys) {
      _.each(keys, function (key) {
        var count, value, timestamp;

        // callback hell :-(
        redisClient.hget(countKey, key, function (err, result) {
          count = result;
          redisClient.hget(valueKey, key, function (err, result) {
            value = result;
            redisClient.hget(timestampKey, key, function (err, result) {
              var alert = {
                count: count,
                value: value,
                timestamp: result
              };
              ws.send(JSON.stringify(alert), function () {} );
            });
          });
        });
      });
    });

    // ws.send(message.value, function () { });

    ws.on('close', function () {
      console.log('ws client disconnected');
    });

    ws.on('error', function (err) {
      console.log('WebSockets ERROR:');
      console.log(err);
    });
  });

  // Register realtime search
  app.post('/alerts', function (req, res) {
    res.send(null);
  });

  // Read realtime search
  app.get('/alerts', function (req, res) {
    res.render('alerts', { flash: req.flash() });
  });

};
<|endoftext|>


<commit_before>// web analytics configuration
module.exports = {
  //ANALYTICS SETTINGS
  google: {
    enabled: true,
    key: 'UA-48605964-17'
  },
  piwik: {
    enabled: false,
    host: '',
    key: ''
  },
  dap: {
    enabled: true,
    source: 'https://analytics.usa.gov/dap/dap.min.js'
  }
};
<commit_msg>Update to new DAP location<commit_after>// web analytics configuration
module.exports = {
  //ANALYTICS SETTINGS
  google: {
    enabled: true,
    key: 'UA-48605964-17'
  },
  piwik: {
    enabled: false,
    host: '',
    key: ''
  },
  dap: {
    enabled: true,
    source: 'https://dap.digitalgov.gov/Universal-Federated-Analytics-Min.js?agency=GSA'
  }
};
<|endoftext|>


<commit_before>var _ = require('underscore');
var cdb = require('cartodb.js');
var Dashboard = require('./dashboard');
var DashboardView = require('../dashboard-view');
var WidgetsCollection = require('../widgets/widgets-collection');
var WidgetsService = require('../widgets-service');
var URLHelper = require('./url-helper');
var layerArray = [];
var layerssum = 0;

/**
 * Translates a vizJSON v3 datastructure into a working dashboard which will be rendered in given selector.
 *
 * @param {String} selector e.g. "#foobar-id", ".some-class"
 * @param {Object} vizJSON JSON datastructure
 * @param {Object} opts (Optional) flags, see 3rd param for cdb.createVis for available ones. Keys used here:
 *   renderMenu: {Boolean} If true (default), render a top-level menu on the left side.
 * @return {Object} with keys:
 *   dashboardView: root (backbone) view of the dashboard
 *   vis: the instantiated vis map, same result as given from cdb.createVis()
 */
var createDashboard = function (selector, vizJSON, opts, callback) {
  var dashboardEl = document.querySelector(selector);
  if (!dashboardEl) throw new Error('no element found with selector ' + selector);

  // Default options
  opts = opts || {};
  opts.renderMenu = _.isBoolean(opts.renderMenu)
    ? opts.renderMenu
    : true;
  opts.autoStyle = _.isBoolean(opts.autoStyle)
    ? opts.autoStyle
    : false;

  var widgets = new WidgetsCollection();

  var model = new cdb.core.Model({
    title: vizJSON.title,
    description: vizJSON.description,
    updatedAt: vizJSON.updated_at,
    userName: vizJSON.user.fullname,
    userProfileURL: vizJSON.user.profile_url,
    userAvatarURL: vizJSON.user.avatar_url,
    renderMenu: opts.renderMenu,
    autoStyle: opts.autoStyle,
    showLogo: opts.cartodb_logo,
    initialPosition: {
      bounds: vizJSON.bounds
    }
  });
  var dashboardView = new DashboardView({
    el: dashboardEl,
    widgets: widgets,
    model: model
  });
  var stateFromURL = opts.state || URLHelper.getStateFromCurrentURL();
  if (stateFromURL && !_.isEmpty(stateFromURL.map)) {
    if (stateFromURL.map.ne && stateFromURL.map.sw) {
      vizJSON.bounds = [stateFromURL.map.ne, stateFromURL.map.sw];
    }
  }

  var vis = cdb.createVis(dashboardView.$('#map'), vizJSON, _.extend(opts, {
    skipMapInstantiation: true
  }));

  vis.once('load', function (vis) {
    /*check the user has tiled layers*/
    const userlocation = userData.username;
    const apikey = opts.apiKey;
    let   visid = location.pathname.split('/');
    visid = visid[visid.length - 1];

    //check there is tiled_layers_collection
    fetch(`http://${userlocation}.${location.hostname}/api/v2/sql?q=SELECT * from tiled_layers_collection where visible = true AND vis LIKE '${visid}';&api_key=${apikey}`)
      .then(
      function(response) {
        if (response.status !== 200) {
          // the user have not created the tiled_layers_collection table
          // let's create that table
          fetch(`http://${userData.username}.${location.hostname}/api/v2/sql?q= create table tiled_layers_collection (tiled_layer string, vis string, layername string, visible bolean);&api_key=${opts.apiKey}`)
            .then(
              function(response) {
                console.info('tiled_layers_collection created, updating...');
                fetch(`http://${userData.username}.${location.hostname}/api/v2/sql?q= select cdb_cartodbfytable('tiled_layers_collection');&api_key=${opts.apiKey}`)
                .then(
                  function(response) {
                    console.info('...updated');
                  }
                )
              }
            )
        } else {
          response.json().then(function(data) {
            var list = document.querySelector('.raster-tiled-layers-content ul');
            data.rows.forEach(function(row, i){
              let listitem = document.createElement('li');
              listitem.innerHTML = row.layername + ' 🗑';
              list.appendChild(listitem);
              let newlayer = new L.TileLayer(row.tiled_layer);
              vis.map.addLayer(newlayer);
              vis.map.getLayerAt(vis.map.layers.length - 1).attributes._updateZIndex(1);
            })
          });
        }
      }
    )
    .catch(function(err) {
      console.error('Error fetching SQL API', err);
    });
    var paintBox = function() {
      var tilebox = document.querySelectorAll('.Editor-ListLayer li');
      tilebox = tilebox[tilebox.length - 1];
      const boxtop = tilebox.offsetTop + tilebox.offsetHeight + 125 + 'px'; /*125px header height*/
      document.querySelector('.Editor-ListLayer-item-raster').style.top = boxtop;
    }
    paintBox();

    document.querySelectorAll('.raster-tiled-layers-content button')[0].onclick = function (ev) {
      let layerInput = this.previousSibling.previousSibling;

      if (!layerInput.value) {
        let elem = document.getElementById('message-raster-layer');
        elem.innerHTML = 'Please add a URL for the layer';
        elem.style.display = 'inline-block';
        elem.classList.add('error');
        return;
      }
      let layername = '';
      if (layerInput.value.toUpperCase().includes('NDVI')){
        layername = 'NDVI';
      } else if (layerInput.value.toUpperCase().includes('NDRE')){
        layername = 'NDRE'
      } else if (layerInput.value.toUpperCase().includes('THLA')){
        layername = 'THLA'
      } else if (layerInput.value.toUpperCase().includes('RGB')){
        layername = 'RGB'
      }
      if (!layername || confirm('Layer name: '+ layername + ', change it?')) {
        layername = prompt('Give this layer a name');
        layername = (!!layername) ? layername : 'Layer';
      }

      let newlayer = new L.TileLayer(layerInput.value);
      let layerindex = layerArray.length +1;
      layerArray.push([newlayer]);
      vis.map.addLayer(newlayer);
      vis.map.getLayerAt(vis.map.layers.length - 1).attributes._updateZIndex(1);

      let listitem = document.createElement('li');
      listitem.innerHTML = layername + ' 🗑';
      ev.target.parentElement.parentElement.lastElementChild.appendChild(listitem);

      //check if the layer exists and update status / insert
      const query = `
      UPDATE tiled_layers_collection
      SET vis = '${visid}', layername = '${layername}', tiled_layer = '${encodeURIComponent(layerInput.value)}', visible = true
      WHERE vis like '${visid}';

      INSERT INTO tiled_layers_collection (vis, tiled_layer, visible, layername)
      SELECT '${visid}','${encodeURIComponent(layerInput.value)}', true, '${layername}'
      WHERE NOT EXISTS (SELECT 1 FROM tiled_layers_collection WHERE vis LIKE '${visid}')
      `;
      fetch(`http://${userlocation}.${location.hostname}/api/v2/sql?q=${query};&api_key=${apikey}`)
      .then(
        function(response) {
          if (response.status == 200) {return console.info('table updated')}
          console.error('error while updating the table')
        }
      );
    }
    document.querySelector('body').addEventListener('click', function(event) {
      paintBox();

      if (event.target.classList.contains('remove-tiled-layer') && confirm('delete layer?')) {
        vis.map.removeLayerAt(~~event.target.dataset.layerindex +1);
        event.target.parentElement.remove();

        //hide on DB
        const query = `
        UPDATE tiled_layers_collection SET visible = false WHERE tiled_layer LIKE '${encodeURIComponent(event.target.dataset.tiledlayer)}' AND vis like '${visid}';
        `;
        fetch(`http://${userlocation}.${location.hostname}/api/v2/sql?q=${query};&api_key=${apikey}`);
      }
    });

    if (stateFromURL && !_.isEmpty(stateFromURL.map)) {
      if (!_.isUndefined(stateFromURL.map.ne) && !_.isUndefined(stateFromURL.map.sw)) {
        vis.map.setBounds([stateFromURL.map.ne, stateFromURL.map.sw]);
      } else if (!_.isUndefined(stateFromURL.map.center) && !_.isUndefined(stateFromURL.map.zoom)) {
        vis.map.setView(stateFromURL.map.center, stateFromURL.map.zoom);
      }
    }

    var widgetsState = stateFromURL && stateFromURL.widgets || {};

    // Create widgets
    var widgetsService = new WidgetsService(widgets, vis.dataviews);
    var widgetModelsMap = {
      list: widgetsService.createListModel.bind(widgetsService),
      formula: widgetsService.createFormulaModel.bind(widgetsService),
      histogram: widgetsService.createHistogramModel.bind(widgetsService),
      'time-series': widgetsService.createTimeSeriesModel.bind(widgetsService),
      category: widgetsService.createCategoryModel.bind(widgetsService)
    };
    vizJSON.widgets.forEach(function (d) {
      // Flatten the data structure given in vizJSON, the widgetsService will use whatever it needs and ignore the rest
      var attrs = _.extend({}, d, d.options);
      var newWidgetModel = widgetModelsMap[d.type];
      var state = widgetsState[d.id];

      if (_.isFunction(newWidgetModel)) {
        // Find the Layer that the Widget should be created for.
        var layer;
        if (d.layer_id) {
          layer = vis.map.layers.get(d.layer_id);
        } else if (Number.isInteger(d.layerIndex)) {
          // TODO Since namedmap doesn't have ids we need to map in another way, here using index
          //   should we solve this in another way?
          layer = vis.map.layers.at(d.layerIndex);
        }

        newWidgetModel(attrs, layer, state, {autoStyleEnabled: opts.autoStyle});
      } else {
        cdb.log.error('No widget found for type ' + d.type);
      }
    });

    dashboardView.render();

    if (widgets.size() > 0) {
      vis.centerMapToOrigin();
    }

    vis.instantiateMap({
      success: function () {
        callback && callback(null, {
          dashboardView: dashboardView,
          widgets: widgetsService,
          vis: vis
        });
      },
      error: function () {
        var error = new Error('Map instantiation failed');
        console.log(error);
        callback && callback(error, {
          dashboardView: dashboardView,
          widgets: widgetsService,
          vis: vis
        });
      }
    });
  });
};

module.exports = function (selector, vizJSON, opts, callback) {
  var args = arguments;
  var fn = args[args.length - 1];

  if (_.isFunction(fn)) {
    callback = fn;
  }

  function _load (vizJSON) {
    createDashboard(selector, vizJSON, opts, function (error, dashboard) {
      var dash = new Dashboard(dashboard);
      dash.onStateChanged(_.debounce(function (state, url) {
        window.history.replaceState('Object', 'Title', url);
      }, 500), opts.share_urls);

      callback && callback(error, dash);
    });
  }

  if (typeof vizJSON === 'string') {
    cdb.core.Loader.get(vizJSON, function (data) {
      if (data) {
        _load(data, opts);
      } else {
        callback && callback(new Error('error fetching viz.json file'));
      }
    });
  } else {
    _load(vizJSON, opts);
  }
};
<commit_msg>Fix up that SQL<commit_after>var _ = require('underscore');
var cdb = require('cartodb.js');
var Dashboard = require('./dashboard');
var DashboardView = require('../dashboard-view');
var WidgetsCollection = require('../widgets/widgets-collection');
var WidgetsService = require('../widgets-service');
var URLHelper = require('./url-helper');
var layerArray = [];
var layerssum = 0;

/**
 * Translates a vizJSON v3 datastructure into a working dashboard which will be rendered in given selector.
 *
 * @param {String} selector e.g. "#foobar-id", ".some-class"
 * @param {Object} vizJSON JSON datastructure
 * @param {Object} opts (Optional) flags, see 3rd param for cdb.createVis for available ones. Keys used here:
 *   renderMenu: {Boolean} If true (default), render a top-level menu on the left side.
 * @return {Object} with keys:
 *   dashboardView: root (backbone) view of the dashboard
 *   vis: the instantiated vis map, same result as given from cdb.createVis()
 */
var createDashboard = function (selector, vizJSON, opts, callback) {
  var dashboardEl = document.querySelector(selector);
  if (!dashboardEl) throw new Error('no element found with selector ' + selector);

  // Default options
  opts = opts || {};
  opts.renderMenu = _.isBoolean(opts.renderMenu)
    ? opts.renderMenu
    : true;
  opts.autoStyle = _.isBoolean(opts.autoStyle)
    ? opts.autoStyle
    : false;

  var widgets = new WidgetsCollection();

  var model = new cdb.core.Model({
    title: vizJSON.title,
    description: vizJSON.description,
    updatedAt: vizJSON.updated_at,
    userName: vizJSON.user.fullname,
    userProfileURL: vizJSON.user.profile_url,
    userAvatarURL: vizJSON.user.avatar_url,
    renderMenu: opts.renderMenu,
    autoStyle: opts.autoStyle,
    showLogo: opts.cartodb_logo,
    initialPosition: {
      bounds: vizJSON.bounds
    }
  });
  var dashboardView = new DashboardView({
    el: dashboardEl,
    widgets: widgets,
    model: model
  });
  var stateFromURL = opts.state || URLHelper.getStateFromCurrentURL();
  if (stateFromURL && !_.isEmpty(stateFromURL.map)) {
    if (stateFromURL.map.ne && stateFromURL.map.sw) {
      vizJSON.bounds = [stateFromURL.map.ne, stateFromURL.map.sw];
    }
  }

  var vis = cdb.createVis(dashboardView.$('#map'), vizJSON, _.extend(opts, {
    skipMapInstantiation: true
  }));

  vis.once('load', function (vis) {
    /*check the user has tiled layers*/
    const userlocation = userData.username;
    const apikey = opts.apiKey;
    let   visid = location.pathname.split('/');
    visid = visid[visid.length - 1];

    //check there is tiled_layers_collection
    fetch(`http://${userlocation}.${location.hostname}/api/v2/sql?q=SELECT * from tiled_layers_collection where visible = true AND vis LIKE '${visid}';&api_key=${apikey}`)
      .then(
      function(response) {
        if (response.status !== 200) {
          // the user have not created the tiled_layers_collection table
          // let's create that table
          fetch(`http://${userData.username}.${location.hostname}/api/v2/sql?q= create table tiled_layers_collection (tiled_layer text, vis text, layername text, visible boolean);&api_key=${opts.apiKey}`)
            .then(
              function(response) {
                console.info('tiled_layers_collection created, updating...');
                fetch(`http://${userData.username}.${location.hostname}/api/v2/sql?q= select cdb_cartodbfytable('tiled_layers_collection');&api_key=${opts.apiKey}`)
                .then(
                  function(response) {
                    console.info('...updated');
                  }
                )
              }
            )
        } else {
          response.json().then(function(data) {
            var list = document.querySelector('.raster-tiled-layers-content ul');
            data.rows.forEach(function(row, i){
              let listitem = document.createElement('li');
              listitem.innerHTML = row.layername + ' 🗑';
              list.appendChild(listitem);
              let newlayer = new L.TileLayer(row.tiled_layer);
              vis.map.addLayer(newlayer);
              vis.map.getLayerAt(vis.map.layers.length - 1).attributes._updateZIndex(1);
            })
          });
        }
      }
    )
    .catch(function(err) {
      console.error('Error fetching SQL API', err);
    });
    var paintBox = function() {
      var tilebox = document.querySelectorAll('.Editor-ListLayer li');
      tilebox = tilebox[tilebox.length - 1];
      const boxtop = tilebox.offsetTop + tilebox.offsetHeight + 125 + 'px'; /*125px header height*/
      document.querySelector('.Editor-ListLayer-item-raster').style.top = boxtop;
    }
    paintBox();

    document.querySelectorAll('.raster-tiled-layers-content button')[0].onclick = function (ev) {
      let layerInput = this.previousSibling.previousSibling;

      if (!layerInput.value) {
        let elem = document.getElementById('message-raster-layer');
        elem.innerHTML = 'Please add a URL for the layer';
        elem.style.display = 'inline-block';
        elem.classList.add('error');
        return;
      }
      let layername = '';
      if (layerInput.value.toUpperCase().includes('NDVI')){
        layername = 'NDVI';
      } else if (layerInput.value.toUpperCase().includes('NDRE')){
        layername = 'NDRE'
      } else if (layerInput.value.toUpperCase().includes('THLA')){
        layername = 'THLA'
      } else if (layerInput.value.toUpperCase().includes('RGB')){
        layername = 'RGB'
      }
      if (!layername || confirm('Layer name: '+ layername + ', change it?')) {
        layername = prompt('Give this layer a name');
        layername = (!!layername) ? layername : 'Layer';
      }

      let newlayer = new L.TileLayer(layerInput.value);
      let layerindex = layerArray.length +1;
      layerArray.push([newlayer]);
      vis.map.addLayer(newlayer);
      vis.map.getLayerAt(vis.map.layers.length - 1).attributes._updateZIndex(1);

      let listitem = document.createElement('li');
      listitem.innerHTML = layername + ' 🗑';
      ev.target.parentElement.parentElement.lastElementChild.appendChild(listitem);

      //check if the layer exists and update status / insert
      const query = `
      UPDATE tiled_layers_collection
      SET vis = '${visid}', layername = '${layername}', tiled_layer = '${encodeURIComponent(layerInput.value)}', visible = true
      WHERE vis like '${visid}';

      INSERT INTO tiled_layers_collection (vis, tiled_layer, visible, layername)
      SELECT '${visid}','${encodeURIComponent(layerInput.value)}', true, '${layername}'
      WHERE NOT EXISTS (SELECT 1 FROM tiled_layers_collection WHERE vis LIKE '${visid}')
      `;
      fetch(`http://${userlocation}.${location.hostname}/api/v2/sql?q=${query};&api_key=${apikey}`)
      .then(
        function(response) {
          if (response.status == 200) {return console.info('table updated')}
          console.error('error while updating the table')
        }
      );
    }
    document.querySelector('body').addEventListener('click', function(event) {
      paintBox();

      if (event.target.classList.contains('remove-tiled-layer') && confirm('delete layer?')) {
        vis.map.removeLayerAt(~~event.target.dataset.layerindex +1);
        event.target.parentElement.remove();

        //hide on DB
        const query = `
        UPDATE tiled_layers_collection SET visible = false WHERE tiled_layer LIKE '${encodeURIComponent(event.target.dataset.tiledlayer)}' AND vis like '${visid}';
        `;
        fetch(`http://${userlocation}.${location.hostname}/api/v2/sql?q=${query};&api_key=${apikey}`);
      }
    });

    if (stateFromURL && !_.isEmpty(stateFromURL.map)) {
      if (!_.isUndefined(stateFromURL.map.ne) && !_.isUndefined(stateFromURL.map.sw)) {
        vis.map.setBounds([stateFromURL.map.ne, stateFromURL.map.sw]);
      } else if (!_.isUndefined(stateFromURL.map.center) && !_.isUndefined(stateFromURL.map.zoom)) {
        vis.map.setView(stateFromURL.map.center, stateFromURL.map.zoom);
      }
    }

    var widgetsState = stateFromURL && stateFromURL.widgets || {};

    // Create widgets
    var widgetsService = new WidgetsService(widgets, vis.dataviews);
    var widgetModelsMap = {
      list: widgetsService.createListModel.bind(widgetsService),
      formula: widgetsService.createFormulaModel.bind(widgetsService),
      histogram: widgetsService.createHistogramModel.bind(widgetsService),
      'time-series': widgetsService.createTimeSeriesModel.bind(widgetsService),
      category: widgetsService.createCategoryModel.bind(widgetsService)
    };
    vizJSON.widgets.forEach(function (d) {
      // Flatten the data structure given in vizJSON, the widgetsService will use whatever it needs and ignore the rest
      var attrs = _.extend({}, d, d.options);
      var newWidgetModel = widgetModelsMap[d.type];
      var state = widgetsState[d.id];

      if (_.isFunction(newWidgetModel)) {
        // Find the Layer that the Widget should be created for.
        var layer;
        if (d.layer_id) {
          layer = vis.map.layers.get(d.layer_id);
        } else if (Number.isInteger(d.layerIndex)) {
          // TODO Since namedmap doesn't have ids we need to map in another way, here using index
          //   should we solve this in another way?
          layer = vis.map.layers.at(d.layerIndex);
        }

        newWidgetModel(attrs, layer, state, {autoStyleEnabled: opts.autoStyle});
      } else {
        cdb.log.error('No widget found for type ' + d.type);
      }
    });

    dashboardView.render();

    if (widgets.size() > 0) {
      vis.centerMapToOrigin();
    }

    vis.instantiateMap({
      success: function () {
        callback && callback(null, {
          dashboardView: dashboardView,
          widgets: widgetsService,
          vis: vis
        });
      },
      error: function () {
        var error = new Error('Map instantiation failed');
        console.log(error);
        callback && callback(error, {
          dashboardView: dashboardView,
          widgets: widgetsService,
          vis: vis
        });
      }
    });
  });
};

module.exports = function (selector, vizJSON, opts, callback) {
  var args = arguments;
  var fn = args[args.length - 1];

  if (_.isFunction(fn)) {
    callback = fn;
  }

  function _load (vizJSON) {
    createDashboard(selector, vizJSON, opts, function (error, dashboard) {
      var dash = new Dashboard(dashboard);
      dash.onStateChanged(_.debounce(function (state, url) {
        window.history.replaceState('Object', 'Title', url);
      }, 500), opts.share_urls);

      callback && callback(error, dash);
    });
  }

  if (typeof vizJSON === 'string') {
    cdb.core.Loader.get(vizJSON, function (data) {
      if (data) {
        _load(data, opts);
      } else {
        callback && callback(new Error('error fetching viz.json file'));
      }
    });
  } else {
    _load(vizJSON, opts);
  }
};
<|endoftext|>


<commit_before>var
	chai = require('chai'),
	should = chai.should();

describe('filter', function () {
	'use strict';

	var
		filterLib = null,
		mongoose = require('mongoose'),
		orClauseItems = [],
		whereClause = {};

	var Kitteh = mongoose.model('kittehs-filter', new mongoose.Schema({
		birthday : { type : Date, default : Date.now },
		features : {
			color : String,
			isFurreh : Boolean
		},
		id : Number,
		isDead: Boolean,
		home : String,
		name : String,
		peePatches : [String]
	}));

	before(function () {
		filterLib = require('../../lib/filter')(mongoose);

		mongoose.Query.prototype.or = function (clause) {
			if (clause) {
				orClauseItems.push(clause);
			}
		};

		mongoose.Query.prototype.where = function (key, val) {
			if (typeof val === 'undefined') {
				val = { expr : '', val : null };
			}

			whereClause[key] = val;

			return {
				gt : function (v) {
					whereClause[key].expr = 'gt';
					whereClause[key].val = v;
				},
				gte : function (v) {
					whereClause[key].expr = 'gte';
					whereClause[key].val = v;
				},
				lt : function (v) {
					whereClause[key].expr = 'lt';
					whereClause[key].val = v;
				},
				lte : function (v) {
					whereClause[key].expr = 'lte';
					whereClause[key].val = v;
				}
			};
		};
	});

	beforeEach(function () {
		orClauseItems = [];
		whereClause = {};
	});

	it ('should return a query when created', function () {
		var query = Kitteh
			.find()
			.filter(null);

		(query instanceof mongoose.Query).should.equals(true);
	});

	it ('should apply both mandatory and optional filters when both are supplied', function () {
		var options = {
			filters : {
				mandatory : {
					contains : {
						name : 'cat'
					}
				},
				optional : {
					exact : {
						'features.color' : 'brindle'
					}
				}
			}
		};

		var query = Kitteh
			.find()
			.filter(options);

		should.exist(query);
		should.exist(whereClause.name);
		orClauseItems.should.have.length(1);
	});

	describe('mandatory filters', function () {
		it ('should look for occurrences of a term within a string using contains', function () {
			var options = {
				filters : {
					mandatory : {
						contains : {
							name : 'cat'
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.name);
			whereClause.name.test('cat').should.equals(true);
			whereClause.name.test('a cat exists').should.equals(true);
			whereClause.name.test('dog').should.equals(false);
		});

		it ('should look for occurrences of a term at the start of a string using endsWith', function () {
			var options = {
				filters : {
					mandatory : {
						endsWith : {
							name : 'cat'
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.name);
			whereClause.name.test('cat').should.equals(true);
			whereClause.name.test('cool cat').should.equals(true);
			whereClause.name.test('this cat is sick').should.equals(false);
		});

		it ('should look for occurrences of a term at the start of a string using startsWith', function () {
			var options = {
				filters : {
					mandatory : {
						startsWith : {
							name : 'cat'
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.name);
			whereClause.name.test('cat').should.equals(true);
			whereClause.name.test('cat exists').should.equals(true);
			whereClause.name.test('this cat is sick').should.equals(false);
		});

		it ('should look for occurrences of an exact match of the term when using exact', function () {
			var options = {
				filters : {
					mandatory : {
						exact : {
							name : 'cat'
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.name);
			whereClause.name.test('cat').should.equals(true);
			whereClause.name.test('cat litter').should.equals(false);
			whereClause.name.test('the cat').should.equals(false);
		});

		it ('should look for occurrences of an exact match of the object when using exact', function () {
			var options = {
				filters : {
					mandatory : {
						exact : {
							isDead : false
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.isDead);
			whereClause.isDead.should.equals(false);
		});

		it ('should look for occurrences of an exact match of a number when using exact', function () {
			var options = {
				filters : {
					mandatory : {
						exact : {
							id : 12345
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.id);
			whereClause.id.should.equals(12345);
		});

		it ('should properly apply where clause when using greaterThan filter', function () {
			var options = {
				filters : {
					mandatory : {
						greaterThan : {
							birthday : new Date(2014, 12, 1)
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.birthday);
			whereClause.birthday.expr.should.equal('gt');
		});

		it ('should properly apply where clause when using gt filter', function () {
			var options = {
				filters : {
					mandatory : {
						gt : {
							birthday : new Date(2014, 12, 1)
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.birthday);
			whereClause.birthday.expr.should.equal('gt');
		});

		it ('should properly apply where clause when using greaterThanEqual filter', function () {
			var options = {
				filters : {
					mandatory : {
						greaterThanEqual : {
							birthday : new Date(2014, 12, 1)
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.birthday);
			whereClause.birthday.expr.should.equal('gte');
		});

		it ('should properly apply where clause when using gte filter', function () {
			var options = {
				filters : {
					mandatory : {
						gte : {
							birthday : new Date(2014, 12, 1)
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.birthday);
			whereClause.birthday.expr.should.equal('gte');
		});

		it ('should properly apply where clause when using lessThan filter', function () {
			var options = {
				filters : {
					mandatory : {
						lessThan : {
							birthday : new Date(2014, 12, 1)
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.birthday);
			whereClause.birthday.expr.should.equal('lt');
		});

		it ('should properly apply where clause when using lt filter', function () {
			var options = {
				filters : {
					mandatory : {
						lt : {
							birthday : new Date(2014, 12, 1)
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.birthday);
			whereClause.birthday.expr.should.equal('lt');
		});

		it ('should properly apply where clause when using lessThanEqual filter', function () {
			var options = {
				filters : {
					mandatory : {
						lessThanEqual : {
							birthday : new Date(2014, 12, 1)
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.birthday);
			whereClause.birthday.expr.should.equal('lte');
		});

		it ('should properly apply where clause when using lte filter', function () {
			var options = {
				filters : {
					mandatory : {
						lte : {
							birthday : new Date(2014, 12, 1)
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.birthday);
			whereClause.birthday.expr.should.equal('lte');
		});
	});

	describe('optional filters', function () {
		it ('should look for occurrences of a term within a string using contains', function () {
			var options = {
				filters : {
					optional : {
						contains : {
							name : 'cat'
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			orClauseItems.should.have.length(1);
			orClauseItems[0][0].name.test('cat').should.equals(true);
			orClauseItems[0][0].name.test('a cat exists').should.equals(true);
			orClauseItems[0][0].name.test('dog').should.equals(false);
		});

		it ('should look for occurrences of a term at the start of a string using endsWith', function () {
			var options = {
				filters : {
					optional : {
						endsWith : {
							name : 'cat'
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			orClauseItems.should.have.length(1);
			orClauseItems[0][0].name.test('cat').should.equals(true);
			orClauseItems[0][0].name.test('cool cat').should.equals(true);
			orClauseItems[0][0].name.test('this cat is sick').should.equals(false);
		});

		it ('should look for occurrences of a term at the start of a string using startsWith', function () {
			var options = {
				filters : {
					optional : {
						startsWith : {
							name : 'cat'
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			orClauseItems.should.have.length(1);
			orClauseItems[0][0].name.test('cat').should.equals(true);
			orClauseItems[0][0].name.test('cat exists').should.equals(true);
			orClauseItems[0][0].name.test('this cat is sick').should.equals(false);
		});

		it ('should look for occurrences of an exact match of the term when using exact', function () {
			var options = {
				filters : {
					optional : {
						exact : {
							name : 'cat'
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			orClauseItems.should.have.length(1);
			orClauseItems[0][0].name.test('cat').should.equals(true);
			orClauseItems[0][0].name.test('cat litter').should.equals(false);
			orClauseItems[0][0].name.test('the cat').should.equals(false);
		});

		it ('should look for occurrences of an exact match of the object when using exact', function () {
			var options = {
				filters : {
					optional : {
						exact : {
							isDead : true
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			orClauseItems.should.have.length(1);
			orClauseItems[0][0].isDead.should.equals(true);
		});

		it ('should look for multiple occurrences of a match when supplying an array', function () {
			var options = {
				filters : {
					optional : {
						exact : {
							name : ['cat', 'Kitteh']
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			orClauseItems.should.have.length(1);
			orClauseItems[0][0].name.test('cat').should.equals(true);
			orClauseItems[0][1].name.test('Kitteh').should.equals(true);
		});
	});
});
<commit_msg>adding tests for notEqual and ne filters<commit_after>var
	chai = require('chai'),
	should = chai.should();

describe('filter', function () {
	'use strict';

	var
		filterLib = null,
		mongoose = require('mongoose'),
		orClauseItems = [],
		whereClause = {};

	var Kitteh = mongoose.model('kittehs-filter', new mongoose.Schema({
		birthday : { type : Date, default : Date.now },
		features : {
			color : String,
			isFurreh : Boolean
		},
		id : Number,
		isDead: Boolean,
		home : String,
		name : String,
		peePatches : [String]
	}));

	before(function () {
		filterLib = require('../../lib/filter')(mongoose);

		mongoose.Query.prototype.or = function (clause) {
			if (clause) {
				orClauseItems.push(clause);
			}
		};

		mongoose.Query.prototype.where = function (key, val) {
			if (typeof val === 'undefined') {
				val = { expr : '', val : null };
			}

			whereClause[key] = val;

			return {
				gt : function (v) {
					whereClause[key].expr = 'gt';
					whereClause[key].val = v;
				},
				gte : function (v) {
					whereClause[key].expr = 'gte';
					whereClause[key].val = v;
				},
				lt : function (v) {
					whereClause[key].expr = 'lt';
					whereClause[key].val = v;
				},
				lte : function (v) {
					whereClause[key].expr = 'lte';
					whereClause[key].val = v;
				},
				ne : function (v) {
					whereClause[key].expr = 'ne';
					whereClause[key].val = v;
				}
			};
		};
	});

	beforeEach(function () {
		orClauseItems = [];
		whereClause = {};
	});

	it ('should return a query when created', function () {
		var query = Kitteh
			.find()
			.filter(null);

		(query instanceof mongoose.Query).should.equals(true);
	});

	it ('should apply both mandatory and optional filters when both are supplied', function () {
		var options = {
			filters : {
				mandatory : {
					contains : {
						name : 'cat'
					}
				},
				optional : {
					exact : {
						'features.color' : 'brindle'
					}
				}
			}
		};

		var query = Kitteh
			.find()
			.filter(options);

		should.exist(query);
		should.exist(whereClause.name);
		orClauseItems.should.have.length(1);
	});

	describe('mandatory filters', function () {
		it ('should look for occurrences of a term within a string using contains', function () {
			var options = {
				filters : {
					mandatory : {
						contains : {
							name : 'cat'
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.name);
			whereClause.name.test('cat').should.equals(true);
			whereClause.name.test('a cat exists').should.equals(true);
			whereClause.name.test('dog').should.equals(false);
		});

		it ('should look for occurrences of a term at the start of a string using endsWith', function () {
			var options = {
				filters : {
					mandatory : {
						endsWith : {
							name : 'cat'
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.name);
			whereClause.name.test('cat').should.equals(true);
			whereClause.name.test('cool cat').should.equals(true);
			whereClause.name.test('this cat is sick').should.equals(false);
		});

		it ('should look for occurrences of a term at the start of a string using startsWith', function () {
			var options = {
				filters : {
					mandatory : {
						startsWith : {
							name : 'cat'
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.name);
			whereClause.name.test('cat').should.equals(true);
			whereClause.name.test('cat exists').should.equals(true);
			whereClause.name.test('this cat is sick').should.equals(false);
		});

		it ('should look for occurrences of an exact match of the term when using exact', function () {
			var options = {
				filters : {
					mandatory : {
						exact : {
							name : 'cat'
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.name);
			whereClause.name.test('cat').should.equals(true);
			whereClause.name.test('cat litter').should.equals(false);
			whereClause.name.test('the cat').should.equals(false);
		});

		it ('should look for occurrences of an exact match of the object when using exact', function () {
			var options = {
				filters : {
					mandatory : {
						exact : {
							isDead : false
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.isDead);
			whereClause.isDead.should.equals(false);
		});

		it ('should look for occurrences of an exact match of a number when using exact', function () {
			var options = {
				filters : {
					mandatory : {
						exact : {
							id : 12345
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.id);
			whereClause.id.should.equals(12345);
		});

		it ('should properly apply where clause when using greaterThan filter', function () {
			var options = {
				filters : {
					mandatory : {
						greaterThan : {
							birthday : new Date(2014, 12, 1)
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.birthday);
			whereClause.birthday.expr.should.equal('gt');
		});

		it ('should properly apply where clause when using gt filter', function () {
			var options = {
				filters : {
					mandatory : {
						gt : {
							birthday : new Date(2014, 12, 1)
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.birthday);
			whereClause.birthday.expr.should.equal('gt');
		});

		it ('should properly apply where clause when using greaterThanEqual filter', function () {
			var options = {
				filters : {
					mandatory : {
						greaterThanEqual : {
							birthday : new Date(2014, 12, 1)
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.birthday);
			whereClause.birthday.expr.should.equal('gte');
		});

		it ('should properly apply where clause when using gte filter', function () {
			var options = {
				filters : {
					mandatory : {
						gte : {
							birthday : new Date(2014, 12, 1)
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.birthday);
			whereClause.birthday.expr.should.equal('gte');
		});

		it ('should properly apply where clause when using lessThan filter', function () {
			var options = {
				filters : {
					mandatory : {
						lessThan : {
							birthday : new Date(2014, 12, 1)
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.birthday);
			whereClause.birthday.expr.should.equal('lt');
		});

		it ('should properly apply where clause when using lt filter', function () {
			var options = {
				filters : {
					mandatory : {
						lt : {
							birthday : new Date(2014, 12, 1)
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.birthday);
			whereClause.birthday.expr.should.equal('lt');
		});

		it ('should properly apply where clause when using lessThanEqual filter', function () {
			var options = {
				filters : {
					mandatory : {
						lessThanEqual : {
							birthday : new Date(2014, 12, 1)
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.birthday);
			whereClause.birthday.expr.should.equal('lte');
		});

		it ('should properly apply where clause when using lte filter', function () {
			var options = {
				filters : {
					mandatory : {
						lte : {
							birthday : new Date(2014, 12, 1)
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.birthday);
			whereClause.birthday.expr.should.equal('lte');
		});

		it ('should properly apply where clause when using notEqual filter', function () {
			var options = {
				filters : {
					mandatory : {
						notEqual : {
							name : 'cat'
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.name);
			whereClause.name.expr.should.equal('ne');
		});

		it ('should properly apply where clause when using ne filter', function () {
			var options = {
				filters : {
					mandatory : {
						notEqual : {
							name : 'cat'
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			should.exist(whereClause.name);
			whereClause.name.expr.should.equal('ne');
		});
	});

	describe('optional filters', function () {
		it ('should look for occurrences of a term within a string using contains', function () {
			var options = {
				filters : {
					optional : {
						contains : {
							name : 'cat'
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			orClauseItems.should.have.length(1);
			orClauseItems[0][0].name.test('cat').should.equals(true);
			orClauseItems[0][0].name.test('a cat exists').should.equals(true);
			orClauseItems[0][0].name.test('dog').should.equals(false);
		});

		it ('should look for occurrences of a term at the start of a string using endsWith', function () {
			var options = {
				filters : {
					optional : {
						endsWith : {
							name : 'cat'
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			orClauseItems.should.have.length(1);
			orClauseItems[0][0].name.test('cat').should.equals(true);
			orClauseItems[0][0].name.test('cool cat').should.equals(true);
			orClauseItems[0][0].name.test('this cat is sick').should.equals(false);
		});

		it ('should look for occurrences of a term at the start of a string using startsWith', function () {
			var options = {
				filters : {
					optional : {
						startsWith : {
							name : 'cat'
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			orClauseItems.should.have.length(1);
			orClauseItems[0][0].name.test('cat').should.equals(true);
			orClauseItems[0][0].name.test('cat exists').should.equals(true);
			orClauseItems[0][0].name.test('this cat is sick').should.equals(false);
		});

		it ('should look for occurrences of an exact match of the term when using exact', function () {
			var options = {
				filters : {
					optional : {
						exact : {
							name : 'cat'
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			orClauseItems.should.have.length(1);
			orClauseItems[0][0].name.test('cat').should.equals(true);
			orClauseItems[0][0].name.test('cat litter').should.equals(false);
			orClauseItems[0][0].name.test('the cat').should.equals(false);
		});

		it ('should look for occurrences of an exact match of the object when using exact', function () {
			var options = {
				filters : {
					optional : {
						exact : {
							isDead : true
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			orClauseItems.should.have.length(1);
			orClauseItems[0][0].isDead.should.equals(true);
		});

		it ('should look for multiple occurrences of a match when supplying an array', function () {
			var options = {
				filters : {
					optional : {
						exact : {
							name : ['cat', 'Kitteh']
						}
					}
				}
			};

			var query = Kitteh
				.find()
				.filter(options);

			should.exist(query);
			orClauseItems.should.have.length(1);
			orClauseItems[0][0].name.test('cat').should.equals(true);
			orClauseItems[0][1].name.test('Kitteh').should.equals(true);
		});
	});
});
<|endoftext|>