<commit_before>"use strict";

const hljs = require("highlight.js");

module.exports = [
  "markedProvider",
  "config",
  "webStructure",
  function(markedProvider, config, webStructure) {
    markedProvider.setOptions({
      gfm: true,
      tables: true,
      highlight: function(code, lang) {
        if (lang) {
          // 9.x API
          return hljs.highlight(lang, code, true).value;
          // 10.x API: return hljs.highlight(code, {language: lang, ignoreIllegals: true}).value;
        } else {
          return hljs.highlightAuto(code).value;
        }
      }
    });

    markedProvider.setRenderer({
      table: function(head, body) {
        return (
          '
' +
          "
" +
          head +
          "
" +
          "
" +
          body +
          "
" +
          "
"
        );
      },
      link: function(href, title, text) {
        // external link
        if (href.indexOf("://") > -1) {
          return (
            '' +
            text +
            ' '
          );
        }
        // anchor link
        if (href.indexOf("#") > -1) {
          return (
            '" +
            text +
            ' '
          );
        }
        // internal link
        var file = findFileInWebstructure(webStructure, href);
        // we don't have the file on the website, make external link
        if (file === null) {
          return (
            '' +
            text +
            ' '
          );
        }
        // we have this file on the website, make internal link
        else {
          return (
            '" +
            text +
            ""
          );
        }
      },
      image: function(href, title, text) {
        // external image
        if (href.indexOf("://") > -1) {
          return (
            '"
          );
        }
        // internal link, load from github
        return (
          '"
        );
      }
    });

    function findFileInWebstructure(list, path) {
      var result = null;
      for (var i = 0; i < list.length; i++) {
        if (list[i].type === "submenu" || list[i].type === "listfiles") {
          result = findFileInWebstructure(list[i].children, path);
          if (result !== null && result.type === "file") {
            if (typeof result.ref === "undefined") {
              result.ref = list[i].ref;
            }
            return result;
          }
        } else if (list[i].type === "file" && list[i].options.path === path) {
          return list[i];
        }
      }
      return null; // did not find path
    }
  }
];
<commit_msg>website: catch errors when highlighting code with highlight.sj<commit_after>"use strict";

const hljs = require("highlight.js");

module.exports = [
  "markedProvider",
  "config",
  "webStructure",
  function(markedProvider, config, webStructure) {
    markedProvider.setOptions({
      gfm: true,
      tables: true,
      highlight: function(code, lang) {
        var ret;
        try {
          if (lang) {
            ret = hljs.highlight(code, {language: lang, ignoreIllegals: true}).value;
          } else {
            ret = hljs.highlightAuto(code).value;
          }
        } catch (err) {
          ret = code;
        }
        return ret;
      }
    });

    markedProvider.setRenderer({
      table: function(head, body) {
        return (
          '
' +
          "
" +
          head +
          "
" +
          "
" +
          body +
          "
" +
          "
"
        );
      },
      link: function(href, title, text) {
        // external link
        if (href.indexOf("://") > -1) {
          return (
            '' +
            text +
            ' '
          );
        }
        // anchor link
        if (href.indexOf("#") > -1) {
          return (
            '" +
            text +
            ' '
          );
        }
        // internal link
        var file = findFileInWebstructure(webStructure, href);
        // we don't have the file on the website, make external link
        if (file === null) {
          return (
            '' +
            text +
            ' '
          );
        }
        // we have this file on the website, make internal link
        else {
          return (
            '" +
            text +
            ""
          );
        }
      },
      image: function(href, title, text) {
        // external image
        if (href.indexOf("://") > -1) {
          return (
            '"
          );
        }
        // internal link, load from github
        return (
          '"
        );
      }
    });

    function findFileInWebstructure(list, path) {
      var result = null;
      for (var i = 0; i < list.length; i++) {
        if (list[i].type === "submenu" || list[i].type === "listfiles") {
          result = findFileInWebstructure(list[i].children, path);
          if (result !== null && result.type === "file") {
            if (typeof result.ref === "undefined") {
              result.ref = list[i].ref;
            }
            return result;
          }
        } else if (list[i].type === "file" && list[i].options.path === path) {
          return list[i];
        }
      }
      return null; // did not find path
    }
  }
];
<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////////
// Copyright (c) Autodesk, Inc. All rights reserved
// Written by Forge Partner Development
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
/////////////////////////////////////////////////////////////////////

'use strict'; // http://www.w3schools.com/js/js_strict.asp

// token handling in session
var Credentials = require('./../../credentials');
// forge config information, such as client ID and secret
var config = require('./../../config');

// entity type encoder
var Encoder = require('node-html-encoder').Encoder;
var encoder = new Encoder('entity');

// web framework
var express = require('express');
var router = express.Router();

// OneDrive SDK
const msGraph = require("@microsoft/microsoft-graph-client").Client

function respondWithError(res, error) {
  if (error.statusCode) {
    res.status(error.statusCode).end(error.statusMessage)
  } else {
    res.status(500).end(error.message)
  }
}

router.get('/api/storage/tree', function (req, res) {
  var token = new Credentials(req.session);
  var credentials = token.getStorageCredentials();
  if (credentials === undefined) {
    res.status(401).end();
    return;
  }

  var id = decodeURIComponent(req.query.id)

  // item id's look like this:
  // <drive id>!<file id> in case of a "personal" drive
  // e.g. BF0BDCFE22A2EFD6!161
  // however the "documentLibrary" drive is different
  // so let's store the drive id in each item's id like this
  // driveId:itemId
  var idParts = id.split(':')
  var driveId = idParts[0]
  var id = idParts[1]
  var path = ''

  try {
    if (driveId === '#') {
      path = '/drives'
    } else if (!id) {
      path = '/drives/' + driveId + '/root/children'
    } else {
      path = '/drives/' + driveId + '/items/' + id + '/children'
    }

    var msGraphClient = msGraph.init({
      defaultVersion: 'v1.0',
      debugLogging: true,
      authProvider: function (done) {
        done(null, credentials.access_token)
      }
    })

    msGraphClient
      .api(path)
      .get(function (error, data) {
        if (error) {
          console.log(error)
          respondWithError(res, error)
          return
        }

        var treeList = []
        // If the user has only one drive then just list the content
        if (driveId === '#' && data.value.length === 1) {
          driveId = data.value[0].id
          msGraphClient
            .api('/drives/' + driveId + '/root/children')
            .get(function (error, data) {
              if (error) {
                console.log(error)
                respondWithError(res, error)
                return
              }

              for (var key in data.value) {
                var item = data.value[key]
                var treeItem = {
                  id: driveId + ":" + item.id,
                  text: encoder.htmlEncode(item.name),
                  type: item.folder ? 'folders' : 'items',
                  children: item.folder ? !!item.folder.childCount : false
                  // !! turns an object into boolean
                }

                treeList.push(treeItem)
              }

              res.json(treeList)
            })
        } else {
          for (var key in data.value) {
            var item = data.value[key]
            var treeItem = {
              id: item.id,
              text: encoder.htmlEncode(item.name),
              type: item.folder ? 'folders' : 'items',
              children: item.folder ? !!item.folder.childCount : false
              // !! turns an object into boolean
            }

            // In case we are listing the drives
            if (driveId === '#') {
              // dealing with differences between
              // driveType = "personal" vs "documentLibrary" drives
              if (!treeItem.text)
                treeItem.text = item.id

              treeItem.type = 'drives'
              treeItem.children = true
            } else {
              treeItem.id = driveId + ":" + treeItem.id
            }
            treeList.push(treeItem)
          }

          res.json(treeList)
        }
      })
  } catch (err) {
    respondWithError(res, err)
  }
});

module.exports = router;<commit_msg>Try fix for OneDrive for Business<commit_after>/////////////////////////////////////////////////////////////////////
// Copyright (c) Autodesk, Inc. All rights reserved
// Written by Forge Partner Development
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
/////////////////////////////////////////////////////////////////////

'use strict'; // http://www.w3schools.com/js/js_strict.asp

// token handling in session
var Credentials = require('./../../credentials');
// forge config information, such as client ID and secret
var config = require('./../../config');

// entity type encoder
var Encoder = require('node-html-encoder').Encoder;
var encoder = new Encoder('entity');

// web framework
var express = require('express');
var router = express.Router();

// OneDrive SDK
const msGraph = require("@microsoft/microsoft-graph-client").Client

function respondWithError(res, error) {
  if (error.statusCode) {
    res.status(error.statusCode).end(error.statusMessage)
  } else {
    res.status(500).end(error.message)
  }
}

router.get('/api/storage/tree', function (req, res) {
  var token = new Credentials(req.session);
  var credentials = token.getStorageCredentials();
  if (credentials === undefined) {
    res.status(401).end();
    return;
  }

  var id = decodeURIComponent(req.query.id)

  // item id's look like this:
  // <drive id>!<file id> in case of a "personal" drive
  // e.g. BF0BDCFE22A2EFD6!161
  // however the "documentLibrary" drive is different
  // so let's store the drive id in each item's id like this
  // driveId:itemId
  var idParts = id.split(':')
  var driveId = idParts[0]
  var id = idParts[1]
  var path = ''

  try {
    if (driveId === '#') {
      path = '/me/drives'
    } else if (!id) {
      path = '/me/drives/' + driveId + '/root/children'
    } else {
      path = '/me/drives/' + driveId + '/items/' + id + '/children'
    }

    var msGraphClient = msGraph.init({
      defaultVersion: 'v1.0',
      debugLogging: true,
      authProvider: function (done) {
        done(null, credentials.access_token)
      }
    })

    msGraphClient
      .api(path)
      .get(function (error, data) {
        if (error) {
          console.log(error)
          respondWithError(res, error)
          return
        }

        var treeList = []
        // If the user has only one drive then just list the content
        if (driveId === '#' && data.value.length === 1) {
          driveId = data.value[0].id
          msGraphClient
            .api('/me/drives/' + driveId + '/root/children')
            .get(function (error, data) {
              if (error) {
                console.log(error)
                respondWithError(res, error)
                return
              }

              for (var key in data.value) {
                var item = data.value[key]
                var treeItem = {
                  id: driveId + ":" + item.id,
                  text: encoder.htmlEncode(item.name),
                  type: item.folder ? 'folders' : 'items',
                  children: item.folder ? !!item.folder.childCount : false
                  // !! turns an object into boolean
                }

                treeList.push(treeItem)
              }

              res.json(treeList)
            })
        } else {
          for (var key in data.value) {
            var item = data.value[key]
            var treeItem = {
              id: item.id,
              text: encoder.htmlEncode(item.name),
              type: item.folder ? 'folders' : 'items',
              children: item.folder ? !!item.folder.childCount : false
              // !! turns an object into boolean
            }

            // In case we are listing the drives
            if (driveId === '#') {
              // dealing with differences between
              // driveType = "personal" vs "documentLibrary" drives
              if (!treeItem.text)
                treeItem.text = item.id

              treeItem.type = 'drives'
              treeItem.children = true
            } else {
              treeItem.id = driveId + ":" + treeItem.id
            }
            treeList.push(treeItem)
          }

          res.json(treeList)
        }
      })
  } catch (err) {
    respondWithError(res, err)
  }
});

module.exports = router;<|endoftext|>


<commit_before>'use strict'
const net = require('net')
const co = require('co')
const expect = require('expect.js')

const describe = require('mocha').describe
const it = require('mocha').it

const Pool = require('../')

describe('pool error handling', function () {
  it('Should complete these queries without dying', function (done) {
    const pool = new Pool()
    let errors = 0
    let shouldGet = 0
    function runErrorQuery() {
      shouldGet++
      return new Promise(function (resolve, reject) {
        pool
          .query("SELECT 'asd'+1 ")
          .then(function (res) {
            reject(res) // this should always error
          })
          .catch(function (err) {
            errors++
            resolve(err)
          })
      })
    }
    const ps = []
    for (let i = 0; i < 5; i++) {
      ps.push(runErrorQuery())
    }
    Promise.all(ps).then(function () {
      expect(shouldGet).to.eql(errors)
      pool.end(done)
    })
  })

  describe('calling release more than once', () => {
    it(
      'should throw each time',
      co.wrap(function* () {
        const pool = new Pool()
        const client = yield pool.connect()
        client.release()
        expect(() => client.release()).to.throwError()
        expect(() => client.release()).to.throwError()
        return yield pool.end()
      })
    )

    it('should throw each time with callbacks', function (done) {
      const pool = new Pool()

      pool.connect(function (err, client, clientDone) {
        expect(err).not.to.be.an(Error)
        clientDone()

        expect(() => clientDone()).to.throwError()
        expect(() => clientDone()).to.throwError()

        pool.end(done)
      })
    })
  })

  describe('calling connect after end', () => {
    it('should return an error', function* () {
      const pool = new Pool()
      const res = yield pool.query('SELECT $1::text as name', ['hi'])
      expect(res.rows[0].name).to.equal('hi')
      const wait = pool.end()
      pool.query('select now()')
      yield wait
      expect(() => pool.query('select now()')).to.reject()
    })
  })

  describe('using an ended pool', () => {
    it('rejects all additional promises', (done) => {
      const pool = new Pool()
      const promises = []
      pool.end().then(() => {
        const squash = (promise) => promise.catch((e) => 'okay!')
        promises.push(squash(pool.connect()))
        promises.push(squash(pool.query('SELECT NOW()')))
        promises.push(squash(pool.end()))
        Promise.all(promises).then((res) => {
          expect(res).to.eql(['okay!', 'okay!', 'okay!'])
          done()
        })
      })
    })

    it('returns an error on all additional callbacks', (done) => {
      const pool = new Pool()
      pool.end(() => {
        pool.query('SELECT *', (err) => {
          expect(err).to.be.an(Error)
          pool.connect((err) => {
            expect(err).to.be.an(Error)
            pool.end((err) => {
              expect(err).to.be.an(Error)
              done()
            })
          })
        })
      })
    })
  })

  describe('error from idle client', () => {
    it(
      'removes client from pool',
      co.wrap(function* () {
        const pool = new Pool()
        const client = yield pool.connect()
        expect(pool.totalCount).to.equal(1)
        expect(pool.waitingCount).to.equal(0)
        expect(pool.idleCount).to.equal(0)
        client.release()
        yield new Promise((resolve, reject) => {
          process.nextTick(() => {
            let poolError
            pool.once('error', (err) => {
              poolError = err
            })

            let clientError
            client.once('error', (err) => {
              clientError = err
            })

            client.emit('error', new Error('expected'))

            expect(clientError.message).to.equal('expected')
            expect(poolError.message).to.equal('expected')
            expect(pool.idleCount).to.equal(0)
            expect(pool.totalCount).to.equal(0)
            pool.end().then(resolve, reject)
          })
        })
      })
    )
  })

  describe('error from in-use client', () => {
    it(
      'keeps the client in the pool',
      co.wrap(function* () {
        const pool = new Pool()
        const client = yield pool.connect()
        expect(pool.totalCount).to.equal(1)
        expect(pool.waitingCount).to.equal(0)
        expect(pool.idleCount).to.equal(0)

        yield new Promise((resolve, reject) => {
          process.nextTick(() => {
            let poolError
            pool.once('error', (err) => {
              poolError = err
            })

            let clientError
            client.once('error', (err) => {
              clientError = err
            })

            client.emit('error', new Error('expected'))

            expect(clientError.message).to.equal('expected')
            expect(poolError).not.to.be.ok()
            expect(pool.idleCount).to.equal(0)
            expect(pool.totalCount).to.equal(1)
            client.release()
            pool.end().then(resolve, reject)
          })
        })
      })
    )
  })

  describe('passing a function to pool.query', () => {
    it('calls back with error', (done) => {
      const pool = new Pool()
      console.log('passing fn to query')
      pool.query((err) => {
        expect(err).to.be.an(Error)
        pool.end(done)
      })
    })
  })

  describe('pool with lots of errors', () => {
    it(
      'continues to work and provide new clients',
      co.wrap(function* () {
        const pool = new Pool({ max: 1 })
        const errors = []
        for (var i = 0; i < 20; i++) {
          try {
            yield pool.query('invalid sql')
          } catch (err) {
            errors.push(err)
          }
        }
        expect(errors).to.have.length(20)
        expect(pool.idleCount).to.equal(0)
        expect(pool.query).to.be.a(Function)
        const res = yield pool.query('SELECT $1::text as name', ['brianc'])
        expect(res.rows).to.have.length(1)
        expect(res.rows[0].name).to.equal('brianc')
        return pool.end()
      })
    )
  })

  it('should continue with queued items after a connection failure', (done) => {
    const closeServer = net
      .createServer((socket) => {
        socket.destroy()
      })
      .unref()

    closeServer.listen(() => {
      const pool = new Pool({ max: 1, port: closeServer.address().port, host: 'localhost' })
      pool.connect((err) => {
        expect(err).to.be.an(Error)
        if (err.code) {
          expect(err.code).to.be('ECONNRESET')
        }
      })
      pool.connect((err) => {
        expect(err).to.be.an(Error)
        if (err.code) {
          expect(err.code).to.be('ECONNRESET')
        }
        closeServer.close(() => {
          pool.end(done)
        })
      })
    })
  })

  it('handles post-checkout client failures in pool.query', (done) => {
    const pool = new Pool({ max: 1 })
    pool.on('error', () => {
      // We double close the connection in this test, prevent exception caused by that
    })
    pool.query('SELECT pg_sleep(5)', [], (err) => {
      expect(err).to.be.an(Error)
      done()
    })

    setTimeout(() => {
      pool._clients[0].end()
    }, 1000)
  })
})
<commit_msg>Remove broken test (#2529)<commit_after>'use strict'
const net = require('net')
const co = require('co')
const expect = require('expect.js')

const describe = require('mocha').describe
const it = require('mocha').it

const Pool = require('../')

describe('pool error handling', function () {
  it('Should complete these queries without dying', function (done) {
    const pool = new Pool()
    let errors = 0
    let shouldGet = 0
    function runErrorQuery() {
      shouldGet++
      return new Promise(function (resolve, reject) {
        pool
          .query("SELECT 'asd'+1 ")
          .then(function (res) {
            reject(res) // this should always error
          })
          .catch(function (err) {
            errors++
            resolve(err)
          })
      })
    }
    const ps = []
    for (let i = 0; i < 5; i++) {
      ps.push(runErrorQuery())
    }
    Promise.all(ps).then(function () {
      expect(shouldGet).to.eql(errors)
      pool.end(done)
    })
  })

  describe('calling release more than once', () => {
    it(
      'should throw each time',
      co.wrap(function* () {
        const pool = new Pool()
        const client = yield pool.connect()
        client.release()
        expect(() => client.release()).to.throwError()
        expect(() => client.release()).to.throwError()
        return yield pool.end()
      })
    )

    it('should throw each time with callbacks', function (done) {
      const pool = new Pool()

      pool.connect(function (err, client, clientDone) {
        expect(err).not.to.be.an(Error)
        clientDone()

        expect(() => clientDone()).to.throwError()
        expect(() => clientDone()).to.throwError()

        pool.end(done)
      })
    })
  })

  describe('using an ended pool', () => {
    it('rejects all additional promises', (done) => {
      const pool = new Pool()
      const promises = []
      pool.end().then(() => {
        const squash = (promise) => promise.catch((e) => 'okay!')
        promises.push(squash(pool.connect()))
        promises.push(squash(pool.query('SELECT NOW()')))
        promises.push(squash(pool.end()))
        Promise.all(promises).then((res) => {
          expect(res).to.eql(['okay!', 'okay!', 'okay!'])
          done()
        })
      })
    })

    it('returns an error on all additional callbacks', (done) => {
      const pool = new Pool()
      pool.end(() => {
        pool.query('SELECT *', (err) => {
          expect(err).to.be.an(Error)
          pool.connect((err) => {
            expect(err).to.be.an(Error)
            pool.end((err) => {
              expect(err).to.be.an(Error)
              done()
            })
          })
        })
      })
    })
  })

  describe('error from idle client', () => {
    it(
      'removes client from pool',
      co.wrap(function* () {
        const pool = new Pool()
        const client = yield pool.connect()
        expect(pool.totalCount).to.equal(1)
        expect(pool.waitingCount).to.equal(0)
        expect(pool.idleCount).to.equal(0)
        client.release()
        yield new Promise((resolve, reject) => {
          process.nextTick(() => {
            let poolError
            pool.once('error', (err) => {
              poolError = err
            })

            let clientError
            client.once('error', (err) => {
              clientError = err
            })

            client.emit('error', new Error('expected'))

            expect(clientError.message).to.equal('expected')
            expect(poolError.message).to.equal('expected')
            expect(pool.idleCount).to.equal(0)
            expect(pool.totalCount).to.equal(0)
            pool.end().then(resolve, reject)
          })
        })
      })
    )
  })

  describe('error from in-use client', () => {
    it(
      'keeps the client in the pool',
      co.wrap(function* () {
        const pool = new Pool()
        const client = yield pool.connect()
        expect(pool.totalCount).to.equal(1)
        expect(pool.waitingCount).to.equal(0)
        expect(pool.idleCount).to.equal(0)

        yield new Promise((resolve, reject) => {
          process.nextTick(() => {
            let poolError
            pool.once('error', (err) => {
              poolError = err
            })

            let clientError
            client.once('error', (err) => {
              clientError = err
            })

            client.emit('error', new Error('expected'))

            expect(clientError.message).to.equal('expected')
            expect(poolError).not.to.be.ok()
            expect(pool.idleCount).to.equal(0)
            expect(pool.totalCount).to.equal(1)
            client.release()
            pool.end().then(resolve, reject)
          })
        })
      })
    )
  })

  describe('passing a function to pool.query', () => {
    it('calls back with error', (done) => {
      const pool = new Pool()
      console.log('passing fn to query')
      pool.query((err) => {
        expect(err).to.be.an(Error)
        pool.end(done)
      })
    })
  })

  describe('pool with lots of errors', () => {
    it(
      'continues to work and provide new clients',
      co.wrap(function* () {
        const pool = new Pool({ max: 1 })
        const errors = []
        for (var i = 0; i < 20; i++) {
          try {
            yield pool.query('invalid sql')
          } catch (err) {
            errors.push(err)
          }
        }
        expect(errors).to.have.length(20)
        expect(pool.idleCount).to.equal(0)
        expect(pool.query).to.be.a(Function)
        const res = yield pool.query('SELECT $1::text as name', ['brianc'])
        expect(res.rows).to.have.length(1)
        expect(res.rows[0].name).to.equal('brianc')
        return pool.end()
      })
    )
  })

  it('should continue with queued items after a connection failure', (done) => {
    const closeServer = net
      .createServer((socket) => {
        socket.destroy()
      })
      .unref()

    closeServer.listen(() => {
      const pool = new Pool({ max: 1, port: closeServer.address().port, host: 'localhost' })
      pool.connect((err) => {
        expect(err).to.be.an(Error)
        if (err.code) {
          expect(err.code).to.be('ECONNRESET')
        }
      })
      pool.connect((err) => {
        expect(err).to.be.an(Error)
        if (err.code) {
          expect(err.code).to.be('ECONNRESET')
        }
        closeServer.close(() => {
          pool.end(done)
        })
      })
    })
  })

  it('handles post-checkout client failures in pool.query', (done) => {
    const pool = new Pool({ max: 1 })
    pool.on('error', () => {
      // We double close the connection in this test, prevent exception caused by that
    })
    pool.query('SELECT pg_sleep(5)', [], (err) => {
      expect(err).to.be.an(Error)
      done()
    })

    setTimeout(() => {
      pool._clients[0].end()
    }, 1000)
  })
})
<|endoftext|>


<commit_before>var
	EventEmitter = require('events').EventEmitter,
	dgram = require('dgram'),
	inherits = require('util').inherits,
	uuid = require('uuid'),

	addrs = require('./addresses'),
	msgs = require('./messages'),
	neigh = require('./neigh');

// ----------------
// Profile container
// ----------------
// Container for neighbor cache

function Profile(uuid, alias, chan) {
	this.uuid = uuid;
	this.alias = alias;
	this.chan = chan;
}

// ----------------
// Client class
// ----------------
// Main client class
// Inherits from: EventEmitter

// ----------------
// Events

// listening
// close

// ----------------
// Class declaration

function Client(chan) {
	var self = this;

	this._uuid = uuid.v1();
	this.alias = this._uuid;
	this._channel = chan;
	this._listening = false;

	// Neighbors cache
	this._client_cache = new neigh.NeighborManager();
	this._group_cache = new neigh.NeighborManager();

	// Tries to connect
	this.start(chan);
};
inherits(Client, EventEmitter);

// ----------------
// Public methods

Client.prototype.start = function(chan) {
	var self = this;

	// Tries to close the current client
	this.close();

	// ----------------
	// Socket initialization

	this._sock = dgram.createSocket({
		type: 'udp6',
		reuseAddr: true
	});

	this._sock.bind(chan.port, function() {
		self._sock.addMembership(chan.address);
	});

	// ----------------
	// Sockets events

	this._sock.on('listening', function() {
		self._channel = chan;
		self._listening = true;

		self.emit('listening', arguments);
	});

	this._sock.on('message', function(message, remote) {
		self._messageHandler(message, remote);
	});

	this._sock.on('close', function() {
		self._listening = false;
		self.emit('close', arguments);
	});
}

// ----------------

Client.prototype.close = function() {
	if (this._sock !== undefined && 'close' in this._sock)
		this._sock.close();
	this._listening = false;
}

// ----------------

Client.prototype.isListening = function() {
	return this._listening;
};

// ----------------

// function send
// @param chan the Channel to which send the message
// @param message the message
// @returns undefined
Client.prototype.send = function(chan, message) {
	var buff = new Buffer(message);
	this._sock.send(buff, 0, buff.length, chan.port, chan.address);
}

// ----------------

Client.prototype.createGroup = function(group_name) {
}

Client.prototype.updateNeighborClients = function() {
	var message = new msgs.Message(
		msgs.types.CLIENT_SOLICITATION,
		this._uuid
	);

	this.send(this._channel, message.toString());
}

// ----------------
// Private methods

// function _messageHandler
// @param message buffer of the message
// @remote object that contains the address and port of the sender
// @returns undefined
Client.prototype._messageHandler = function(message, remote) {

	var data = JSON.parse(message.toString());

	// Checks that this message isn't comming from us
	if (data.sender == this._uuid) return;

	// Configures sender object
	// var sender = {
	// 	uuid:
	// 	alias: data.alias,
	// }
	sender_chan = new addrs.Channel(remote.address, remote.port);

	switch(data.type) {

		// ----------------
		// General messages handling

		case msgs.types.CLIENT_ONLINE:
		case msgs.types.CLIENT_REPORT:
		case msgs.types.CLIENT_ADVERTISEMENT:
			// Save client in cache
			console.log('Someone is around (virtually).');
			// var entry = new neigh.Neighbor(
			// 	data.sender,
			// 	{ alias: data.lias, addr: sender_chan }
			// );
			// this._client_cache.addNeighbor(entry);
			break;
		case msgs.types.CLIENT_CHANGE:
			// Update client data
			break;
		case msgs.types.CLIENT_SOLICITATION:
			// Tell client we are online
			var message = new msgs.Message(
				msgs.types.CLIENT_REPORT,
				this._uuid//,
				// { alias: this.alias }
			);
			this.send(sender_chan, message.toString());
			break;
		case msgs.types.CLIENT_OFFLINE:
			// Delete client from list of neighbors
			break;

		// ----------------
		// All / Group messages handling

		case msgs.types.GROUP_SOLICITATION:
			// Tell client of all groups we have
			break;
		case msgs.types.GROUP_ADVERTISEMENT:
			// Save group in neighbor-groups list
			break;

		// ----------------
		// Single / Group messages handling

		case msgs.types.GROUP_CREATE:
			// Group was created, save it in neighbor-group list
			break;
		case msgs.types.GROUP_DELETE:
			// Group deleted, remove it from neighbor-group list
			break;
		case msgs.types.GROUP_JOIN:
			// Client is trying to join a group (maybe of ours)
			break;
		case msgs.types.GROUP_LEAVE:
			// Somebody is leaving a group
			break;
		case msgs.types.GROUP_MESSAGE:
			// Messages to a group
			break;
		case msgs.types.GROUP_JOIN_OK:
			// We were able to join a group
			break;
		case msgs.types.GROUP_JOIN_ERR:
			// We weren't able to join a group
			break;
		case msgs.types.SINGLE_MESSAGE:
			// We received an unicast message
			break;
	} // switch

} // messageHandler

// ----------------
// Exports
// ----------------

module.exports = Client;<commit_msg>Added debug entries<commit_after>var
	EventEmitter = require('events').EventEmitter,
	dgram = require('dgram'),
	inherits = require('util').inherits,
	uuid = require('uuid'),

	addrs = require('./addresses'),
	msgs = require('./messages'),
	neigh = require('./neigh');

// ----------------
// Profile container
// ----------------
// Container for neighbor cache

function Profile(uuid, alias, chan) {
	this.uuid = uuid;
	this.alias = alias;
	this.chan = chan;
}

// ----------------
// Client class
// ----------------
// Main client class
// Inherits from: EventEmitter

// ----------------
// Events

// listening
// close

// ----------------
// Class declaration

function Client(chan) {
	var self = this;

	this._uuid = uuid.v1();
	this.alias = this._uuid;
	this._channel = chan;
	this._listening = false;

	// Neighbors cache
	this._client_cache = new neigh.NeighborManager();
	this._group_cache = new neigh.NeighborManager();

	// Tries to connect
	this.start(chan);
};
inherits(Client, EventEmitter);

// ----------------
// Public methods

Client.prototype.start = function(chan) {
	var self = this;

	// Tries to close the current client
	this.close();

	// ----------------
	// Socket initialization

	this._sock = dgram.createSocket({
		type: 'udp6',
		reuseAddr: true
	});

	this._sock.bind(chan.port, function() {
		self._sock.addMembership(chan.address);
	});

	// ----------------
	// Sockets events

	this._sock.on('listening', function() {
		self._channel = chan;
		self._listening = true;

		self.emit('listening', arguments);
	});

	this._sock.on('message', function(message, remote) {
		self._messageHandler(message, remote);
	});

	this._sock.on('close', function() {
		self._listening = false;
		self.emit('close', arguments);
	});
}

// ----------------

Client.prototype.close = function() {
	if (this._sock !== undefined && 'close' in this._sock)
		this._sock.close();
	this._listening = false;
}

// ----------------

Client.prototype.isListening = function() {
	return this._listening;
};

// ----------------

// function send
// @param chan the Channel to which send the message
// @param message the message
// @returns undefined
Client.prototype.send = function(chan, message) {
	var buff = new Buffer(message);
	this._sock.send(buff, 0, buff.length, chan.port, chan.address);
}

// ----------------

Client.prototype.createGroup = function(group_name) {
}

Client.prototype.updateNeighborClients = function() {
	var message = new msgs.Message(
		msgs.types.CLIENT_SOLICITATION,
		this._uuid,
		{ alias: this.alias }
	);

	this.send(this._channel, message.toString());
}

// ----------------
// Private methods

// function _messageHandler
// @param message buffer of the message
// @remote object that contains the address and port of the sender
// @returns undefined
Client.prototype._messageHandler = function(message, remote) {

	var data = JSON.parse(message.toString());

	console.log('Sent by: ' + data.extras.alias);
	console.log('Captured by: ' + this.alias);
	console.log('Type is: ' + data.type);
	console.log();

	// Checks that this message isn't comming from us
	if (data.sender == this._uuid) return;

	// Configures sender object
	// var sender = {
	// 	uuid:
	// 	alias: data.alias,
	// }
	sender_chan = new addrs.Channel(remote.address, remote.port);

	switch(data.type) {

		// ----------------
		// General messages handling

		case msgs.types.CLIENT_ONLINE:
		case msgs.types.CLIENT_REPORT:
		case msgs.types.CLIENT_ADVERTISEMENT:
			// Save client in cache
			console.log('Someone is around (virtually).');
			// var entry = new neigh.Neighbor(
			// 	data.sender,
			// 	{ alias: data.lias, addr: sender_chan }
			// );
			// this._client_cache.addNeighbor(entry);
			break;
		case msgs.types.CLIENT_CHANGE:
			// Update client data
			break;
		case msgs.types.CLIENT_SOLICITATION:
			// Tell client we are online
			var message = new msgs.Message(
				msgs.types.CLIENT_REPORT,
				this._uuid,
				{ alias: this.alias }
			);
			this.send(sender_chan, message.toString());
			break;
		case msgs.types.CLIENT_OFFLINE:
			// Delete client from list of neighbors
			break;

		// ----------------
		// All / Group messages handling

		case msgs.types.GROUP_SOLICITATION:
			// Tell client of all groups we have
			break;
		case msgs.types.GROUP_ADVERTISEMENT:
			// Save group in neighbor-groups list
			break;

		// ----------------
		// Single / Group messages handling

		case msgs.types.GROUP_CREATE:
			// Group was created, save it in neighbor-group list
			break;
		case msgs.types.GROUP_DELETE:
			// Group deleted, remove it from neighbor-group list
			break;
		case msgs.types.GROUP_JOIN:
			// Client is trying to join a group (maybe of ours)
			break;
		case msgs.types.GROUP_LEAVE:
			// Somebody is leaving a group
			break;
		case msgs.types.GROUP_MESSAGE:
			// Messages to a group
			break;
		case msgs.types.GROUP_JOIN_OK:
			// We were able to join a group
			break;
		case msgs.types.GROUP_JOIN_ERR:
			// We weren't able to join a group
			break;
		case msgs.types.SINGLE_MESSAGE:
			// We received an unicast message
			break;
	} // switch

} // messageHandler

// ----------------
// Exports
// ----------------

module.exports = Client;<|endoftext|>


<commit_before>'use strict';

var Promise = require('bluebird');
var uuid = require('uuid');
var amqp = require('amqplib');
var ClientResponse = require('./client/Response');
var ErrorResponse = require('./client/ErrorResponse');

function Client(channel) {
  this.channel = channel;
  this.messages = {};
}

Client.prototype._onReply = function(message) {
  var correlationId = message.properties.correlationId;

  if (this.messages[correlationId]) {

    if (Buffer.isBuffer(message.content)) {
      message.content = message.content.toString('utf8');

      try {
        message.content = JSON.parse(message.content);
      } catch (err) {}
    }

    if (message.content.error) {
      this.messages[correlationId].reject(new ErrorResponse(message));
    } else {
      this.messages[correlationId].resolve(new ClientResponse(message));
    }

    delete this.messages[correlationId];
  }
};

Client.prototype._createAnonymousReplyQueue = function() {
  return Promise.resolve(this.channel.assertQueue('', {
    exclusive : true,
    autoDelete : true
  }));
};

Client.prototype._subscribeToQueue = function(queue) {
  return Promise.resolve(this.channel.consume(queue, this._onReply.bind(this)))
    .disposer(function(consumer) {
      return Promise.resolve(this.channel.ackAll())
        .bind(this)
        .then(function() {
          return this.channel.cancel(consumer.consumerTag);
        });
    }.bind(this));
};

Client.prototype.awaitMethod = function(method, params, options) {
  return this.awaitMethodBulk(method, [ params ], options)
    .then(function(results) {
      return results[0];
    });
};

/**
 * @deprecated
 */
Client.prototype.call = Client.prototype.awaitMethod;

Client.prototype.awaitMethodBulk = function(method, paramList, options) {

  return Promise.resolve(this._createAnonymousReplyQueue())
    .bind(this)
    .then(function(anonymousQueue) {

      var replyQueue = anonymousQueue.queue;

      return Promise.using(this._subscribeToQueue(replyQueue), function() {
        var promises = paramList.map(function(params) {
          return new Promise(function(resolve, reject) {
            var correlationId = uuid.v4();

            this.messages[correlationId] = {
              resolve : resolve,
              reject : reject
            };

            options = options || {};

            options.correlationId = correlationId;
            options.replyTo = replyQueue;

            return this.invokeMethod(method, params, options);
          }.bind(this));
        }, this);

        return Promise.all(promises.map(function(promise) {
          return promise.reflect();
        })).map(function(result) {
          if (result.isFulfilled()) {
            return result.value();
          } else {
            return result.reason();
          }
        });
      }.bind(this));
    }.bind(this));
};

Client.prototype.invokeMethod = function(method, params, options) {

  options = options || {};
  options.headers = options.headers || {};

  options.headers['harmonia-message'] = '1.0';

  var content = new Buffer(JSON.stringify(params));

  return Promise.resolve(this.channel.sendToQueue(method, content, options));
};

Client.ErrorResponse = ErrorResponse;

Client.createConnection = function(amqpUrl) {
  return Promise.resolve(amqp.connect(amqpUrl))
    .disposer(function(connection) {
      return connection.close();
    });
};

Client.createChannel = function(connection) {
  return Promise.resolve(connection.createChannel())
    .disposer(function(channel) {
      return channel.close();
    });
};

Client.createClient = function(amqpUrl, callback) {
  return Promise.using(Client.createConnection(amqpUrl), function(connection) {
    return Promise.using(Client.createChannel(connection), function(channel) {
      var client = new Client(channel);

      var result = callback(client);

      if (! result || typeof result.then !== 'function') {
        throw new Error('Callback must return a promise');
      }

      return result;
    });
  });
};

/**
 * @deprecated
 */
Client.create = Client.createClient;

module.exports = Client;
<commit_msg>client always specifies message id when sending<commit_after>'use strict';

var Promise = require('bluebird');
var uuid = require('uuid');
var amqp = require('amqplib');
var ClientResponse = require('./client/Response');
var ErrorResponse = require('./client/ErrorResponse');

function Client(channel) {
  this.channel = channel;
  this.messages = {};
}

Client.prototype._onReply = function(message) {
  var correlationId = message.properties.correlationId;

  if (this.messages[correlationId]) {

    if (Buffer.isBuffer(message.content)) {
      message.content = message.content.toString('utf8');

      try {
        message.content = JSON.parse(message.content);
      } catch (err) {}
    }

    if (message.content.error) {
      this.messages[correlationId].reject(new ErrorResponse(message));
    } else {
      this.messages[correlationId].resolve(new ClientResponse(message));
    }

    delete this.messages[correlationId];
  }
};

Client.prototype._createAnonymousReplyQueue = function() {
  return Promise.resolve(this.channel.assertQueue('', {
    exclusive : true,
    autoDelete : true
  }));
};

Client.prototype._subscribeToQueue = function(queue) {
  return Promise.resolve(this.channel.consume(queue, this._onReply.bind(this)))
    .disposer(function(consumer) {
      return Promise.resolve(this.channel.ackAll())
        .bind(this)
        .then(function() {
          return this.channel.cancel(consumer.consumerTag);
        });
    }.bind(this));
};

Client.prototype.awaitMethod = function(method, params, options) {
  return this.awaitMethodBulk(method, [ params ], options)
    .then(function(results) {
      return results[0];
    });
};

/**
 * @deprecated
 */
Client.prototype.call = Client.prototype.awaitMethod;

Client.prototype.awaitMethodBulk = function(method, paramList, options) {

  return Promise.resolve(this._createAnonymousReplyQueue())
    .bind(this)
    .then(function(anonymousQueue) {

      var replyQueue = anonymousQueue.queue;

      return Promise.using(this._subscribeToQueue(replyQueue), function() {
        var promises = paramList.map(function(params) {
          return new Promise(function(resolve, reject) {
            var correlationId = uuid.v4();

            this.messages[correlationId] = {
              resolve : resolve,
              reject : reject
            };

            options = options || {};

            options.messageId = correlationId;
            options.correlationId = correlationId;
            options.replyTo = replyQueue;

            return this.invokeMethod(method, params, options);
          }.bind(this));
        }, this);

        return Promise.all(promises.map(function(promise) {
          return promise.reflect();
        })).map(function(result) {
          if (result.isFulfilled()) {
            return result.value();
          } else {
            return result.reason();
          }
        });
      }.bind(this));
    }.bind(this));
};

Client.prototype.invokeMethod = function(method, params, options) {

  options = options || {};
  options.headers = options.headers || {};

  options.headers['harmonia-message'] = '1.0';

  if (! options.messageId) {
    options.messageId = uuid.v4();
  }

  var content = new Buffer(JSON.stringify(params));

  return Promise.resolve(this.channel.sendToQueue(method, content, options));
};

Client.ErrorResponse = ErrorResponse;

Client.createConnection = function(amqpUrl) {
  return Promise.resolve(amqp.connect(amqpUrl))
    .disposer(function(connection) {
      return connection.close();
    });
};

Client.createChannel = function(connection) {
  return Promise.resolve(connection.createChannel())
    .disposer(function(channel) {
      return channel.close();
    });
};

Client.createClient = function(amqpUrl, callback) {
  return Promise.using(Client.createConnection(amqpUrl), function(connection) {
    return Promise.using(Client.createChannel(connection), function(channel) {
      var client = new Client(channel);

      var result = callback(client);

      if (! result || typeof result.then !== 'function') {
        throw new Error('Callback must return a promise');
      }

      return result;
    });
  });
};

/**
 * @deprecated
 */
Client.create = Client.createClient;

module.exports = Client;
<|endoftext|>


<commit_before>const deepmerge = require('deepmerge');
const path = require('path');

const RequestCache = require('./RequestCache');

const util = require('./util');
const {EndpointUtil} = util;

/**
 * @typedef {leagueJSDefaultConfig}
 */
let leagueJSDefaultConfig = {
	'debug': false,
	'PLATFORM_ID': process.env.LEAGUE_API_PLATFORM_ID,
	'API_HOST': 'api.riotgames.com',
	'API_VERSION': 'v3',
	// temp solution during migration to v4 (and if endpoints differ in versions)
	// use this to set different versions per endpoint
	'apiVersionOverrides': {
		'Champion': 'v3',
		'ChampionMastery': 'v4',
		'League': 'v4',
		'LolStatus': 'v3',
		'Match': 'v4',
		'Spectator': 'v4',
		'Summoner': 'v4',
		'ThirdPartyCode': 'v4',
		// 'TournamentStub': 'v4',
		// 'Tournament': 'v4'
	},
	'STATIC_DATA_ROOT': path.resolve(__dirname, '../', 'StaticDataDefaultRoot'),
	'caching': {
		'isEnabled': false,
		'constructor': RequestCache,
		'defaults': {
			/** the standard ttl as number in seconds for every generated cache element.
			 * (default: 0) 0 = unlimited
			 * */
			stdTTL: 0,
			/**
			 * The period in seconds, as a number, used for the automatic delete check interval.
			 * 0 = no periodic check.
			 * (default: 600) 0 = no periodic checks
			 */
			checkperiod: 600,
			/**
			 * en/disable throwing or passing an error to the callback if attempting to .get a missing or expired value.
			 * (default: false)
			 */
			errorOnMissing: false,
			/**
			 * en/disable cloning of variables. If true you'll get a copy of the cached variable.
			 * If false you'll save and get just the reference.
			 * Note: true is recommended, because it'll behave like a server-based caching.
			 * You should set false if you want to save mutable objects or other complex types
			 * with mutability involved and wanted.
			 */
			useClones: true
		}
	},
	'limits': {
		/** @deprecated */
		'per10': 10,
		/** @deprecated */
		'per600': 500,
		'allowBursts': false,
		// maximum amount of retries done when encountering 500 or 503
		'numMaxRetries': 3,
		// starting retry backoff time on RIOT service overload (not related to API key limits)
		// will be increased exponentially with every retry
		'intervalRetryMS': 1000,
		// per default, retry is enabled on all endpoints
		'retryEndpoints': EndpointUtil.getEndpointNames()
	}
};

class Config {
	constructor(optionsOverwrites){
		this.defaults = leagueJSDefaultConfig;
		this.current = optionsOverwrites? deepmerge(this.defaults, optionsOverwrites) : this.defaults;
		return this.current;
	}
}

module.exports = Config;<commit_msg>use v4 as default<commit_after>const deepmerge = require('deepmerge');
const path = require('path');

const RequestCache = require('./RequestCache');

const util = require('./util');
const {EndpointUtil} = util;

/**
 * @typedef {leagueJSDefaultConfig}
 */
let leagueJSDefaultConfig = {
	'debug': false,
	'PLATFORM_ID': process.env.LEAGUE_API_PLATFORM_ID,
	'API_HOST': 'api.riotgames.com',
	'API_VERSION': 'v4',
	// temp solution during migration to v4 (and if endpoints differ in versions)
	// use this to set different versions per endpoint
	'apiVersionOverrides': {
		'Champion': 'v3',
		'Match': 'v5',
	},
	'STATIC_DATA_ROOT': path.resolve(__dirname, '../', 'StaticDataDefaultRoot'),
	'caching': {
		'isEnabled': false,
		'constructor': RequestCache,
		'defaults': {
			/** the standard ttl as number in seconds for every generated cache element.
			 * (default: 0) 0 = unlimited
			 * */
			stdTTL: 0,
			/**
			 * The period in seconds, as a number, used for the automatic delete check interval.
			 * 0 = no periodic check.
			 * (default: 600) 0 = no periodic checks
			 */
			checkperiod: 600,
			/**
			 * en/disable throwing or passing an error to the callback if attempting to .get a missing or expired value.
			 * (default: false)
			 */
			errorOnMissing: false,
			/**
			 * en/disable cloning of variables. If true you'll get a copy of the cached variable.
			 * If false you'll save and get just the reference.
			 * Note: true is recommended, because it'll behave like a server-based caching.
			 * You should set false if you want to save mutable objects or other complex types
			 * with mutability involved and wanted.
			 */
			useClones: true
		}
	},
	'limits': {
		/** @deprecated */
		'per10': 10,
		/** @deprecated */
		'per600': 500,
		'allowBursts': false,
		// maximum amount of retries done when encountering 500 or 503
		'numMaxRetries': 3,
		// starting retry backoff time on RIOT service overload (not related to API key limits)
		// will be increased exponentially with every retry
		'intervalRetryMS': 1000,
		// per default, retry is enabled on all endpoints
		'retryEndpoints': EndpointUtil.getEndpointNames()
	}
};

class Config {
	constructor(optionsOverwrites){
		this.defaults = leagueJSDefaultConfig;
		this.current = optionsOverwrites? deepmerge(this.defaults, optionsOverwrites) : this.defaults;
		return this.current;
	}
}

module.exports = Config;<|endoftext|>


<commit_before>var sax = require("sax"),
  Note = require('./Note').Note,
  Attachment = require('./Attachment').Attachment

var Parser = function (enex, cbEach, cbEnd) {
  var strict = true // sax.parser: set to false for html-mode
  var parser = sax.parser(strict, {trim: false, normalize: false})

  parser.note_composers = {
    'title': function (text) {
      parser.note.title = text
    },
    'created': function (text) {
      parser.note.created = Note.parseENMLDate(text)
    },
    'updated': function (text) {
      parser.note.updated = Note.parseENMLDate(text)
    },
    'tag': function (text) {
      parser.note.tags.push(text)
    },
    'data': function (text) {
      attachment = new Attachment
      attachment.data = text
      parser.note.attachments.push(attachment) // base64 string
    }
  }
  parser.onopentag = function (node) {
    if (node.name == 'note') {
      this.note = new Note
    } else {
      this.current_element = node.name
    }
  }
  parser.ontext = function (text) {
    var note_composer = this.note_composers[this.current_element]
    if (typeof note_composer == 'function') {
      note_composer(text)
    }
  }
  parser.onopencdata = function () {
    this.cdata = ''
  }
  parser.oncdata = function (text) {
    this.cdata = text
  }
  parser.onclosecdata = function () {
    this.note.content = Note.parseENMLContent(this.cdata)
    // TODO: parse inside CDATA to obtain attachments
  }
  parser.onclosetag = function (nodeName) {
    if (nodeName == 'note') {
      enex.count = enex.count + 1
      if (cbEach) cbEach(this.note)
    } else {
      // ignore
    }
  }
  parser.onend = function () {
    if (cbEnd) cbEnd()
  }

  return parser
}

exports.Parser = Parser<commit_msg>refactoring Parser<commit_after>var sax = require("sax"),
  Note = require('./Note').Note,
  Attachment = require('./Attachment').Attachment

var Parser = function (enex, cbEach, cbEnd) {
  var strict = true // sax.parser: set to false for html-mode
  var parser = sax.parser(strict, {trim: false, normalize: false})

  parser.ontextHandlers = {
    'title': function (text) {
      parser.note.title = text
    },
    'created': function (text) {
      parser.note.created = Note.parseENMLDate(text)
    },
    'updated': function (text) {
      parser.note.updated = Note.parseENMLDate(text)
    },
    'tag': function (text) {
      parser.note.tags.push(text)
    },
    'data': function (text) {
      attachment = new Attachment
      attachment.data = text
      parser.note.attachments.push(attachment) // base64 string
    }
  }
  parser.onopentag = function (node) {
    this.currentElement = node.name
    if (node.name == 'note') {
      this.note = new Note
    }
  }
  parser.onclosetag = function (nodeName) {
    if (nodeName == 'note') {
      enex.count = enex.count + 1
      if (cbEach) cbEach(this.note)
    }
  }
  parser.ontext = function (text) {
    var handler = this.ontextHandlers[this.currentElement]
    if (typeof handler == 'function') {
      handler(text)
    }
  }
  parser.oncdata = function (text) {
    this.cdata = text
  }
  parser.onclosecdata = function () {
    this.note.content = Note.parseENMLContent(this.cdata)
    // TODO: parse inside CDATA to obtain attachments
  }
  parser.onend = function () {
    if (cbEnd) cbEnd()
  }

  return parser
}

exports.Parser = Parser<|endoftext|>


<commit_before>'use strict'

var co = require('co')

var Delete = function (ctx, file_id, filename) {
  return co(function *() {
    var result = yield ctx.r.table(ctx.conf.fileTable).get(file_id).update({filename: filename}).run()
    return result.replaced === 1 || result.unchanged === 1
  }).catch(function (err) {
    console.log(err.stack)
    throw err
  })
}

module.exports = Delete
<commit_msg>use correct name<commit_after>'use strict'

var co = require('co')

var Rename = function (ctx, file_id, filename) {
  return co(function *() {
    var result = yield ctx.r.table(ctx.conf.fileTable).get(file_id).update({filename: filename}).run()
    return result.replaced === 1 || result.unchanged === 1
  }).catch(function (err) {
    console.log(err.stack)
    throw err
  })
}

module.exports = Rename
<|endoftext|>


<commit_before>'use strict'
var debug = require('debug')('netcat:server')
const fs = require('fs')
const EventEmitter = require('events').EventEmitter
const net = require('net')
const Stream = require('stream')
const shortid = require('shortid')

function noop () {}

class Server extends EventEmitter {

  constructor (opts) {
    super()
    opts = opts || {}
    debug = opts.verbose ? function () {
      var args = Array.prototype.slice.call(arguments)
      process.stderr.write(args.join(' ') + '\n')
    } : debug
    this._protocol = opts.protocol || 'tcp'
    this._address = opts.address || '0.0.0.0'
    this._port = opts.port || null
    this._keepalive = false
    this.passThrough = new Stream.PassThrough()
    this._clients = {}
  }

  protocol (p) {
    this._protocol = p
    debug('Protocol is', this._protocol)
    return this /* chainable method */
  }

  address (a) {
    debug('setting address', a)
    this._address = a
    return this /* chainable method */
  }

  addr (a) {
    /* address alias */
    return this.address(a)
  }

  port (p) {
    if (!Number.isInteger(p)) throw Error('Port should be a positive number!')
    this._port = p
    debug('Port set to', this._port)
    return this /* chainable method */
  }

  udp () {
    return this.protocol('udp') /* chainable method */
  }

  tcp () {
    return this.protocol('tcp') /* chainable method */
  }

  keepalive (bool) {
    this._keepalive = typeof bool !== 'undefined' ? bool : true
    debug('Keepalive connection.')
    return this /* chainable method */
  }

  k (bool) { /* keepalive alias */
    this.keepalive(bool)
    return this /* chainable method */
  }

  close (cb) {
    debug('Server: closing socket.')
    cb = cb || noop
    if (this.server) this.server.close(cb)
    return this
  }

  _createServer () {
    var self = this
    this.server = net.createServer()

    function listening () {
      debug('Server listening on port', self._port, 'addr', self._address)
      self.emit('ready')
    }

    function connection (socket) {
      socket.id = shortid.generate()
      debug('New connection', socket.id, socket.remoteAddress, socket.remotePort)
      self._clients[socket.id] = socket

      /* outcoming */
      if (self._serveFile) {
        debug('Serving given', self._serveFile, 'as a stream to client', socket.id)
        fs.createReadStream(self._serveFile).pipe(socket)
      }
      /* incoming */
      socket.pipe(self.passThrough, { end: !self._keepalive })

      function data (data) { // emitting also chunks
        self.emit('data', socket, data)
      }

      function error (err) {
        debug('Socket error:', err)
        self.emit('error', socket, err)
      }

      function timeout () {
        debug('Connection timed out')
        delete self._clients[socket.id]
        self.emit('timeout', socket)
      }

      function end () {
        debug('Connection end.')
        delete self._clients[socket.id]
        self.emit('end', socket)
        if (!self._keepalive) self.close()
      }

      function close (hadError) {
        debug('Connection closed', hadError ? 'because of a conn. error' : 'by client')
        self.emit('close', socket, hadError)
      }

      process.nextTick(function () {
        socket.on('data', data)
        socket.on('error', error)
        socket.on('timeout', timeout)
        socket.on('end', end)
        socket.on('close', close)
      })
    }

    function close () {
      debug('Server close event')
      self._clients = {}
      self.emit('srvClose')
    }

    function error (err) {
      debug('Server error', err)
      self.emit('error', err)
    }

    process.nextTick(function () {
      self.server.on('listening', listening)
      self.server.on('connection', connection)
      self.server.on('close', close)
      self.server.on('error', error)
    })
  }

  listen () {
    debug('listen called')
    this._createServer()
    this.server.listen(this._port, this._address)
    return this /* chainable method */
  }

  pipe (outputStream) {
    debug('Pipe method called')
    this.passThrough.pipe(outputStream, { end: !this._keepalive })
    return this
  }

  serve (filePath) {
    debug('Setting file/stream to serve', filePath)
    if (typeof filePath === 'string') fs.statSync(filePath) // check that file exists
    else { // check stream
      // TODO
    }
    this._serveFile = filePath
    return this /* chainable method */
  }

  getClients () {
    return this._clients
  }

  q () {
    // TODO

  }

}

module.exports = Server

if (!module.parent) {
  const fs = require('fs')
  const nc = new Server()
  nc.port(2389).k().listen().serve('Client.js')
    .pipe(fs.createWriteStream('output.txt'))
    .on('data', function (s, data) { console.log(s.id, 'got', data) })
}
<commit_msg>destroy all the clients sockets and use unref() to avoid hanging<commit_after>'use strict'
var debug = require('debug')('netcat:server')
const fs = require('fs')
const EventEmitter = require('events').EventEmitter
const net = require('net')
const Stream = require('stream')
const shortid = require('shortid')

function noop () {}

class Server extends EventEmitter {

  constructor (opts) {
    super()
    opts = opts || {}
    debug = opts.verbose ? function () {
      var args = Array.prototype.slice.call(arguments)
      process.stderr.write(args.join(' ') + '\n')
    } : debug
    this._protocol = opts.protocol || 'tcp'
    this._address = opts.address || '0.0.0.0'
    this._port = opts.port || null
    this._keepalive = false
    this.passThrough = new Stream.PassThrough()
    this._clients = {}
  }

  protocol (p) {
    this._protocol = p
    debug('Protocol is', this._protocol)
    return this /* chainable method */
  }

  address (a) {
    debug('setting address', a)
    this._address = a
    return this /* chainable method */
  }

  addr (a) {
    /* address alias */
    return this.address(a)
  }

  port (p) {
    if (!Number.isInteger(p)) throw Error('Port should be a positive number!')
    this._port = p
    debug('Port set to', this._port)
    return this /* chainable method */
  }

  udp () {
    return this.protocol('udp') /* chainable method */
  }

  tcp () {
    return this.protocol('tcp') /* chainable method */
  }

  keepalive (bool) {
    this._keepalive = typeof bool !== 'undefined' ? bool : true
    debug('Keepalive connection.')
    return this /* chainable method */
  }

  k (bool) { /* keepalive alias */
    this.keepalive(bool)
    return this /* chainable method */
  }

  close (cb) {
    debug('Server: closing sockets...')
    cb = cb || noop
    for (var c in this._clients) {
      this._clients[c].destroy() // closing existing sockets
    }
    if (this.server) this.server.close(cb)
    return this
  }

  _createServer () {
    var self = this
    this.server = net.createServer()

    function listening () {
      debug('Server listening on port', self._port, 'addr', self._address)
      self.emit('ready')
    }

    function connection (socket) {
      socket.id = shortid.generate()
      debug('New connection', socket.id, socket.remoteAddress + ':' + socket.remotePort)
      self._clients[socket.id] = socket

      /* outcoming */
      if (self._serveFile) {
        debug('Serving given', self._serveFile, 'as a stream to client', socket.id)
        fs.createReadStream(self._serveFile).pipe(socket)
      }
      /* incoming */
      socket.pipe(self.passThrough, { end: !self._keepalive })

      function data (data) { // emitting also chunks
        self.emit('data', socket, data)
      }

      function error (err) {
        debug('Socket error:', err)
        self.emit('error', socket, err)
      }

      function timeout () {
        debug('Connection timed out')
        delete self._clients[socket.id]
        self.emit('timeout', socket)
      }

      function end () {
        debug('Connection end.')
        delete self._clients[socket.id]
        self.emit('end', socket)
        if (!self._keepalive) self.close()
      }

      function close (hadError) {
        debug('Connection closed', hadError ? 'because of a conn. error' : 'by client')
        self.emit('close', socket, hadError)
      }

      process.nextTick(function () {
        socket.on('data', data)
        socket.on('error', error)
        socket.on('timeout', timeout)
        socket.on('end', end)
        socket.on('close', close)
      })
    }

    function close () {
      self.server.unref()
      debug('Server closed')
      self._clients = {}
      self.emit('srvClose')
    }

    function error (err) {
      debug('Server error', err)
      self.emit('error', err)
    }

    process.nextTick(function () {
      self.server.on('listening', listening)
      self.server.on('connection', connection)
      self.server.on('close', close)
      self.server.on('error', error)
    })
  }

  listen () {
    debug('listen called')
    this._createServer()
    this.server.listen(this._port, this._address)
    return this /* chainable method */
  }

  pipe (outputStream) {
    debug('Pipe method called')
    this.passThrough.pipe(outputStream, { end: !this._keepalive })
    return this
  }

  serve (filePath) {
    debug('Setting file/stream to serve', filePath)
    if (typeof filePath === 'string') fs.statSync(filePath) // check that file exists
    else { // check stream
      // TODO
    }
    this._serveFile = filePath
    return this /* chainable method */
  }

  getClients () {
    return this._clients
  }

  q () {
    // TODO

  }

}

module.exports = Server

if (!module.parent) {
  const fs = require('fs')
  const nc = new Server()
  nc.port(2389).k().listen().serve('Client.js')
    .pipe(fs.createWriteStream('output.txt'))
    .on('data', function (s, data) { console.log(s.id, 'got', data) })
}
<|endoftext|>


<commit_before>var Predicates = require("./Predicates")
  , Attributes = require("./Attributes")
  , Value = require("./Value")

function Update(table, database) {
  this.TableName = table

  Object.defineProperty(
    this, "database",
    {value: database, enumerable: false}
  )
}

Update.prototype = {
  when: function(name, operator, value) {
    var predicates = new Predicates(name, operator, value)
      , expectation = this.Expected = {}
      , names = Object.keys(predicates)

    if (names.length > 1) {
      throw new Error("Only one condition allowed per expectation.")
    }

    name = names[0]
    operator = predicates[name].ComparisonOperator
    value = predicates[name].AttributeValueList[0]

    switch (operator) {
      case "NULL":
        expectation[name] = {Exists: false}
        return this

      case "NOT_NULL":
        expectation[name] = {Exists: true}
        return this

      case "EQ":
        expectation[name] = {Value: value}
        return this
    }

    throw new Error("Invalid expectation: " + [name, operator, value])
  },

  returning: function(constant) {
    this.ReturnValues = constant

    return this
  },

  update: function(action, key, value) {
    var updates = this.AttributeUpdates || (this.AttributeUpdates = {})

    if (updates[key]) {
      throw new Error("Attribute '" + key + "' cannot be updated more than once.")
    }

    updates[key] = {Action: action}

    if (value != null) updates[key].Value = Value(value)

    return this
  },

  put: function(key, value) {
    return this.update("PUT", key, value)
  },

  add: function(key, value) {
    return this.update("ADD", key, value)
  },

  remove: function(key) {
    return this.update("DELETE", key)
  },

  save: function(cb) {
    if (this.Item) {
      this.database.request(
        "PutItem",
        this,
        function(err, data) {
          if (err) return cb(err)

          if (data = data.Attributes) {
            cb(null, Attributes.prototype.parse(data))
          }

          else cb()
        }
      )

      return this
    }

    if (this.AttributeUpdates) {
      this.database.request(
        "UpdateItem",
        this,
        cb
      )

      return this
    }

    throw new Error("Nothing to save.")
  }
}

module.exports = Update
<commit_msg>update Update.js: remove should take values<commit_after>var Predicates = require("./Predicates")
  , Attributes = require("./Attributes")
  , Value = require("./Value")

function Update(table, database) {
  this.TableName = table

  Object.defineProperty(
    this, "database",
    {value: database, enumerable: false}
  )
}

Update.prototype = {
  when: function(name, operator, value) {
    var predicates = new Predicates(name, operator, value)
      , expectation = this.Expected = {}
      , names = Object.keys(predicates)

    if (names.length > 1) {
      throw new Error("Only one condition allowed per expectation.")
    }

    name = names[0]
    operator = predicates[name].ComparisonOperator
    value = predicates[name].AttributeValueList[0]

    switch (operator) {
      case "NULL":
        expectation[name] = {Exists: false}
        return this

      case "NOT_NULL":
        expectation[name] = {Exists: true}
        return this

      case "EQ":
        expectation[name] = {Value: value}
        return this
    }

    throw new Error("Invalid expectation: " + [name, operator, value])
  },

  returning: function(constant) {
    this.ReturnValues = constant

    return this
  },

  update: function(action, key, value) {
    var updates = this.AttributeUpdates || (this.AttributeUpdates = {})

    if (updates[key]) {
      throw new Error("Attribute '" + key + "' cannot be updated more than once.")
    }

    updates[key] = {Action: action}

    if (value != null) updates[key].Value = Value(value)

    return this
  },

  put: function(key, value) {
    return this.update("PUT", key, value)
  },

  add: function(key, value) {
    return this.update("ADD", key, value)
  },

  remove: function(key, value) {
    return this.update("DELETE", key, value)
  },

  save: function(cb) {
    if (this.Item) {
      this.database.request(
        "PutItem",
        this,
        function(err, data) {
          if (err) return cb(err)

          if (data = data.Attributes) {
            cb(null, Attributes.prototype.parse(data))
          }

          else cb()
        }
      )

      return this
    }

    if (this.AttributeUpdates) {
      this.database.request(
        "UpdateItem",
        this,
        cb
      )

      return this
    }

    throw new Error("Nothing to save.")
  }
}

module.exports = Update
<|endoftext|>


<commit_before>const { execSync } = require('child_process');
const path = require('path');
const { stat, readFile: readFileCallback, unlink } = require('fs');
const babel = require('babel-core');
const chokidar = require('chokidar');
const glob = require('glob');
const readdir = require('fs-readdir-recursive');
const slash = require('slash');
const Lock = require('lock');
const Queue = require('promise-queue');
const promiseCallback = require('promise-callback-factory').default;
const Logger = require('nightingale').default;
const copyChmod = require('./utils/copyChmod');
const copyFile = require('./utils/copyFile');
const writeFile = require('./utils/writeFile');
const destFromSrc = require('./utils/destFromSrc');
const plugins = require('./plugins');
const options = require(`./babel-options`);
const { logger: parentLogger } = require('./logger');
const Task = require('./cli-spinner');

const readFile = filepath => promiseCallback(done => readFileCallback(filepath, done));

const queue = new Queue(40, Infinity);

function toErrorStack(err) {
    if (err._babel && err instanceof SyntaxError) {
        return `${err.name}: ${err.message}\n${err.codeFrame}`;
    } else {
        return err.stack;
    }
}

module.exports = function transpile(pobrc, cwd, src, outFn, envs, watch) {
    const srcFiles = glob.sync(src, { cwd });
    const _lock = Lock();
    const lock = resource => new Promise(resolve => _lock(resource, release => resolve(() => release()())));
    let task = new Task(`build ${src}`);

    let logger = parentLogger.child('build', 'build');
    const watchLogger = parentLogger.child('watch', 'watch');
    let watching = false;

    const timeBuildStarted = 0;// logger.infoTime('building ' + src);
    logger.debug('envs', { envs });

    const optsManagers = {};

    envs.forEach(env => {
        const optsManager = new babel.OptionManager;

        optsManager.mergeOptions({
            options: options(env, pobrc.react),
            alias: 'base',
            loc: cwd,
        });

        optsManagers[env] = optsManager;
    });

    function handle(filename) {
        return promiseCallback(done => stat(filename, done))
            .catch(err => {
                console.log(err);
                process.exit(1);
            })
            .then(stat => {
                if (stat.isDirectory(filename)) {
                    let dirname = filename;

                    const allSrcFiles = readdir(dirname);
                    const allAllowedDestFiles = allSrcFiles.map(relative => destFromSrc(relative));

                    envs.forEach(env => {
                        const out = outFn(env);
                        const envAllFiles = readdir(out);

                        const diff = envAllFiles.filter(path => !allAllowedDestFiles.includes(path.replace(/.map$/, '')));
                        if (diff.length) {
                            logger.debug(`${out}: removing: ${diff.join(',')}`);
                            execSync('rm -Rf ' + diff.map(filename => path.join(out, filename)).join(' '));
                        }
                    });

                    return Promise.all(allSrcFiles.map(filename => {
                        let src = path.join(dirname, filename);
                        return handleFile(src, filename);
                    }));
                } else {
                }
            });
    }

    function handleFile(src, relative) {
        if (_lock.isLocked(relative)) logger.debug(relative + ' locked, waiting...');
        return lock(relative).then(release => {
            return queue.add(() => {
                if (babel.util.canCompile(relative)) {
                    const subtask = task.subtask('compiling: ' + relative);
                    logger.debug('compiling: ' + relative);

                    return Promise.resolve(src)
                        .then(src => readFile(src))
                        .then(content => {
                            return Promise.all(envs.map(env => {
                                const dest = path.join(outFn(env), destFromSrc(relative));

                                const opts = optsManagers[env].init({ filename: relative });
                                opts.babelrc = false;
                                opts.sourceMap = true;
                                opts.sourceFileName = slash(path.relative(dest + "/..", src));
                                opts.sourceMapTarget = path.basename(relative);

                                return Promise.resolve(content)
                                    .then(content => babel.transform(content, opts))
                                    .catch(watch && (err => {
                                        console.log(toErrorStack(err));

                                        return { map: null, code: 'throw new Error("Syntax Error");' };
                                    }))
                                    .then(data => {
                                        const mapLoc = dest + ".map";
                                        data.code = data.code + "\n//# sourceMappingURL=" + path.basename(mapLoc);
                                        return writeFile(dest, data.code)
                                            .then(() => Promise.all([
                                                copyChmod(src, dest),
                                                writeFile(mapLoc, JSON.stringify(data.map)),
                                            ]));
                                    });
                            }));
                        })
                        .then(() => {
                            logger[watching ? 'success' : 'debug']('compiled: ' + relative);
                        })
                        .then(() => release(), err => { release(); throw err; })
                        .then(() => subtask.done(), err => { subtask.done(); throw err; });
                } else {
                    const extension = path.extname(relative).substr(1);
                    const plugin = plugins.findByExtension(extension);
                    if (plugin) {
                        const subtask = task.subtask(plugin.extension + ': ' + relative);
                        logger.debug(plugin.extension + ': ' + relative);
                        const destRelative = destFromSrc(relative, plugin);
                        return Promise.resolve(src)
                            .then(src => readFile(src))
                            .then(content => plugin.transform(content, { src, relative }))
                            .catch(watch && (err => {
                                console.log(toErrorStack(err));

                                return { map: null, code: 'throw new Error("Syntax Error");' };
                            }))
                            .then(({ code, map }) => Promise.all(envs.map(env => {
                                const dest = path.join(outFn(env), destRelative);
                                const mapLoc = dest + ".map";
                                return writeFile(dest, code)
                                    .then(() => Promise.all([
                                        copyChmod(src, dest),
                                        map && writeFile(mapLoc, JSON.stringify(map)),
                                    ]));
                            })))
                            .then(() => release(), err => { release(); throw err; })
                            .then(() => subtask.done(), err => { subtask.done(); throw err; });
                    } else {
                        const subtask = task.subtask('copy: ' + relative);
                        logger.debug('copy: ' + relative);
                        return Promise.all(envs.map(env => {
                            const out = outFn(env);
                            const dest = path.join(out, relative);
                            return copyFile(src, dest).then(() => copyChmod(src, dest));
                        }))
                        .then(() => release(), err => { release(); throw err; })
                        .then(() => subtask.done(), err => { subtask.done(); throw err; });
                    }
                 }
            });
        }).catch(err => {
            console.log(toErrorStack(err));
            if (!watch) {
                process.exit(1);
            }
        });
    }

    if (watch) {
        process.nextTick(() => {
            srcFiles.forEach(dirname => {
                const watcher = chokidar.watch(dirname, {
                    persistent: true,
                    ignoreInitial: true
                });

                function handleChange(filename) {
                    let relative = path.relative(dirname, filename) || filename;
                    watchLogger.debug('changed: ' + relative);
                    task.subtask('changed: ' + relative);
                    handleFile(filename, relative)
                        .catch(err => {
                            console.log(err.stack);
                        })
                        .then(() => watch.emit('changed', filename));
                }

                watcher.on('add', handleChange);
                watcher.on('change', handleChange);
                watcher.on('unlink', filename => {
                    let relative = path.relative(dirname, filename) || filename;
                    watchLogger.debug('unlink: ' + relative);
                    const subtask = task.subtask('delete: ' + relative);
                    if (_lock.isLocked(relative)) watchLogger.debug(relative + ' locked, waiting...');
                    lock(relative).then(release => {
                        return Promise.all(envs.map(env => {
                            const dest = path.join(outFn(env), destFromSrc(relative));

                            return Promise.all([
                                promiseCallback(done => unlink(dest, done)).catch(() => {}),
                                promiseCallback(done => unlink(`${dest}.map`, done)).catch(() => {}),
                            ]);
                        }))
                        .then(() => release())
                        .then(() => watch.emit('changed', filename))
                        .then(() => subtask.done());
                    });
                });
            });
        });
    }

    return Promise.all(srcFiles.map(filename => handle(filename)))
        .then(() => {
            logger.infoSuccessTimeEnd(timeBuildStarted, 'build finished');
            task.succeed();
            if (watch) {
                task = new Task('watch');
                logger.info('watching');
                watching = true;
                logger = watchLogger;
            }
        })
        .catch(err => {
            console.log(err.stack);
            process.exit(1);
        });
};
<commit_msg>fix build started time<commit_after>const { execSync } = require('child_process');
const path = require('path');
const { stat, readFile: readFileCallback, unlink } = require('fs');
const babel = require('babel-core');
const chokidar = require('chokidar');
const glob = require('glob');
const readdir = require('fs-readdir-recursive');
const slash = require('slash');
const Lock = require('lock');
const Queue = require('promise-queue');
const promiseCallback = require('promise-callback-factory').default;
const Logger = require('nightingale').default;
const copyChmod = require('./utils/copyChmod');
const copyFile = require('./utils/copyFile');
const writeFile = require('./utils/writeFile');
const destFromSrc = require('./utils/destFromSrc');
const plugins = require('./plugins');
const options = require(`./babel-options`);
const { logger: parentLogger } = require('./logger');
const Task = require('./cli-spinner');

const readFile = filepath => promiseCallback(done => readFileCallback(filepath, done));

const queue = new Queue(40, Infinity);

function toErrorStack(err) {
    if (err._babel && err instanceof SyntaxError) {
        return `${err.name}: ${err.message}\n${err.codeFrame}`;
    } else {
        return err.stack;
    }
}

module.exports = function transpile(pobrc, cwd, src, outFn, envs, watch) {
    const srcFiles = glob.sync(src, { cwd });
    const _lock = Lock();
    const lock = resource => new Promise(resolve => _lock(resource, release => resolve(() => release()())));
    let task = new Task(`build ${src}`);

    let logger = parentLogger.child('build', 'build');
    const watchLogger = parentLogger.child('watch', 'watch');
    let watching = false;

    const timeBuildStarted = Date.now();// logger.infoTime('building ' + src);
    logger.debug('envs', { envs });

    const optsManagers = {};

    envs.forEach(env => {
        const optsManager = new babel.OptionManager;

        optsManager.mergeOptions({
            options: options(env, pobrc.react),
            alias: 'base',
            loc: cwd,
        });

        optsManagers[env] = optsManager;
    });

    function handle(filename) {
        return promiseCallback(done => stat(filename, done))
            .catch(err => {
                console.log(err);
                process.exit(1);
            })
            .then(stat => {
                if (stat.isDirectory(filename)) {
                    let dirname = filename;

                    const allSrcFiles = readdir(dirname);
                    const allAllowedDestFiles = allSrcFiles.map(relative => destFromSrc(relative));

                    envs.forEach(env => {
                        const out = outFn(env);
                        const envAllFiles = readdir(out);

                        const diff = envAllFiles.filter(path => !allAllowedDestFiles.includes(path.replace(/.map$/, '')));
                        if (diff.length) {
                            logger.debug(`${out}: removing: ${diff.join(',')}`);
                            execSync('rm -Rf ' + diff.map(filename => path.join(out, filename)).join(' '));
                        }
                    });

                    return Promise.all(allSrcFiles.map(filename => {
                        let src = path.join(dirname, filename);
                        return handleFile(src, filename);
                    }));
                } else {
                }
            });
    }

    function handleFile(src, relative) {
        if (_lock.isLocked(relative)) logger.debug(relative + ' locked, waiting...');
        return lock(relative).then(release => {
            return queue.add(() => {
                if (babel.util.canCompile(relative)) {
                    const subtask = task.subtask('compiling: ' + relative);
                    logger.debug('compiling: ' + relative);

                    return Promise.resolve(src)
                        .then(src => readFile(src))
                        .then(content => {
                            return Promise.all(envs.map(env => {
                                const dest = path.join(outFn(env), destFromSrc(relative));

                                const opts = optsManagers[env].init({ filename: relative });
                                opts.babelrc = false;
                                opts.sourceMap = true;
                                opts.sourceFileName = slash(path.relative(dest + "/..", src));
                                opts.sourceMapTarget = path.basename(relative);

                                return Promise.resolve(content)
                                    .then(content => babel.transform(content, opts))
                                    .catch(watch && (err => {
                                        console.log(toErrorStack(err));

                                        return { map: null, code: 'throw new Error("Syntax Error");' };
                                    }))
                                    .then(data => {
                                        const mapLoc = dest + ".map";
                                        data.code = data.code + "\n//# sourceMappingURL=" + path.basename(mapLoc);
                                        return writeFile(dest, data.code)
                                            .then(() => Promise.all([
                                                copyChmod(src, dest),
                                                writeFile(mapLoc, JSON.stringify(data.map)),
                                            ]));
                                    });
                            }));
                        })
                        .then(() => {
                            logger[watching ? 'success' : 'debug']('compiled: ' + relative);
                        })
                        .then(() => release(), err => { release(); throw err; })
                        .then(() => subtask.done(), err => { subtask.done(); throw err; });
                } else {
                    const extension = path.extname(relative).substr(1);
                    const plugin = plugins.findByExtension(extension);
                    if (plugin) {
                        const subtask = task.subtask(plugin.extension + ': ' + relative);
                        logger.debug(plugin.extension + ': ' + relative);
                        const destRelative = destFromSrc(relative, plugin);
                        return Promise.resolve(src)
                            .then(src => readFile(src))
                            .then(content => plugin.transform(content, { src, relative }))
                            .catch(watch && (err => {
                                console.log(toErrorStack(err));

                                return { map: null, code: 'throw new Error("Syntax Error");' };
                            }))
                            .then(({ code, map }) => Promise.all(envs.map(env => {
                                const dest = path.join(outFn(env), destRelative);
                                const mapLoc = dest + ".map";
                                return writeFile(dest, code)
                                    .then(() => Promise.all([
                                        copyChmod(src, dest),
                                        map && writeFile(mapLoc, JSON.stringify(map)),
                                    ]));
                            })))
                            .then(() => release(), err => { release(); throw err; })
                            .then(() => subtask.done(), err => { subtask.done(); throw err; });
                    } else {
                        const subtask = task.subtask('copy: ' + relative);
                        logger.debug('copy: ' + relative);
                        return Promise.all(envs.map(env => {
                            const out = outFn(env);
                            const dest = path.join(out, relative);
                            return copyFile(src, dest).then(() => copyChmod(src, dest));
                        }))
                        .then(() => release(), err => { release(); throw err; })
                        .then(() => subtask.done(), err => { subtask.done(); throw err; });
                    }
                 }
            });
        }).catch(err => {
            console.log(toErrorStack(err));
            if (!watch) {
                process.exit(1);
            }
        });
    }

    if (watch) {
        process.nextTick(() => {
            srcFiles.forEach(dirname => {
                const watcher = chokidar.watch(dirname, {
                    persistent: true,
                    ignoreInitial: true
                });

                function handleChange(filename) {
                    let relative = path.relative(dirname, filename) || filename;
                    watchLogger.debug('changed: ' + relative);
                    task.subtask('changed: ' + relative);
                    handleFile(filename, relative)
                        .catch(err => {
                            console.log(err.stack);
                        })
                        .then(() => watch.emit('changed', filename));
                }

                watcher.on('add', handleChange);
                watcher.on('change', handleChange);
                watcher.on('unlink', filename => {
                    let relative = path.relative(dirname, filename) || filename;
                    watchLogger.debug('unlink: ' + relative);
                    const subtask = task.subtask('delete: ' + relative);
                    if (_lock.isLocked(relative)) watchLogger.debug(relative + ' locked, waiting...');
                    lock(relative).then(release => {
                        return Promise.all(envs.map(env => {
                            const dest = path.join(outFn(env), destFromSrc(relative));

                            return Promise.all([
                                promiseCallback(done => unlink(dest, done)).catch(() => {}),
                                promiseCallback(done => unlink(`${dest}.map`, done)).catch(() => {}),
                            ]);
                        }))
                        .then(() => release())
                        .then(() => watch.emit('changed', filename))
                        .then(() => subtask.done());
                    });
                });
            });
        });
    }

    return Promise.all(srcFiles.map(filename => handle(filename)))
        .then(() => {
            logger.infoSuccessTimeEnd(timeBuildStarted, 'build finished');
            task.succeed();
            if (watch) {
                task = new Task('watch');
                logger.info('watching');
                watching = true;
                logger = watchLogger;
            }
        })
        .catch(err => {
            console.log(err.stack);
            process.exit(1);
        });
};
<|endoftext|>