<commit_before>var EventEmitter = require('events').EventEmitter;
var Winston = require("winston");
var Util = require("util");
var ZeroMQ = require("zmq");
var msgpack = require('msgpack');
var Promise = require('promise');

function RPCException(message, code) {
    this.code = code || 0;
    this.message = message;
    this.toString = function () {
        return this.message;
    };
}

function _send_response(data, client_id) {
    var self = this;
    var response = msgpack.pack(data);
    if (client_id) {
        self.logger.debug(Util.format(
            "0MQ [%s] => %s: %s",
            data.id, client_id.toString('base64'), JSON.stringify(data)
        ));
        self.socket.send([client_id, response]);
    }
    else {
        self.logger.debug(Util.format(
            "0MQ [%s] => %s",
            data.id, JSON.stringify(data)
        ));
        self.socket.send(response);
    }
}

function _process(data, client_id) {
    var request;
    var self = this;

    try {
        request = msgpack.unpack(data);
        self.logger.debug(Util.format(
            "0MQ [%s] <= %s", request.id || "N/A", JSON.stringify(request)
        ));
    }
    catch (e) {
        _send_response.apply(self, [{
            jsonrpc:'2.0',
            error: {
                code: -32700,
                message: 'Parse error'
            }
        }, client_id]);
        return;
    }

    if (request.jsonrpc !== '2.0') {
        _send_response.apply(self, [{
            jsonrpc:'2.0',
            error: {
                code: -32600,
                message: 'Invalid Request'
            }
        }, client_id]);
        return;
    }

    if (request.hasOwnProperty('method')) {

        function _response(e, result) {

            if (e) {
                if (request.id) {
                    _send_response.apply(self, [{
                        jsonrpc: "2.0",
                        error: {
                            code: e.code || -32603,
                            message: e.message || "Internal Error"
                        },
                        id: request.id
                    }, client_id]);
                }
            }
            else {
                if (result !== undefined && request.id) {
                    _send_response.apply(self, [{
                        jsonrpc: "2.0",
                        result: result,
                        id: request.id
                    }, client_id]);
                }

            }

        }

        var cb = self._callings[request.method];
        if (!cb) _response({code: -32601, message: 'Method not found'});

        try {
            var result = cb.apply(self, [request.params, client_id ? client_id.toString('base64') : null]);
        } catch (e) {
            if (e instanceof RPCException) {
                _response(e);
            } else {
                throw e;
            }
        }

        if (typeof(result) == 'function') {
            // deferred callback
            result(_response);
        } else {
            _response(null, result);
        }

    } else if (request.id && self.promisedRequests.hasOwnProperty(request.id)) {
        var rq = self.promisedRequests[request.id];
        clearTimeout(rq.timeout);
        delete self.promisedRequests[request.id];

        if (request.hasOwnProperty('result')) {
            self.logger.debug(Util.format(
                "0MQ remote: %s(%s) <= %s",
                rq.method, JSON.stringify(rq.params),
                JSON.stringify(request.result)
            ));
            rq.resolve(request.result);
        }
        else if (request.hasOwnProperty('error')) {
            self.logger.debug(Util.format(
                "0MQ remote: %s(%s) <= %s",
                rq.method, JSON.stringify(rq.params),
                JSON.stringify(request.error)
            ));
            rq.reject(request.error);
        }
        else {
            rq.reject({
                code: -32603,
                message: "Internal Error"
            });
        }
    }
    else {
        _send_response.apply(self, [{
            jsonrpc:'2.0',
            error: {
                code: -32600,
                message: 'Invalid Request'
            }
        }, client_id]);
    }
}

var RPC = function (path) {
    this.promisedRequests = {};
    this._callings = {};
    this.callTimeout = 5000;
    this.isServer = false;
    this.Exception = RPCException;
    this.logger = new Winston.Logger();
}

RPC.prototype.bind = function (path) {

    var self = this;
    self.isServer = true;

    var socket = ZeroMQ.socket("router");
    self.socket = socket;

    socket
    .bind(path, function (err) {
        if (err) throw err;

        socket
        .on("message", function (id, data) {
            _process.apply(self, [data, id]);
        });

    });

    return self;
};

RPC.prototype.connect = function (path) {

    var self = this;
    self.isServer = false;

    var socket = ZeroMQ.socket("dealer");

    self.socket = socket;
    socket.connect(path);

    socket
    .on("error", function (err){
        self.logger.debug(Util.format("0MQ error: %s", err));
        // reconnect in 3s
        setTimeout(function (){
            socket.connect(path);
        }, 3000);
    })
    .on("message", function (data) {
        _process.apply(self, [data]);
    });

    return self;
};

// inherit EventEmitter
RPC.prototype.__proto__ = EventEmitter.prototype;

var _uniqsec = 0;
var _uniqid = 0;
var Moment = require('moment');

RPC.prototype.getUniqueId = function () {
    // var uuid = require("uuid");
    // var buffer = new Buffer(16);
    // uuid.v4(null, buffer);
    // return buffer.toString("hex");
    var sec = Moment().valueOf();
    if (sec !== _uniqsec) {
        _uniqsec = sec;
        _uniqid  = 0;
    }
    else {
        _uniqid ++;
    }
    return _uniqsec.toString(36) + _uniqid.toString();
}

RPC.prototype.calling = function (method, cb) {
    var self = this;
    self._callings[method] = cb;
    return self;
}

RPC.prototype.removeCalling = function (key) {
    var self = this;
    if (self._callings.hasOwnProperty(key)) delete self._callings[key];
    return self;
}

RPC.prototype.removeCallings = function (pattern) {
    var self = this;
    var wildcard = require('wildcard');

    wildcard(pattern, Object.keys(self._callings)).forEach(function (key){
        delete self._callings[key];
    });

    return self;
}

RPC.prototype.call = function (method, params, client_id) {

    var self = this;

    return new Promise(function(resolve, reject) {

        var id = self.getUniqueId();

        params = params || {};

        var data = {
            jsonrpc:'2.0',
            method: method,
            params: params,
            id: id
        };

        if (client_id) {
            self.logger.debug(Util.format("0MQ [%s] => [%s] %s", id, client_id, JSON.stringify(data)));
        }
        else {
            self.logger.debug(Util.format("0MQ [%s] => %s", id, JSON.stringify(data)));
        }

        var msg = msgpack.pack(data)
        if (self.isServer) {
            self.socket.send([new Buffer(client_id, 'base64'), msg]);
        }
        else {
            self.socket.send(msg);
        }

        self.promisedRequests[id] = {
            method: method,
            params: params,
            resolve: resolve,
            reject: reject
        };

        self.promisedRequests[id].timeout = setTimeout(function (){
            self.logger.debug(Util.format("0MQ [%s] <= timeout", id));
            delete self.promisedRequests[id];
            reject({
                code: -32603,
                message: "Call Timeout"
            });
        }, self.callTimeout);

    })

};

module.exports = {
    connect: function (path) {
        var rpc = new RPC();
        return rpc.connect(path);
    },
    bind: function (path) {
        var rpc = new RPC();
        return rpc.bind(path);
    }
};<commit_msg>add rpc() method to export a RPC object, which will usually bind some APIs later, then bind a port<commit_after>var EventEmitter = require('events').EventEmitter;
var Winston = require("winston");
var Util = require("util");
var ZeroMQ = require("zmq");
var msgpack = require('msgpack');
var Promise = require('promise');

function RPCException(message, code) {
    this.code = code || 0;
    this.message = message;
    this.toString = function () {
        return this.message;
    };
}

function _send_response(data, client_id) {
    var self = this;
    var response = msgpack.pack(data);
    if (client_id) {
        self.logger.debug(Util.format(
            "0MQ [%s] => %s: %s",
            data.id, client_id.toString('base64'), JSON.stringify(data)
        ));
        self.socket.send([client_id, response]);
    }
    else {
        self.logger.debug(Util.format(
            "0MQ [%s] => %s",
            data.id, JSON.stringify(data)
        ));
        self.socket.send(response);
    }
}

function _process(data, client_id) {
    var request;
    var self = this;

    try {
        request = msgpack.unpack(data);
        self.logger.debug(Util.format(
            "0MQ [%s] <= %s", request.id || "N/A", JSON.stringify(request)
        ));
    }
    catch (e) {
        _send_response.apply(self, [{
            jsonrpc:'2.0',
            error: {
                code: -32700,
                message: 'Parse error'
            }
        }, client_id]);
        return;
    }

    if (request.jsonrpc !== '2.0') {
        _send_response.apply(self, [{
            jsonrpc:'2.0',
            error: {
                code: -32600,
                message: 'Invalid Request'
            }
        }, client_id]);
        return;
    }

    if (request.hasOwnProperty('method')) {

        function _response(e, result) {

            if (e) {
                if (request.id) {
                    _send_response.apply(self, [{
                        jsonrpc: "2.0",
                        error: {
                            code: e.code || -32603,
                            message: e.message || "Internal Error"
                        },
                        id: request.id
                    }, client_id]);
                }
            }
            else {
                if (result !== undefined && request.id) {
                    _send_response.apply(self, [{
                        jsonrpc: "2.0",
                        result: result,
                        id: request.id
                    }, client_id]);
                }

            }

        }

        var cb = self._callings[request.method];
        if (!cb) _response({code: -32601, message: 'Method not found'});

        try {
            var result = cb.apply(self, [request.params, client_id ? client_id.toString('base64') : null]);
        } catch (e) {
            if (e instanceof RPCException) {
                _response(e);
            } else {
                throw e;
            }
        }

        if (typeof(result) == 'function') {
            // deferred callback
            result(_response);
        } else {
            _response(null, result);
        }

    } else if (request.id && self.promisedRequests.hasOwnProperty(request.id)) {
        var rq = self.promisedRequests[request.id];
        clearTimeout(rq.timeout);
        delete self.promisedRequests[request.id];

        if (request.hasOwnProperty('result')) {
            self.logger.debug(Util.format(
                "0MQ remote: %s(%s) <= %s",
                rq.method, JSON.stringify(rq.params),
                JSON.stringify(request.result)
            ));
            rq.resolve(request.result);
        }
        else if (request.hasOwnProperty('error')) {
            self.logger.debug(Util.format(
                "0MQ remote: %s(%s) <= %s",
                rq.method, JSON.stringify(rq.params),
                JSON.stringify(request.error)
            ));
            rq.reject(request.error);
        }
        else {
            rq.reject({
                code: -32603,
                message: "Internal Error"
            });
        }
    }
    else {
        _send_response.apply(self, [{
            jsonrpc:'2.0',
            error: {
                code: -32600,
                message: 'Invalid Request'
            }
        }, client_id]);
    }
}

var RPC = function (path) {
    this.promisedRequests = {};
    this._callings = {};
    this.callTimeout = 5000;
    this.isServer = false;
    this.Exception = RPCException;
    this.logger = new Winston.Logger();
}

RPC.prototype.bind = function (path) {

    var self = this;
    self.isServer = true;

    var socket = ZeroMQ.socket("router");
    self.socket = socket;

    socket
    .bind(path, function (err) {
        if (err) throw err;

        socket
        .on("message", function (id, data) {
            _process.apply(self, [data, id]);
        });

    });

    return self;
};

RPC.prototype.connect = function (path) {

    var self = this;
    self.isServer = false;

    var socket = ZeroMQ.socket("dealer");

    self.socket = socket;
    socket.connect(path);

    socket
    .on("error", function (err){
        self.logger.debug(Util.format("0MQ error: %s", err));
        // reconnect in 3s
        setTimeout(function (){
            socket.connect(path);
        }, 3000);
    })
    .on("message", function (data) {
        _process.apply(self, [data]);
    });

    return self;
};

// inherit EventEmitter
RPC.prototype.__proto__ = EventEmitter.prototype;

var _uniqsec = 0;
var _uniqid = 0;
var Moment = require('moment');

RPC.prototype.getUniqueId = function () {
    // var uuid = require("uuid");
    // var buffer = new Buffer(16);
    // uuid.v4(null, buffer);
    // return buffer.toString("hex");
    var sec = Moment().valueOf();
    if (sec !== _uniqsec) {
        _uniqsec = sec;
        _uniqid  = 0;
    }
    else {
        _uniqid ++;
    }
    return _uniqsec.toString(36) + _uniqid.toString();
}

RPC.prototype.calling = function (method, cb) {
    var self = this;
    self._callings[method] = cb;
    return self;
}

RPC.prototype.removeCalling = function (key) {
    var self = this;
    if (self._callings.hasOwnProperty(key)) delete self._callings[key];
    return self;
}

RPC.prototype.removeCallings = function (pattern) {
    var self = this;
    var wildcard = require('wildcard');

    wildcard(pattern, Object.keys(self._callings)).forEach(function (key){
        delete self._callings[key];
    });

    return self;
}

RPC.prototype.call = function (method, params, client_id) {

    var self = this;

    return new Promise(function(resolve, reject) {

        var id = self.getUniqueId();

        params = params || {};

        var data = {
            jsonrpc:'2.0',
            method: method,
            params: params,
            id: id
        };

        if (client_id) {
            self.logger.debug(Util.format("0MQ [%s] => [%s] %s", id, client_id, JSON.stringify(data)));
        }
        else {
            self.logger.debug(Util.format("0MQ [%s] => %s", id, JSON.stringify(data)));
        }

        var msg = msgpack.pack(data)
        if (self.isServer) {
            self.socket.send([new Buffer(client_id, 'base64'), msg]);
        }
        else {
            self.socket.send(msg);
        }

        self.promisedRequests[id] = {
            method: method,
            params: params,
            resolve: resolve,
            reject: reject
        };

        self.promisedRequests[id].timeout = setTimeout(function (){
            self.logger.debug(Util.format("0MQ [%s] <= timeout", id));
            delete self.promisedRequests[id];
            reject({
                code: -32603,
                message: "Call Timeout"
            });
        }, self.callTimeout);

    })

};

module.exports = {
    connect: function (path) {
        var rpc = new RPC();
        return rpc.connect(path);
    },
    bind: function (path) {
        var rpc = new RPC();
        return rpc.bind(path);
    },
    rpc: function () {
        return new RPC();
    }
};
<|endoftext|>


<commit_before>if (process.env.NODE_ENV !== 'development') {
  process.env.NODE_ENV = 'production'
}

var passport = require('passport')
var facebook_strategy = require('passport-facebook').Strategy

var express = require('express')
var session = require('express-session')
var session_store = require('connect-mongo')(session)
var cookie_parser = require('cookie-parser')
var body_parser = require('body-parser')
var consolidate = require('consolidate')
var getSlug = require('speakingurl')

var util = require('util')

var config = require('./config')

var db = require('monk')(config.database.host + config.database.name)
var users = db.get('users')
var urlencodedParser = body_parser.urlencoded({ extended: false })

// TODO Move this out using cluster to a separate file, add more files for routes etc!
// TODO Index auth.facebook etc
// TODO set callback URLs etc in Facebook dev console
// TODO Set enableProof: true
// TODO Set fallback photo to actual link
// TODO Reauthenticate etc?
passport.use(new facebook_strategy({
    clientID: config.facebook.app_id,
    clientSecret: config.facebook.app_secret,
    callbackURL: config.facebook.callback,
    profileFields: ['id', 'name', 'displayName', 'picture.type(large)']
  },

  function (access_token, refresh_token, profile, done) {
    users.findAndModify({
      auth: {
        facebook: profile.id
      }
    }, {
      $setOnInsert: {
        auth: {
          facebook: profile.id
        },

        name: {
          display_name: profile.displayName,
          first: profile.name.givenName
        },

        photo: profile.photos ? profile.photos[0].value : '/unknown_user.png'
      }
    }, {
      new: true,
      upsert: true
    }, function (error, result) {
      done(error, {
        id: result._id,
        display_name: result.display_name,
        photo: result.photo
      })
    })
  }
))

var app = express()

// TODO Replace this with streaming json parser
app.engine('html', consolidate.ejs)
app.set('view engine', 'html')
app.set('views', __dirname + '/views')
app.use(body_parser.json())

app.use(cookie_parser())
// TODO re-use db connection
// TODO resave/saveUnitialized
// TODO heighten cookie max time?
// TODO set secure: true later when redirecting for https etc!
// TODO use redis store?
app.use(session({
  secret: config.session_secret,
  resave: false,
  saveUninitialized: false,
  store: new session_store({
    url: config.database.host + config.database.name
  }),
  cookie: {
    maxAge: 60*60*1000,
    secure: false
  }
}))

app.use(passport.initialize())
app.use(passport.session())

if (process.env.NODE_ENV === 'development') {
  app.use(express.static(__dirname + '/public'))
}

passport.serializeUser(function (user, done) {
  done(null, user.id)
})

// TODO error handling etc
passport.deserializeUser(function (id, done) {
  users.findById(id, ['_id', 'name', 'photo', 'info'], function (error, result) {
    done(error, result)
  })
})

// TODO dynamically generate routes?

// TODO cache views etc, NODE_ENV === production?

// TODO make one default template instead of the same includes in every?
app.get('/', function (req, res) {
  var pagesdb = db.get('pages')
  if(typeof req.query.s !== 'undefined') {
    var query = {
      title: {
        $regex: req.query.s,
        $options: 'i' //i: ignore case, m: multiline, etc
      }
    }
    pagesdb.find(query, {}, function(err, doc) {
      res.render('index', { user: req.user, pages: doc, showsearch: true })
    })
  } else {
    pagesdb.find({}, function(err, doc) {
      res.render('index', { user: req.user, pages: doc, showsearch: false })
    })
  }
})

app.get('/test/view', function (req, res) {
  var testing = db.get('pages')
  testing.find({}, function(err, doc) {
    res.json(doc)
  })
})

app.get('/test/users', function (req, res) {
  var users = db.get('users')
  users.find({}, function(err, doc) {
    res.json(doc)
  })
})

app.get('/logga-in', function (req, res) {

  // TODO make this a middleware or something
  if (req.isAuthenticated()) {
    // TODO get latest page we were on or something instead
    return res.redirect('/')
  }

  res.render('login', { })
})

app.get('/om', function(req, res) {
  res.render('about', { user: req.user });
})

app.get('/annonsera', function (req, res) {
  res.render('advertise', { user: req.user });
})

app.get('/riktlinjer', function (req, res) {
  res.render('guidelines', { user: req.user, hidelink: true })
});

app.get('/vanliga-fragor', function (req, res) {
  res.render('faq', { user: req.user })
});

app.get('/auth/facebook', passport.authenticate('facebook'), function(req, res) {})

// TODO manually handle failure?
// TODO redirect to /konto?
app.get('/auth/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/login' }), function (req, res) {
  // TODO get the page we were on when we got sent to auth instead!
  res.redirect('/')
})

app.get('/logga-ut', function (req, res) {
  req.logout()
  res.redirect('/')
})

app.use(function ensure_authenticated (req, res, next) {
  if (req.isAuthenticated()) {
    return next()
  }

  res.redirect('/logga-in')
})

app.get('/konto', function (req, res) {
  res.render('konto', { user: req.user })
})

app.get('/installningar', function (req, res) {
  res.render('settings', { user: req.user })
})

app.post('/installningar/submit', urlencodedParser, function (req, res) {
  var id = req.user._id
  console.log(id)
  var display_name = req.body.displayName
  var website = req.body.website
  var description = req.body.description
  var users = db.get('users')
  console.log(display_name)
  users.update(
    { _id : id },
    { $set:
      { "name.display_name": display_name,
       "info.website":website,
       "info.description":description }
    }
  )
  res.send('1')
})

app.get('/mina-sidor', function (req, res) {
  var pages = db.get('pages')
  var userid = req.user.id
  pages.find({id:userid}, function(err, doc) {
    res.render('pages', { user: req.user, pages:doc })
  })
})

app.get('/ny', function (req, res) {
  res.render('new', { user: req.user })
})

app.get('/ny/publicerad', function (req, res) {
  if(typeof req.query.newpost === 'undefined') {
    res.render('post/published', { user: req.user, type: "product", hideredirect:true })
  } else {
    res.render('post/published', { user: req.user, type: "product", post_url: req.query.newpost })
  }
})

app.get('/ny/:type', function (req, res) {
  res.render('post/'+req.params.type, { type: req.params.type })
})

app.post('/submit', urlencodedParser, function (req, res) { // Controller for handling page inputs.
                                                            // ## TODO ######################################################
                                                            // # Add error handling, check and sanitize inputs              #
                                                            // # Improve this code and make it smaller + more simple,       #
                                                            // # Not having to if clause every type would be nice           #
                                                            // # Add support for multiple sources, ingredients, steps et.c. #
                                                            // ##############################################################
  var type = req.body.type

    if(req.body.hidden) {
      var hidden = true
    } else {
      var hidden = false
    }

    var niceurl = getSlug(req.body.title, {
      // URL Settings
      separator: '-',
      maintainCase: false,
      symbols: false
    })

  if(type == 1) {
    var title = req.body.title
    var content = req.body.content
    var source = req.body.source
    var query = db.get('pages')
    query.insert({title: title, url:niceurl, post:{ content: content, cover_image: "https://unsplash.it/200/300/?random", sources:{ 1:source }, type: type }, "user_info":{ "id": req.user._id, hidden: hidden }}, function(err, doc) {
      if(err) throw err
    })
  } else if(type == 2) {
    var title = req.body.title
    var content = req.body.content
    var ingredient = req.body.ingredient
    var step = req.body.step
    var query = db.get('pages')
    query.insert({title: title, url:niceurl, post:{ content: content, ingredients:{ 1:ingredient }, steps:{ 1:step }, type:type }, "user_info":{ "id":req.user._id, hidden: hidden } }, function(err, doc) {
      if(err) throw err
    })
  } else if(type == 3) {
    var title = req.body.title
    var content = req.body.content //
    var adress = req.body.adress
    var city = req.body.city
    var sources = req.body.sources // & Type
    var query = db.get('pages')
    query.insert({title: title, url:niceurl, post:{ content: content, city: city, adress: adress, opentimes:{ mon:req.body.opentimes_mon, tue:req.body.opentimes_tue, wed:req.body.opentimes_wed, thu:req.body.opentimes_thu, fri:req.body.opentimes_fri, sat:req.body.opentimes_sat, sun:req.body.opentimes_sun }, sources:{ 1:sources }, type:type },"user_info":{ "id":req.user._id, hidden: hidden }}, function(err, doc) {
      if(err) throw err
    })
  } else if(type == 4) {
    var title = req.body.title
    var content = req.body.content
    var source = req.body.source
    var query = db.get('pages')
    query.insert({title: title, url:niceurl, post:{ content: content, sources:{ 1:source }, type:type }, "user_info":{ "id": req.user._id, hidden:hidden }}, function(err, doc) {
      if(err) throw err
    })
  } else {
    res.redirect('/ny')
  }
    res.redirect('/ny/publicerad/?newpost='+niceurl)
})

app.get('/:url', function (req, res) {
  var url = req.params.url
  var post = db.get('pages')
  post.find({ url : url }, function(err, result) {
    users.find({ _id : result[0].user_info.id }, function(err, user_info) {
      res.render('page', { user: req.user, post: result[0], user_info: user_info[0] })
    })
  })
})

// TODO 'uncaughtException' as well? See what happens if DB goes down etc
app.use(function error_handler (error, req, res, next) {
  // TODO better error page
  console.error(error.stack)
  res.status(500)
  res.send('An error occured!')
})

app.listen(process.env.PORT || config.port, config.address)<commit_msg>Fix merge issue created by @perloov<commit_after>if (process.env.NODE_ENV !== 'development') {
  process.env.NODE_ENV = 'production'
}

var passport = require('passport')
var facebook_strategy = require('passport-facebook').Strategy

var express = require('express')
var session = require('express-session')
var session_store = require('connect-mongo')(session)
var cookie_parser = require('cookie-parser')
var body_parser = require('body-parser')
var consolidate = require('consolidate')
var getSlug = require('speakingurl')

var util = require('util')

var config = require('./config')

var db = require('monk')(config.database.host + config.database.name)
var users = db.get('users')
var urlencodedParser = body_parser.urlencoded({ extended: false })

// TODO Move this out using cluster to a separate file, add more files for routes etc!
// TODO Index auth.facebook etc
// TODO set callback URLs etc in Facebook dev console
// TODO Set enableProof: true
// TODO Set fallback photo to actual link
// TODO Reauthenticate etc?
passport.use(new facebook_strategy({
    clientID: config.facebook.app_id,
    clientSecret: config.facebook.app_secret,
    callbackURL: config.facebook.callback,
    profileFields: ['id', 'name', 'displayName', 'picture.type(large)']
  },

  function (access_token, refresh_token, profile, done) {
    users.findAndModify({
      auth: {
        facebook: profile.id
      }
    }, {
      $setOnInsert: {
        auth: {
          facebook: profile.id
        },

        name: {
          display_name: profile.displayName,
          first: profile.name.givenName
        },

        photo: profile.photos ? profile.photos[0].value : '/unknown_user.png'
      }
    }, {
      new: true,
      upsert: true
    }, function (error, result) {
      done(error, {
        id: result._id,
        display_name: result.display_name,
        photo: result.photo
      })
    })
  }
))

var app = express()

// TODO Replace this with streaming json parser
app.engine('html', consolidate.ejs)
app.set('view engine', 'html')
app.set('views', __dirname + '/views')
app.use(body_parser.json())

app.use(cookie_parser())
// TODO re-use db connection
// TODO resave/saveUnitialized
// TODO heighten cookie max time?
// TODO set secure: true later when redirecting for https etc!
// TODO use redis store?
app.use(session({
  secret: config.session_secret,
  resave: false,
  saveUninitialized: false,
  store: new session_store({
    url: config.database.host + config.database.name
  }),
  cookie: {
    maxAge: 60*60*1000,
    secure: false
  }
}))

app.use(passport.initialize())
app.use(passport.session())

if (process.env.NODE_ENV === 'development') {
  app.use(express.static(__dirname + '/public'))
}

passport.serializeUser(function (user, done) {
  done(null, user.id)
})

// TODO error handling etc
passport.deserializeUser(function (id, done) {
  users.findById(id, ['_id', 'name', 'photo', 'info'], function (error, result) {
    done(error, result)
  })
})

// TODO dynamically generate routes?

// TODO cache views etc, NODE_ENV === production?

// TODO make one default template instead of the same includes in every?
app.get('/', function (req, res) {
  var pagesdb = db.get('pages')
  if(typeof req.query.s !== 'undefined') {
    var query = {
      title: {
        $regex: req.query.s,
        $options: 'i' //i: ignore case, m: multiline, etc
      }
    }
    pagesdb.find(query, {}, function(err, doc) {
      res.render('index', { user: req.user, pages: doc, showsearch: true })
    })
  } else {
    pagesdb.find({}, function(err, doc) {
      res.render('index', { user: req.user, pages: doc, showsearch: false })
    })
  }
})

app.get('/test/view', function (req, res) {
  var testing = db.get('pages')
  testing.find({}, function(err, doc) {
    res.json(doc)
  })
})

app.get('/test/users', function (req, res) {
  var users = db.get('users')
  users.find({}, function(err, doc) {
    res.json(doc)
  })
})

app.get('/logga-in', function (req, res) {

  // TODO make this a middleware or something
  if (req.isAuthenticated()) {
    // TODO get latest page we were on or something instead
    return res.redirect('/')
  }

  res.render('login', { })
})

app.get('/om', function(req, res) {
  res.render('about', { user: req.user });
})

app.get('/annonsera', function (req, res) {
  res.render('advertise', { user: req.user });
})

app.get('/riktlinjer', function (req, res) {
  res.render('guidelines', { user: req.user, hidelink: true })
});

app.get('/vanliga-fragor', function (req, res) {
  res.render('faq', { user: req.user })
});

app.get('/auth/facebook', passport.authenticate('facebook'), function(req, res) {})

// TODO manually handle failure?
// TODO redirect to /konto?
app.get('/auth/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/login' }), function (req, res) {
  // TODO get the page we were on when we got sent to auth instead!
  res.redirect('/')
})

app.get('/logga-ut', function (req, res) {
  req.logout()
  res.redirect('/')
})

app.use(function ensure_authenticated (req, res, next) {
  if (req.isAuthenticated()) {
    return next()
  }

  res.redirect('/logga-in')
})

app.get('/konto', function (req, res) {
  res.render('konto', { user: req.user })
})

app.get('/installningar', function (req, res) {
  res.render('settings', { user: req.user })
})

app.post('/installningar/submit', urlencodedParser, function (req, res) {
  var id = req.user._id
  console.log(id)
  var display_name = req.body.displayName
  var website = req.body.website
  var description = req.body.description
  var users = db.get('users')
  console.log(display_name)
  users.update(
    { _id : id },
    { $set:
      { "name.display_name": display_name,
       "info.website":website,
       "info.description":description }
    }
  )
  res.send('1')
})

app.get('/mina-sidor', function (req, res) {
  var pages = db.get('pages')
  var userid = req.user.id
  pages.find({id:userid}, function(err, doc) {
    res.render('pages', { user: req.user, pages:doc })
  })
})

app.get('/ny', function (req, res) {
  res.render('new', { user: req.user })
})

app.get('/ny/publicerad', function (req, res) {
  if(typeof req.query.newpost === 'undefined') {
    res.render('post/published', { user: req.user, type: "product", hideredirect:true })
  } else {
    res.render('post/published', { user: req.user, type: "product", post_url: req.query.newpost })
  }
})

app.get('/ny/:type', function (req, res) {
  res.render('post/'+req.params.type, { type: req.params.type })
})

app.post('/submit', urlencodedParser, function (req, res) { // Controller for handling page inputs.
                                                            // ## TODO ######################################################
                                                            // # Add error handling, check and sanitize inputs              #
                                                            // # Improve this code and make it smaller + more simple,       #
                                                            // # Not having to if clause every type would be nice           #
                                                            // # Add support for multiple sources, ingredients, steps et.c. #
                                                            // ##############################################################
  var type = req.body.type

    if(req.body.hidden) {
      var hidden = true
    } else {
      var hidden = false
    }

    var niceurl = getSlug(req.body.title, {
      // URL Settings
      separator: '-',
      maintainCase: false,
      symbols: false
    })

  if(type == 1) {
    var title = req.body.title
    var content = req.body.content
    var source = req.body.source
    var query = db.get('pages')
    query.insert({title: title, url:niceurl, post:{ content: content, cover_image: "https://unsplash.it/200/300/?random", sources:{ 1:source }, type: type }, "user_info":{ "id": req.user._id, hidden: hidden }}, function(err, doc) {
      if(err) throw err
    })
  } else if(type == 2) {
    var title = req.body.title
    var content = req.body.content
    var ingredient = req.body.ingredient
    var step = req.body.step
    var query = db.get('pages')
    query.insert({title: title, url:niceurl, post:{ content: content, ingredients:{ 1:ingredient }, steps:{ 1:step }, type:type }, "user_info":{ "id":req.user._id, hidden: hidden } }, function(err, doc) {
      if(err) throw err
    })
  } else if(type == 3) {
    var title = req.body.title
    var content = req.body.content //
    var adress = req.body.adress
    var city = req.body.city
    var sources = req.body.sources // & Type
    var query = db.get('pages')
    query.insert({title: title, url:niceurl, post:{ content: content, city: city, adress: adress, opentimes:{ mon:req.body.opentimes_mon, tue:req.body.opentimes_tue, wed:req.body.opentimes_wed, thu:req.body.opentimes_thu, fri:req.body.opentimes_fri, sat:req.body.opentimes_sat, sun:req.body.opentimes_sun }, sources:{ 1:sources }, type:type },"user_info":{ "id":req.user._id, hidden: hidden }}, function(err, doc) {
      if(err) throw err
    })
  } else if(type == 4) {
    var title = req.body.title
    var content = req.body.content
    var source = req.body.source
    var query = db.get('pages')
    query.insert({title: title, url:niceurl, post:{ content: content, sources:{ 1:source }, type:type }, "user_info":{ "id": req.user._id, hidden:hidden }}, function(err, doc) {
      if(err) throw err
    })
  } else {
    res.redirect('/ny')
  }
    res.redirect('/ny/publicerad/?newpost='+niceurl)
})

app.get('/:url', function (req, res) { // test
  var url = req.params.url
  var post = db.get('pages')
  post.find({ url : url }, function(err, result) {
    users.find({ _id : result[0].user_info.id }, function(err, user_info) {
      res.render('page', { user: req.user, post: result[0], user_info: user_info[0] })
    })
  })
})

// TODO 'uncaughtException' as well? See what happens if DB goes down etc
app.use(function error_handler (error, req, res, next) {
  // TODO better error page
  console.error(error.stack)
  res.status(500)
  res.send('An error occured!')
})

app.listen(process.env.PORT || config.port, config.address)<|endoftext|>


<commit_before>'use strict';
const callsites = require('callsites');

module.exports = filepath => {
	const stacks = callsites();

	if (!filepath) {
		return stacks[2].getFileName();
	}

	let seenVal = false;

	// Skip the first stack as it's this function
	stacks.shift();

	for (const stack of stacks) {
		const parentFilepath = stack.getFileName();

		if (parentFilepath === filepath) {
			seenVal = true;
			continue;
		}

		// Skip native modules
		if (parentFilepath === 'module.js') {
			continue;
		}

		if (seenVal && parentFilepath !== filepath) {
			return parentFilepath;
		}
	}
};
<commit_msg>Ensure the filepath is a string<commit_after>'use strict';
const callsites = require('callsites');

module.exports = filepath => {
	const stacks = callsites();

	if (!filepath) {
		return stacks[2].getFileName();
	}

	let seenVal = false;

	// Skip the first stack as it's this function
	stacks.shift();

	for (const stack of stacks) {
		const parentFilepath = stack.getFileName();

		if (typeof parentFilepath !== 'string') {
			continue;
		}

		if (parentFilepath === filepath) {
			seenVal = true;
			continue;
		}

		// Skip native modules
		if (parentFilepath === 'module.js') {
			continue;
		}

		if (seenVal && parentFilepath !== filepath) {
			return parentFilepath;
		}
	}
};
<|endoftext|>


<commit_before>var dust
var fs = require('fs')
var Path = require('path')

try {
  dust = require('dustjs-linkedin')
  try { require('dustjs-helpers') }
  catch (ex) {}
}
catch (ex) {
  try { dust = require('dust') }
  catch (ex) {}
}

if (!dust) throw new Error('"dustjs-linkedin" or "dust" module not found')

module.exports = {
  module: {

    compile: function(template, options, callback) {

      var compiled = dust.compileFn(template, options && options.name)

      // process.nextTick(function() {

        callback(null, function(context, options, callback) {
          compiled(context, callback)
        })
      // })
    },

    registerPartial: function(name, data) {
      var compiled = dust.compileFn(data, name)
    },

    registerHelper: function(name, helper) {
      if (helper.length > 1)
        dust.helpers[name] = helper
      else
        dust.filters[name] = helper
    }

  },
  compileMode: 'async'
}
<commit_msg>clean up<commit_after>var dust
var fs = require('fs')
var Path = require('path')

try {
  dust = require('dustjs-linkedin')
  try { require('dustjs-helpers') }
  catch (ex) {}
}
catch (ex) {
  try { dust = require('dust') }
  catch (ex) {}
}

if (!dust) throw new Error('"dustjs-linkedin" or "dust" module not found')

module.exports = {
  module: {

    compile: function(template, options, callback) {

      var compiled = dust.compileFn(template, options && options.name)

      callback(null, function(context, options, callback) {
        compiled(context, callback)
      })
    },

    registerPartial: function(name, data) {
      dust.compileFn(data, name)
    },

    registerHelper: function(name, helper) {
      if (helper.length > 1)
        dust.helpers[name] = helper
      else
        dust.filters[name] = helper
    }

  },
  compileMode: 'async'
}
<|endoftext|>


<commit_before>/*jshint esversion:6, node:true*/
'use strict';

const BaseModel = require('./lib/BaseModel');

const extend = require('gextend');
const Promise = require('bluebird');
const Waterline = require('waterline');
const EventEmitter = require('events');

const fs = Promise.promisifyAll(require('fs'));

const join = require('path').join;
const resolve = require('path').resolve;
const basename = require('path').basename;

var DEFAULTS = {
    logger: console,
    autoinitialize: true,
    exportToGlobal: true,
    eventTypePrefix: 'persistence',
    timeout: 0.5 * 60 * 1000,// 30s timeout,
    modelsDir: process.cwd() + '/models',
    REGEXP_FILE: /[^\/\~]$/,
    orm: require('./lib/config')
};

class Persistence extends EventEmitter {
    constructor(config){
        super();
        this.name = 'persistence';

        config = extend({}, DEFAULTS, config);
        if(config.autoinitialize) this.init(config);
    }

    init(options){

        /*
         * Initialize all future BaseModel instances
         * with this Persistence intance as their
         * "persistence" attribute.
         */
        BaseModel.prototype.persistence = this;

        if(!options.dispatcher) options.dispatcher = this;

        extend(this, options);

        var ormConfig = options.orm;

        this._validateORMConfig(ormConfig);

        var ormTimeout = options.timeout;

        this.orm = new Waterline();

        this.orm.connect = function(config){
            config = extend({}, ormConfig, config);

            return new Promise((resolve, reject) => {
                var __timeout = setTimeout(function(){
                    reject(new Error('ORM time out'));
                }, ormTimeout);

                this.initialize(config, (err, orm)=> {
                    clearTimeout(__timeout);
                    if(err) reject(err);
                    else resolve(orm);
                });
            });
        };
    }

    _validateORMConfig(config){
        if(!config){
            this.logger.warn('Persistence did not get any ORM configuration options.');
        }

        if(!config.connections){
            this.logger.warn('Persistence did not get a connection configuration.');
            this.logger.warn('At the very least you need to define "%s".', BaseModel.prototype.connection);
            this.logger.warn('Did you forget?');

            throw new Error('Connection details not defined: ', BaseModel.connection);
        }
    }

    /*
     * Perform all async tasks needed to
     * bootstrap the engine.
     *
     * TODO: make recursive so we can load models
     *      from multiple directories.
     * TODO: posibly want to call loadDir multiple
     *       times before calling connect. One per
     *       module.
     */
    connect(){
        return this.loadDir(this.modelsDir).then((identities) => {
            this.logger.info('Persistence: connected. Identitites are: %j', identities);

            return this.orm.connect().then((orm) => {
                if(!orm) throw new Error('Error creating ORM instance...');
                if(!orm.connections) throw new Error('No connections created');
                if(!orm.collections) this.logger.warn('ORM initialized but without models...');

                this.connections = orm.connections;
                this.collections = orm.collections;

                this.export();

                // if(this.exportToGlobal) this.export(orm.collections);
                // else this.logger.warn('Skipping export of models...');

                this.emit('persistence.ready', orm);

                return orm;
            }).catch((err)=> {
                this.emit('persistence.error', err);
                return err;
            });
        }).catch((err)=> {
            this.logger.error('ERROR %s', err.message);
            return err;
        });
    }

    loadDir(dir){
        this.logger.log('Persistence: loading directory "%s".', dir);
        /*
         * does the dir exist
         */
        if(!this._dirExists(dir)){
            //TODO: How should we handle this?! this _will_ screw most things
            //unless is an optional path... which, maybe but not really.
            var err = new Error('Persistence: model dir "' + dir + '" not found.');
            this.logger.error(err.message);
            return Promise.reject(err);
        }

        let identities = [];
        return fs.readdirAsync(dir).each((file)=>{
            if(!this.REGEXP_FILE.test(file)) return;
            var p = resolve(join(dir, basename(file, '.js')));
            var m = require(p);
            var id = m.prototype.identity;
            identities.push(id);
            return this.loadModel(id, m);
        }).then(() => identities);
    }

    _dirExists(dir){
        try {
            fs.accessSync(dir);
        } catch (e) {
            return false;
        }

        return true;
    }

    /*
     * used by BaseModel instances to update on:
     * - create
     * - update
     * - delete
     */
    emitModelEvent(identity, action, record){

        //ie: persistence.user.update
        var etype = this.getEventType(identity, action);
        this.dispatcher.emit(etype, record);

        //ie: persistence.user.*
        etype = this.getEventType(identity, '*');
        this.dispatcher.emit(etype, record);

        //catch all event
        this.dispatcher.emit('persistence.*', {
            identity,
            action,
            record
        });
    }

    /*
     * Makes the event type for the
     * entity's event.
     * If we want to customize it
     * we should override it.
     */
    getEventType(identity, action){
        let type = identity + '.' + action;

        if(this.eventTypePrefix){
            type = this.eventTypePrefix + '.' + type;
        }

        return type;
    }

    loadModel(id, model){
        this.logger.info('Persistence: registering model %s', id);
        this.orm.loadCollection(model);
    }

    getModel(id) {
        var Model = this.collections[id];
        if(Model) return Promise.resolve(Model);
        return Promise.reject(new Error('No model found matching identity: ' + id));
    }

    export(collections, target=global){
        collections = collections || this.collections;

        if(!collections) {
            this.logger.warn('The module %s was unable to export models...', this.name);
            this.logger.warn('ORM returned empty collections');
            return;
        }

        this.logger.info('Exporting models to target...');

        Object.keys(collections).map((m) =>{
            var name = collections[m].exportName || capitalize(m);
            this.logger.info('Exporting model "%s" as "%s"', m, name);
            target[name] = collections[m];
        });
    }
}

function capitalize(str){
    str = str || '';
    return str.charAt(0).toUpperCase() + str.slice(1);
}

/*
 * Expose components
 */
module.exports = Persistence;
module.exports.BaseModel = BaseModel;
module.exports.capitalize = capitalize;
<commit_msg>module refactoring how we expose components<commit_after>/*jshint esversion:6, node:true*/
'use strict';

/*
 * Expose Persistence
 */
module.exports.Persistence = require('./lib/Persistence');

/*
 * Expose BaseModel.
 * Our models will extend this class.
 */
module.exports.BaseModel = require('./lib/BaseModel');

/*
 * Default initializer for the module.
 *
 * You can always override this and make
 * a custom initializer.
 */
module.exports.initializer = require('./lib/init');

module.exports.capitalize = require('./lib/capitalize');
<|endoftext|>


<commit_before>'use stricts';

/**
 * Project: DCrawler
 *
 * Build: 03/2015
 * Author: Van-Duyet Le <lvduit08@gmail.com>
 */

var Crawler = require('./lib/crawler');
var url = require('url');

var config = require('./config');

console.log('Startup system: ' + config.global.name);

var modulePath = require("path").join(__dirname, config.global.modulesDir);
require("fs").readdirSync(modulePath).forEach(function(f) {
	if (f.match(/^.+\.js$/g) !== null && config.global.ignoreModule.indexOf(f) == -1) {
		console.log('Loading module ' + f + '...')
		require('./' + config.global.modulesDir + '/' + f)(Crawler, config);
	}
});

console.log('Finish!');
process.exit(0);<commit_msg>Test: make change inside submodule<commit_after>'use stricts';

/**
 * Project: DCrawler
 *
 * Build: 03/2015
 * Author: Van-Duyet Le <lvduit08@gmail.com>
 */

var Crawler = require('./lib/crawler');
var url = require('url');

var config = require('./config');

console.log('Startup system: ' + config.global.name);

var modulePath = require("path").join(__dirname, config.global.modulesDir);
require("fs").readdirSync(modulePath).forEach(function(f) {
	if (f.match(/^.+\.js$/g) !== null && config.global.ignoreModule.indexOf(f) == -1) {
		console.log('Loading module ' + f + '...')
		require('./' + config.global.modulesDir + '/' + f)(Crawler, config);
	}
});

// console.log('Finish!');
// process.exit(0);<|endoftext|>


<commit_before>'use strict';
var osxBattery = require('osx-battery');

module.exports = function (cb) {
	if (process.platform !== 'darwin') {
		throw new Error('Only OS X systems are supported');
	}

	osxBattery(function (err, res) {
		if (err) {
			cb(err);
			return;
		}

	    cb(null, parseFloat((res.mAhRemaining / res.mAhCapacity).toFixed(4)));
	});
};
<commit_msg>Use tabs everywhere<commit_after>'use strict';
var osxBattery = require('osx-battery');

module.exports = function (cb) {
	if (process.platform !== 'darwin') {
		throw new Error('Only OS X systems are supported');
	}

	osxBattery(function (err, res) {
		if (err) {
			cb(err);
			return;
		}

		cb(null, parseFloat((res.mAhRemaining / res.mAhCapacity).toFixed(4)));
	});
};
<|endoftext|>


<commit_before>var module_ = require("module"), pth = require("path"), fs = require("fs")
var url_ = require("url")

var host = "localhost", port = 8080, dir = ".", transform = null

function usage() {
  console.log("Usage: moduleserve [--port port] [--host host] [--transform module] [dir]")
  process.exit(1)
}

for (var i = 2; i < process.argv.length; i++) {
  var arg = process.argv[i], next = process.argv[i + 1]
  if (arg == "--port" && next) { port = +next; i++ }
  else if (arg == "--host" && next) { host = next; i++ }
  else if (arg == "--transform" && next) { transform = next; i++ }
  else if (dir == "." && arg[0] != "-") dir = arg
  else usage()
}

var here = pth.resolve(dir)
if (here.charAt(here.length - 1) != "/") here += "/"

if (transform) {
  var transformMod = require(transform == "babel" ? "./babel-transform" : pth.resolve(transform))
  if (transformMod.init) transformMod.init(here)
  transform = transformMod.transform
}

var ecstatic = require("ecstatic")({root: here})
var client_js = fs.readFileSync(__dirname + "/client.js", "utf8")

var resolved = Object.create(null)

require("http").createServer(function(req, resp) {
  var url = url_.parse(req.url)
  var handle = /^\/moduleserve\/(?:load\.js$|mod\/(.*))/.exec(url.pathname)

  if (!handle) return ecstatic(req, resp)

  var send = function(status, text, headers) {
    var hds = {"access-control-allow-origin": "*"}
    if (!headers || typeof headers == "string")
      hds["content-type"] = headers || "text/plain"
    else
      for (var prop in headers) hds[prop] = headers[prop]
    resp.writeHead(status, hds)
    resp.end(text)
  }

  // matched /moduleserve/load.js
  if (!handle[1]) return send(200, client_js, "application/javascript")

  var path = undash(handle[1])
  var found = resolved[path]
  if (!found) {
    found = resolveModule(path)
    if (!found) return send(404, "Not found")
    resolved[path] = found
  }

  if (found != path) {
    if (!(found in resolved)) resolved[found] = found
    if (found != path + ".js")
      return send(301, null, {location: "/moduleserve/mod/" + dash(found)})
  } else if (/\.js$/.test(path)) {
    return send(301, null, {location: "/moduleserve/mod/" + dash(found.slice(0, found.length - 3))})
  }

  var cached = cache[found]
  if (cached) {
    var noneMatch = req.headers["if-none-match"]
    if (noneMatch && noneMatch.indexOf(cached.headers.etag) > -1) return send(304, null)
    else return send(200, cached.content, cached.headers)
  }

  return sendScript(found, send)

}).listen(port, host)

function undash(path) { return path.replace(/(^|\/)__(?=$|\/)/g, "$1..") }
function dash(path) { return path.replace(/(^|\/)\.\.(?=$|\/)/g, "$1__") }

function resolveModule(path) {
  var localPath = pth.resolve(here, path)
  var hasMod = localPath.indexOf("/__mod/"), parent, modPath, resolved
  if (hasMod > -1) {
    parent = localPath.slice(0, hasMod)
    modPath = localPath.slice(hasMod + 7)
  } else {
    parent = here
    modPath = localPath
  }

  var dummyMod = {
    id: parent,
    paths: module_._nodeModulePaths(parent).concat(module_.globalPaths)
  }
  try { resolved = module_._resolveFilename(modPath, dummyMod) }
  catch(e) { return null }

  // Handle builtin modules resolving to strings like "fs", try again
  // with slash which makes it possible to locally install an equivalent.
  if (resolved.indexOf("/") == -1) {
    try { resolved = module_._resolveFilename(modPath + "/", dummyMod) }
    catch(e) { return null }
  }

  return pth.relative(here, resolved)
}

var cache = Object.create(null), nextTag = 0

function Cached(file, content, headers) {
  this.file = file
  this.content = content
  this.headers = headers
}

function sendScript(path, send) {
  var content, localPath = pth.resolve(here, path)
  try { content = fs.readFileSync(localPath, "utf8") }
  catch(e) { return send(404, "Not found") }
  if (transform) content = transform(localPath, content)
  var headers = {
    "content-type": "application/javascript",
    "etag": '"' + (++nextTag) + '"'
  }
  cache[path] = new Cached(localPath, content, headers)
  var watching = fs.watch(localPath, function() {
    watching.close()
    cache[path] = null
  })
  return send(200, content, headers)
}
<commit_msg>A fix to make it work on Windows<commit_after>var module_ = require("module"), pth = require("path"), fs = require("fs")
var url_ = require("url")

function resolve() { return unwin(pth.resolve.apply(pth, arguments)) }
function relative() { return unwin(pth.relative.apply(pth, arguments)) }
function unwin(s) { return s.replace(/\\/g, '/') }

var host = "localhost", port = 8080, dir = ".", transform = null

function usage() {
  console.log("Usage: moduleserve [--port port] [--host host] [--transform module] [dir]")
  process.exit(1)
}

for (var i = 2; i < process.argv.length; i++) {
  var arg = process.argv[i], next = process.argv[i + 1]
  if (arg == "--port" && next) { port = +next; i++ }
  else if (arg == "--host" && next) { host = next; i++ }
  else if (arg == "--transform" && next) { transform = next; i++ }
  else if (dir == "." && arg[0] != "-") dir = arg
  else usage()
}

var here = resolve(dir)
if (here.charAt(here.length - 1) != "/") here += "/"

if (transform) {
  var transformMod = require(transform == "babel" ? "./babel-transform" : resolve(transform))
  if (transformMod.init) transformMod.init(here)
  transform = transformMod.transform
}

var ecstatic = require("ecstatic")({root: here})
var client_js = fs.readFileSync(__dirname + "/client.js", "utf8")

var resolved = Object.create(null)

require("http").createServer(function(req, resp) {
  var url = url_.parse(req.url)
  var handle = /^\/moduleserve\/(?:load\.js$|mod\/(.*))/.exec(url.pathname)

  if (!handle) return ecstatic(req, resp)

  var send = function(status, text, headers) {
    var hds = {"access-control-allow-origin": "*"}
    if (!headers || typeof headers == "string")
      hds["content-type"] = headers || "text/plain"
    else
      for (var prop in headers) hds[prop] = headers[prop]
    resp.writeHead(status, hds)
    resp.end(text)
  }

  // matched /moduleserve/load.js
  if (!handle[1]) return send(200, client_js, "application/javascript")

  var path = undash(handle[1])
  var found = resolved[path]
  if (!found) {
    found = resolveModule(path)
    if (!found) return send(404, "Not found")
    resolved[path] = found
  }

  if (found != path) {
    if (!(found in resolved)) resolved[found] = found
    if (found != path + ".js")
      return send(301, null, {location: "/moduleserve/mod/" + dash(found)})
  } else if (/\.js$/.test(path)) {
    return send(301, null, {location: "/moduleserve/mod/" + dash(found.slice(0, found.length - 3))})
  }

  var cached = cache[found]
  if (cached) {
    var noneMatch = req.headers["if-none-match"]
    if (noneMatch && noneMatch.indexOf(cached.headers.etag) > -1) return send(304, null)
    else return send(200, cached.content, cached.headers)
  }

  return sendScript(found, send)

}).listen(port, host)

function undash(path) { return path.replace(/(^|\/)__(?=$|\/)/g, "$1..") }
function dash(path) { return path.replace(/(^|\/)\.\.(?=$|\/)/g, "$1__") }

function resolveModule(path) {
  var localPath = resolve(here, path)
  var hasMod = localPath.indexOf("/__mod/"), parent, modPath, resolved
  if (hasMod > -1) {
    parent = localPath.slice(0, hasMod)
    modPath = localPath.slice(hasMod + 7)
  } else {
    parent = here
    modPath = localPath
  }

  var dummyMod = {
    id: parent,
    paths: module_._nodeModulePaths(parent).concat(module_.globalPaths)
  }
  try { resolved = unwin(module_._resolveFilename(modPath, dummyMod)) }
  catch(e) { return null }

  // Handle builtin modules resolving to strings like "fs", try again
  // with slash which makes it possible to locally install an equivalent.
  if (resolved.indexOf("/") == -1) {
    try { resolved = unwin(module_._resolveFilename(modPath + "/", dummyMod)) }
    catch(e) { return null }
  }

  return relative(here, resolved)
}

var cache = Object.create(null), nextTag = 0

function Cached(file, content, headers) {
  this.file = file
  this.content = content
  this.headers = headers
}

function sendScript(path, send) {
  var content, localPath = resolve(here, path)
  try { content = fs.readFileSync(localPath, "utf8") }
  catch(e) { return send(404, "Not found") }
  if (transform) content = transform(localPath, content)
  var headers = {
    "content-type": "application/javascript",
    "etag": '"' + (++nextTag) + '"'
  }
  cache[path] = new Cached(localPath, content, headers)
  var watching = fs.watch(localPath, function() {
    watching.close()
    cache[path] = null
  })
  return send(200, content, headers)
}
<|endoftext|>


<commit_before>'use strict'

const express = require('express')
const app = express()
const bodyParser = require('body-parser')
const twitterParse = require('twitter-url-parser')
const twitterAPI = require('node-twitter-api')
const twitter = new twitterAPI({
  consumerKey: process.env.TWITTER_CONSUMER_KEY,
  consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
  callback: process.env.TWITTER_OAUTH_CALLBACK || 'http://localhost:8080/oauth'
})

let sessionRequestToken
let sessionRequestTokenSecret
let sessionAccessToken
let sessionAccessTokenSecret

twitter.getRequestToken(function (error, requestToken, requestTokenSecret, results) {
  if (error) {
    console.log('Error getting OAuth request token : ' + error)
  } else {
    sessionRequestToken = requestToken
    sessionRequestTokenSecret = requestTokenSecret

    console.log(twitter.getAuthUrl(sessionRequestToken))
  }
})

app.use(bodyParser.json())

app.post('/', (req, res) => {
  twitter.search(
    { q: '"' + req.body.text + '"' },
    sessionAccessToken,
    sessionAccessTokenSecret,
    (err, data, response) => {
      if (data.statuses[0]) {
        twitter.statuses(
          'update',
          {
            status: 'ney ' + data.statuses[0].id_str
          },
          sessionAccessToken,
          sessionAccessTokenSecret,
          function (error, data, response) {
            if (error) {
              console.log(error)
            }
          }
        )
      }
    })
  res.end()
})

app.get('/oauth', (req, res) => {
  twitter.getAccessToken(
    sessionRequestToken,
    sessionRequestTokenSecret,
    req.query.oauth_verifier,
    (error, accessToken, accessTokenSecret, results) => {
      if (error) {
        console.log(error)
      } else {
        sessionAccessToken = accessToken
        sessionAccessTokenSecret = accessTokenSecret
        twitter.verifyCredentials(
          sessionAccessToken,
          sessionAccessTokenSecret,
          {},
          (error, data, response) => {
            if (error) {
              console.log(error)
            } else {
              console.log(data['screen_name'])
            }
          })
      }
    })

  res.end()
})

app.listen(process.env.PORT || 8080, () => console.log('listening ' + (process.env.PORT || 8080)))
<commit_msg>Try the second returned tweet<commit_after>'use strict'

const express = require('express')
const app = express()
const bodyParser = require('body-parser')
const twitterParse = require('twitter-url-parser')
const twitterAPI = require('node-twitter-api')
const twitter = new twitterAPI({
  consumerKey: process.env.TWITTER_CONSUMER_KEY,
  consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
  callback: process.env.TWITTER_OAUTH_CALLBACK || 'http://localhost:8080/oauth'
})

let sessionRequestToken
let sessionRequestTokenSecret
let sessionAccessToken
let sessionAccessTokenSecret

twitter.getRequestToken(function (error, requestToken, requestTokenSecret, results) {
  if (error) {
    console.log('Error getting OAuth request token : ' + error)
  } else {
    sessionRequestToken = requestToken
    sessionRequestTokenSecret = requestTokenSecret

    console.log(twitter.getAuthUrl(sessionRequestToken))
  }
})

app.use(bodyParser.json())

app.post('/', (req, res) => {
  twitter.search(
    {
      q: '"' + req.body.text + '"'
    },
    sessionAccessToken,
    sessionAccessTokenSecret,
    (err, data, response) => {
      if (data.statuses[1]) {
        twitter.statuses(
          'update',
          {
            status: 'ney ' + data.statuses[0].id_str
          },
          sessionAccessToken,
          sessionAccessTokenSecret,
          function (error, data, response) {
            if (error) {
              console.log(error)
            }
          }
        )
      }
    })
  res.end()
})

app.get('/oauth', (req, res) => {
  twitter.getAccessToken(
    sessionRequestToken,
    sessionRequestTokenSecret,
    req.query.oauth_verifier,
    (error, accessToken, accessTokenSecret, results) => {
      if (error) {
        console.log(error)
      } else {
        sessionAccessToken = accessToken
        sessionAccessTokenSecret = accessTokenSecret
        twitter.verifyCredentials(
          sessionAccessToken,
          sessionAccessTokenSecret,
          {},
          (error, data, response) => {
            if (error) {
              console.log(error)
            } else {
              console.log(data['screen_name'])
            }
          })
      }
    })

  res.end()
})

app.listen(process.env.PORT || 8080, () => console.log('listening ' + (process.env.PORT || 8080)))
<|endoftext|>


<commit_before>const crypto = require('crypto'),
  debug = require('debug'),
  minimatch = require('minimatch'),
  path = require('path');

const defaultOptions = {
  algo: 'sha1', // see crypto.getHashes() for options
  encoding: 'base64', // 'base64', 'hex' or 'binary'
  files: {
    exclude: [],
    include: [],
    matchBasename: true,
    matchPath: false,
    ignoreBasename: false,
    ignoreRootName: false,
  },
  folders: {
    exclude: [],
    include: [],
    matchBasename: true,
    matchPath: false,
    ignoreBasename: false,
    ignoreRootName: false,
  },
  symbolicLinks: {
    include: true,
    ignoreBasename: false,
    ignoreTargetPath: true,
    ignoreTargetContent: false,
    ignoreTargetContentAfterError: false,
  },
};

// Use the environment variable DEBUG to log output, e.g. `set DEBUG=fhash:*`
const log = {
  match: debug('fhash:match'),
  params: params => {
    debug('fhash:parameters')(params);
    return params;
  },
  err: debug('fhash:err'),
  symlink: debug('fhash:symlink'),
};

function prep(fs) {
  function hashElement(name, dir, options, callback) {
    callback = arguments[arguments.length - 1];

    return parseParameters(arguments)
      .then(({ basename, dir, options }) => {
        // this is only used for the root level
        options.skipMatching = true;
        return fs.promises
          .lstat(path.join(dir, basename))
          .then(stats => {
            stats.name = basename;
            return stats;
          })
          .then(stats => hashElementPromise(stats, dir, options, true));
      })
      .then(result => {
        if (isFunction(callback)) {
          return callback(undefined, result);
        } else {
          return result;
        }
      })
      .catch(reason => {
        log.err('Fatal error:', reason);
        if (isFunction(callback)) {
          return callback(reason);
        } else {
          throw reason;
        }
      });
  }

  /**
   * @param {fs.Stats} stats folder element, can also be of type fs.Dirent
   * @param {string} dirname
   * @param {Options} options
   * @param {boolean} isRootElement
   */
  function hashElementPromise(stats, dirname, options, isRootElement = false) {
    const name = stats.name;
    if (stats.isDirectory()) {
      return hashFolderPromise(name, dirname, options, isRootElement);
    } else if (stats.isFile()) {
      return hashFilePromise(name, dirname, options, isRootElement);
    } else if (stats.isSymbolicLink()) {
      return hashSymLinkPromise(name, dirname, options, isRootElement);
    } else {
      log.err('hashElementPromise cannot handle ', stats);
      return { name, hash: 'Error: unknown element type' };
    }
  }

  function hashFolderPromise(name, dir, options, isRootElement = false) {
    const folderPath = path.join(dir, name);
    let ignoreBasenameOnce = options.ignoreBasenameOnce;
    delete options.ignoreBasenameOnce;

    if (options.skipMatching) {
      // this is currently only used for the root folder
      log.match(`skipped '${folderPath}'`);
      delete options.skipMatching;
    } else if (ignore(name, folderPath, options.folders)) {
      return undefined;
    }

    return fs.promises.readdir(folderPath, { withFileTypes: true }).then(files => {
      const children = files.sort().map(child => {
        return hashElementPromise(child, folderPath, options);
      });

      return Promise.all(children).then(children => {
        if (ignoreBasenameOnce) options.ignoreBasenameOnce = true;
        const hash = new HashedFolder(name, children.filter(notUndefined), options, isRootElement);
        return hash;
      });
    });
  }

  function hashFilePromise(name, dir, options, isRootElement = false) {
    const filePath = path.join(dir, name);

    if (options.skipMatching) {
      // this is currently only used for the root folder
      log.match(`skipped '${filePath}'`);
      delete options.skipMatching;
    } else if (ignore(name, filePath, options.files)) {
      return undefined;
    }

    return new Promise((resolve, reject) => {
      try {
        const hash = crypto.createHash(options.algo);
        if (
          options.files.ignoreBasename ||
          options.ignoreBasenameOnce ||
          (isRootElement && options.files.ignoreRootName)
        ) {
          delete options.ignoreBasenameOnce;
          log.match(`omitted name of ${filePath} from hash`);
        } else {
          hash.update(name);
        }

        const f = fs.createReadStream(filePath);
        f.pipe(hash, { end: false });

        f.on('end', () => {
          const hashedFile = new HashedFile(name, hash, options.encoding);
          return resolve(hashedFile);
        });
      } catch (ex) {
        return reject(ex);
      }
    });
  }

  async function hashSymLinkPromise(name, dir, options, isRootElement = false) {
    const target = await fs.promises.readlink(path.join(dir, name));
    log.symlink(`handling symbolic link ${name} -> ${target}`);
    if (options.symbolicLinks.include) {
      if (options.symbolicLinks.ignoreTargetContent) {
        return symLinkIgnoreTargetContent(name, target, options, isRootElement);
      } else {
        return symLinkResolve(name, dir, target, options, isRootElement);
      }
    } else {
      log.symlink('skipping symbolic link');
      return Promise.resolve(undefined);
    }
  }

  function symLinkIgnoreTargetContent(name, target, options, isRootElement) {
    delete options.skipMatching; // only used for the root level
    log.symlink('ignoring symbolic link target content');
    const hash = crypto.createHash(options.algo);
    if (!options.symbolicLinks.ignoreBasename && !(isRootElement && options.files.ignoreRootName)) {
      log.symlink('hash basename');
      hash.update(name);
    }
    if (!options.symbolicLinks.ignoreTargetPath) {
      log.symlink('hash targetpath');
      hash.update(target);
    }
    return Promise.resolve(new HashedFile(name, hash, options.encoding));
  }

  async function symLinkResolve(name, dir, target, options, isRootElement) {
    delete options.skipMatching; // only used for the root level
    if (options.symbolicLinks.ignoreBasename) {
      options.ignoreBasenameOnce = true;
    }

    try {
      const stats = await fs.promises.stat(path.join(dir, name));
      stats.name = name;
      const temp = await hashElementPromise(stats, dir, options, isRootElement);

      if (!options.symbolicLinks.ignoreTargetPath) {
        const hash = crypto.createHash(options.algo);
        hash.update(temp.hash);
        log.symlink('hash targetpath');
        hash.update(target);
        temp.hash = hash.digest(options.encoding);
      }
      return temp;
    } catch (err) {
      if (options.symbolicLinks.ignoreTargetContentAfterError) {
        log.symlink(`Ignoring error "${err.code}" when hashing symbolic link ${name}`, err);
        const hash = crypto.createHash(options.algo);
        if (
          !options.symbolicLinks.ignoreBasename &&
          !(isRootElement && options.files.ignoreRootName)
        ) {
          hash.update(name);
        }
        if (!options.symbolicLinks.ignoreTargetPath) {
          hash.update(target);
        }
        return new HashedFile(name, hash, options.encoding);
      } else {
        log.symlink(`Error "${err.code}": When hashing symbolic link ${name}`, err);
        throw err;
      }
    }
  }

  function ignore(name, path, rules) {
    if (rules.exclude) {
      if (rules.matchBasename && rules.exclude(name)) {
        log.match(`exclude basename '${name}'`);
        return true;
      } else if (rules.matchPath && rules.exclude(path)) {
        log.match(`exclude path '${path}'`);
        return true;
      }
    }
    if (rules.include) {
      if (rules.matchBasename && rules.include(name)) {
        log.match(`include basename '${name}'`);
        return false;
      } else if (rules.matchPath && rules.include(path)) {
        log.match(`include path '${path}'`);
        return false;
      } else {
        log.match(`include rule failed for path '${path}'`);
        return true;
      }
    }

    log.match(`Will not ignore unmatched '${path}'`);
    return false;
  }

  return hashElement;
}

function parseParameters(args) {
  let basename = args[0],
    dir = args[1],
    options_ = args[2];

  if (!isString(basename)) {
    return Promise.reject(new TypeError('First argument must be a string'));
  }

  if (!isString(dir)) {
    dir = path.dirname(basename);
    basename = path.basename(basename);
    options_ = args[1];
  }

  // parse options (fallback default options)
  if (!isObject(options_)) options_ = {};
  const options = {
    algo: options_.algo || defaultOptions.algo,
    encoding: options_.encoding || defaultOptions.encoding,
    files: Object.assign({}, defaultOptions.files, options_.files),
    folders: Object.assign({}, defaultOptions.folders, options_.folders),
    match: Object.assign({}, defaultOptions.match, options_.match),
    symbolicLinks: Object.assign({}, defaultOptions.symbolicLinks, options_.symbolicLinks),
  };

  // transform match globs to Regex
  options.files.exclude = reduceGlobPatterns(options.files.exclude);
  options.files.include = reduceGlobPatterns(options.files.include);
  options.folders.exclude = reduceGlobPatterns(options.folders.exclude);
  options.folders.include = reduceGlobPatterns(options.folders.include);

  return Promise.resolve(log.params({ basename, dir, options }));
}

const HashedFolder = function HashedFolder(name, children, options, isRootElement = false) {
  this.name = name;
  this.children = children;

  const hash = crypto.createHash(options.algo);
  if (
    options.folders.ignoreBasename ||
    options.ignoreBasenameOnce ||
    (isRootElement && options.folders.ignoreRootName)
  ) {
    delete options.ignoreBasenameOnce;
    log.match(`omitted name of folder ${name} from hash`);
  } else {
    hash.update(name);
  }
  children.forEach(child => {
    if (child.hash) {
      hash.update(child.hash);
    }
  });

  this.hash = hash.digest(options.encoding);
};

HashedFolder.prototype.toString = function (padding = '') {
  const first = `${padding}{ name: '${this.name}', hash: '${this.hash}',\n`;
  padding += '  ';

  return `${first}${padding}children: ${this.childrenToString(padding)}}`;
};

HashedFolder.prototype.childrenToString = function (padding = '') {
  if (this.children.length === 0) {
    return '[]';
  } else {
    const nextPadding = padding + '  ';
    const children = this.children.map(child => child.toString(nextPadding)).join('\n');
    return `[\n${children}\n${padding}]`;
  }
};

const HashedFile = function HashedFile(name, hash, encoding) {
  this.name = name;
  this.hash = hash.digest(encoding);
};

HashedFile.prototype.toString = function (padding = '') {
  return padding + "{ name: '" + this.name + "', hash: '" + this.hash + "' }";
};

function isFunction(any) {
  return typeof any === 'function';
}

function isString(str) {
  return typeof str === 'string' || str instanceof String;
}

function isObject(obj) {
  return obj !== null && typeof obj === 'object';
}

function notUndefined(obj) {
  return typeof obj !== 'undefined';
}

function reduceGlobPatterns(globs) {
  if (isFunction(globs)) {
    return globs;
  } else if (!globs || !Array.isArray(globs) || globs.length === 0) {
    return undefined;
  } else {
    // combine globs into one single RegEx
    const regex = new RegExp(
      globs
        .reduce((acc, exclude) => {
          return acc + '|' + minimatch.makeRe(exclude).source;
        }, '')
        .substr(1),
    );
    return param => regex.test(param);
  }
}

module.exports = {
  defaults: defaultOptions,
  hashElement: prep(require('graceful-fs')),
  // exposed for testing
  prep,
  parseParameters,
};
<commit_msg>Fix sorting of files by name after b2c9fc6 broke it<commit_after>const crypto = require('crypto'),
  debug = require('debug'),
  minimatch = require('minimatch'),
  path = require('path');

const defaultOptions = {
  algo: 'sha1', // see crypto.getHashes() for options
  encoding: 'base64', // 'base64', 'hex' or 'binary'
  files: {
    exclude: [],
    include: [],
    matchBasename: true,
    matchPath: false,
    ignoreBasename: false,
    ignoreRootName: false,
  },
  folders: {
    exclude: [],
    include: [],
    matchBasename: true,
    matchPath: false,
    ignoreBasename: false,
    ignoreRootName: false,
  },
  symbolicLinks: {
    include: true,
    ignoreBasename: false,
    ignoreTargetPath: true,
    ignoreTargetContent: false,
    ignoreTargetContentAfterError: false,
  },
};

// Use the environment variable DEBUG to log output, e.g. `set DEBUG=fhash:*`
const log = {
  match: debug('fhash:match'),
  params: params => {
    debug('fhash:parameters')(params);
    return params;
  },
  err: debug('fhash:err'),
  symlink: debug('fhash:symlink'),
};

function prep(fs) {
  function hashElement(name, dir, options, callback) {
    callback = arguments[arguments.length - 1];

    return parseParameters(arguments)
      .then(({ basename, dir, options }) => {
        // this is only used for the root level
        options.skipMatching = true;
        return fs.promises
          .lstat(path.join(dir, basename))
          .then(stats => {
            stats.name = basename;
            return stats;
          })
          .then(stats => hashElementPromise(stats, dir, options, true));
      })
      .then(result => {
        if (isFunction(callback)) {
          return callback(undefined, result);
        } else {
          return result;
        }
      })
      .catch(reason => {
        log.err('Fatal error:', reason);
        if (isFunction(callback)) {
          return callback(reason);
        } else {
          throw reason;
        }
      });
  }

  /**
   * @param {fs.Stats} stats folder element, can also be of type fs.Dirent
   * @param {string} dirname
   * @param {Options} options
   * @param {boolean} isRootElement
   */
  function hashElementPromise(stats, dirname, options, isRootElement = false) {
    const name = stats.name;
    if (stats.isDirectory()) {
      return hashFolderPromise(name, dirname, options, isRootElement);
    } else if (stats.isFile()) {
      return hashFilePromise(name, dirname, options, isRootElement);
    } else if (stats.isSymbolicLink()) {
      return hashSymLinkPromise(name, dirname, options, isRootElement);
    } else {
      log.err('hashElementPromise cannot handle ', stats);
      return { name, hash: 'Error: unknown element type' };
    }
  }

  function hashFolderPromise(name, dir, options, isRootElement = false) {
    const folderPath = path.join(dir, name);
    let ignoreBasenameOnce = options.ignoreBasenameOnce;
    delete options.ignoreBasenameOnce;

    if (options.skipMatching) {
      // this is currently only used for the root folder
      log.match(`skipped '${folderPath}'`);
      delete options.skipMatching;
    } else if (ignore(name, folderPath, options.folders)) {
      return undefined;
    }

    return fs.promises.readdir(folderPath, { withFileTypes: true }).then(files => {
      const children = files
        .sort((a, b) => a.name.localeCompare(b.name))
        .map(child => {
          return hashElementPromise(child, folderPath, options);
        });

      return Promise.all(children).then(children => {
        if (ignoreBasenameOnce) options.ignoreBasenameOnce = true;
        const hash = new HashedFolder(name, children.filter(notUndefined), options, isRootElement);
        return hash;
      });
    });
  }

  function hashFilePromise(name, dir, options, isRootElement = false) {
    const filePath = path.join(dir, name);

    if (options.skipMatching) {
      // this is currently only used for the root folder
      log.match(`skipped '${filePath}'`);
      delete options.skipMatching;
    } else if (ignore(name, filePath, options.files)) {
      return undefined;
    }

    return new Promise((resolve, reject) => {
      try {
        const hash = crypto.createHash(options.algo);
        if (
          options.files.ignoreBasename ||
          options.ignoreBasenameOnce ||
          (isRootElement && options.files.ignoreRootName)
        ) {
          delete options.ignoreBasenameOnce;
          log.match(`omitted name of ${filePath} from hash`);
        } else {
          hash.update(name);
        }

        const f = fs.createReadStream(filePath);
        f.pipe(hash, { end: false });

        f.on('end', () => {
          const hashedFile = new HashedFile(name, hash, options.encoding);
          return resolve(hashedFile);
        });
      } catch (ex) {
        return reject(ex);
      }
    });
  }

  async function hashSymLinkPromise(name, dir, options, isRootElement = false) {
    const target = await fs.promises.readlink(path.join(dir, name));
    log.symlink(`handling symbolic link ${name} -> ${target}`);
    if (options.symbolicLinks.include) {
      if (options.symbolicLinks.ignoreTargetContent) {
        return symLinkIgnoreTargetContent(name, target, options, isRootElement);
      } else {
        return symLinkResolve(name, dir, target, options, isRootElement);
      }
    } else {
      log.symlink('skipping symbolic link');
      return Promise.resolve(undefined);
    }
  }

  function symLinkIgnoreTargetContent(name, target, options, isRootElement) {
    delete options.skipMatching; // only used for the root level
    log.symlink('ignoring symbolic link target content');
    const hash = crypto.createHash(options.algo);
    if (!options.symbolicLinks.ignoreBasename && !(isRootElement && options.files.ignoreRootName)) {
      log.symlink('hash basename');
      hash.update(name);
    }
    if (!options.symbolicLinks.ignoreTargetPath) {
      log.symlink('hash targetpath');
      hash.update(target);
    }
    return Promise.resolve(new HashedFile(name, hash, options.encoding));
  }

  async function symLinkResolve(name, dir, target, options, isRootElement) {
    delete options.skipMatching; // only used for the root level
    if (options.symbolicLinks.ignoreBasename) {
      options.ignoreBasenameOnce = true;
    }

    try {
      const stats = await fs.promises.stat(path.join(dir, name));
      stats.name = name;
      const temp = await hashElementPromise(stats, dir, options, isRootElement);

      if (!options.symbolicLinks.ignoreTargetPath) {
        const hash = crypto.createHash(options.algo);
        hash.update(temp.hash);
        log.symlink('hash targetpath');
        hash.update(target);
        temp.hash = hash.digest(options.encoding);
      }
      return temp;
    } catch (err) {
      if (options.symbolicLinks.ignoreTargetContentAfterError) {
        log.symlink(`Ignoring error "${err.code}" when hashing symbolic link ${name}`, err);
        const hash = crypto.createHash(options.algo);
        if (
          !options.symbolicLinks.ignoreBasename &&
          !(isRootElement && options.files.ignoreRootName)
        ) {
          hash.update(name);
        }
        if (!options.symbolicLinks.ignoreTargetPath) {
          hash.update(target);
        }
        return new HashedFile(name, hash, options.encoding);
      } else {
        log.symlink(`Error "${err.code}": When hashing symbolic link ${name}`, err);
        throw err;
      }
    }
  }

  function ignore(name, path, rules) {
    if (rules.exclude) {
      if (rules.matchBasename && rules.exclude(name)) {
        log.match(`exclude basename '${name}'`);
        return true;
      } else if (rules.matchPath && rules.exclude(path)) {
        log.match(`exclude path '${path}'`);
        return true;
      }
    }
    if (rules.include) {
      if (rules.matchBasename && rules.include(name)) {
        log.match(`include basename '${name}'`);
        return false;
      } else if (rules.matchPath && rules.include(path)) {
        log.match(`include path '${path}'`);
        return false;
      } else {
        log.match(`include rule failed for path '${path}'`);
        return true;
      }
    }

    log.match(`Will not ignore unmatched '${path}'`);
    return false;
  }

  return hashElement;
}

function parseParameters(args) {
  let basename = args[0],
    dir = args[1],
    options_ = args[2];

  if (!isString(basename)) {
    return Promise.reject(new TypeError('First argument must be a string'));
  }

  if (!isString(dir)) {
    dir = path.dirname(basename);
    basename = path.basename(basename);
    options_ = args[1];
  }

  // parse options (fallback default options)
  if (!isObject(options_)) options_ = {};
  const options = {
    algo: options_.algo || defaultOptions.algo,
    encoding: options_.encoding || defaultOptions.encoding,
    files: Object.assign({}, defaultOptions.files, options_.files),
    folders: Object.assign({}, defaultOptions.folders, options_.folders),
    match: Object.assign({}, defaultOptions.match, options_.match),
    symbolicLinks: Object.assign({}, defaultOptions.symbolicLinks, options_.symbolicLinks),
  };

  // transform match globs to Regex
  options.files.exclude = reduceGlobPatterns(options.files.exclude);
  options.files.include = reduceGlobPatterns(options.files.include);
  options.folders.exclude = reduceGlobPatterns(options.folders.exclude);
  options.folders.include = reduceGlobPatterns(options.folders.include);

  return Promise.resolve(log.params({ basename, dir, options }));
}

const HashedFolder = function HashedFolder(name, children, options, isRootElement = false) {
  this.name = name;
  this.children = children;

  const hash = crypto.createHash(options.algo);
  if (
    options.folders.ignoreBasename ||
    options.ignoreBasenameOnce ||
    (isRootElement && options.folders.ignoreRootName)
  ) {
    delete options.ignoreBasenameOnce;
    log.match(`omitted name of folder ${name} from hash`);
  } else {
    hash.update(name);
  }
  children.forEach(child => {
    if (child.hash) {
      hash.update(child.hash);
    }
  });

  this.hash = hash.digest(options.encoding);
};

HashedFolder.prototype.toString = function (padding = '') {
  const first = `${padding}{ name: '${this.name}', hash: '${this.hash}',\n`;
  padding += '  ';

  return `${first}${padding}children: ${this.childrenToString(padding)}}`;
};

HashedFolder.prototype.childrenToString = function (padding = '') {
  if (this.children.length === 0) {
    return '[]';
  } else {
    const nextPadding = padding + '  ';
    const children = this.children.map(child => child.toString(nextPadding)).join('\n');
    return `[\n${children}\n${padding}]`;
  }
};

const HashedFile = function HashedFile(name, hash, encoding) {
  this.name = name;
  this.hash = hash.digest(encoding);
};

HashedFile.prototype.toString = function (padding = '') {
  return padding + "{ name: '" + this.name + "', hash: '" + this.hash + "' }";
};

function isFunction(any) {
  return typeof any === 'function';
}

function isString(str) {
  return typeof str === 'string' || str instanceof String;
}

function isObject(obj) {
  return obj !== null && typeof obj === 'object';
}

function notUndefined(obj) {
  return typeof obj !== 'undefined';
}

function reduceGlobPatterns(globs) {
  if (isFunction(globs)) {
    return globs;
  } else if (!globs || !Array.isArray(globs) || globs.length === 0) {
    return undefined;
  } else {
    // combine globs into one single RegEx
    const regex = new RegExp(
      globs
        .reduce((acc, exclude) => {
          return acc + '|' + minimatch.makeRe(exclude).source;
        }, '')
        .substr(1),
    );
    return param => regex.test(param);
  }
}

module.exports = {
  defaults: defaultOptions,
  hashElement: prep(require('graceful-fs')),
  // exposed for testing
  prep,
  parseParameters,
};
<|endoftext|>


<commit_before>const queued = {};

function callQueued() {
  const keys = Object.keys(queued);
  for (let i = 0; i < keys.length; i++) {
    const id = keys[i];
    if (queued[id]) {
      queued[id]();
      queued[id] = null;
    }
  }

  window.requestAnimationFrame(callQueued);
}

callQueued();

function queue(cb, id) {
  if (typeof cb === 'function') {
    queued[id] = cb;
  }
}

function cancel(id) {
  if (queued[id]) {
    queued[id] = null;
  }
}

export default { queue, cancel };
<commit_msg>refactor: export functions instead of object<commit_after>const queued = {};

function callQueued() {
  const keys = Object.keys(queued);
  for (let i = 0; i < keys.length; i++) {
    const id = keys[i];
    if (queued[id]) {
      queued[id]();
      queued[id] = null;
    }
  }

  window.requestAnimationFrame(callQueued);
}

callQueued();

export function queue(cb, id) {
  if (typeof cb === 'function') {
    queued[id] = cb;
  }
}

export function cancel(id) {
  if (queued[id]) {
    queued[id] = null;
  }
}
<|endoftext|>