<commit_before>// Copyright (c) 2014, Google Inc. Please see the AUTHORS file for details.
// All rights reserved. Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

Polymer('cde-polymer-designer', {
  // NOTE: Make sure this is in-sync with ide/web/manifest.json.
  _STORAGE_PARTITION: 'cde-polymer-designer',
  // NOTE: We must use the full path as viewed by a client app.
  _LOCAL_ENTRY_POINT:
      'packages/cde_polymer_designer/src/polymer_designer/index.html',
  _ONLINE_ENTRY_POINT:
      'https://www.polymer-project.org/tools/designer/',

  /**
   * Specifies whether to use the local, compiled-in copy of Polymer Designer
   * or the online one.
   *
   * @attribute attr
   * @type string
   */
  entryPoint: 'local',

  /**
   * The dynamically created <webview> element.
   */
  _webview: null,

  /**
   * Fires after the <webview> has been created, its UI tweaked and the proxy
   * script injected into it.
   *
   * @type: Promise
   */
  _webviewReady: null,
  _webviewReadyResolve: null,

  /**
   * Fires when the asynchronous code export requested from the proxy has
   * completed.
   *
   * @type: Promise<String>
   */
  _codeExported: null,
  _codeExportedResolve: null,

  /**
   * Registers an event listener to complete initialization once the
   * <webview> is up and running.
   */
  attached: function() {
    this._registerDesignerProxyListener();
  },

  /**
   * Initializes this object from an idle state:
   * - Creates a new <webview>.
   * - Inserts it into the shadow DOM.
   * - Navigates it to the Polymer Designer local or online entry point.
   *
   * @type: Promise
   */
  load: function() {
    this._webviewReady = new Promise(function(resolve, reject) {
      this._webviewReadyResolve = resolve;
      // TODO(ussuri): BUG #3466.
      setTimeout(function() {
        this._webview = document.createElement('webview');
        this._webview.addEventListener(
            'contentload', this._onWebviewContentLoad.bind(this));
        this._webview.partition = this._STORAGE_PARTITION;
        this._webview.src =
            this.entryPoint == 'local' ?
            this._LOCAL_ENTRY_POINT :
            this._ONLINE_ENTRY_POINT;
        this.shadowRoot.appendChild(this._webview);
      }.bind(this), 500);
    }.bind(this));

    return this._webviewReady;
  },

  /**
   * Returns the object to the idle state:
   * - terminates the running <webview>, if any.
   * - removes the <webview> element from the shadow DOM.
   * - Resets the [Completer]s.
   *
   * @type: void
   */
  unload: function() {
    if (this._webview != null) {
      this._webview.terminate();
      this.shadowRoot.removeChild(this._webview);
    }
    this._webview = this._webviewReady = this._webviewReadyResolve = null;
    this._codeExported = this._codeExportedResolve = null;
  },

  /**
   * Reinitializes the object from a running state.
   *
   * @type: Promise
   */
  reload: function() {
    this.unload();
    return this.load();
  },

  /**
   * Sets the internal design code inside the Polymer Designer running within
   * the <webview>. This results in PD re-rendering the design, if it can
   * parse the code. If it can't, it resets the design to an empty one.
   *
   * @type: Promise
   */
  setCode: function(code) {
    // Escape all special charachters and enclose in double-quotes.
    code = JSON.stringify(code);
    // Just in case we are called too early, wait until the webview is ready.
    return this._webviewReady.then(function () {
      // TODO(ussuri): This doesn't work without a delay:
      // find some way to detect when PD is fully ready.
      return setTimeout(function() {
        // The request is received and handled by the JS proxy script injected
        // into [_webview>] by [_injectDesignerProxy].
        return this._executeScriptInWebview(
          "function() { window.postMessage({action: 'set_code', code: " +
          code +
          "}, '*'); }"
        );
      }.bind(this), 500);
    }.bind(this));
  },

  /**
   * Extracts and returns to the caller the current design code from the
   * Polymer Designer.
   *
   * @type: Promise<String>
   */
  getCode: function() {
    if (this._codeExported == null) {
      this._codeExported = new Promise(function(resolve, reject) {
        this._codeExportedResolve = resolve;
        // The request is received and handled by [_designerProxy], which
        // asynchronously returns the result via a chrome.runtime.sendMessage,
        // received and handled by [_designProxyListener], which resolves the
        // [_codeExported] promise with the code string.
        this._executeScriptInWebview(
          "function() { window.postMessage({action: 'get_code'}, '*'); }"
        );
      }.bind(this));
    } else {
      // There already is a pending [getCode] request: just fall through
      // to returning the same promise to the new caller.
    }
    return this._codeExported;
  },

  /**
   * Tweaks the Polymer Designer UI and inject a proxy script.
   *
   * @type: void
   */
  _onWebviewContentLoad: function(event) {
    this._tweakDesignerUI();
    this._injectDesignerProxy().then(function() {
      this._webviewReadyResolve(null);
    }.bind(this));
  },

  /**
   * Tweaks the Polymer Designer UI by inserting some CSS into [_webview]:
   * - Adjusts font sizes.
   * - Reduces toolbar sizes.
   * - Removes some buttons we don't need.
   *
   * @type: void
   */
  _tweakDesignerUI: function() {
    // TODO(ussuri): Some of this will become unnecessary once BUG #3467 is
    // resolved.
    this._insertCssIntoWebview("\
        /* Reduce the initial font sizes */\
        html /deep/ *, html /deep/ #tabs > * {\
          font-size: 12px;\
        }\
        html /deep/ #tabs {\
          padding-top: 0;\
          padding-bottom: 0;\
        }\
        html /deep/ core-toolbar,\
        html /deep/ core-toolbar::shadow > #topBar {\
          height: 40px;\
        }\
        /* Hide some UI elements we do not need */\
        #designer::shadow > #appbar > * {\
          display: none;\
        }\
        #designer::shadow > #appbar > .design-controls {\
          display: block;\
        }\
        #designer::shadow > #appbar > .design-controls > .separator:first-child {\
          display: none;\
        }\
        /* Revert font size for the current element */\
        #designer /deep/ #selectedElement {\
          font-size: 15px;\
        }\
        /* Adjust palette elements' style */\
        #designer /deep/ .simple-item {\
          height: 30px;\
          line-height: 30px;\
          font-size: 12px;\
        }"
    );
  },

  /**
   * Registers a listener for responses sent by [_designerProxy].
   *
   * @type: void
   */
  _registerDesignerProxyListener: function() {
    chrome.runtime.onMessage.addListener(this._designerProxyListener.bind(this));
  },

  /**
   * Handles messages/responses sent from inside [_webview] by [_designerProxy].
   *
   * @type: void
   */
  _designerProxyListener: function(event) {
    // TODO(ussuri): Check the sender?
    switch (event.type) {
      case 'get_code_response':
        this._codeExportedResolve(event.code);
        // Null the promise so new [getCode] requests can work properly.
        this._codeExported = this._codeExportedResolve = null;
        break;
    }
  },

  /**
   * The proxy script injected into the scripting context ("main world") of
   * [_webview] in order to receive and handle requests on behalf of this object.
   *
   * @type: string
   */
  _designerProxy: function() {
    // This will receive events sent by the main code via window.postMessage
    // executed inside [_webview]'s DOM.
    window.addEventListener('message', function(event) {
      var designer = document.querySelector('#designer');
      switch (event.data.action) {
        case 'get_code':
          chrome.runtime.sendMessage({
              type: 'get_code_response',
              code: designer.html
          });
          break;
        case 'set_code':
          // After this, PD will detect the new design code and try to parse
          // and render it.
          designer.loadHtml(event.data.code);
          break;
      }
    });
  },

  /**
   * Injects [_designerProxy] into the scripting context ("main world") of
   * [_webview]. This is necessary in contrast to the "isolated world" in
   * order for the proxy to have access to the JS context of the Designer
   * (within "isolated world", the proxy would only see the Designer's DOM).
   *
   * @type: Promise
   */
  _injectDesignerProxy: function() {
    return this._injectScriptIntoWebviewMainWorld(this._designerProxy);
  },

  /**
   * Effectively injects and runs a given script in the [_webview]'s scripting
   * context ("main world"). This is achieved by creating a new <script> tag in
   * the [_webview]'s DOM and setting its inner HTML to the script's code.
   * Doing that will cause the script to run and be able to register event
   * listeners which will have access to various Polymer Designer's JS
   * properties.
   *
   * @type: Promise
   */
  _injectScriptIntoWebviewMainWorld: function(func) {
    var script = JSON.stringify('(' + func.toString() + ')();');

    return this._executeScriptInWebview("function() {\n\
      var scriptTag = document.createElement('script');\n\
      scriptTag.innerHTML = " + script + ";\n\
      document.body.appendChild(scriptTag);\n\
    }");
  },

  /**
   * Executes a script in [_webview]'s "isolated world", which give the script
   * access only to the webview's DOM, but not the JS context.
   *
   * @type: Promise<array of any>
   */
  _executeScriptInWebview: function(func) {
    var script = '(' + func.toString() + ')();';

    return new Promise(function(resolve, reject) {
      this._webview.executeScript(
          {code: script},
          function(result) { resolve(result); }
      );
    }.bind(this));
  },

  /**
   * Inserts a fragment of CSS into [_webview]'s DOM.
   *
   * @type: void
   */
  _insertCssIntoWebview: function(css) {
    this._webview.insertCSS({code: css});
  }
});
<commit_msg>Switch from .bind(this) to that=this idiom + persist storage partition across sessions<commit_after>// Copyright (c) 2014, Google Inc. Please see the AUTHORS file for details.
// All rights reserved. Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

Polymer('cde-polymer-designer', {
  // NOTE: Make sure this is in-sync with ide/web/manifest.json.
  _STORAGE_PARTITION: 'persist:cde-polymer-designer',
  // NOTE: We must use the full path as viewed by a client app.
  _LOCAL_ENTRY_POINT:
      'packages/cde_polymer_designer/src/polymer_designer/index.html',
  _ONLINE_ENTRY_POINT:
      'https://www.polymer-project.org/tools/designer/',

  /**
   * Specifies whether to use the local, compiled-in copy of Polymer Designer
   * or the online one.
   *
   * @attribute attr
   * @type string
   */
  entryPoint: 'local',

  /**
   * The dynamically created <webview> element.
   */
  _webview: null,

  /**
   * Fires after the <webview> has been created, its UI tweaked and the proxy
   * script injected into it.
   *
   * @type: Promise
   */
  _webviewReady: null,
  _webviewReadyResolve: null,

  /**
   * Fires when the asynchronous code export requested from the proxy has
   * completed.
   *
   * @type: Promise<String>
   */
  _codeExported: null,
  _codeExportedResolve: null,

  /**
   * Registers an event listener to complete initialization once the
   * <webview> is up and running.
   */
  attached: function() {
    this._registerDesignerProxyListener();
  },

  /**
   * Initializes this object from an idle state:
   * - Creates a new <webview>.
   * - Inserts it into the shadow DOM.
   * - Navigates it to the Polymer Designer local or online entry point.
   *
   * @type: Promise
   */
  load: function() {
    var that = this;

    that._webviewReady = new Promise(function(resolve, reject) {
      that._webviewReadyResolve = resolve;
      // TODO(ussuri): BUG #3466.
      setTimeout(function() {
        that._webview = document.createElement('webview');
        that._webview.addEventListener(
            'contentload', that._onWebviewContentLoad.bind(that));
        that._webview.partition = that._STORAGE_PARTITION;
        that._webview.src =
            that.entryPoint == 'local' ?
            that._LOCAL_ENTRY_POINT :
            that._ONLINE_ENTRY_POINT;
        that.shadowRoot.appendChild(that._webview);
      }, 500);
    });

    return that._webviewReady;
  },

  /**
   * Returns the object to the idle state:
   * - terminates the running <webview>, if any.
   * - removes the <webview> element from the shadow DOM.
   * - Resets the [Completer]s.
   *
   * @type: void
   */
  unload: function() {
    if (this._webview != null) {
      this._webview.terminate();
      this.shadowRoot.removeChild(this._webview);
    }
    this._webview = this._webviewReady = this._webviewReadyResolve = null;
    this._codeExported = this._codeExportedResolve = null;
  },

  /**
   * Reinitializes the object from a running state.
   *
   * @type: Promise
   */
  reload: function() {
    this.unload();
    return this.load();
  },

  /**
   * Sets the internal design code inside the Polymer Designer running within
   * the <webview>. This results in PD re-rendering the design, if it can
   * parse the code. If it can't, it resets the design to an empty one.
   *
   * @type: Promise
   */
  setCode: function(code) {
    var that = this;

    // Escape all special charachters and enclose in double-quotes.
    code = JSON.stringify(code);
    // Just in case we are called too early, wait until the webview is ready.
    return that._webviewReady.then(function () {
      // TODO(ussuri): This doesn't work without a delay:
      // find some way to detect when PD is fully ready.
      return setTimeout(function() {
        // The request is received and handled by the JS proxy script injected
        // into [_webview>] by [_injectDesignerProxy].
        return that._executeScriptInWebview(
          "function() { window.postMessage({action: 'set_code', code: " +
          code +
          "}, '*'); }"
        );
      }, 500);
    });
  },

  /**
   * Extracts and returns to the caller the current design code from the
   * Polymer Designer.
   *
   * @type: Promise<String>
   */
  getCode: function() {
    var that = this;

    if (that._codeExported == null) {
      that._codeExported = new Promise(function(resolve, reject) {
        that._codeExportedResolve = resolve;
        // The request is received and handled by [_designerProxy], which
        // asynchronously returns the result via a chrome.runtime.sendMessage,
        // received and handled by [_designProxyListener], which resolves the
        // [_codeExported] promise with the code string.
        that._executeScriptInWebview(
          "function() { window.postMessage({action: 'get_code'}, '*'); }"
        );
      });
    } else {
      // There already is a pending [getCode] request: just fall through
      // to returning the same promise to the new caller.
    }

    return that._codeExported;
  },

  /**
   * Tweaks the Polymer Designer UI and inject a proxy script.
   *
   * @type: void
   */
  _onWebviewContentLoad: function(event) {
    var that = this;

    that._tweakDesignerUI();
    that._injectDesignerProxy().then(function() {
      that._webviewReadyResolve(null);
    });
  },

  /**
   * Tweaks the Polymer Designer UI by inserting some CSS into [_webview]:
   * - Adjusts font sizes.
   * - Reduces toolbar sizes.
   * - Removes some buttons we don't need.
   *
   * @type: void
   */
  _tweakDesignerUI: function() {
    // TODO(ussuri): Some of this will become unnecessary once BUG #3467 is
    // resolved.
    this._insertCssIntoWebview("\
        /* Reduce the initial font sizes */\
        html /deep/ *, html /deep/ #tabs > * {\
          font-size: 12px;\
        }\
        html /deep/ #tabs {\
          padding-top: 0;\
          padding-bottom: 0;\
        }\
        html /deep/ core-toolbar,\
        html /deep/ core-toolbar::shadow > #topBar {\
          height: 40px;\
        }\
        /* Hide some UI elements we do not need */\
        #designer::shadow > #appbar > * {\
          display: none;\
        }\
        #designer::shadow > #appbar > .design-controls {\
          display: block;\
        }\
        #designer::shadow > #appbar > .design-controls > .separator:first-child {\
          display: none;\
        }\
        /* Revert font size for the current element */\
        #designer /deep/ #selectedElement {\
          font-size: 15px;\
        }\
        /* Adjust palette elements' style */\
        #designer /deep/ .simple-item {\
          height: 30px;\
          line-height: 30px;\
          font-size: 12px;\
        }"
    );
  },

  /**
   * Registers a listener for responses sent by [_designerProxy].
   *
   * @type: void
   */
  _registerDesignerProxyListener: function() {
    chrome.runtime.onMessage.addListener(this._designerProxyListener.bind(this));
  },

  /**
   * Handles messages/responses sent from inside [_webview] by [_designerProxy].
   *
   * @type: void
   */
  _designerProxyListener: function(event) {
    // TODO(ussuri): Check the sender?
    switch (event.type) {
      case 'get_code_response':
        this._codeExportedResolve(event.code);
        // Null the promise so new [getCode] requests can work properly.
        this._codeExported = this._codeExportedResolve = null;
        break;
    }
  },

  /**
   * The proxy script injected into the scripting context ("main world") of
   * [_webview] in order to receive and handle requests on behalf of this object.
   *
   * @type: string
   */
  _designerProxy: function() {
    // This will receive events sent by the main code via window.postMessage
    // executed inside [_webview]'s DOM.
    window.addEventListener('message', function(event) {
      var designer = document.querySelector('#designer');
      switch (event.data.action) {
        case 'get_code':
          chrome.runtime.sendMessage({
              type: 'get_code_response',
              code: designer.html
          });
          break;
        case 'set_code':
          // After this, PD will detect the new design code and try to parse
          // and render it.
          designer.loadHtml(event.data.code);
          break;
      }
    });
  },

  /**
   * Injects [_designerProxy] into the scripting context ("main world") of
   * [_webview]. This is necessary in contrast to the "isolated world" in
   * order for the proxy to have access to the JS context of the Designer
   * (within "isolated world", the proxy would only see the Designer's DOM).
   *
   * @type: Promise
   */
  _injectDesignerProxy: function() {
    return this._injectScriptIntoWebviewMainWorld(this._designerProxy);
  },

  /**
   * Effectively injects and runs a given script in the [_webview]'s scripting
   * context ("main world"). This is achieved by creating a new <script> tag in
   * the [_webview]'s DOM and setting its inner HTML to the script's code.
   * Doing that will cause the script to run and be able to register event
   * listeners which will have access to various Polymer Designer's JS
   * properties.
   *
   * @type: Promise
   */
  _injectScriptIntoWebviewMainWorld: function(func) {
    var script = JSON.stringify('(' + func.toString() + ')();');

    return this._executeScriptInWebview("function() {\n\
      var scriptTag = document.createElement('script');\n\
      scriptTag.innerHTML = " + script + ";\n\
      document.body.appendChild(scriptTag);\n\
    }");
  },

  /**
   * Executes a script in [_webview]'s "isolated world", which give the script
   * access only to the webview's DOM, but not the JS context.
   *
   * @type: Promise<array of any>
   */
  _executeScriptInWebview: function(func) {
    var that = this;

    var script = '(' + func.toString() + ')();';

    return new Promise(function(resolve, reject) {
      that._webview.executeScript(
          {code: script},
          function(result) { resolve(result); }
      );
    });
  },

  /**
   * Inserts a fragment of CSS into [_webview]'s DOM.
   *
   * @type: void
   */
  _insertCssIntoWebview: function(css) {
    this._webview.insertCSS({code: css});
  }
});
<|endoftext|>


<commit_before>'use strict'

const prettier = require('prettier');
const glob = require('glob');
const fs = require('fs');
const globPattern = 'app/{src, test}/**/*.{ts, tsx}'
const prettierOptions = {
  "parser": "typescript",
  "singleQuote": true,
  "trailingComma": "all",
  "semi": false,
  "printWidth": 100
}

glob(globPattern, (err, matches) => {
  if (err) {
    console.error(err);
    process.exit(1);
  }

  const uglyFiles = [];
  const matchCount = matches.length;

  for (const match of matches) {
    const fileContents = fs.readFileSync(match, 'utf8');
    const isPretty = prettier.check(fileContents, prettierOptions);

      if (!isPretty) {
        uglyFiles.push(match);
      }
  }

  if (uglyFiles.length === 0) {
    console.log("This is some pretty code");
  } else {
    console.log(`${uglyFiles.length} out of ${matchCount} code files are ugly. Please prettify the following files:`);

    for (const file of uglyFiles) {
      console.log(`\t${file}`);
    }

    process.exit(1);
  }
});
<commit_msg>Updated CI checks<commit_after>'use strict'

const prettier = require('prettier');
const glob = require('glob');
const fs = require('fs');
const globPattern = 'app/{src, test}/**/*.{ts, tsx}'
const prettierOptions = {
  "parser": "typescript",
  "singleQuote": true,
  "trailingComma": "es5",
  "semi": false,
  "printWidth": 80
}

glob(globPattern, (err, matches) => {
  if (err) {
    console.error(err);
    process.exit(1);
  }

  const uglyFiles = [];
  const matchCount = matches.length;

  for (const match of matches) {
    const fileContents = fs.readFileSync(match, 'utf8');
    const isPretty = prettier.check(fileContents, prettierOptions);

      if (!isPretty) {
        uglyFiles.push(match);
      }
  }

  if (uglyFiles.length === 0) {
    console.log("This is some pretty code");
  } else {
    console.log(`${uglyFiles.length} out of ${matchCount} code files are ugly. Please prettify the following files:`);

    for (const file of uglyFiles) {
      console.log(`\t${file}`);
    }

    process.exit(1);
  }
});
<|endoftext|>


<commit_before>import { injectGlobal } from 'styled-components';
import { greyDark, blackLight, blueLight } from 'shared/styles/colors';

import {
  ffBody,
  ffHeading,
  ffJapanese,
  epsilon,
  milli,
} from 'shared/styles/typography';

/* eslint no-unused-expressions: 0 */
injectGlobal`
  html {
    box-sizing: border-box;
    height: 100%;
    max-width: 100vw;
    overflow-x: hidden;
  }

  *,
  *:before,
  *:after {
    box-sizing: inherit;
  }

  body {
    ${epsilon}
    min-height: 100%;
    margin: 0;
    padding: 0;
    font-family: ${ffBody};
    color: ${blackLight};
    line-height: 1;
    display: flex;
    flex-direction: column;
  }

  [lang="ja"],
  p[lang="ja"],
  span[lang="ja"] {
    font-family: ${ffJapanese};
    word-break: break-word;
    letter-spacing: 0.01em;
    line-height: 1.2;
  }

  #app {
    display: flex;
    flex-direction: column;
    flex: 1 0 100%;
  }

  *:focus {
    outline: none;
  }

  /* inputs already have fancy focus states */
  .user-is-tabbing :not(input):focus {
    opacity: 1;
    outline: ${blueLight} auto .2rem;
  }

  h1, h2, h3, h4, h5, h6 {
    font-family: ${ffHeading};
    margin: 0;
    color: ${greyDark};
    line-height: 1.2;
  }

  a,
  button {
    cursor: pointer;
  }

  p {
    line-height: 1.3;
    + p {
      margin-top: .4em;
    }
  }

  small {
    ${milli}
  }
`;
<commit_msg>styles: focus color inherit text currentcolor<commit_after>import { injectGlobal } from 'styled-components';
import { greyDark, blackLight } from 'shared/styles/colors';

import {
  ffBody,
  ffHeading,
  ffJapanese,
  epsilon,
  milli,
} from 'shared/styles/typography';

/* eslint no-unused-expressions: 0 */
injectGlobal`
  html {
    box-sizing: border-box;
    height: 100%;
    max-width: 100vw;
    overflow-x: hidden;
  }

  *,
  *:before,
  *:after {
    box-sizing: inherit;
  }

  body {
    ${epsilon}
    min-height: 100%;
    margin: 0;
    padding: 0;
    font-family: ${ffBody};
    color: ${blackLight};
    line-height: 1;
    display: flex;
    flex-direction: column;
  }

  [lang="ja"],
  p[lang="ja"],
  span[lang="ja"] {
    font-family: ${ffJapanese};
    word-break: break-word;
    letter-spacing: 0.01em;
    line-height: 1.2;
  }

  #app {
    display: flex;
    flex-direction: column;
    flex: 1 0 100%;
  }

  *:focus {
    outline: none;
  }

  /* inputs already have fancy focus states */
  .user-is-tabbing :not(input):focus {
    opacity: 1;
    transition: outline 0s;
    outline: .15rem solid;
    outline-offset: .15rem;
  }

  h1, h2, h3, h4, h5, h6 {
    font-family: ${ffHeading};
    margin: 0;
    color: ${greyDark};
    line-height: 1.2;
  }

  a,
  button {
    cursor: pointer;
  }

  p {
    line-height: 1.3;
    + p {
      margin-top: .4em;
    }
  }

  small {
    ${milli}
  }
`;
<|endoftext|>


<commit_before>var fs = require('fs')
  , path = require('path')
  , kerouac = require('kerouac')
  , utils = require('../utils');

exports = module.exports = function(postsDB) {
  var dir = 'blog'
    , layout;

  var exts = [ '.md' ];

  function loadPost(page, next) {
    var q = {
      slug: page.params.slug,
      year: page.params.year,
      month: page.params.month,
      day: page.params.day
    }

    postsDB.find(q, function(err, post) {
      page.locals.title = post.title;
      page.locals.createdAt = post.createdAt;
      page.locals.modifiedAt = post.modifiedAt;
      page.content = post.content;

      next();
    });
  }

  function findFile(page, next) {
    var file, ext
      , i, len;

    for (i = 0, len = exts.length; i < len; ++i) {
      ext = exts[i];
      file = path.resolve(dir, page.params.slug + ext);
      if (fs.existsSync(file)) {
        page.inputPath = file;
        return next();
      }
    }

    return next('route');
  }

  function meta(page, next) {
    page.locals.createdAt = page.createdAt;

    page.post = true;
    page.title = page.locals.title;
    page.tags = utils.tarray(page.locals.tags);
    next();
  }

  return [
    kerouac.manifest(),
    kerouac.canonicalURL(),
    loadPost,
    //findFile,
    //kerouac.timestamps(),
    kerouac.layout(layout),
    //kerouac.loadContent(),
    meta,
    kerouac.render()
  ];
};

exports['@require'] = [
  'http://i.kerouacjs.org/blog/PostsDatabase'
];
<commit_msg>Simplify handler chain for rendering post.<commit_after>var kerouac = require('kerouac')
  , utils = require('../utils');

exports = module.exports = function(postsDB) {

  function loadPost(page, next) {
    var q = {
      slug: page.params.slug,
      year: page.params.year,
      month: page.params.month,
      day: page.params.day
    }

    postsDB.find(q, function(err, post) {
      page.locals.title = post.title;
      page.locals.createdAt = post.createdAt;
      page.locals.modifiedAt = post.modifiedAt;
      page.content = post.content;

      next();
    });
  }

  function meta(page, next) {
    page.locals.createdAt = page.createdAt;

    page.post = true;
    page.title = page.locals.title;
    page.tags = utils.tarray(page.locals.tags);
    next();
  }

  return [
    loadPost,
    meta,
    kerouac.render()
  ];
};

exports['@require'] = [
  'http://i.kerouacjs.org/blog/PostsDatabase'
];
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var assert = require('assert');
var inherits = require('util').inherits;
var EventEmitter = require('./lib/event_emitter');
var StateMachine = require('./state_machine');
var net = require('net');

var TChannelConnection = require('./connection');
var errors = require('./errors');
var states = require('./states');

var DEFAULT_REPORT_INTERVAL = 1000;

function TChannelPeer(channel, hostPort, options) {
    if (!(this instanceof TChannelPeer)) {
        return new TChannelPeer(channel, hostPort, options);
    }
    var self = this;
    EventEmitter.call(self);
    StateMachine.call(self);
    self.stateChangedEvent = self.defineEvent('stateChanged');
    self.allocConnectionEvent = self.defineEvent('allocConnection');

    assert(hostPort !== '0.0.0.0:0', 'Cannot create ephemeral peer');

    self.channel = channel;
    self.logger = self.channel.logger;
    self.options = options || {};
    self.hostPort = hostPort;
    self.connections = [];
    self.random = self.channel.random;

    self.stateOptions = {
        timers: self.channel.timers,
        random: self.channel.random,
        period: self.options.period,
        maxErrorRate: self.options.maxErrorRate,
        minimumRequests: self.options.minimumRequests,
        probation: self.options.probation,
        stateMachine: self,
        nextHandler: self
    };

    if (self.options.initialState) {
        self.setState(self.options.initialState);
        delete self.options.initialState;
    } else {
        self.setState(states.HealthyState);
    }

    self.reportInterval = self.options.reportInterval || DEFAULT_REPORT_INTERVAL;
    if (self.reportInterval > 0) {
        self.reportTimer = self.stateOptions.timers.setTimeout(
            onReport, self.reportInterval
        );
    }

    function onReport() {
        if (!self.hostPort) {
            return;
        }

        var count = self.countConnections('out');
        self.channel.connectionsActiveStat.update(count, {
            'host-port': self.channel.hostPort,
            'peer-host-port': self.hostPort
        });

        self.reportTimer = self.stateOptions.timers.setTimeout(
            onReport, self.reportInterval
        );
    }
}

inherits(TChannelPeer, EventEmitter);

TChannelPeer.prototype.isConnected = function isConnected(direction, identified) {
    var self = this;
    if (identified === undefined) identified = true;
    for (var i = 0; i < self.connections.length; i++) {
        var conn = self.connections[i];
        if (direction && conn.direction !== direction) {
            continue;
        } else if (conn.closing) {
            continue;
        } else if (conn.remoteName !== null || !identified) {
            return true;
        }
    }
    return false;
};

TChannelPeer.prototype.close = function close(callback) {
    var self = this;
    if (self.reportTimer) {
        self.stateOptions.timers.clearTimeout(self.reportTimer);
        self.reportTimer = null;
    }

    var counter = self.connections.length;
    if (counter) {
        self.connections.forEach(function eachConn(conn) {
            conn.close(onClose);
        });
    } else {
        self.state.close(callback);
    }
    function onClose() {
        if (--counter <= 0) {
            if (counter < 0) {
                self.logger.error('closed more peer sockets than expected', {
                    counter: counter
                });
            }
            self.state.close(callback);
        }
    }
};

TChannelPeer.prototype.setState = StateMachine.prototype.setState;

TChannelPeer.prototype.getInConnection = function getInConnection() {
    var self = this;
    for (var i = 0; i < self.connections.length; i++) {
        var conn = self.connections[i];
        if (!conn.closing) return conn;
    }
    return null;
};

TChannelPeer.prototype.getOutConnection = function getOutConnection(preferIdentified) {
    var self = this;
    var candidate = null;
    for (var i = self.connections.length - 1; i >= 0; i--) {
        var conn = self.connections[i];
        if (conn.closing) continue;
        if (!preferIdentified) return conn; // user doesn't care, take last outgoing
        if (conn.remoteName) return conn; // user wanted an identified channel, and we found one
        if (!candidate) candidate = conn; // we'll fallback to returning this if we can't find an identified one
    }
    return candidate;
};

TChannelPeer.prototype.countConnections = function countConnections(direction) {
    var self = this;
    if (!direction) {
        return self.connections.length;
    }

    var count = 0;
    for (var i = 0; i < self.connections.length; i++) {
        var conn = self.connections[i];
        if (conn.direction === direction) {
            count++;
        }
    }

    return count;
};

TChannelPeer.prototype.connect = function connect(outOnly) {
    var self = this;
    var conn = self.getOutConnection(true);
    if (!conn || (outOnly && conn.direction !== 'out')) {
        var socket = self.makeOutSocket();
        conn = self.makeOutConnection(socket);
        self.addConnection(conn);
    }
    return conn;
};

TChannelPeer.prototype.waitForIdentified =
function waitForIdentified(callback) {
    var self = this;

    var conn = self.connect();

    if (conn.closing) {
        onConnectionClose(conn.closeError);
    } else {
        conn.closeEvent.on(onConnectionClose);

        // conn.handler is a self peer detection
        if (!self.isConnected() && conn.handler) {
            conn.identifiedEvent.on(onIdentified);
            return;
        } else {
            onIdentified();
        }
    }

    function onConnectionClose(err) {
        conn.closeEvent.removeListener(onConnectionClose);
        callback(err || errors.TChannelConnectionCloseError());
    }

    function onIdentified() {
        conn.closeEvent.removeListener(onConnectionClose);
        callback(null);
    }
};

TChannelPeer.prototype.request = function peerRequest(options) {
    var self = this;
    var req = self.connect().request(options);

    self.state.onRequest(req);

    req.errorEvent.on(onError);
    req.responseEvent.on(onResponse);

    function onError(err) {
        self.state.onRequestError(err);
    }

    function onResponse(res) {
        self.state.onRequestResponse(req);
    }

    return req;
};

TChannelPeer.prototype.addConnection = function addConnection(conn) {
    var self = this;
    // TODO: first approx alert for self.connections.length > 2
    // TODO: second approx support pruning
    if (conn.direction === 'out') {
        self.connections.push(conn);
    } else {
        self.connections.unshift(conn);
    }
    conn.errorEvent.on(onConnectionError);
    conn.closeEvent.on(onConnectionClose);
    return conn;

    function onConnectionError(err) {
        var codeName = errors.classify(err);

        var loggerInfo = {
            err: err,
            direction: conn.direction,
            remoteName: conn.remoteName,
            socketRemoteAddr: conn.socketRemoteAddr
        };

        if (codeName === 'Timeout') {
            self.logger.warn('Got a connection error', loggerInfo);
        } else {
            self.logger.error('Got an unexpected connection error', loggerInfo);
        }

        self.removeConnection(conn);
    }

    function onConnectionClose() {
        self.removeConnection(conn);
    }
};

TChannelPeer.prototype.removeConnection = function removeConnection(conn) {
    var self = this;
    var list = self.connections;
    var index = list ? list.indexOf(conn) : -1;
    if (index !== -1) {
        return list.splice(index, 1)[0];
    } else {
        return null;
    }
};

TChannelPeer.prototype.makeOutSocket = function makeOutSocket() {
    var self = this;
    var parts = self.hostPort.split(':');
    assert(parts.length === 2, 'invalid destination');
    var host = parts[0];
    var port = parts[1];
    assert(host !== '0.0.0.0', 'cannot connect to ephemeral peer');
    assert(port !== '0', 'cannot connect to dynamic port');
    var socket = net.createConnection({host: host, port: port});
    return socket;
};

TChannelPeer.prototype.makeOutConnection = function makeOutConnection(socket) {
    var self = this;
    var chan = self.channel.topChannel || self.channel;
    var conn = new TChannelConnection(chan, socket, 'out', self.hostPort);
    conn.spanEvent.on(handleSpanFromConn);
    self.allocConnectionEvent.emit(self, conn);
    return conn;

    function handleSpanFromConn(span) {
        chan.tracer.report(span);
    }
};

TChannelPeer.prototype.outPendingWeightedRandom = function outPendingWeightedRandom() {
    // A weighted random variable:
    //   random() ** (1 / weight)
    // Such that the probability distribution is uniform for weights of 0, but
    // an increasing bias with increasing weight.
    // However, although weight should start at 0 and increase probability,
    // the number of pending requests starts at 0 and should decrease
    // probability as it increases.
    // For 0 pending requests, we produce a uniform probability distribution by
    // raising a uniform random variable to the power of 1 (pending + 1).
    // As the number of pending requests increase, the magnitude of the power
    // increases and the probability distribution develops a bias toward zero.
    // TODO review weighted reservoir sampling:
    // http://arxiv.org/pdf/1012.0256.pdf
    var self = this;
    var pending = self.countOutPending();
    return Math.pow(self.random(), 1 + pending);
};

TChannelPeer.prototype.countOutPending = function countOutPending() {
    var self = this;
    var pending = 0;
    for (var index = 0; index < self.connections.length; index++) {
        var connPending = self.connections[index].ops.getPending();

        pending += connPending.out;
    }
    return pending;
};

// Consulted depending on the peer state
TChannelPeer.prototype.shouldRequest = function shouldRequest() {
    var self = this;
    // space:
    //   [0.1, 0.2)  unconnected peers
    //   [0.2, 0.3)  incoming connections
    //   [0.3, 0.4)  new outgoing connections
    //   [0.4, 1.0)  identified outgoing connections
    var inconn = self.getInConnection();
    var outconn = self.getOutConnection();
    var random = self.outPendingWeightedRandom();
    if (!inconn && !outconn) {
        return 0.1 + random * 0.1;
    } else if (!outconn || outconn.direction !== 'out') {
        self.connect();
        return 0.2 + random * 0.1;
    } else if (outconn.remoteName === null) {
        return 0.3 + random * 0.1;
    } else {
        return 0.4 + random * 0.6;
    }
};

module.exports = TChannelPeer;
<commit_msg>TChannelPeer.prototype.waitForIdentified: it should check the selected connection for identified<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var assert = require('assert');
var inherits = require('util').inherits;
var EventEmitter = require('./lib/event_emitter');
var StateMachine = require('./state_machine');
var net = require('net');

var TChannelConnection = require('./connection');
var errors = require('./errors');
var states = require('./states');

var DEFAULT_REPORT_INTERVAL = 1000;

function TChannelPeer(channel, hostPort, options) {
    if (!(this instanceof TChannelPeer)) {
        return new TChannelPeer(channel, hostPort, options);
    }
    var self = this;
    EventEmitter.call(self);
    StateMachine.call(self);
    self.stateChangedEvent = self.defineEvent('stateChanged');
    self.allocConnectionEvent = self.defineEvent('allocConnection');

    assert(hostPort !== '0.0.0.0:0', 'Cannot create ephemeral peer');

    self.channel = channel;
    self.logger = self.channel.logger;
    self.options = options || {};
    self.hostPort = hostPort;
    self.connections = [];
    self.random = self.channel.random;

    self.stateOptions = {
        timers: self.channel.timers,
        random: self.channel.random,
        period: self.options.period,
        maxErrorRate: self.options.maxErrorRate,
        minimumRequests: self.options.minimumRequests,
        probation: self.options.probation,
        stateMachine: self,
        nextHandler: self
    };

    if (self.options.initialState) {
        self.setState(self.options.initialState);
        delete self.options.initialState;
    } else {
        self.setState(states.HealthyState);
    }

    self.reportInterval = self.options.reportInterval || DEFAULT_REPORT_INTERVAL;
    if (self.reportInterval > 0) {
        self.reportTimer = self.stateOptions.timers.setTimeout(
            onReport, self.reportInterval
        );
    }

    function onReport() {
        if (!self.hostPort) {
            return;
        }

        var count = self.countConnections('out');
        self.channel.connectionsActiveStat.update(count, {
            'host-port': self.channel.hostPort,
            'peer-host-port': self.hostPort
        });

        self.reportTimer = self.stateOptions.timers.setTimeout(
            onReport, self.reportInterval
        );
    }
}

inherits(TChannelPeer, EventEmitter);

TChannelPeer.prototype.isConnected = function isConnected(direction, identified) {
    var self = this;
    if (identified === undefined) identified = true;
    for (var i = 0; i < self.connections.length; i++) {
        var conn = self.connections[i];
        if (direction && conn.direction !== direction) {
            continue;
        } else if (conn.closing) {
            continue;
        } else if (conn.remoteName !== null || !identified) {
            return true;
        }
    }
    return false;
};

TChannelPeer.prototype.close = function close(callback) {
    var self = this;
    if (self.reportTimer) {
        self.stateOptions.timers.clearTimeout(self.reportTimer);
        self.reportTimer = null;
    }

    var counter = self.connections.length;
    if (counter) {
        self.connections.forEach(function eachConn(conn) {
            conn.close(onClose);
        });
    } else {
        self.state.close(callback);
    }
    function onClose() {
        if (--counter <= 0) {
            if (counter < 0) {
                self.logger.error('closed more peer sockets than expected', {
                    counter: counter
                });
            }
            self.state.close(callback);
        }
    }
};

TChannelPeer.prototype.setState = StateMachine.prototype.setState;

TChannelPeer.prototype.getInConnection = function getInConnection() {
    var self = this;
    for (var i = 0; i < self.connections.length; i++) {
        var conn = self.connections[i];
        if (!conn.closing) return conn;
    }
    return null;
};

TChannelPeer.prototype.getOutConnection = function getOutConnection(preferIdentified) {
    var self = this;
    var candidate = null;
    for (var i = self.connections.length - 1; i >= 0; i--) {
        var conn = self.connections[i];
        if (conn.closing) continue;
        if (!preferIdentified) return conn; // user doesn't care, take last outgoing
        if (conn.remoteName) return conn; // user wanted an identified channel, and we found one
        if (!candidate) candidate = conn; // we'll fallback to returning this if we can't find an identified one
    }
    return candidate;
};

TChannelPeer.prototype.countConnections = function countConnections(direction) {
    var self = this;
    if (!direction) {
        return self.connections.length;
    }

    var count = 0;
    for (var i = 0; i < self.connections.length; i++) {
        var conn = self.connections[i];
        if (conn.direction === direction) {
            count++;
        }
    }

    return count;
};

TChannelPeer.prototype.connect = function connect(outOnly) {
    var self = this;
    var conn = self.getOutConnection(true);
    if (!conn || (outOnly && conn.direction !== 'out')) {
        var socket = self.makeOutSocket();
        conn = self.makeOutConnection(socket);
        self.addConnection(conn);
    }
    return conn;
};

TChannelPeer.prototype.waitForIdentified =
function waitForIdentified(callback) {
    var self = this;

    var conn = self.connect();

    if (conn.closing) {
        onConnectionClose(conn.closeError);
    } else {
        conn.closeEvent.on(onConnectionClose);

        // conn.handler is a self peer detection
        if (!conn.remoteName) {
            conn.identifiedEvent.on(onIdentified);
            return;
        } else {
            onIdentified();
        }
    }

    function onConnectionClose(err) {
        conn.closeEvent.removeListener(onConnectionClose);
        callback(err || errors.TChannelConnectionCloseError());
    }

    function onIdentified() {
        conn.closeEvent.removeListener(onConnectionClose);
        callback(null);
    }
};

TChannelPeer.prototype.request = function peerRequest(options) {
    var self = this;
    var req = self.connect().request(options);

    self.state.onRequest(req);

    req.errorEvent.on(onError);
    req.responseEvent.on(onResponse);

    function onError(err) {
        self.state.onRequestError(err);
    }

    function onResponse(res) {
        self.state.onRequestResponse(req);
    }

    return req;
};

TChannelPeer.prototype.addConnection = function addConnection(conn) {
    var self = this;
    // TODO: first approx alert for self.connections.length > 2
    // TODO: second approx support pruning
    if (conn.direction === 'out') {
        self.connections.push(conn);
    } else {
        self.connections.unshift(conn);
    }
    conn.errorEvent.on(onConnectionError);
    conn.closeEvent.on(onConnectionClose);
    return conn;

    function onConnectionError(err) {
        var codeName = errors.classify(err);

        var loggerInfo = {
            err: err,
            direction: conn.direction,
            remoteName: conn.remoteName,
            socketRemoteAddr: conn.socketRemoteAddr
        };

        if (codeName === 'Timeout') {
            self.logger.warn('Got a connection error', loggerInfo);
        } else {
            self.logger.error('Got an unexpected connection error', loggerInfo);
        }

        self.removeConnection(conn);
    }

    function onConnectionClose() {
        self.removeConnection(conn);
    }
};

TChannelPeer.prototype.removeConnection = function removeConnection(conn) {
    var self = this;
    var list = self.connections;
    var index = list ? list.indexOf(conn) : -1;
    if (index !== -1) {
        return list.splice(index, 1)[0];
    } else {
        return null;
    }
};

TChannelPeer.prototype.makeOutSocket = function makeOutSocket() {
    var self = this;
    var parts = self.hostPort.split(':');
    assert(parts.length === 2, 'invalid destination');
    var host = parts[0];
    var port = parts[1];
    assert(host !== '0.0.0.0', 'cannot connect to ephemeral peer');
    assert(port !== '0', 'cannot connect to dynamic port');
    var socket = net.createConnection({host: host, port: port});
    return socket;
};

TChannelPeer.prototype.makeOutConnection = function makeOutConnection(socket) {
    var self = this;
    var chan = self.channel.topChannel || self.channel;
    var conn = new TChannelConnection(chan, socket, 'out', self.hostPort);
    conn.spanEvent.on(handleSpanFromConn);
    self.allocConnectionEvent.emit(self, conn);
    return conn;

    function handleSpanFromConn(span) {
        chan.tracer.report(span);
    }
};

TChannelPeer.prototype.outPendingWeightedRandom = function outPendingWeightedRandom() {
    // A weighted random variable:
    //   random() ** (1 / weight)
    // Such that the probability distribution is uniform for weights of 0, but
    // an increasing bias with increasing weight.
    // However, although weight should start at 0 and increase probability,
    // the number of pending requests starts at 0 and should decrease
    // probability as it increases.
    // For 0 pending requests, we produce a uniform probability distribution by
    // raising a uniform random variable to the power of 1 (pending + 1).
    // As the number of pending requests increase, the magnitude of the power
    // increases and the probability distribution develops a bias toward zero.
    // TODO review weighted reservoir sampling:
    // http://arxiv.org/pdf/1012.0256.pdf
    var self = this;
    var pending = self.countOutPending();
    return Math.pow(self.random(), 1 + pending);
};

TChannelPeer.prototype.countOutPending = function countOutPending() {
    var self = this;
    var pending = 0;
    for (var index = 0; index < self.connections.length; index++) {
        var connPending = self.connections[index].ops.getPending();

        pending += connPending.out;
    }
    return pending;
};

// Consulted depending on the peer state
TChannelPeer.prototype.shouldRequest = function shouldRequest() {
    var self = this;
    // space:
    //   [0.1, 0.2)  unconnected peers
    //   [0.2, 0.3)  incoming connections
    //   [0.3, 0.4)  new outgoing connections
    //   [0.4, 1.0)  identified outgoing connections
    var inconn = self.getInConnection();
    var outconn = self.getOutConnection();
    var random = self.outPendingWeightedRandom();
    if (!inconn && !outconn) {
        return 0.1 + random * 0.1;
    } else if (!outconn || outconn.direction !== 'out') {
        self.connect();
        return 0.2 + random * 0.1;
    } else if (outconn.remoteName === null) {
        return 0.3 + random * 0.1;
    } else {
        return 0.4 + random * 0.6;
    }
};

module.exports = TChannelPeer;
<|endoftext|>


<commit_before>/**
 * @file DraggableList component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {DragDropContext, Droppable} from 'react-beautiful-dnd';
import isArray from 'lodash/isArray';
import classNames from 'classnames';

import DraggableListItem from '../_DraggableListItem';
import Tip from '../Tip';
import Theme from '../Theme';

import Util from '../_vendors/Util';
import Event from '../_vendors/Event';
import Calculation from '../_vendors/Calculation';
import SelectMode from '../_statics/SelectMode';
import LIST_SEPARATOR from '../_statics/ListSeparator';

class DraggableList extends Component {

    static SelectMode = SelectMode;
    static LIST_SEPARATOR = LIST_SEPARATOR;
    static Theme = Theme;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            data: props.data,
            value: Calculation.getInitValue(props)
        };

        this.listItemSelectHandler = ::this.listItemSelectHandler;
        this.listItemDeselectHandler = ::this.listItemDeselectHandler;
        this.onItemDragEnd = ::this.onItemDragEnd;
        this.renderListItem = ::this.renderListItem;

    }

    listItemSelectHandler(item, index) {

        const {selectMode} = this.props;

        let {value} = this.state;

        if (selectMode === SelectMode.MULTI_SELECT) {

            if (!value || !isArray(value)) {
                value = [];
            }

            value.push(item);

        } else if (selectMode === SelectMode.SINGLE_SELECT) {
            value = item;
        }

        this.setState({
            value
        }, () => {
            const {onItemSelect, onChange} = this.props;
            onItemSelect && onItemSelect(item, index);
            onChange && onChange(value, index);
        });

    }

    listItemDeselectHandler(item, index) {

        const {selectMode} = this.props;

        if (selectMode !== SelectMode.MULTI_SELECT) {
            return;
        }

        const {valueField, displayField} = this.props;
        let {value} = this.state;

        if (!value || !isArray(value)) {
            value = [];
        } else {
            value = value.filter(valueItem => {
                return Util.getValueByValueField(valueItem, valueField, displayField)
                    != Util.getValueByValueField(item, valueField, displayField);
            });
        }

        this.setState({
            value
        }, () => {
            const {onItemDeselect, onChange} = this.props;
            onItemDeselect && onItemDeselect(item, index);
            onChange && onChange(value, index);
        });

    }

    onItemDragEnd(result) {

        /**
         *  result: {
         *      draggableId,
         *      type,
         *      source: {
         *          droppableId,
         *          index
         *      },
         *      destination: {
         *          droppableId,
         *          index
         *      }
         *  }
         */

        if (!result || !('draggableId' in result)
            || !result.source || !('index' in result.source)
            || !result.destination || !('index' in result.destination)) {
            return;
        }

        const {data} = this.state;

        Util.reorder(data, result.source.index, result.destination.index);

        this.setState({
            data
        }, () => {
            const {onItemDragEnd, onSequenceChange} = this.props;
            onItemDragEnd && onItemDragEnd(result);
            onSequenceChange && onSequenceChange(data);
        });

    }

    componentWillReceiveProps(nextProps) {

        let state;

        if (nextProps.data !== this.state.data) {
            state = state ? state : {};
            state.data = nextProps.data;
        }
        if (nextProps.value !== this.state.value) {
            state = state ? state : {};
            state.value = Calculation.getInitValue(nextProps);
        }

        if (state) {
            this.setState(state);
        }

    }

    renderListItem(item, index) {

        const {

                theme, itemHeight, idField, valueField, displayField, descriptionField, disabled, isLoading, renderer,

                selectTheme, selectMode, radioUncheckedIconCls, radioCheckedIconCls,
                checkboxUncheckedIconCls, checkboxCheckedIconCls, checkboxIndeterminateIconCls,

                onItemTouchTap

            } = this.props,
            {value} = this.state,
            self = this,

            props = {
                index,
                style: {height: itemHeight},
                theme: item.theme || theme,
                selectTheme: item.selectTheme || selectTheme,
                radioUncheckedIconCls: item.radioUncheckedIconCls || radioUncheckedIconCls,
                radioCheckedIconCls: item.radioCheckedIconCls || radioCheckedIconCls,
                checkboxUncheckedIconCls: item.checkboxUncheckedIconCls || checkboxUncheckedIconCls,
                checkboxCheckedIconCls: item.checkboxCheckedIconCls || checkboxCheckedIconCls,
                checkboxIndeterminateIconCls: item.checkboxIndeterminateIconCls || checkboxIndeterminateIconCls,
                checked: Calculation.isItemChecked(item, value, self.props),
                selectMode,
                renderer,
                onSelect() {
                    self.listItemSelectHandler(item, index);
                },
                onDeselect() {
                    self.listItemDeselectHandler(item, index);
                }
            };

        return typeof item === 'object' ?
            (
                <DraggableListItem {...item}
                                   {...props}
                                   key={item[idField] || index}
                                   data={item}
                                   value={Util.getValueByValueField(item, valueField, displayField)}
                                   text={Util.getTextByDisplayField(item, displayField, valueField)}
                                   desc={item[descriptionField] || null}
                                   disabled={disabled || item.disabled}
                                   isLoading={isLoading || item.isLoading}
                                   onTouchTap={e => {
                                       onItemTouchTap && onItemTouchTap(item, index, e);
                                       item.onTouchTap && item.onTouchTap(e);
                                   }}/>
            )
            :
            (
                <DraggableListItem {...props}
                                   key={index}
                                   data={item}
                                   value={item}
                                   text={item}
                                   disabled={disabled}
                                   isLoading={isLoading}
                                   onTouchTap={e => {
                                       onItemTouchTap && onItemTouchTap(item, index, e);
                                   }}/>
            );

    }

    render() {

        const {children, className, style, disabled, onNodeDragStart} = this.props,
            {data} = this.state,

            listClassName = classNames('draggable-list', {
                [className]: className
            });

        return (
            <DragDropContext onDragStart={onNodeDragStart}
                             onDragEnd={this.onItemDragEnd}>

 {
                         Event.wheelHandler(e, this.props);
                     }}>

                    <Droppable droppableId="droppable">

                        {
                            dropProvided => (

                                    {
                                        data.map((item, index) => {

                                            if (item === LIST_SEPARATOR) {
                                                return

;
                                            }

                                            return this.renderListItem(item, index);

                                        })
                                    }

                                    {dropProvided.placeholder}

                            )
                        }

                    </Droppable>

                    {children}

            </DragDropContext>
        );
    }
};

DraggableList.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * The theme of the list item.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The theme of the list item select radio or checkbox.
     */
    selectTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The mode of listItem.
     */
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    /**
     * Children passed into the ListItem.
     */
    data: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape({

        /**
         * The CSS class name of the list button.
         */
        className: PropTypes.string,

        /**
         * Override the styles of the list button.
         */
        style: PropTypes.object,

        /**
         * The theme of the list button.
         */
        theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

        /**
         * The text value of the list button.Type can be string or number.
         */
        value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * The list item's display text. Type can be string, number or bool.
         */
        text: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * The desc value of the list button. Type can be string or number.
         */
        desc: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

        /**
         * If true,the list item will be disabled.
         */
        disabled: PropTypes.bool,

        /**
         * If true,the button will be have loading effect.
         */
        isLoading: PropTypes.bool,

        /**
         * If true,the element's ripple effect will be disabled.
         */
        disableTouchRipple: PropTypes.bool,

        /**
         * Use this property to display an icon. It will display on the left.
         */
        iconCls: PropTypes.string,

        /**
         * Use this property to display an icon. It will display on the right.
         */
        rightIconCls: PropTypes.string,

        /**
         * The message of tip.
         */
        tip: PropTypes.string,

        /**
         * The position of tip.
         */
        tipPosition: PropTypes.oneOf(Util.enumerateValue(Tip.Position)),

        /**
         * If true,the item will have center displayed ripple effect.
         */
        rippleDisplayCenter: PropTypes.bool,

        /**
         * You can create a complicated renderer callback instead of value and desc prop.
         */
        itemRenderer: PropTypes.func,

        /**
         * Callback function fired when a list item touch-tapped.
         */
        onTouchTap: PropTypes.func

    }), PropTypes.string, PropTypes.number, PropTypes.symbol])),

    value: PropTypes.any,

    /**
     * The id field name in data. (default: "id")
     */
    idField: PropTypes.string,

    /**
     * The value field name in data. (default: "value")
     */
    valueField: PropTypes.string,

    /**
     * The display field name in data. (default: "text")
     */
    displayField: PropTypes.string,

    /**
     * The description field name in data. (default: "desc")
     */
    descriptionField: PropTypes.string,

    /**
     * If true, the list will be disabled.
     */
    disabled: PropTypes.bool,

    /**
     * If true, the list will be at loading status.
     */
    isLoading: PropTypes.bool,

    shouldPreventContainerScroll: PropTypes.bool,

    radioUncheckedIconCls: PropTypes.string,
    radioCheckedIconCls: PropTypes.string,
    checkboxUncheckedIconCls: PropTypes.string,
    checkboxCheckedIconCls: PropTypes.string,
    checkboxIndeterminateIconCls: PropTypes.string,

    /**
     * You can create a complicated renderer callback instead of value and desc prop.
     */
    renderer: PropTypes.func,

    /**
     * Callback function fired when the list-item touch tap.
     */
    onItemTouchTap: PropTypes.func,

    /**
     * Callback function fired when the list-item select.
     */
    onItemSelect: PropTypes.func,

    /**
     * Callback function fired when the list-item deselect.
     */
    onItemDeselect: PropTypes.func,

    /**
     * Callback function fired when the list changed.
     */
    onChange: PropTypes.func,

    /**
     * Callback function fired when wrapper wheeled.
     */
    onWheel: PropTypes.func,

    onNodeDragStart: PropTypes.func,
    onItemDragEnd: PropTypes.func,

    onSequenceChange: PropTypes.func

};

DraggableList.defaultProps = {

    className: null,
    style: null,
    theme: Theme.DEFAULT,

    selectTheme: Theme.DEFAULT,
    selectMode: SelectMode.SINGLE_SELECT,

    data: null,

    idField: 'id',
    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',
    disabled: false,
    shouldPreventContainerScroll: true,

    radioUncheckedIconCls: null,
    radioCheckedIconCls: null,
    checkboxUncheckedIconCls: 'far fa-square',
    checkboxCheckedIconCls: 'fas fa-check-square',
    checkboxIndeterminateIconCls: 'fas fa-minus-square'

};

export default DraggableList;<commit_msg>update DraggableList<commit_after>/**
 * @file DraggableList component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import {DragDropContext, Droppable} from 'react-beautiful-dnd';
import isArray from 'lodash/isArray';
import classNames from 'classnames';

import DraggableListItem from '../_DraggableListItem';
import Tip from '../Tip';
import Theme from '../Theme';

import LIST_SEPARATOR from '../_statics/ListSeparator';
import SelectMode from '../_statics/SelectMode';

import PureRender from '../_vendors/PureRender';
import Util from '../_vendors/Util';
import Event from '../_vendors/Event';
import Calculation from '../_vendors/Calculation';

@PureRender
class DraggableList extends Component {

    static SelectMode = SelectMode;
    static LIST_SEPARATOR = LIST_SEPARATOR;
    static Theme = Theme;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            data: props.data,
            value: Calculation.getInitValue(props)
        };

        this.listItemSelectHandler = ::this.listItemSelectHandler;
        this.listItemDeselectHandler = ::this.listItemDeselectHandler;
        this.onItemDragEnd = ::this.onItemDragEnd;
        this.renderListItem = ::this.renderListItem;

    }

    listItemSelectHandler(item, index) {

        const {selectMode} = this.props;

        let {value} = this.state;

        if (selectMode === SelectMode.MULTI_SELECT) {

            if (!value || !isArray(value)) {
                value = [];
            }

            value.push(item);

        } else if (selectMode === SelectMode.SINGLE_SELECT) {
            value = item;
        }

        this.setState({
            value
        }, () => {
            const {onItemSelect, onChange} = this.props;
            onItemSelect && onItemSelect(item, index);
            onChange && onChange(value, index);
        });

    }

    listItemDeselectHandler(item, index) {

        const {selectMode} = this.props;

        if (selectMode !== SelectMode.MULTI_SELECT) {
            return;
        }

        const {valueField, displayField} = this.props;
        let {value} = this.state;

        if (!value || !isArray(value)) {
            value = [];
        } else {
            value = value.filter(valueItem => {
                return Util.getValueByValueField(valueItem, valueField, displayField)
                    != Util.getValueByValueField(item, valueField, displayField);
            });
        }

        this.setState({
            value
        }, () => {
            const {onItemDeselect, onChange} = this.props;
            onItemDeselect && onItemDeselect(item, index);
            onChange && onChange(value, index);
        });

    }

    onItemDragEnd(result) {

        /**
         *  result: {
         *      draggableId,
         *      type,
         *      source: {
         *          droppableId,
         *          index
         *      },
         *      destination: {
         *          droppableId,
         *          index
         *      }
         *  }
         */

        if (!result || !('draggableId' in result)
            || !result.source || !('index' in result.source)
            || !result.destination || !('index' in result.destination)) {
            return;
        }

        const {data} = this.state;

        Util.reorder(data, result.source.index, result.destination.index);

        this.setState({
            data
        }, () => {
            const {onItemDragEnd, onSequenceChange} = this.props;
            onItemDragEnd && onItemDragEnd(result);
            onSequenceChange && onSequenceChange(data);
        });

    }

    componentWillReceiveProps(nextProps) {

        let state;

        if (nextProps.data !== this.state.data) {
            state = state ? state : {};
            state.data = nextProps.data;
        }
        if (nextProps.value !== this.state.value) {
            state = state ? state : {};
            state.value = Calculation.getInitValue(nextProps);
        }

        if (state) {
            this.setState(state);
        }

    }

    renderListItem(item, index) {

        const {

                theme, itemHeight, idField, valueField, displayField, descriptionField, disabled, isLoading, renderer,

                selectTheme, selectMode, radioUncheckedIconCls, radioCheckedIconCls,
                checkboxUncheckedIconCls, checkboxCheckedIconCls, checkboxIndeterminateIconCls,

                onItemTouchTap

            } = this.props,
            {value} = this.state,
            self = this,

            props = {
                index,
                style: {height: itemHeight},
                theme: item.theme || theme,
                selectTheme: item.selectTheme || selectTheme,
                radioUncheckedIconCls: item.radioUncheckedIconCls || radioUncheckedIconCls,
                radioCheckedIconCls: item.radioCheckedIconCls || radioCheckedIconCls,
                checkboxUncheckedIconCls: item.checkboxUncheckedIconCls || checkboxUncheckedIconCls,
                checkboxCheckedIconCls: item.checkboxCheckedIconCls || checkboxCheckedIconCls,
                checkboxIndeterminateIconCls: item.checkboxIndeterminateIconCls || checkboxIndeterminateIconCls,
                checked: Calculation.isItemChecked(item, value, self.props),
                selectMode,
                renderer,
                onSelect() {
                    self.listItemSelectHandler(item, index);
                },
                onDeselect() {
                    self.listItemDeselectHandler(item, index);
                }
            };

        return typeof item === 'object' ?
            (
                <DraggableListItem {...item}
                                   {...props}
                                   key={item[idField] || index}
                                   data={item}
                                   value={Util.getValueByValueField(item, valueField, displayField)}
                                   text={Util.getTextByDisplayField(item, displayField, valueField)}
                                   desc={item[descriptionField] || null}
                                   disabled={disabled || item.disabled}
                                   isLoading={isLoading || item.isLoading}
                                   onTouchTap={e => {
                                       onItemTouchTap && onItemTouchTap(item, index, e);
                                       item.onTouchTap && item.onTouchTap(e);
                                   }}/>
            )
            :
            (
                <DraggableListItem {...props}
                                   key={index}
                                   data={item}
                                   value={item}
                                   text={item}
                                   disabled={disabled}
                                   isLoading={isLoading}
                                   onTouchTap={e => {
                                       onItemTouchTap && onItemTouchTap(item, index, e);
                                   }}/>
            );

    }

    render() {

        const {children, className, style, disabled, onNodeDragStart} = this.props,
            {data} = this.state,

            listClassName = classNames('draggable-list', {
                [className]: className
            });

        return (
            <DragDropContext onDragStart={onNodeDragStart}
                             onDragEnd={this.onItemDragEnd}>

 {
                         Event.wheelHandler(e, this.props);
                     }}>

                    <Droppable droppableId="droppable">

                        {
                            dropProvided => (

                                    {
                                        data.map((item, index) => {

                                            if (item === LIST_SEPARATOR) {
                                                return

;
                                            }

                                            return this.renderListItem(item, index);

                                        })
                                    }

                                    {dropProvided.placeholder}

                            )
                        }

                    </Droppable>

                    {children}

            </DragDropContext>
        );
    }
};

if (process.env.NODE_ENV === 'development') {

    const PropTypes = require('prop-types');

    DraggableList.propTypes = {

        /**
         * The CSS class name of the root element.
         */
        className: PropTypes.string,

        /**
         * Override the styles of the root element.
         */
        style: PropTypes.object,

        /**
         * The theme of the list item.
         */
        theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

        /**
         * The theme of the list item select radio or checkbox.
         */
        selectTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

        /**
         * The mode of listItem.
         */
        selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

        /**
         * Children passed into the ListItem.
         */
        data: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape({

            /**
             * The CSS class name of the list button.
             */
            className: PropTypes.string,

            /**
             * Override the styles of the list button.
             */
            style: PropTypes.object,

            /**
             * The theme of the list button.
             */
            theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

            /**
             * The text value of the list button.Type can be string or number.
             */
            value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

            /**
             * The list item's display text. Type can be string, number or bool.
             */
            text: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

            /**
             * The desc value of the list button. Type can be string or number.
             */
            desc: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

            /**
             * If true,the list item will be disabled.
             */
            disabled: PropTypes.bool,

            /**
             * If true,the button will be have loading effect.
             */
            isLoading: PropTypes.bool,

            /**
             * If true,the element's ripple effect will be disabled.
             */
            disableTouchRipple: PropTypes.bool,

            /**
             * Use this property to display an icon. It will display on the left.
             */
            iconCls: PropTypes.string,

            /**
             * Use this property to display an icon. It will display on the right.
             */
            rightIconCls: PropTypes.string,

            /**
             * The message of tip.
             */
            tip: PropTypes.string,

            /**
             * The position of tip.
             */
            tipPosition: PropTypes.oneOf(Util.enumerateValue(Tip.Position)),

            /**
             * If true,the item will have center displayed ripple effect.
             */
            rippleDisplayCenter: PropTypes.bool,

            /**
             * You can create a complicated renderer callback instead of value and desc prop.
             */
            itemRenderer: PropTypes.func,

            /**
             * Callback function fired when a list item touch-tapped.
             */
            onTouchTap: PropTypes.func

        }), PropTypes.string, PropTypes.number, PropTypes.symbol])),

        value: PropTypes.any,

        /**
         * The id field name in data. (default: "id")
         */
        idField: PropTypes.string,

        /**
         * The value field name in data. (default: "value")
         */
        valueField: PropTypes.string,

        /**
         * The display field name in data. (default: "text")
         */
        displayField: PropTypes.string,

        /**
         * The description field name in data. (default: "desc")
         */
        descriptionField: PropTypes.string,

        /**
         * If true, the list will be disabled.
         */
        disabled: PropTypes.bool,

        /**
         * If true, the list will be at loading status.
         */
        isLoading: PropTypes.bool,

        shouldPreventContainerScroll: PropTypes.bool,

        radioUncheckedIconCls: PropTypes.string,
        radioCheckedIconCls: PropTypes.string,
        checkboxUncheckedIconCls: PropTypes.string,
        checkboxCheckedIconCls: PropTypes.string,
        checkboxIndeterminateIconCls: PropTypes.string,

        /**
         * You can create a complicated renderer callback instead of value and desc prop.
         */
        renderer: PropTypes.func,

        /**
         * Callback function fired when the list-item touch tap.
         */
        onItemTouchTap: PropTypes.func,

        /**
         * Callback function fired when the list-item select.
         */
        onItemSelect: PropTypes.func,

        /**
         * Callback function fired when the list-item deselect.
         */
        onItemDeselect: PropTypes.func,

        /**
         * Callback function fired when the list changed.
         */
        onChange: PropTypes.func,

        /**
         * Callback function fired when wrapper wheeled.
         */
        onWheel: PropTypes.func,

        onNodeDragStart: PropTypes.func,
        onItemDragEnd: PropTypes.func,

        onSequenceChange: PropTypes.func

    };

}

DraggableList.defaultProps = {

    theme: Theme.DEFAULT,

    selectTheme: Theme.DEFAULT,
    selectMode: SelectMode.SINGLE_SELECT,

    idField: 'id',
    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',
    disabled: false,
    shouldPreventContainerScroll: true,

    checkboxUncheckedIconCls: 'far fa-square',
    checkboxCheckedIconCls: 'fas fa-check-square',
    checkboxIndeterminateIconCls: 'fas fa-minus-square'

};

export default DraggableList;<|endoftext|>


<commit_before>var express = require("express")
var server = require("http").createServer();
var wss = new require("ws").Server({server});
var app = express();
var models = require("./models")
var bodyParser = require("body-parser")
var url_module = require("url")
var tokenAuth = require("./utils/tokenAuth")
var multer = require("multer")()
var models = require("./models")
app.use(bodyParser.urlencoded({extended:true}))
app.use(bodyParser.json())
app.use(function(req,res,next){
    res.append("Access-Control-Allow-Origin","*")
    res.append("Access-Control-Allow-Method","GET, POST, OPTIONS");
    res.append("Access-Control-Allow-Headers","X-Kyoppie-Access-Token");
    res.append("Access-Control-Max-Age","86400")
    next();
})
app.options('*',function(req,res){
    res.end();
})
app.post('*',function(req,res,next){
    var log = new models.logs();
    log.ipaddr = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
    log.path = req.originalUrl;
    res.send_ = res.send;
    res.code_ = res.code;
    res.code = function(code){
        var obj_ = res.code_(code);
        return {
            send:function(obj){
                obj_.send(obj)
                try{
                    log.response = JSON.stringify(obj);
                    log.save();
                }catch(e){}
            }
        }
    }
    res.send = function(obj){
        res.send_(obj)
        try{
            log.response = JSON.stringify(obj);
            log.save();
        }catch(e){}
    }
    next();
})

var routes = require("./routes")
routes.rest.forEach(function(route){
    var login = true;
    if(route.login !== undefined) login = route.login;
    var method = route.method;
    var path = route.name;
    var authFunc = tokenAuth(route,login)
    if(route.file)
        app[method](path,multer.single("file"),authFunc,require("./handlers/web"+path));
    else
        app[method](path,authFunc,require("./handlers/web"+path));
})
var ws_route = {};
routes.websocket.forEach(function(route){
    var login = true;
    if(route.login !== undefined) login = route.login;
    var path = route.name;
    ws_route[path] = route;
    ws_route[path]["login"] = login;
    ws_route[path]["callback"] = require("./handlers/ws"+path)
})
console.log(ws_route)
app.all("*",function(req,res){
    // not found
    res.status(404).send({result:false,error:"not-found-api"})
})
wss.on("connection",function(ws){
    var location = url_module.parse(ws.upgradeReq.url,true);
    var url = location.pathname;
    ws.sendJSON = function(json){
        ws.send(JSON.stringify(json))
    }
    if(!ws_route[url]){
        ws.sendJSON({result:false,error:"api-not-found"})
        ws.close();
        return
    }
    console.log(ws_route)
    if(ws_route[url].login){
        if(location.query.access_token){
            models.access_tokens.findOne({
                secret:location.query.access_token
            }).populate("app user").then(function(token){
                console.log(token)
                if(token){
                    ws.token=token;
                    ws_route[url].callback(ws);
                } else {
                    ws.sendJSON({result:false,error:"please-auth"})
                    ws.close()
                    return
                }
            },function(){
                ws.send(JSON.strigify({response:false,error:"server-side-auth-error"}))
                ws.close()
                return
            })
        } else {
            ws.sendJSON({result:false,error:"please-auth"})
            ws.close()
            return
        }
    } else {
        ws_route[url].callback(ws);
    }
})
server.on("request",app);
server.listen(4005,function(){
    console.log("listen for "+server.address().port+" port");
})<commit_msg>起動時のメッセージを実装<commit_after>var express = require("express")
var server = require("http").createServer();
var wss = new require("ws").Server({server});
var app = express();
var models = require("./models")
var bodyParser = require("body-parser")
var url_module = require("url")
var tokenAuth = require("./utils/tokenAuth")
var multer = require("multer")()
var models = require("./models")

console.log("###################")
console.log("### Kyoppie API ###")
console.log("###################")
console.log("Repository: https://github.com/kyoppie/kyoppie-api")

app.use(bodyParser.urlencoded({extended:true}))
app.use(bodyParser.json())
app.use(function(req,res,next){
    res.append("Access-Control-Allow-Origin","*")
    res.append("Access-Control-Allow-Method","GET, POST, OPTIONS");
    res.append("Access-Control-Allow-Headers","X-Kyoppie-Access-Token");
    res.append("Access-Control-Max-Age","86400")
    next();
})
app.options('*',function(req,res){
    res.end();
})
app.post('*',function(req,res,next){
    var log = new models.logs();
    log.ipaddr = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
    log.path = req.originalUrl;
    res.send_ = res.send;
    res.code_ = res.code;
    res.code = function(code){
        var obj_ = res.code_(code);
        return {
            send:function(obj){
                obj_.send(obj)
                try{
                    log.response = JSON.stringify(obj);
                    log.save();
                }catch(e){}
            }
        }
    }
    res.send = function(obj){
        res.send_(obj)
        try{
            log.response = JSON.stringify(obj);
            log.save();
        }catch(e){}
    }
    next();
})

var routes = require("./routes")
routes.rest.forEach(function(route){
    var login = true;
    if(route.login !== undefined) login = route.login;
    var method = route.method;
    var path = route.name;
    var authFunc = tokenAuth(route,login)
    if(route.file)
        app[method](path,multer.single("file"),authFunc,require("./handlers/web"+path));
    else
        app[method](path,authFunc,require("./handlers/web"+path));
})
var ws_route = {};
routes.websocket.forEach(function(route){
    var login = true;
    if(route.login !== undefined) login = route.login;
    var path = route.name;
    ws_route[path] = route;
    ws_route[path]["login"] = login;
    ws_route[path]["callback"] = require("./handlers/ws"+path)
})
app.all("*",function(req,res){
    // not found
    res.status(404).send({result:false,error:"not-found-api"})
})
wss.on("connection",function(ws){
    var location = url_module.parse(ws.upgradeReq.url,true);
    var url = location.pathname;
    ws.sendJSON = function(json){
        ws.send(JSON.stringify(json))
    }
    if(!ws_route[url]){
        ws.sendJSON({result:false,error:"api-not-found"})
        ws.close();
        return
    }
    console.log(ws_route)
    if(ws_route[url].login){
        if(location.query.access_token){
            models.access_tokens.findOne({
                secret:location.query.access_token
            }).populate("app user").then(function(token){
                console.log(token)
                if(token){
                    ws.token=token;
                    ws_route[url].callback(ws);
                } else {
                    ws.sendJSON({result:false,error:"please-auth"})
                    ws.close()
                    return
                }
            },function(){
                ws.send(JSON.strigify({response:false,error:"server-side-auth-error"}))
                ws.close()
                return
            })
        } else {
            ws.sendJSON({result:false,error:"please-auth"})
            ws.close()
            return
        }
    } else {
        ws_route[url].callback(ws);
    }
})
server.on("request",app);
server.listen(4005,function(){
    console.log("listen for "+server.address().port+" port");
})<|endoftext|>


<commit_before>var roleAllocator = require('roleAllocator')
var roleGeneralist = require('roleGeneralist')
var _ = require('lodash')

module.exports.loop = function () {

    for(var name in Memory.creeps) {
	    if(!Game.creeps[name]) {
	        delete Memory.creeps[name];
	        console.log('Clearing non-existing creep memory:', name);
	    }
    }

    for(var sourceId in Memory.energySources) {
        var creeps = Memory.energySources[sourceId];
        var toDelete = [];
        for (var i=0; i < creeps.length; i++) {
            if(!Game.creeps[creeps[i]]) {
                toDelete.push(creeps[i])
            }
        }
        _.pullAll(creeps, toDelete);
    }

    roleAllocator.spawnNecessary()

    for(var name in Game.creeps) {
	    var creep = Game.creeps[name];
	    if(creep.memory.role == 'generalist') {
	        roleGeneralist.run(creep);
	    }
    }
}
<commit_msg>removing function not in their lodash<commit_after>var roleAllocator = require('roleAllocator')
var roleGeneralist = require('roleGeneralist')
var _ = require('lodash')

module.exports.loop = function () {

    for(var name in Memory.creeps) {
	    if(!Game.creeps[name]) {
	        delete Memory.creeps[name];
	        console.log('Clearing non-existing creep memory:', name);
	    }
    }

    for(var sourceId in Memory.energySources) {
        var creeps = Memory.energySources[sourceId];
        var toDelete = [];
        for (var i=0; i < creeps.length; i++) {
            if(!Game.creeps[creeps[i]]) {
                toDelete.push(creeps[i])
            }
        }
        for (var i=0; i < toDelete.length; i++) {
             _.pull(creeps, toDelete[i]);
        }
    }

    roleAllocator.spawnNecessary()

    for(var name in Game.creeps) {
	    var creep = Game.creeps[name];
	    if(creep.memory.role == 'generalist') {
	        roleGeneralist.run(creep);
	    }
    }
}
<|endoftext|>