<commit_before>/* ************************************************************************
 *
 *    qxcompiler - node.js based replacement for the Qooxdoo python
 *    toolchain
 *
 *    https://github.com/qooxdoo/qxcompiler
 *
 *    Copyright:
 *      2011-2017 Zenesis Limited, http://www.zenesis.com
 *
 *    License:
 *      MIT: https://opensource.org/licenses/MIT
 *
 *      This software is provided under the same licensing terms as Qooxdoo,
 *      please see the LICENSE file in the Qooxdoo project's top-level directory
 *      for details.
 *
 *    Authors:
 *      * John Spackman (john.spackman@zenesis.com, @johnspackman)
 *
 * ************************************************************************/

var fs = require("fs");
var path = require("path");
var child_process = require("child_process");
var async = require('async');
var qx = require("qooxdoo");
var util = require("../../util");
var imageSize = require("image-size");
var jsonlint = require("jsonlint");

var log = util.createLog("resource-manager");

require("./ImageHandler");
require("./MetaHandler");
require("./SCSSHandler");

/**
 * Analyses library resources, collecting information into a cached database
 * file
 */
module.exports = qx.Class.define("qxcompiler.resources.Manager", {
  extend: qx.core.Object,

  /**
   * Constructor
   *
   * @param dbFilename
   *          {String?} database filename, default is "resource-db.json"
   */
  construct: function (analyser) {
    this.base(arguments);
    this.__analyser = analyser;
    this.__dbFilename = analyser.getResDbFilename() || "resource-db.json";
    this.__handlers = [
      new qxcompiler.resources.ImageHandler(),
      new qxcompiler.resources.MetaHandler(),
      new qxcompiler.resources.ScssHandler(this.__analyser)
    ];
  },

  members: {
    /** {String} filename of database */
    __dbFilename: null,

    /** {Object} Database */
    __db: null,

    /** the used analyser */
    __analyser: null,

    /** {Map{String,Library}} Lookup of libraries, indexed by resource URI */
    __librariesByResourceUri: null,

    /** {String[]} Array of all resource URIs, sorted alphabetically (ie these are the keys in __librariesByResourceUri) */
    __allResourceUris: null,

    /** {Map{String,Library}} Lookup of libraries, indexed by resource folder URI */
    __librariesByResourceFolderUri: null,

    /**
     * Loads the cached database
     *
     * @param callback
     */
    loadDatabase: function (callback) {
      var t = this;
      async.waterfall([
        function readDb(callback) {
          fs.exists(t.__dbFilename, function (exists) {
            if (exists)
              fs.readFile(t.__dbFilename, {
                encoding: "utf-8"
              }, callback);
            else
              callback(null, null);
          });
        },

        function parseDb(data, callback) {
          t.__db = data && data.trim().length ? jsonlint.parse(data) : {};
          callback(null, t.__db);
        }
      ], callback);
    },

    /**
     * Saves the database
     *
     * @param callback
     */
    saveDatabase: function (callback) {
      log.debug("saving resource manager database");
      fs.writeFile(this.__dbFilename, JSON.stringify(this.__db, null, 2), callback);
    },

    /**
     * Returns the loaded database
     *
     * @returns
     */
    getDatabase: function () {
      return this.__db;
    },

    /**
     * Finds the library needed for a resource; this depends on `findAllResources` having
     * already been called.  `uri` can include optional explicit namespace (eg "qx:blah/blah.png"),
     * otherwise the library resource lookups are examined to find the library.
     *
     * @param uri {String} URI
     * @return {Library?} the library, null if not found
     */
    findLibraryForResource: function (uri) {
      var t = this;
      var db = this.__db;

      // Explicit library?
      var pos = uri.indexOf(':');
      if (pos !== -1) {
        var ns = uri.substring(0, pos);
        var library = this.__analyser.findLibrary(ns);
        return library || null;
      }

      // Non-wildcards are a direct lookup
      var pos = uri.indexOf('*');
      if (pos === -1)
        pos = uri.indexOf('$'); // Variable references are effectively a wildcard lookup
      if (pos === -1) {
        var library = t.__librariesByResourceUri[uri] || null;
        return library;
      }

      // Strip wildcard
      var isFolderMatch = uri[pos - 1] === '/';
      uri = uri.substring(0, pos - 1);

      // Fast folder match
      if (isFolderMatch) {
        var library = t.__librariesByResourceFolderUri[uri] || null;
        return library;
      }

      // Slow scan
      pos = qxcompiler.utils.Values.binaryStartsWith(t.__allResourceUris, uri);
      if (pos > -1) {
        var firstUri = t.__allResourceUris[pos];
        var library = t.__librariesByResourceUri[firstUri] || t.__librariesByResourceFolderUri[firstUri] || null;
        return library;
      }

      return null;
    },

    /**
     * Scans all libraries looking for resources; this does not analyse the
     * files, simply compiles the list
     *
     * @param callback
     */
    findAllResources: function (callback) {
      var t = this;
      var db = this.__db;
      if (!db.resources)
        db.resources = {};
      t.__librariesByResourceUri = {};
      t.__librariesByResourceFolderUri = {};

      // Scan all the libraries
      async.forEach(t.__analyser.getLibraries(),
        function (library, callback) {
          var resources = db.resources[library.getNamespace()];
          if (!resources)
            db.resources[library.getNamespace()] = resources = {};
          var unconfirmed = {};
          for (let relFile in resources)
            unconfirmed[relFile] = true;
          var tasks = [];

          // Scans a folder, recursively, looking for resource files
          function scanDir(rootDir, dir, resource, doNotCopy, callback) {
            // Get the list of files
            fs.readdir(dir, function (err, files) {
              if (err)
                return callback(err);

              // and process each one
              async.forEach(files,
                function (file, callback) {
                  var absFile = path.join(dir, file);
                  fs.stat(absFile, function (err, stat) {
                    if (err)
                      return callback(err);

                    // Directory? recurse
                    if (stat.isDirectory()) {
                      scanDir(rootDir, absFile, resource, doNotCopy, callback);
                    } else {
                      var relFile = absFile.substring(rootDir.length + 1).replace(/\\/g, '/');
                      var fileInfo = resources[relFile];
                      delete unconfirmed[relFile];
                      if (!fileInfo)
                        fileInfo = resources[relFile] = {};
                      fileInfo.doNotCopy = doNotCopy;
                      fileInfo.resource = resource;
                      t.__librariesByResourceUri[relFile] = library;
                      var relDir = dir.substring(rootDir.length + 1).replace(/\\/g, '/');
                      t.__librariesByResourceFolderUri[relDir] = library;
                      var tmp = "";
                      relDir.split('/').forEach((seg) => {
                        if (tmp.length)
                          tmp += '/';
                        tmp += seg;
                        t.__librariesByResourceFolderUri[tmp] = library;
                      });

                      var handlers = t.__handlers.filter((handler) => handler.matches(absFile));
                      if (!handlers.length)
                        return callback();

                      if (handlers.some((handler) => handler.needsCompile(absFile, fileInfo, stat))) {
                        fileInfo.mtime = stat.mtime;
                        tasks.push({
                          fileInfo: fileInfo,
                          absFile: absFile,
                          library: library,
                          handlers: handlers
                        });
                      }
                      callback();
                    }
                  });
                },
                callback);
            });
          }

          function testUntested(callback) {
            // Check the unconfirmed resources to make sure that they still exist;
            //  delete from the database if they don't
            async.forEach(Object.keys(unconfirmed),
              function (relFile, callback) {
                let fileInfo = resources[relFile];
                let rootDir = path.join(library.getRootDir(), library.get(fileInfo.resource));
                fs.stat(path.join(rootDir, relFile), function (err, stat) {
                  if (err)
                    delete resources[relFile];
                  callback();
                });
              },
              callback);
          }

          function flushTasks(callback) {
            if (tasks.length == 0)
              return callback(null);

            // inspect all the files that need it
            var identifyQueue = async.queue(function (task, callback) {
              var promises = [];
              task.handlers.forEach((handler) => {
                promises.push(handler.compile(task.absFile, task.library, task.fileInfo));
              });
              Promise.all(promises)
                .then(() => {
                  callback();
                })
                .catch((err) => {
                  callback(err);
                });

            }, 20);

            identifyQueue.push(tasks);
            identifyQueue.drain = callback;
            identifyQueue.error = function (err) {
              t.error(err.stack || err);
            };
          }

          function scanResource(resource, doNotCopy, callback) {
            // If the root folder exists, scan it
            var rootDir = path.join(library.getRootDir(), library.get(resource));
            fs.exists(rootDir, function (exists) {
              if (!exists)
                return callback(null);
              scanDir(rootDir, rootDir, resource, doNotCopy, function (err) {
                if (err)
                  return callback(err);
                callback();
              });
            });
          };

          scanResource("resourcePath", false, function () {
            scanResource("themePath", true, function () {
              testUntested((err) => {
                if (err)
                  return callback(err);
                flushTasks(function (err) {
                  t.__allResourceUris = Object.keys(t.__librariesByResourceUri).sort();
                  callback(err);
                });
              });
            });
          });
        },
        callback);
    },

    /**
     * Collects information about the assets listed in srcPaths;
     * @param srcPaths
     */
    getAssets: function (srcPaths) {
      var t = this;
      var db = this.__db;

      // Generate a lookup that maps the resource name to the meta file that
      //  contains the composite
      var metas = {};
      for (var libraryName in db.resources) {
        var libraryData = db.resources[libraryName];
        for (var resourcePath in libraryData) {
          var fileInfo = libraryData[resourcePath];
          if (!fileInfo.meta)
            continue;
          for (var altPath in fileInfo.meta) {
            metas[altPath] = resourcePath;
          }
        }
      }

      // Collect a list of assets
      var assets = [];
      var assetPaths = {};

      function addAsset(library, resourceName) {
        if (assetPaths[resourceName] !== undefined)
          return;

        var libraryData = db.resources[library.getNamespace()];
        var fileInfo = libraryData[resourceName];
        if (fileInfo.doNotCopy === true)
          return;
        var asset = {
          libraryName: library.getNamespace(),
          filename: resourceName,
          fileInfo: fileInfo
        };

        // Does this have meta data for a composite?
        var metaPath = metas[resourceName];
        if (metaPath != null) {
          var metaInfo = libraryData[metaPath];
          if (metaInfo) {
            // Extract the fragment from the meta data for this particular resource
            var resMetaData = metaInfo.meta[resourceName];
            fileInfo.composite = resMetaData[3];
            fileInfo.x = resMetaData[4];
            fileInfo.y = resMetaData[5];
            if (!assetPaths[metaPath])
              srcPaths.push(metaPath);
          }
        }
        assets.push(asset);
        assetPaths[resourceName] = assets.length - 1;
      }

      for (var i = 0; i < srcPaths.length; i++) {
        var srcPath = srcPaths[i];
        var library = t.findLibraryForResource(srcPath);
        if (!library) {
          t.warn("Cannot find library for " + srcPath);
          continue;
        }

        var pos = srcPath.indexOf(':');
        if (pos > -1)
          srcPath = srcPath.substring(pos + 1);

        var libraryData = db.resources[library.getNamespace()];
        var pos = srcPath.indexOf('*');
        if (pos > -1) {
          srcPath = srcPath.substring(0, pos);
          for (var resourceName in libraryData) {
            if (resourceName.substring(0, srcPath.length) == srcPath)
              addAsset(library, resourceName);
          }
        } else {
          var fileInfo = libraryData[srcPath];
          if (fileInfo && (fileInfo.doNotCopy !== true))
            addAsset(library, srcPath);
        }
      }

      return assets;
    }
  }
});<commit_msg>Quick-fix - match file name and `require`<commit_after>/* ************************************************************************
 *
 *    qxcompiler - node.js based replacement for the Qooxdoo python
 *    toolchain
 *
 *    https://github.com/qooxdoo/qxcompiler
 *
 *    Copyright:
 *      2011-2017 Zenesis Limited, http://www.zenesis.com
 *
 *    License:
 *      MIT: https://opensource.org/licenses/MIT
 *
 *      This software is provided under the same licensing terms as Qooxdoo,
 *      please see the LICENSE file in the Qooxdoo project's top-level directory
 *      for details.
 *
 *    Authors:
 *      * John Spackman (john.spackman@zenesis.com, @johnspackman)
 *
 * ************************************************************************/

var fs = require("fs");
var path = require("path");
var child_process = require("child_process");
var async = require('async');
var qx = require("qooxdoo");
var util = require("../../util");
var imageSize = require("image-size");
var jsonlint = require("jsonlint");

var log = util.createLog("resource-manager");

require("./ImageHandler");
require("./MetaHandler");
require("./ScssHandler");

/**
 * Analyses library resources, collecting information into a cached database
 * file
 */
module.exports = qx.Class.define("qxcompiler.resources.Manager", {
  extend: qx.core.Object,

  /**
   * Constructor
   *
   * @param dbFilename
   *          {String?} database filename, default is "resource-db.json"
   */
  construct: function (analyser) {
    this.base(arguments);
    this.__analyser = analyser;
    this.__dbFilename = analyser.getResDbFilename() || "resource-db.json";
    this.__handlers = [
      new qxcompiler.resources.ImageHandler(),
      new qxcompiler.resources.MetaHandler(),
      new qxcompiler.resources.ScssHandler(this.__analyser)
    ];
  },

  members: {
    /** {String} filename of database */
    __dbFilename: null,

    /** {Object} Database */
    __db: null,

    /** the used analyser */
    __analyser: null,

    /** {Map{String,Library}} Lookup of libraries, indexed by resource URI */
    __librariesByResourceUri: null,

    /** {String[]} Array of all resource URIs, sorted alphabetically (ie these are the keys in __librariesByResourceUri) */
    __allResourceUris: null,

    /** {Map{String,Library}} Lookup of libraries, indexed by resource folder URI */
    __librariesByResourceFolderUri: null,

    /**
     * Loads the cached database
     *
     * @param callback
     */
    loadDatabase: function (callback) {
      var t = this;
      async.waterfall([
        function readDb(callback) {
          fs.exists(t.__dbFilename, function (exists) {
            if (exists)
              fs.readFile(t.__dbFilename, {
                encoding: "utf-8"
              }, callback);
            else
              callback(null, null);
          });
        },

        function parseDb(data, callback) {
          t.__db = data && data.trim().length ? jsonlint.parse(data) : {};
          callback(null, t.__db);
        }
      ], callback);
    },

    /**
     * Saves the database
     *
     * @param callback
     */
    saveDatabase: function (callback) {
      log.debug("saving resource manager database");
      fs.writeFile(this.__dbFilename, JSON.stringify(this.__db, null, 2), callback);
    },

    /**
     * Returns the loaded database
     *
     * @returns
     */
    getDatabase: function () {
      return this.__db;
    },

    /**
     * Finds the library needed for a resource; this depends on `findAllResources` having
     * already been called.  `uri` can include optional explicit namespace (eg "qx:blah/blah.png"),
     * otherwise the library resource lookups are examined to find the library.
     *
     * @param uri {String} URI
     * @return {Library?} the library, null if not found
     */
    findLibraryForResource: function (uri) {
      var t = this;
      var db = this.__db;

      // Explicit library?
      var pos = uri.indexOf(':');
      if (pos !== -1) {
        var ns = uri.substring(0, pos);
        var library = this.__analyser.findLibrary(ns);
        return library || null;
      }

      // Non-wildcards are a direct lookup
      var pos = uri.indexOf('*');
      if (pos === -1)
        pos = uri.indexOf('$'); // Variable references are effectively a wildcard lookup
      if (pos === -1) {
        var library = t.__librariesByResourceUri[uri] || null;
        return library;
      }

      // Strip wildcard
      var isFolderMatch = uri[pos - 1] === '/';
      uri = uri.substring(0, pos - 1);

      // Fast folder match
      if (isFolderMatch) {
        var library = t.__librariesByResourceFolderUri[uri] || null;
        return library;
      }

      // Slow scan
      pos = qxcompiler.utils.Values.binaryStartsWith(t.__allResourceUris, uri);
      if (pos > -1) {
        var firstUri = t.__allResourceUris[pos];
        var library = t.__librariesByResourceUri[firstUri] || t.__librariesByResourceFolderUri[firstUri] || null;
        return library;
      }

      return null;
    },

    /**
     * Scans all libraries looking for resources; this does not analyse the
     * files, simply compiles the list
     *
     * @param callback
     */
    findAllResources: function (callback) {
      var t = this;
      var db = this.__db;
      if (!db.resources)
        db.resources = {};
      t.__librariesByResourceUri = {};
      t.__librariesByResourceFolderUri = {};

      // Scan all the libraries
      async.forEach(t.__analyser.getLibraries(),
        function (library, callback) {
          var resources = db.resources[library.getNamespace()];
          if (!resources)
            db.resources[library.getNamespace()] = resources = {};
          var unconfirmed = {};
          for (let relFile in resources)
            unconfirmed[relFile] = true;
          var tasks = [];

          // Scans a folder, recursively, looking for resource files
          function scanDir(rootDir, dir, resource, doNotCopy, callback) {
            // Get the list of files
            fs.readdir(dir, function (err, files) {
              if (err)
                return callback(err);

              // and process each one
              async.forEach(files,
                function (file, callback) {
                  var absFile = path.join(dir, file);
                  fs.stat(absFile, function (err, stat) {
                    if (err)
                      return callback(err);

                    // Directory? recurse
                    if (stat.isDirectory()) {
                      scanDir(rootDir, absFile, resource, doNotCopy, callback);
                    } else {
                      var relFile = absFile.substring(rootDir.length + 1).replace(/\\/g, '/');
                      var fileInfo = resources[relFile];
                      delete unconfirmed[relFile];
                      if (!fileInfo)
                        fileInfo = resources[relFile] = {};
                      fileInfo.doNotCopy = doNotCopy;
                      fileInfo.resource = resource;
                      t.__librariesByResourceUri[relFile] = library;
                      var relDir = dir.substring(rootDir.length + 1).replace(/\\/g, '/');
                      t.__librariesByResourceFolderUri[relDir] = library;
                      var tmp = "";
                      relDir.split('/').forEach((seg) => {
                        if (tmp.length)
                          tmp += '/';
                        tmp += seg;
                        t.__librariesByResourceFolderUri[tmp] = library;
                      });

                      var handlers = t.__handlers.filter((handler) => handler.matches(absFile));
                      if (!handlers.length)
                        return callback();

                      if (handlers.some((handler) => handler.needsCompile(absFile, fileInfo, stat))) {
                        fileInfo.mtime = stat.mtime;
                        tasks.push({
                          fileInfo: fileInfo,
                          absFile: absFile,
                          library: library,
                          handlers: handlers
                        });
                      }
                      callback();
                    }
                  });
                },
                callback);
            });
          }

          function testUntested(callback) {
            // Check the unconfirmed resources to make sure that they still exist;
            //  delete from the database if they don't
            async.forEach(Object.keys(unconfirmed),
              function (relFile, callback) {
                let fileInfo = resources[relFile];
                let rootDir = path.join(library.getRootDir(), library.get(fileInfo.resource));
                fs.stat(path.join(rootDir, relFile), function (err, stat) {
                  if (err)
                    delete resources[relFile];
                  callback();
                });
              },
              callback);
          }

          function flushTasks(callback) {
            if (tasks.length == 0)
              return callback(null);

            // inspect all the files that need it
            var identifyQueue = async.queue(function (task, callback) {
              var promises = [];
              task.handlers.forEach((handler) => {
                promises.push(handler.compile(task.absFile, task.library, task.fileInfo));
              });
              Promise.all(promises)
                .then(() => {
                  callback();
                })
                .catch((err) => {
                  callback(err);
                });

            }, 20);

            identifyQueue.push(tasks);
            identifyQueue.drain = callback;
            identifyQueue.error = function (err) {
              t.error(err.stack || err);
            };
          }

          function scanResource(resource, doNotCopy, callback) {
            // If the root folder exists, scan it
            var rootDir = path.join(library.getRootDir(), library.get(resource));
            fs.exists(rootDir, function (exists) {
              if (!exists)
                return callback(null);
              scanDir(rootDir, rootDir, resource, doNotCopy, function (err) {
                if (err)
                  return callback(err);
                callback();
              });
            });
          };

          scanResource("resourcePath", false, function () {
            scanResource("themePath", true, function () {
              testUntested((err) => {
                if (err)
                  return callback(err);
                flushTasks(function (err) {
                  t.__allResourceUris = Object.keys(t.__librariesByResourceUri).sort();
                  callback(err);
                });
              });
            });
          });
        },
        callback);
    },

    /**
     * Collects information about the assets listed in srcPaths;
     * @param srcPaths
     */
    getAssets: function (srcPaths) {
      var t = this;
      var db = this.__db;

      // Generate a lookup that maps the resource name to the meta file that
      //  contains the composite
      var metas = {};
      for (var libraryName in db.resources) {
        var libraryData = db.resources[libraryName];
        for (var resourcePath in libraryData) {
          var fileInfo = libraryData[resourcePath];
          if (!fileInfo.meta)
            continue;
          for (var altPath in fileInfo.meta) {
            metas[altPath] = resourcePath;
          }
        }
      }

      // Collect a list of assets
      var assets = [];
      var assetPaths = {};

      function addAsset(library, resourceName) {
        if (assetPaths[resourceName] !== undefined)
          return;

        var libraryData = db.resources[library.getNamespace()];
        var fileInfo = libraryData[resourceName];
        if (fileInfo.doNotCopy === true)
          return;
        var asset = {
          libraryName: library.getNamespace(),
          filename: resourceName,
          fileInfo: fileInfo
        };

        // Does this have meta data for a composite?
        var metaPath = metas[resourceName];
        if (metaPath != null) {
          var metaInfo = libraryData[metaPath];
          if (metaInfo) {
            // Extract the fragment from the meta data for this particular resource
            var resMetaData = metaInfo.meta[resourceName];
            fileInfo.composite = resMetaData[3];
            fileInfo.x = resMetaData[4];
            fileInfo.y = resMetaData[5];
            if (!assetPaths[metaPath])
              srcPaths.push(metaPath);
          }
        }
        assets.push(asset);
        assetPaths[resourceName] = assets.length - 1;
      }

      for (var i = 0; i < srcPaths.length; i++) {
        var srcPath = srcPaths[i];
        var library = t.findLibraryForResource(srcPath);
        if (!library) {
          t.warn("Cannot find library for " + srcPath);
          continue;
        }

        var pos = srcPath.indexOf(':');
        if (pos > -1)
          srcPath = srcPath.substring(pos + 1);

        var libraryData = db.resources[library.getNamespace()];
        var pos = srcPath.indexOf('*');
        if (pos > -1) {
          srcPath = srcPath.substring(0, pos);
          for (var resourceName in libraryData) {
            if (resourceName.substring(0, srcPath.length) == srcPath)
              addAsset(library, resourceName);
          }
        } else {
          var fileInfo = libraryData[srcPath];
          if (fileInfo && (fileInfo.doNotCopy !== true))
            addAsset(library, srcPath);
        }
      }

      return assets;
    }
  }
});
<|endoftext|>


<commit_before>
import { resolve } from 'path';
import { writeFile, remove } from 'fs-extra';
import { execSync } from 'child_process';
import { Bridge } from '../src';
import Kapok from 'kapok-js';
import delay from 'delay';
import { Client } from 'promise-ws';

const command = resolve('bin/pot');

Kapok.config.shouldKillOnDone = true;

afterEach(async () => {
	await Kapok.killAll();
});

describe('cli `pot start`', () => {
	test('should work', async () => {
		return Kapok
			.start(command, ['start', '--entry', 'test/fixtures/server.js'])
			.assertUntil(/started/)
			.assertUntil('test server started')
			.done()
		;
	});

	test('should throw error if `--entry` is not exists.', async () => {
		return Kapok
			.start(command, ['start'])
			.assertUntil(/^ERROR Cannot find module/)
			.done()
		;
	});

	test('should `--name` work', async () => {
		const name = 'hello';
		return Kapok
			.start(command, [
				'start', '--entry', 'test/fixtures/server.js', '--name', name,
			])
			.assertUntil(new RegExp(`"${name}" started`, 'i'))
			.done()
		;
	});

	test('should auto restart after killed', async () => {
		return Kapok
			.start(command, [
				'start',
				'--entry=test/fixtures/server.js',
				'--maxRestarts=1',
			])
			.assertUntil(/started/)
			.assertUntil('test server started', {
				action: async () => {
					const bridges = await Bridge.getList();
					const { pid } = await bridges[0].getInfo();
					execSync(`kill -9 ${pid}`); // kill client process
				},
			})
			.assertUntil(/sleeped/)
			.assertUntil('test server started') // restarted
			.done()
		;
	});
});

describe('cli `pot start` with daemon mode', async () => {
	const name = 'daemon-testing';

	afterEach(async () => {
		try {
			await Kapok.start(command, ['stop', name, '-f']).done();
		}
		catch (err) {}
	});

	test('should `daemon` mode work', async () => {
		await Kapok
			.start(command, [
				'start',
				'--name', name,
				'--env.PORT', 3010,
				'--entry', 'test/fixtures/socket.js',
				'--daemon',
			])
			.done()
		;

		await delay(1000);
		await Client.connect('ws://127.0.0.1:3010', async (client) => {
			const text = await client.emit('test', 'test');
			expect(text).toBe('test');
		});
	});
});

describe('cli `pot start` with config file', async () => {
	afterEach(async () => {
		await remove(resolve(__dirname, '.potrc.json'));
		await remove(resolve(__dirname, '.potrc'));
	});

	async function writeConfig(filename, data) {
		const file = resolve(__dirname, filename);
		return writeFile(file, data, 'utf8');
	}

	test('should read `.potrc` config file', async () => {
		await writeConfig('.potrc', `module.exports = { entry: 'fixtures/server.js' }`);
		return Kapok
			.start(command, ['start'], { cwd: __dirname })
			.assertUntil('test server started')
			.done()
		;
	});

	test('should read `.potrc.json` config file', async () => {
		await writeConfig('.potrc.json', `{ "entry": "fixtures/server.js" }`);
		return Kapok
			.start(command, ['start'], { cwd: __dirname })
			.assertUntil('test server started')
			.done()
		;
	});
});

describe('cli `pot stop`', () => {
	test('should work', async () => {
		await Kapok
			.start(command, ['start', '--entry', 'test/fixtures/server.js'])
			.until('test server started', {
				async action() {
					return Kapok
						.start(command, ['stop', '-f'])
						.assert('INFO "pot-js" stopped')
						.done()
					;
				},
			})
			.done()
		;
	});

	test('should throw error when no process is running', async () => {
		return Kapok
			.start(command, ['stop'])
			.assert('ERROR No process is running')
			.done()
		;
	});
});

// FIXME: hard to test
describe.skip('cli `pot ls`', () => {
	test('should work`', async () => {
		jest.setTimeout(20000);
		const createClient = async (port, name) => {
			await Kapok
				.start(command, [
					'start',
					'--entry', 'test/fixtures/server.js',
				], {
					env: {
						...process.env,
						PORT: port,
					},
				}, name)
				.until('test server started')
				.done()
			;
		};

		await createClient(3001, 'app-1');
		await createClient(3002, 'app-2');

		await Kapok
			.start(command, ['ls'])
			.ignoreUntil(/┐\s*$/)
			.joinUntil(/Pid/)
			.assert((message) => {
				return ['Name', 'Status', 'Crashes', 'Memory', 'CPU', 'Started', 'Pid']
					.every((key) => message.includes(key))
				;
			})
			.assertUntil(/app-1/)
			.assertUntil(/app-2/)
			.done()
		;
	});
});

describe('cli `pot dir`', () => {
	test('should work', async () => {
		return Kapok
			.start(
				command,
				['start', '--entry', 'test/fixtures/server.js', '--name', 'app'],
				{ env: { ...process.env, PORT: 3001 } },
			)
			.until('test server started', {
				async assert() {
					return Kapok
						.start(command, ['dir'])
						.assertUntil(process.cwd())
						.done()
					;
				}
			})
			.done()
		;
	});
});
<commit_msg>update testing<commit_after>
import { resolve } from 'path';
import { writeFile, remove } from 'fs-extra';
import { execSync } from 'child_process';
import { Bridge } from '../src';
import Kapok from 'kapok-js';
import delay from 'delay';
import { Client } from 'promise-ws';

const command = resolve('bin/pot');

Kapok.config.shouldKillOnDone = true;

afterEach(async () => {
	await Kapok.killAll();
});

describe('cli `pot start`', () => {
	test('should work', async () => {
		return Kapok
			.start(command, ['start', '--entry', 'test/fixtures/server.js'])
			.assertUntil(/started/)
			.assertUntil('test server started')
			.done()
		;
	});

	test('should throw error if `--entry` is not exists.', async () => {
		return Kapok
			.start(command, ['start'])
			.assertUntil(/^ERROR Cannot find module/)
			.done()
		;
	});

	test('should `--name` work', async () => {
		const name = 'hello';
		return Kapok
			.start(command, [
				'start', '--entry', 'test/fixtures/server.js', '--name', name,
			])
			.assertUntil(new RegExp(`"${name}" started`, 'i'))
			.done()
		;
	});

	test('should auto restart after killed', async () => {
		return Kapok
			.start(command, [
				'start',
				'--entry=test/fixtures/server.js',
				'--maxRestarts=1',
			])
			.assertUntil(/started/)
			.assertUntil('test server started', {
				action: async () => {
					const bridges = await Bridge.getList();
					const { pid } = await bridges[0].getInfo();
					execSync(`kill -9 ${pid}`); // kill client process
				},
			})
			.assertUntil(/sleeped/)
			.assertUntil('test server started') // restarted
			.done()
		;
	});
});

describe('cli `pot start` with daemon mode', async () => {
	const name = 'daemon-testing';

	afterEach(async () => {
		try {
			await Kapok.start(command, ['stop', name, '-f']).done();
		}
		catch (err) {}
	});

	test('should `daemon` mode work', async () => {
		await Kapok
			.start(command, [
				'start',
				'--name', name,
				'--env.PORT', 3010,
				'--entry', 'test/fixtures/socket.js',
				'--daemon',
			])
			.done()
		;

		await delay(2000);
		await Client.connect('ws://127.0.0.1:3010', async (client) => {
			const text = await client.emit('test', 'test');
			expect(text).toBe('test');
		});
	});
});

describe('cli `pot start` with config file', async () => {
	afterEach(async () => {
		await remove(resolve(__dirname, '.potrc.json'));
		await remove(resolve(__dirname, '.potrc'));
	});

	async function writeConfig(filename, data) {
		const file = resolve(__dirname, filename);
		return writeFile(file, data, 'utf8');
	}

	test('should read `.potrc` config file', async () => {
		await writeConfig('.potrc', `module.exports = { entry: 'fixtures/server.js' }`);
		return Kapok
			.start(command, ['start'], { cwd: __dirname })
			.assertUntil('test server started')
			.done()
		;
	});

	test('should read `.potrc.json` config file', async () => {
		await writeConfig('.potrc.json', `{ "entry": "fixtures/server.js" }`);
		return Kapok
			.start(command, ['start'], { cwd: __dirname })
			.assertUntil('test server started')
			.done()
		;
	});
});

describe('cli `pot stop`', () => {
	test('should work', async () => {
		await Kapok
			.start(command, ['start', '--entry', 'test/fixtures/server.js'])
			.until('test server started', {
				async action() {
					return Kapok
						.start(command, ['stop', '-f'])
						.assert('INFO "pot-js" stopped')
						.done()
					;
				},
			})
			.done()
		;
	});

	test('should throw error when no process is running', async () => {
		return Kapok
			.start(command, ['stop'])
			.assert('ERROR No process is running')
			.done()
		;
	});
});

// FIXME: hard to test
describe.skip('cli `pot ls`', () => {
	test('should work`', async () => {
		jest.setTimeout(20000);
		const createClient = async (port, name) => {
			await Kapok
				.start(command, [
					'start',
					'--entry', 'test/fixtures/server.js',
				], {
					env: {
						...process.env,
						PORT: port,
					},
				}, name)
				.until('test server started')
				.done()
			;
		};

		await createClient(3001, 'app-1');
		await createClient(3002, 'app-2');

		await Kapok
			.start(command, ['ls'])
			.ignoreUntil(/┐\s*$/)
			.joinUntil(/Pid/)
			.assert((message) => {
				return ['Name', 'Status', 'Crashes', 'Memory', 'CPU', 'Started', 'Pid']
					.every((key) => message.includes(key))
				;
			})
			.assertUntil(/app-1/)
			.assertUntil(/app-2/)
			.done()
		;
	});
});

describe('cli `pot dir`', () => {
	test('should work', async () => {
		return Kapok
			.start(
				command,
				['start', '--entry', 'test/fixtures/server.js', '--name', 'app'],
				{ env: { ...process.env, PORT: 3001 } },
			)
			.until('test server started', {
				async assert() {
					return Kapok
						.start(command, ['dir'])
						.assertUntil(process.cwd())
						.done()
					;
				}
			})
			.done()
		;
	});
});
<|endoftext|>


<commit_before>
/**
 * @list dependencies
 **/

var mongoose = require('mongoose');

/**
 * @method paginate
 * @param {Object} query Mongoose Query Object
 * @param {Number} pageNumber
 * @param {Number} resultsPerPage
 * Extend Mongoose Models to paginate queries
 **/

mongoose.Model.paginate = function(q, pageNumber, resultsPerPage, callback) {
  var model = this;
  callback = callback || function(){};

  var skipFrom = (pageNumber * resultsPerPage) - resultsPerPage;
  var query = model.find(q).skip(skipFrom).limit(resultsPerPage);

  query.exec(function(error, results) {
    if (error) {
      callback(error, null, null);
    } else {
      model.count(q, function(error, count) {
        if (error) {
          callback(error, null, null);
        } else {
          var pageCount = Math.floor(count / resultsPerPage);
          if (pageCount == 0) {
            pageCount = 1;
          };
          callback(null, pageCount, results);
        };
      });
    };
  });
};

/* EOF */<commit_msg>Fixed pageCount math operation<commit_after>/**
 * @list dependencies
 **/

var mongoose = require('mongoose');

/**
 * @method paginate
 * @param {Object} query Mongoose Query Object
 * @param {Number} pageNumber
 * @param {Number} resultsPerPage
 * Extend Mongoose Models to paginate queries
 **/

mongoose.Model.paginate = function(q, pageNumber, resultsPerPage, callback) {
  var model = this;
  callback = callback || function(){};

  var skipFrom = (pageNumber * resultsPerPage) - resultsPerPage;
  var query = model.find(q).skip(skipFrom).limit(resultsPerPage);

  query.exec(function(error, results) {
    if (error) {
      callback(error, null, null);
    } else {
      model.count(q, function(error, count) {
        if (error) {
          callback(error, null, null);
        } else {
          var pageCount = Math.ceil(count / resultsPerPage);
          if (pageCount == 0) {
            pageCount = 1;
          };
          callback(null, pageCount, results);
        };
      });
    };
  });
};

/* EOF */
<|endoftext|>


<commit_before>// Batch Request

var _ = require('lodash'),
    check = require('validator').check,
    methods = require('methods'),
    Promise = require('bluebird'),
    request = require('request'),
    url = require('url');

var batchRequest = function(params) {

    // Set default option values
    params = params || {};
    params.localOnly = (typeof params.localOnly === 'undefined') ? true : params.localOnly;
    params.httpsAlways = (typeof params.localOnly === 'undefined') ? false : params.localOnly;
    params.max = (typeof params.max === 'undefined') ? 20 : params.max;
    params.validateRespond = (typeof params.validateRespond === 'undefined') ? true : params.validateRespond;

    var batch = function(req, res, next) {
        // Here we assume it the request has already been validated, either by
        // our included middleware or otherwise by the app developer.

        // We also assume it has been run through some middleware like
        // express.bodyParser() or express.json() to parse the requests

        var requests = req.body;

        // First, let's fire off all calls without any dependencies, accumulate their promises
        var requestPromises = _.reduce(requests, function(promises, r, key) {
            if (!r.dependency || r.dependency === 'none') {
                promises[key] = new Promise(function(resolve, reject) {
                    request(r, function(error, response, body) {
                        var resp = {};
                        resp.key = key;
                        resp.data = response;
                        resolve(resp);
                    });
                });
            }
            // And while we do that, build the dependency object with those items as keys
            // { key: Promise }
            return promises;
        }, {});

        // Then recursively iterate over all items with dependencies, resolving some at each pass
        var recurseDependencies = function (requests) {
            // End state hit when the number of promises we have matches the number
            // of request objects we started with.
            if (_.size(requestPromises) >= _.size(requests)) {
                return;
            } else {
                _.each(requestPromises, function(rp, key) {
                    var dependentKey = null;
                    var dependent = _.find(requests, function(request, dKey) {
                        dependentKey = dKey;
                        return request.dependency === key && (typeof requestPromises[dKey] === 'undefined');
                    });
                    if (dependent) {
                        requestPromises[dependentKey] = rp.then(function() {
                            return new Promise(function(resolve, reject) {
                                request(dependent, function(error, response, body) {
                                    var resp = {};
                                    resp.key = dependentKey;
                                    resp.data = response;
                                    resolve(resp);
                                });
                            });
                        });
                    }
                });
                recurseDependencies(requests);
            }
        };

        // Recurse dependencies
        recurseDependencies(requests);

        // Wait for all to complete before responding
        Promise.all(_.values(requestPromises)).then(function(results) {
            var result = {};
            results.forEach(function(item) {
                result[item.key] = item.data;
            });
            res.json(result);
            next();
        });
    };

    batch.validate = function(req, res, next) {
        var err = null;
        var requests = req.body;

        // Validation on Request object as a whole
        try {
            check(_.size(requests), 'Cannot make a batch request with an empty request object').min(1);
            check(_.size(requests), 'Over the max request limit. Please limit batches to ' + params.max + ' requests').max(params.max);
            if (req.method === 'POST' && !req.is('json')) {
                throw new Error('Batch Request will only accept body as json');
            }
        } catch (e) {
            err = {
                error: {
                    'message': e.message,
                    'type': 'ValidationError'
                }
            };
        }

        // Validation on each request object
        _.each(requests, function(r, key) {

            // If no method provided, default to GET
            r.method = (typeof r.method === 'string') ? r.method.toLowerCase() : 'get';

            // Accept either uri or url (this is what request does, we just mirror)
            r.url = r.url || r.uri;

            try {
                check(r.url, 'Invalid URL').isUrl();
                check(r.method, 'Invalid method').isIn(methods);
            } catch (e) {
                err = {
                    error: {
                        'message': e.message,
                        'request': key,
                        'type': 'ValidationError'
                    }
                };
            }

            // TODO: Convert relative paths to full paths
            // var fullURL = req.protocol + "://" + req.get('host') + req.url;

        });

        if (err !== null) {
            res.send(400, err);
            next(err);
        } else {
            next();
        }
    };

    return batch;
};

module.exports = batchRequest;
<commit_msg>Simplify usage of promises<commit_after>// Batch Request

var _ = require('lodash'),
    check = require('validator').check,
    methods = require('methods'),
    Promise = require('bluebird'),
    request = require('request'),
    requestGet = Promise.promisify(request),
    url = require('url');

var batchRequest = function(params) {

    // Set default option values
    params = params || {};
    params.localOnly = (typeof params.localOnly === 'undefined') ? true : params.localOnly;
    params.httpsAlways = (typeof params.localOnly === 'undefined') ? false : params.localOnly;
    params.max = (typeof params.max === 'undefined') ? 20 : params.max;
    params.validateRespond = (typeof params.validateRespond === 'undefined') ? true : params.validateRespond;

    var batch = function(req, res, next) {
        // Here we assume it the request has already been validated, either by
        // our included middleware or otherwise by the app developer.

        // We also assume it has been run through some middleware like
        // express.bodyParser() or express.json() to parse the requests

        var requests = req.body;

        // First, let's fire off all calls without any dependencies, accumulate their promises
        var requestPromises = _.reduce(requests, function(promises, r, key) {
            if (!r.dependency || r.dependency === 'none') {
                promises[key] = requestGet(r).spread(function(response, body) {
                    return response;
                });
            }
            // And while we do that, build the dependency object with those items as keys
            // { key: Promise }
            return promises;
        }, {});

        // Then recursively iterate over all items with dependencies, resolving some at each pass
        var recurseDependencies = function (requests) {
            // End state hit when the number of promises we have matches the number
            // of request objects we started with.
            if (_.size(requestPromises) >= _.size(requests)) {
                return;
            } else {
                _.each(requestPromises, function(rp, key) {
                    var dependentKey = null;
                    var dependent = _.find(requests, function(request, dKey) {
                        dependentKey = dKey;
                        return request.dependency === key && (typeof requestPromises[dKey] === 'undefined');
                    });
                    if (dependent) {
                        requestPromises[dependentKey] = rp.then(function() {
                            return requestGet(dependent);
                        }).spread(function(response, body) {
                            return response;
                        });
                    }
                });
                recurseDependencies(requests);
            }
        };

        // Recurse dependencies
        recurseDependencies(requests);

        // Wait for all to complete before responding
        Promise.props(requestPromises).then(function(result) {
            res.json(result);
            next();
        });
    };

    batch.validate = function(req, res, next) {
        var err = null;
        var requests = req.body;

        // Validation on Request object as a whole
        try {
            check(_.size(requests), 'Cannot make a batch request with an empty request object').min(1);
            check(_.size(requests), 'Over the max request limit. Please limit batches to ' + params.max + ' requests').max(params.max);
            if (req.method === 'POST' && !req.is('json')) {
                throw new Error('Batch Request will only accept body as json');
            }
        } catch (e) {
            err = {
                error: {
                    'message': e.message,
                    'type': 'ValidationError'
                }
            };
        }

        // Validation on each request object
        _.each(requests, function(r, key) {

            // If no method provided, default to GET
            r.method = (typeof r.method === 'string') ? r.method.toLowerCase() : 'get';

            // Accept either uri or url (this is what request does, we just mirror)
            r.url = r.url || r.uri;

            try {
                check(r.url, 'Invalid URL').isUrl();
                check(r.method, 'Invalid method').isIn(methods);
            } catch (e) {
                err = {
                    error: {
                        'message': e.message,
                        'request': key,
                        'type': 'ValidationError'
                    }
                };
            }

            // TODO: Convert relative paths to full paths
            // var fullURL = req.protocol + "://" + req.get('host') + req.url;

        });

        if (err !== null) {
            res.send(400, err);
            next(err);
        } else {
            next();
        }
    };

    return batch;
};

module.exports = batchRequest;
<|endoftext|>


<commit_before>import React from 'react'
import { observer } from 'mobx-react'
// text mapbox-gl and uglify ❤
import mapboxgl from 'mapbox-gl'
// test packages written for newer node version
import ky from 'ky'
import { ReactComponent as Logo } from 'images/logo.svg'
import mmm from 'images/mmmpiselli.jpg'
import styles from './App.module.css'

// test decorators
@observer
export default class App extends React.Component {
  // test class properties
  state = {}

  render() {
    // test object spread
    const { ...props } = this.props

    // test optionsl chaining
    const foo = props?.foo

    console.log(foo, mapboxgl, ky)

    // test pipeline operator
    const exclaim = string => `${string}!`
    const message = 'Hello world' |> exclaim

    return (

        {/* test svgs */}
        <Logo className="w5" />

        {/* test images */}

        {/* test css modules */}

{message}

    )
  }
}
<commit_msg>✅ Add spread operator to fixtures<commit_after>import React from 'react'
import { observer } from 'mobx-react'
// text mapbox-gl and uglify ❤
import mapboxgl from 'mapbox-gl'
// test packages written for newer node version
import ky from 'ky'
import { ReactComponent as Logo } from 'images/logo.svg'
import mmm from 'images/mmmpiselli.jpg'
import styles from './App.module.css'

// test decorators
@observer
export default class App extends React.Component {
  // test class properties
  state = {}

  render() {
    // test object spread
    const { ...props } = this.props

    // test optionsl chaining
    const foo = props?.foo

    console.log(foo, mapboxgl, ky)

    // test pipeline operator
    const exclaim = string => `${string}!`
    const message = 'Hello world' |> exclaim

    return (

        {/* test svgs */}
        <Logo className="w5" />

        {/* test images */}

        {/* test css modules */}

{message}

    )
  }
}
<|endoftext|>


<commit_before>/**
 * Render the point.
 * @private
 */
cg.Renderer.prototype._renderPoints = function (blockPointsGroup) {
    var points = blockPointsGroup
        .selectAll("g")
        .data(function (block) { return block.inputs.concat(block.outputs); });
    this._createPoints(points);
    this._updatePoints(points);
    this._removePoints(points);
};

/**
 *
 * @param points
 * @private
 */
cg.Renderer.prototype._createPoints = function (points) {
    var renderer = this;
    var pointGroup = points
        .enter()
        .append("svg:g")
        .attr({
            "class": function (point) { return "point type-" + point.type + " " + (point.isInput ? "input" : "output"); }
        });
    var cursorPoint = null;
    var cursorConnections = [];
    var _getCursorPointConnections = function () {
        return renderer._cursorConnectionLayer
            .selectAll("path")
            .data(cursorConnections);
    };
    pointGroup
        .call(d3.behavior.drag()
            .on("dragstart", function () {
                var pointElement = d3.select(this);
                var point = pointElement.datum();
                cursorPoint = new cg.Renderer.Point(point, renderer._getPointAbsolutePosition(point));
                cursorConnections.push(new cg.Connection(cursorPoint, point));
                renderer._renderConnections(_getCursorPointConnections());
                pandora.preventCallback(d3.event.sourceEvent);
            })
            .on("drag", function () {
                cursorPoint.position.x += d3.event.dx;
                cursorPoint.position.y += d3.event.dy;
                cursorPoint.emit("move");
            })
            .on("dragend", function () {
                var connection = cursorConnections.pop();
                var r = 20;
                var pointArea = new pandora.Box2(cursorPoint.position.subtract(r / 2, r / 2), new pandora.Vec2(r, r));
                var newPoint = renderer._getNearestPointInArea(pointArea);
                if (newPoint !== null && connection.replacePoint(cursorPoint, newPoint)) {
                    renderer._graph.addConnection(connection);
                } else {
                    renderer._graph.emit("error", new cg.GraphError("No " + (cursorPoint.isInput ? "input" : "output") + " found around"));
                }
                renderer._renderConnections(renderer.getConnections());
                renderer._renderConnections(_getCursorPointConnections());
            })
        )
        .each(function(point) {
            d3.select(this)
                .append("svg:circle")
                .attr({
                    "class": "circle"
                });
            pandora.polymorphic(point.block.model, {
                "Action": function () {
                    d3.select(this)
                        .append("svg:text")
                        .attr({
                            "class": "description",
                            "text-anchor": function (point) { return point.isInput ? "start" : "end"; }
                        });
                }.bind(this),
                "_": pandora.defaultCallback
            });
        });
};

/**
 *
 * @param points
 * @private
 */
cg.Renderer.prototype._updatePoints = function (points) {
    var renderer = this;
    points
        .attr({
            "transform": function (point) {
                var value = this._getPointRelativePosition(point).toArray();
                pandora.polymorphic(point.block.model, {
                    "Action": pandora.defaultCallback,
                    "Getter": function () { value[1] = renderer._config.block.heading / 2; },
                    "Picker": function () { value[1] = renderer._config.block.heading / 2; }
                });
                return "translate(" + value + ")";
            }.bind(this)
        });
    points
        .select(".circle")
        .attr({
            "class": function(point) { return point.connections.length ? "" : "empty"; },
            "r": this._config.point["circle-size"],
            "x": 0,
            "y" : 0
        });
    points
        .select(".description")
        .text(function(point) { return point.name; })
        .attr({
            "x": function(point) { return (point.isInput ? 1 : -1) * (this._config.point["circle-size"] * 2 + this._config.point.padding); }.bind(this),
            "y": this._config.point["circle-size"]
        });
    points
        .each(function(point) {
            point.block.data.pointHeight = renderer._config.point.height;
            if (point.isInput) {
                point.block.data.maxInputWidth = Math.max(point.block.data.maxInputWidth, this.getBBox().width);
            } else {
                point.block.data.maxOutputWidth = Math.max(point.block.data.maxOutputWidth, this.getBBox().width);
            }
        });
};

/**
 *
 * @param points
 * @private
 */
cg.Renderer.prototype._removePoints = function (points) {
    points
        .exit()
        .remove();
};

/**
 * Get relative point position in action
 * @param point {cg.Point}
 * @returns {pandora.Vec2}
 * @private
 */
cg.Renderer.prototype._getPointRelativePosition = function (point) {
    if (point.block.data.computedWidth === undefined) {
        return new pandora.Vec2();
    }
    return new pandora.Vec2(
        point.isInput ? this._config.block["padding"] : point.block.data.computedWidth - this._config.block.padding,
        point.block.data.computedHeadingOffset + point.index * this._config.point.height
    );
};

/**
 * Get absolute point position
 * @param point {cg.Point}
 * @returns {pandora.Vec2}
 * @private
 */
cg.Renderer.prototype._getPointAbsolutePosition = function (point) {
    if (point instanceof cg.Point) {
        return point.block.absolutePosition.add(this._getPointRelativePosition(point));
    }
    return point.position;
};<commit_msg>Update cursor connection selector<commit_after>/**
 * Render the point.
 * @private
 */
cg.Renderer.prototype._renderPoints = function (blockPointsGroup) {
    var points = blockPointsGroup
        .selectAll("g")
        .data(function (block) { return block.inputs.concat(block.outputs); });
    this._createPoints(points);
    this._updatePoints(points);
    this._removePoints(points);
};

/**
 *
 * @param points
 * @private
 */
cg.Renderer.prototype._createPoints = function (points) {
    var renderer = this;
    var pointGroup = points
        .enter()
        .append("svg:g")
        .attr({
            "class": function (point) { return "point type-" + point.type + " " + (point.isInput ? "input" : "output"); }
        });
    var cursorPoint = null;
    var cursorConnections = [];
    var _getCursorPointConnections = function () {
        return renderer._cursorConnectionLayer
            .selectAll(".connection")
            .data(cursorConnections);
    };
    pointGroup
        .call(d3.behavior.drag()
            .on("dragstart", function () {
                var pointElement = d3.select(this);
                var point = pointElement.datum();
                cursorPoint = new cg.Renderer.Point(point, renderer._getPointAbsolutePosition(point));
                cursorConnections.push(new cg.Connection(cursorPoint, point));
                renderer._renderConnections(_getCursorPointConnections());
                pandora.preventCallback(d3.event.sourceEvent);
            })
            .on("drag", function () {
                cursorPoint.position.x += d3.event.dx;
                cursorPoint.position.y += d3.event.dy;
                cursorPoint.emit("move");
            })
            .on("dragend", function () {
                var connection = cursorConnections.pop();
                var r = 20;
                var pointArea = new pandora.Box2(cursorPoint.position.subtract(r / 2, r / 2), new pandora.Vec2(r, r));
                var newPoint = renderer._getNearestPointInArea(pointArea);
                if (newPoint !== null && connection.replacePoint(cursorPoint, newPoint)) {
                    renderer._graph.addConnection(connection);
                } else {
                    renderer._graph.emit("error", new cg.GraphError("No " + (cursorPoint.isInput ? "input" : "output") + " found around"));
                }
                renderer._renderConnections(renderer.getConnections());
                renderer._removeConnections(_getCursorPointConnections());
            })
        )
        .each(function(point) {
            d3.select(this)
                .append("svg:circle")
                .attr({
                    "class": "circle"
                });
            pandora.polymorphic(point.block.model, {
                "Action": function () {
                    d3.select(this)
                        .append("svg:text")
                        .attr({
                            "class": "description",
                            "text-anchor": function (point) { return point.isInput ? "start" : "end"; }
                        });
                }.bind(this),
                "_": pandora.defaultCallback
            });
        });
};

/**
 *
 * @param points
 * @private
 */
cg.Renderer.prototype._updatePoints = function (points) {
    var renderer = this;
    points
        .attr({
            "transform": function (point) {
                var value = this._getPointRelativePosition(point).toArray();
                pandora.polymorphic(point.block.model, {
                    "Action": pandora.defaultCallback,
                    "Getter": function () { value[1] = renderer._config.block.heading / 2; },
                    "Picker": function () { value[1] = renderer._config.block.heading / 2; }
                });
                return "translate(" + value + ")";
            }.bind(this)
        });
    points
        .select(".circle")
        .attr({
            "class": function(point) { return point.connections.length ? "" : "empty"; },
            "r": this._config.point["circle-size"],
            "x": 0,
            "y" : 0
        });
    points
        .select(".description")
        .text(function(point) { return point.name; })
        .attr({
            "x": function(point) { return (point.isInput ? 1 : -1) * (this._config.point["circle-size"] * 2 + this._config.point.padding); }.bind(this),
            "y": this._config.point["circle-size"]
        });
    points
        .each(function(point) {
            point.block.data.pointHeight = renderer._config.point.height;
            if (point.isInput) {
                point.block.data.maxInputWidth = Math.max(point.block.data.maxInputWidth, this.getBBox().width);
            } else {
                point.block.data.maxOutputWidth = Math.max(point.block.data.maxOutputWidth, this.getBBox().width);
            }
        });
};

/**
 *
 * @param points
 * @private
 */
cg.Renderer.prototype._removePoints = function (points) {
    points
        .exit()
        .remove();
};

/**
 * Get relative point position in action
 * @param point {cg.Point}
 * @returns {pandora.Vec2}
 * @private
 */
cg.Renderer.prototype._getPointRelativePosition = function (point) {
    if (point.block.data.computedWidth === undefined) {
        return new pandora.Vec2();
    }
    return new pandora.Vec2(
        point.isInput ? this._config.block["padding"] : point.block.data.computedWidth - this._config.block.padding,
        point.block.data.computedHeadingOffset + point.index * this._config.point.height
    );
};

/**
 * Get absolute point position
 * @param point {cg.Point}
 * @returns {pandora.Vec2}
 * @private
 */
cg.Renderer.prototype._getPointAbsolutePosition = function (point) {
    if (point instanceof cg.Point) {
        return point.block.absolutePosition.add(this._getPointRelativePosition(point));
    }
    return point.position;
};<|endoftext|>


<commit_before>/**
 * Pseudo-rule for metadata extraction: patent-policy.
 */

// 'self.name' would be 'metadata.patent-policy'

const w3capi = require('node-w3capi');

exports.name = "metadata.patent-policy";

exports.check = function(sr, done) {

    const deliverers = sr.getDelivererIDs()
    ,     docDate = sr.getDocumentDate();

    if (deliverers.length) {
        w3capi.apiKey = process.env.W3C_API_KEY;
        w3capi.group(deliverers[0]).charters().fetch({ embed: true }, (err, charters) => {
          if (err) {
              return done();
          } else {
              let patentPolicy;
              charters.forEach (c => {
                  if (docDate >= new Date(c.start) && docDate <= new Date(c.end)) {
                      patentPolicy = c["patent-policy"];
                  }
              });
              return done({patentPolicy: patentPolicy});
          }
        });
    }
};
<commit_msg>fix member submission stuck, fix #969 (#971)<commit_after>/**
 * Pseudo-rule for metadata extraction: patent-policy.
 */

// 'self.name' would be 'metadata.patent-policy'

const w3capi = require('node-w3capi');

exports.name = "metadata.patent-policy";

exports.check = function(sr, done) {

    const deliverers = sr.getDelivererIDs()
    ,     docDate = sr.getDocumentDate();

    if (deliverers.length) {
        w3capi.apiKey = process.env.W3C_API_KEY;
        w3capi.group(deliverers[0]).charters().fetch({ embed: true }, (err, charters) => {
          if (err) {
              return done();
          } else {
              let patentPolicy;
              charters.forEach (c => {
                  if (docDate >= new Date(c.start) && docDate <= new Date(c.end)) {
                      patentPolicy = c["patent-policy"];
                  }
              });
              return done({patentPolicy: patentPolicy});
          }
        });
    } else {
        return done();
    }
};
<|endoftext|>


<commit_before>/**
 * Requires an extra comma following the final element of an array or object literal.
 *
 * Types: `Boolean` or `Object`
 *
 * Values:
 *
 * - `true`: validates all arrays and objects
 * - `Object`:
 *     - `ignoreSingleValue`: allows single property objects and single element arrays to not require a trailing comma
 *     - `ignoreSingleLine`: allows objects and arrays on a single line to not require a trailing comma
 *
 * #### Example
 *
 * ```js
 * "requireTrailingComma": true
 * ```
 *
 * ##### Valid
 *
 * ```js
 * var foo = [1, 2, 3,];
 * var bar = {a: "a", b: "b",}
 * ```
 *
 * ##### Valid with ignoreSingleValue
 *
 * ```js
 * var car = [1];
 * var dar = {a: "a"};
 * ```
 *
 * ##### Valid with ignoreSingleLine
 *
 * ```js
 * var car = [1, 2, 3];
 * var dar = {a: "a", b: "b"};
 * ```
 *
 * ##### Invalid
 *
 * ```js
 * var foo = [1, 2, 3];
 * var bar = {a: "a", b: "b"}
 * ```
 */

var assert = require('assert');

module.exports = function() {};

module.exports.prototype = {
    configure: function(options) {

        if (typeof options === 'object') {
            if ('ignoreSingleValue' in options) {
                assert(
                    options.ignoreSingleValue === true,
                    this.getOptionName() + ' option ignoreSingleValue requires true value or should be removed'
                );
                this._ignoreSingleValue = true;
            }
            if ('ignoreSingleLine' in options) {
                assert(
                    options.ignoreSingleLine === true,
                    this.getOptionName() + ' option ignoreSingleLine requires true value or should be removed'
                );
                this._ignoreSingleLine = true;
            }
        } else {
            assert(
                options === true,
                this.getOptionName() + ' option requires a true value or should be removed'
            );
        }
    },

    getOptionName: function() {
        return 'requireTrailingComma';
    },

    check: function(file, errors) {
        var _this = this;

        file.iterateNodesByType(['ObjectExpression', 'ArrayExpression'], function(node) {
            var isObject = node.type === 'ObjectExpression';
            var entities = isObject ? node.properties : node.elements;

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

            if (_this._ignoreSingleValue && entities.length === 1) {
                return;
            }

            if (_this._ignoreSingleLine && node.loc.start.line === node.loc.end.line) {
                return;
            }

            var closingToken = file.getLastNodeToken(node);

            errors.assert.tokenBefore({
                token: closingToken,
                expectedTokenBefore: {type: 'Punctuator', value: ','},
                message: 'Missing comma before closing ' + (isObject ? ' curly brace' : ' bracket')
            });
        });
    }

};
<commit_msg>requireTrailingComma: correct error message<commit_after>/**
 * Requires an extra comma following the final element of an array or object literal.
 *
 * Types: `Boolean` or `Object`
 *
 * Values:
 *
 * - `true`: validates all arrays and objects
 * - `Object`:
 *     - `ignoreSingleValue`: allows single property objects and single element arrays to not require a trailing comma
 *     - `ignoreSingleLine`: allows objects and arrays on a single line to not require a trailing comma
 *
 * #### Example
 *
 * ```js
 * "requireTrailingComma": true
 * ```
 *
 * ##### Valid
 *
 * ```js
 * var foo = [1, 2, 3,];
 * var bar = {a: "a", b: "b",}
 * ```
 *
 * ##### Valid with ignoreSingleValue
 *
 * ```js
 * var car = [1];
 * var dar = {a: "a"};
 * ```
 *
 * ##### Valid with ignoreSingleLine
 *
 * ```js
 * var car = [1, 2, 3];
 * var dar = {a: "a", b: "b"};
 * ```
 *
 * ##### Invalid
 *
 * ```js
 * var foo = [1, 2, 3];
 * var bar = {a: "a", b: "b"}
 * ```
 */

var assert = require('assert');

module.exports = function() {};

module.exports.prototype = {
    configure: function(options) {

        if (typeof options === 'object') {
            if ('ignoreSingleValue' in options) {
                assert(
                    options.ignoreSingleValue === true,
                    this.getOptionName() + ' option ignoreSingleValue requires true value or should be removed'
                );
                this._ignoreSingleValue = true;
            }
            if ('ignoreSingleLine' in options) {
                assert(
                    options.ignoreSingleLine === true,
                    this.getOptionName() + ' option ignoreSingleLine requires true value or should be removed'
                );
                this._ignoreSingleLine = true;
            }
        } else {
            assert(
                options === true,
                this.getOptionName() + ' option requires a true value or should be removed'
            );
        }
    },

    getOptionName: function() {
        return 'requireTrailingComma';
    },

    check: function(file, errors) {
        var _this = this;

        file.iterateNodesByType(['ObjectExpression', 'ArrayExpression'], function(node) {
            var isObject = node.type === 'ObjectExpression';
            var entities = isObject ? node.properties : node.elements;

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

            if (_this._ignoreSingleValue && entities.length === 1) {
                return;
            }

            if (_this._ignoreSingleLine && node.loc.start.line === node.loc.end.line) {
                return;
            }

            var closingToken = file.getLastNodeToken(node);

            errors.assert.tokenBefore({
                token: closingToken,
                expectedTokenBefore: {type: 'Punctuator', value: ','},
                message: 'Missing comma before closing ' + (isObject ? 'curly brace' : 'bracket')
            });
        });
    }

};
<|endoftext|>


<commit_before>var Message = require("./message").Message;

var Room = function(campfire, data) {
  this.id              = data.id;
  this.name            = data.name;
  this.topic           = data.topic;
  this.locked          = data.locked;
  this.createdAt       = new Date(data.created_at);
  this.updatedAt       = new Date(data.updated_at);
  this.membershipLimit = data.membership_limit;

  this.path     = "/room/" + this.id;
  this.campfire = campfire;
};

Room.prototype.join = function(callback) {
  this.post("/join", "", callback);
};

Room.prototype.leave = function(callback) {
  this.post("/leave", "", callback);
};

Room.prototype.listen = function(callback) {
  if (!(callback instanceof Function)) {
    throw new Error("A callback must be provided for listening.");
  }

  var campfire = this.campfire,
      options  = {
        host    : "streaming.campfirenow.com",
        port    : campfire.port,
        agent   : false,
        method  : "GET",
        path    : this.path + "/live.json",
        headers : {
          "Host"          : "streaming.campfirenow.com",
          "Authorization" : campfire.authorization
        }
      };

  campfire.http.request(options, function(response) {
    response.setEncoding("utf8");
    response.on("data", function(data) {
      data.split("\r").forEach(function(chunk) {
        try {
          var data = JSON.parse(chunk.trim());
        } catch(e) {
          return;
        }

        callback(new Message(campfire, data));
      });
    });
  }).end();
};

Room.prototype.lock = function(callback) {
  this.post("/lock", "", callback);
};

Room.prototype.message = function(text, type, callback) {
  this.post("/speak", { message : { body : text, type : type } }, callback);
};

Room.prototype.paste = function(text, callback) {
  this.message(text, "PasteMessage", callback);
};

Room.prototype.messages = function(callback) {
  this.get("/recent", function(error, response) {
    if (response) {
      var messages = response.messages.map(function(message) {
        return new Message(this.campfire, message);
      }, this);
    }

    callback(error, messages);
  }.bind(this));
};

Room.prototype.show = function(callback) {
  this.post("", "", callback);
};

Room.prototype.sound = function(text, callback) {
  this.message(text, "SoundMessage", callback);
};

Room.prototype.speak = function(text, callback) {
  this.message(text, "TextMessage", callback);
};

Room.prototype.transcript = function(date, callback) {
  var path     = "/transcript",
      callback = callback || date;

  if (date instanceof Date) {
    path += "/" + date.getFullYear() + "/" + date.getMonth() + "/" + date.getDate();
  }

  this.get(path, function(error, response) {
    if (response) {
      var messages = response.messages.map(function(message) {
        return new Message(this.campfire, message);
      }, this);
    }

    callback(error, messages);
  }.bind(this));
};

Room.prototype.tweet = function(url, callback) {
  this.message(url, "TweetMessage", callback);
};

Room.prototype.unlock = function(callback) {
  this.post("/unlock", "", callback);
};

Room.prototype.uploads = function(callback) {
  this.get("/uploads", function(error, response) {
    if (response) {
      var uploads = response.uploads;
    }

    callback(error, uploads);
  });
};

Room.prototype.get = function(path, callback) {
  this.campfire.get(this.path + path, callback);
};

Room.prototype.post = function(path, body, callback) {
  this.campfire.post(this.path + path, body, callback);
};

exports.Room = Room;
<commit_msg>Added users, full, and openToGuests to the room constructor.<commit_after>var Message = require("./message").Message;

var Room = function(campfire, data) {
  this.id              = data.id;
  this.name            = data.name;
  this.full            = data.full;
  this.topic           = data.topic;
  this.users           = data.users;
  this.locked          = data.locked;
  this.createdAt       = new Date(data.created_at);
  this.updatedAt       = new Date(data.updated_at);
  this.openToGuests    = data.open_to_guests;
  this.membershipLimit = data.membership_limit;

  this.path     = "/room/" + this.id;
  this.campfire = campfire;
};

Room.prototype.join = function(callback) {
  this.post("/join", "", callback);
};

Room.prototype.leave = function(callback) {
  this.post("/leave", "", callback);
};

Room.prototype.listen = function(callback) {
  if (!(callback instanceof Function)) {
    throw new Error("A callback must be provided for listening.");
  }

  var campfire = this.campfire,
      options  = {
        host    : "streaming.campfirenow.com",
        port    : campfire.port,
        agent   : false,
        method  : "GET",
        path    : this.path + "/live.json",
        headers : {
          "Host"          : "streaming.campfirenow.com",
          "Authorization" : campfire.authorization
        }
      };

  campfire.http.request(options, function(response) {
    response.setEncoding("utf8");
    response.on("data", function(data) {
      data.split("\r").forEach(function(chunk) {
        try {
          var data = JSON.parse(chunk.trim());
        } catch(e) {
          return;
        }

        callback(new Message(campfire, data));
      });
    });
  }).end();
};

Room.prototype.lock = function(callback) {
  this.post("/lock", "", callback);
};

Room.prototype.message = function(text, type, callback) {
  this.post("/speak", { message : { body : text, type : type } }, callback);
};

Room.prototype.paste = function(text, callback) {
  this.message(text, "PasteMessage", callback);
};

Room.prototype.messages = function(callback) {
  this.get("/recent", function(error, response) {
    if (response) {
      var messages = response.messages.map(function(message) {
        return new Message(this.campfire, message);
      }, this);
    }

    callback(error, messages);
  }.bind(this));
};

Room.prototype.show = function(callback) {
  this.post("", "", callback);
};

Room.prototype.sound = function(text, callback) {
  this.message(text, "SoundMessage", callback);
};

Room.prototype.speak = function(text, callback) {
  this.message(text, "TextMessage", callback);
};

Room.prototype.transcript = function(date, callback) {
  var path     = "/transcript",
      callback = callback || date;

  if (date instanceof Date) {
    path += "/" + date.getFullYear() + "/" + date.getMonth() + "/" + date.getDate();
  }

  this.get(path, function(error, response) {
    if (response) {
      var messages = response.messages.map(function(message) {
        return new Message(this.campfire, message);
      }, this);
    }

    callback(error, messages);
  }.bind(this));
};

Room.prototype.tweet = function(url, callback) {
  this.message(url, "TweetMessage", callback);
};

Room.prototype.unlock = function(callback) {
  this.post("/unlock", "", callback);
};

Room.prototype.uploads = function(callback) {
  this.get("/uploads", function(error, response) {
    if (response) {
      var uploads = response.uploads;
    }

    callback(error, uploads);
  });
};

Room.prototype.get = function(path, callback) {
  this.campfire.get(this.path + path, callback);
};

Room.prototype.post = function(path, body, callback) {
  this.campfire.post(this.path + path, body, callback);
};

exports.Room = Room;
<|endoftext|>


<commit_before>/* gui module for config.json editing */
var CloudCommander;

(function(){
    "use strict";

    var cloudcmd = CloudCommander;

    var Config = {};

    Config.Show = (function(){
        console.log('config showed');
    });

    Config.Keys = function(){
        console.log('config.js loaded');
        cloudcmd.Viewer(function(){
                Config.Show();
            });
    };

    cloudcmd.Config = Config;

})();<commit_msg>minor changes<commit_after>/* gui module for config.json editing */
var CloudCommander;

(function(){
    "use strict";

    var cloudcmd = CloudCommander;

    var Config = {};

    Config.Show = (function(){
        console.log('config showed');

        var lFancyBox = cloudcmd.Viewer.FancyBox;
         lFancyBox.loadData({hreef: 'htlm/config.html'},
            lFancyBox.onDataLoaded);
    });

    Config.Keys = function(){
        console.log('config.js loaded');
        cloudcmd.Viewer(function(){
                Config.Show();
            });
    };

    cloudcmd.Config = Config;

})();<|endoftext|>


<commit_before>E('engine', function (require, module, exports, global, engine) {

    // client flag
    engine.client = true;

    var EventEmitter = require('EventEmitter');

    // extend engine with event emitter
    for (var key in EventEmitter) {
        engine[key] = EventEmitter[key];
    }
    engine._events = {};

    var InstaceLoader = require('InstanceLoader');

    /**
     * Empties all caches and reloads the modules.
     *
     * @public
     * @param {boolean} Don't remove the DOM nodes.
     * @todo check for memory leaks
     */
    engine.reload = function (keepDom) {
        engine.emit('reload', keepDom);
    };
});

<commit_msg>init engine<commit_after>var EventEmitter = require('./events');
var Link = require('./link');
var Instance = require('./instance');

// extend engine with event emitter
for (var key in EventEmitter) {
    engine[key] = EventEmitter[key];
}
engine._events = {};

// client flag
engine.client = true;

// link
engine.link = Link;

Instance();

/**
 * Empties all caches and reloads the modules.
 *
 * @public
 * @param {boolean} Don't remove the DOM nodes.
 * @todo check for memory leaks
 */
engine.reload = function (keepDom) {
    engine.emit('reload', keepDom);
};

<|endoftext|>