<commit_before>'use strict'

// setup
const http = require('http')
const Pg = require('pg').Pool
const jsonwebtoken = require('jsonwebtoken')
const tinyParams = require('tiny-params')
const port = process.env.PORT || process.env.port || 8091
const handlers = {
  search: (name, req) => findAll(name, req.params),
  create: (name, req) => create(name, req.params),
  read: (name, req) => find(name, req.id, req.params),
  update: (name, req) => save(name, req.id, req.params),
  delete: (name, req) => destroy(name, req.id, req.params)
}
const scrud = {
  GET: 'search',
  'GET?': 'search',
  POST: 'create',
  'POST/': 'create',
  'GET/': 'read',
  'PUT/': 'update',
  'DELETE/': 'delete'
}
const hasBody = {create: true, update: true}
const wlSign = [
  'algorithm',
  'expiresIn',
  'notBefore',
  'audience',
  'issuer',
  'jwtid',
  'subject',
  'noTimestamp',
  'header'
]

// globals
let logger
let pgPool
let jwtOpts
let authTrans
let pgPrefix = ''
let base = ''
let baseRgx = new RegExp(`^/?${base}/`)
let maxBodyBytes = 1e6
let resources = {}

// local helpers
const logIt = (e) => typeof logger === 'function' ? logger(e) : console.log(e)

const cleanPath = (url) => {
  return decodeURIComponent(url).replace(baseRgx, '').replace(/\/$/, '')
}

const parseId = (url) => {
  let id = (url.match(/\/(.+?)(\/|\?|$)/) || [])[1]
  return (id || '').match(/^\d+$/) ? parseInt(id, 10) : id || null
}

const callPgFunc = (name, params) => {
  let q = `SELECT * FROM ${name}($1);`
  if (!pgPool) return Promise.reject(new Error('no database configured'))
  return new Promise((resolve, reject) => {
    pgPool.connect((err, client, done) => {
      if (err) return reject(err)
      client.query(q, [params], (err, result) => {
        done(err)
        if (err) return reject(err)
        resolve((result.rows[0] || {})[name] ? result.rows[0][name] : [])
      })
    })
  })
}

const bodyParse = (req) => new Promise((resolve, reject) => {
  let body = ''
  req.on('data', (d) => {
    body += d.toString()
    if (body.length > maxBodyBytes) return reject(new Error('body too large'))
  })
  req.on('end', () => resolve(body ? JSON.parse(body) : {}))
})

const noIdErr = () => JSON.stringify(new Error('no id passed'))

const filterObj = (obj, ary) => {
  let base = {}
  ary.forEach((o) => { base[o] = obj[o] })
  return base
}

// exports
module.exports = {
  register,
  start,
  sendData,
  sendErr,
  fourOhOne,
  fourOhFour,
  genToken,
  authenticate,
  find,
  findAll,
  create,
  save,
  destroy
}

// register resource
function register (name, opts = {}) {
  if (!name) return Promise.reject(new Error(`no name specified in register`))
  return new Promise((resolve, reject) => {
    let r = resources[name] = Object.assign(opts, {name})
    if (Array.isArray(r.skipAuth)) {
      let skippers = {}
      r.skipAuth.forEach((a) => { skippers[a] = true })
      r.skipAuth = skippers
    }
    return resolve(r)
  })
}

// start server
function start (opts = {}) {
  if (opts.namespace) pgPrefix = `${opts.namespace.toLowerCase()}_`
  if (opts.maxBodyBytes) maxBodyBytes = opts.maxBodyBytes
  if (opts.jsonwebtoken) jwtOpts = opts.jsonwebtoken
  if (opts.logger) logger = opts.logger
  if (opts.base) base = opts.base
  if (opts.authTrans) authTrans = opts.authTrans
  baseRgx = new RegExp(`^/?${base}/`)
  return new Promise((resolve, reject) => {
    let server = http.createServer(handleRequest)
    server.listen(opts.port || port)
    if (opts.postgres) pgPool = new Pg(opts.postgres)
    return resolve(server)
  })
}

// request handler
function handleRequest (req, res) {
  if (!baseRgx.test(req.url)) return fourOhFour(res)
  let url = cleanPath(req.url)
  let matches = url.match(/^\/?(.+?)(\/|\?|$)/) || []
  let resource = resources[matches[1] || '']
  let modifier = matches[2]
  let action = scrud[`${req.method}${modifier}`]
  if (!resource || !action) return fourOhFour(res)
  let name = resource.name
  res.setHeader('Content-Type', 'application/json')
  res.setHeader('SCRUD', `${name}:${action}`)
  req.id = parseId(url)
  req.params = tinyParams(url)
  let headers = req.headers || {}
  let connection = req.connection || {}
  req.params.ip = headers['x-forwarded-for'] || connection.remoteAddress
  req.once('error', (err) => sendErr(res, err))
  let handler = resource[action] || actionHandler
  let jwt = (headers.authorization || '').replace(/^Bearer\s/, '')
  let callHandler = () => {
    if (!hasBody[action]) return handler(req, res, name, action)
    return bodyParse(req).then((body) => {
      req.params = Object.assign(body, req.params)
      return handler(req, res, name, action)
    }).catch((e) => sendErr(res, e))
  }
  if (resource.skipAuth && resource.skipAuth[action]) return callHandler()
  authenticate(jwt).then((authData) => {
    req.auth = req.params.auth = authTrans ? authTrans(authData) : authData
    return callHandler()
  }).catch((err) => fourOhOne(res, err))
}

function sendData (res, data = null) {
  if (res.headersSent) {
    logIt(new Error(`can't send data after headers sent`), 'warn')
    return Promise.resolve()
  }
  return new Promise((resolve, reject) => {
    res.end(JSON.stringify({data, error: null}))
    return resolve()
  })
}

function sendErr (res, err, code = 500) {
  res.statusCode = code
  if (!err || res.headersSent) {
    logIt(err || new Error(`can't send error after headers sent`), 'warn')
    return Promise.resolve()
  }
  return new Promise((resolve, reject) => {
    logIt(err, 'fatal')
    err = err instanceof Error ? (err.message || err.name) : err.toString()
    res.end(JSON.stringify({data: null, error: err}))
    return resolve()
  })
}

function fourOhOne (res, err = new Error(`unable to auhenticate request`)) {
  return sendErr(res, err, 401)
}

function fourOhFour (res, err = new Error(`no match for requested route`)) {
  return sendErr(res, err, 404)
}

function genToken (payload = {}) {
  let key = jwtOpts.secret || jwtOpts.privateKey
  let noOpts = () => new Error('missing required jsonwebtoken opts')
  if (!jwtOpts || !key) return Promise.reject(noOpts())
  let opts = filterObj(jwtOpts, wlSign)
  return new Promise((resolve, reject) => {
    jsonwebtoken.sign(payload, key, opts, (err, token) => {
      return err ? reject(err) : resolve(token)
    })
  })
}

function authenticate (jwt) {
  let key = jwtOpts.secret || jwtOpts.publicKey
  if (!jwtOpts || !key) return Promise.resolve()
  return new Promise((resolve, reject) => {
    jsonwebtoken.verify(jwt, key, jwtOpts, (err, d = {}) => {
      return err ? reject(err) : resolve(d)
    })
  })
}

// helper: find resource
function find (resource, id, params) {
  if (!id && id !== 0) return Promise.reject(noIdErr())
  params.id_array = [id]
  let firstRecord = (d) => Promise.resolve(d[0])
  return callPgFunc(`${pgPrefix}${resource}_read`, params).then(firstRecord)
}

// helper: find set of resources
function findAll (resource, params) {
  Object.keys(params).forEach((k) => {
    if (!Array.isArray(params[k])) return
    params[`${k}_array`] = params[k]
    delete params[k]
  })
  return callPgFunc(`${pgPrefix}${resource}_search`, params)
}

// helper: create resource
function create (resource, params) {
  let firstRecord = (d) => Promise.resolve(d[0])
  return callPgFunc(`${pgPrefix}${resource}_create`, params).then(firstRecord)
}

// helper: update resource
function save (resource, id, params) {
  if (!id && id !== 0) return Promise.reject(noIdErr())
  params.id = id
  let firstRecord = (d) => Promise.resolve(d[0])
  return callPgFunc(`${pgPrefix}${resource}_update`, params).then(firstRecord)
}

// helper: delete resource
function destroy (resource, id, params) {
  if (!id && id !== 0) return Promise.reject(noIdErr())
  params.id = id
  return callPgFunc(`${pgPrefix}${resource}_delete`, params)
}

// default handler for all resource methods
function actionHandler (req, res, name, action) {
  let bq = resources[name].beforeQuery || {} // (req, res)
  if (typeof bq !== 'function') bq = bq[action]
  let bs = resources[name].beforeSend || {} // (req, res, data)
  if (typeof bs !== 'function') bs = bs[action]
  let act = () => handlers[action](name, req)
  let send = (d) => sendData(res, d)
  let finish = (d) => bs ? bs(req, res, d).then((d) => send(d)) : send(d)
  let run = () => bq ? bq(req, res).then(act).then(finish) : act().then(finish)
  return run().catch((e) => sendErr(res, e))
}
<commit_msg>Handle no error with headers not sent<commit_after>'use strict'

// setup
const http = require('http')
const Pg = require('pg').Pool
const jsonwebtoken = require('jsonwebtoken')
const tinyParams = require('tiny-params')
const port = process.env.PORT || process.env.port || 8091
const handlers = {
  search: (name, req) => findAll(name, req.params),
  create: (name, req) => create(name, req.params),
  read: (name, req) => find(name, req.id, req.params),
  update: (name, req) => save(name, req.id, req.params),
  delete: (name, req) => destroy(name, req.id, req.params)
}
const scrud = {
  GET: 'search',
  'GET?': 'search',
  POST: 'create',
  'POST/': 'create',
  'GET/': 'read',
  'PUT/': 'update',
  'DELETE/': 'delete'
}
const hasBody = {create: true, update: true}
const wlSign = [
  'algorithm',
  'expiresIn',
  'notBefore',
  'audience',
  'issuer',
  'jwtid',
  'subject',
  'noTimestamp',
  'header'
]

// globals
let logger
let pgPool
let jwtOpts
let authTrans
let pgPrefix = ''
let base = ''
let baseRgx = new RegExp(`^/?${base}/`)
let maxBodyBytes = 1e6
let resources = {}

// local helpers
const logIt = (e) => typeof logger === 'function' ? logger(e) : console.log(e)

const cleanPath = (url) => {
  return decodeURIComponent(url).replace(baseRgx, '').replace(/\/$/, '')
}

const parseId = (url) => {
  let id = (url.match(/\/(.+?)(\/|\?|$)/) || [])[1]
  return (id || '').match(/^\d+$/) ? parseInt(id, 10) : id || null
}

const callPgFunc = (name, params) => {
  let q = `SELECT * FROM ${name}($1);`
  if (!pgPool) return Promise.reject(new Error('no database configured'))
  return new Promise((resolve, reject) => {
    pgPool.connect((err, client, done) => {
      if (err) return reject(err)
      client.query(q, [params], (err, result) => {
        done(err)
        if (err) return reject(err)
        resolve((result.rows[0] || {})[name] ? result.rows[0][name] : [])
      })
    })
  })
}

const bodyParse = (req) => new Promise((resolve, reject) => {
  let body = ''
  req.on('data', (d) => {
    body += d.toString()
    if (body.length > maxBodyBytes) return reject(new Error('body too large'))
  })
  req.on('end', () => resolve(body ? JSON.parse(body) : {}))
})

const noIdErr = () => JSON.stringify(new Error('no id passed'))

const filterObj = (obj, ary) => {
  let base = {}
  ary.forEach((o) => { base[o] = obj[o] })
  return base
}

// exports
module.exports = {
  register,
  start,
  sendData,
  sendErr,
  fourOhOne,
  fourOhFour,
  genToken,
  authenticate,
  find,
  findAll,
  create,
  save,
  destroy
}

// register resource
function register (name, opts = {}) {
  if (!name) return Promise.reject(new Error(`no name specified in register`))
  return new Promise((resolve, reject) => {
    let r = resources[name] = Object.assign(opts, {name})
    if (Array.isArray(r.skipAuth)) {
      let skippers = {}
      r.skipAuth.forEach((a) => { skippers[a] = true })
      r.skipAuth = skippers
    }
    return resolve(r)
  })
}

// start server
function start (opts = {}) {
  if (opts.namespace) pgPrefix = `${opts.namespace.toLowerCase()}_`
  if (opts.maxBodyBytes) maxBodyBytes = opts.maxBodyBytes
  if (opts.jsonwebtoken) jwtOpts = opts.jsonwebtoken
  if (opts.logger) logger = opts.logger
  if (opts.base) base = opts.base
  if (opts.authTrans) authTrans = opts.authTrans
  baseRgx = new RegExp(`^/?${base}/`)
  return new Promise((resolve, reject) => {
    let server = http.createServer(handleRequest)
    server.listen(opts.port || port)
    if (opts.postgres) pgPool = new Pg(opts.postgres)
    return resolve(server)
  })
}

// request handler
function handleRequest (req, res) {
  if (!baseRgx.test(req.url)) return fourOhFour(res)
  let url = cleanPath(req.url)
  let matches = url.match(/^\/?(.+?)(\/|\?|$)/) || []
  let resource = resources[matches[1] || '']
  let modifier = matches[2]
  let action = scrud[`${req.method}${modifier}`]
  if (!resource || !action) return fourOhFour(res)
  let name = resource.name
  res.setHeader('Content-Type', 'application/json')
  res.setHeader('SCRUD', `${name}:${action}`)
  req.id = parseId(url)
  req.params = tinyParams(url)
  let headers = req.headers || {}
  let connection = req.connection || {}
  req.params.ip = headers['x-forwarded-for'] || connection.remoteAddress
  req.once('error', (err) => sendErr(res, err))
  let handler = resource[action] || actionHandler
  let jwt = (headers.authorization || '').replace(/^Bearer\s/, '')
  let callHandler = () => {
    if (!hasBody[action]) return handler(req, res, name, action)
    return bodyParse(req).then((body) => {
      req.params = Object.assign(body, req.params)
      return handler(req, res, name, action)
    }).catch((e) => sendErr(res, e))
  }
  if (resource.skipAuth && resource.skipAuth[action]) return callHandler()
  authenticate(jwt).then((authData) => {
    req.auth = req.params.auth = authTrans ? authTrans(authData) : authData
    return callHandler()
  }).catch((err) => fourOhOne(res, err))
}

function sendData (res, data = null) {
  if (res.headersSent) {
    logIt(new Error(`can't send data after headers sent`), 'warn')
    return Promise.resolve()
  }
  return new Promise((resolve, reject) => {
    res.end(JSON.stringify({data, error: null}))
    return resolve()
  })
}

function sendErr (res, err, code = 500) {
  res.statusCode = code
  if (res.headersSent) {
    logIt(err || new Error(`can't send error after headers sent`), 'warn')
    return Promise.resolve()
  }
  if (!err) {
    res.end(JSON.stringify({data: null, error: 'unspecified error'}))
    return Promise.resolve()
  }
  return new Promise((resolve, reject) => {
    logIt(err, 'fatal')
    err = err instanceof Error ? (err.message || err.name) : err.toString()
    res.end(JSON.stringify({data: null, error: err}))
    return resolve()
  })
}

function fourOhOne (res, err = new Error(`unable to auhenticate request`)) {
  return sendErr(res, err, 401)
}

function fourOhFour (res, err = new Error(`no match for requested route`)) {
  return sendErr(res, err, 404)
}

function genToken (payload = {}) {
  let key = jwtOpts.secret || jwtOpts.privateKey
  let noOpts = () => new Error('missing required jsonwebtoken opts')
  if (!jwtOpts || !key) return Promise.reject(noOpts())
  let opts = filterObj(jwtOpts, wlSign)
  return new Promise((resolve, reject) => {
    jsonwebtoken.sign(payload, key, opts, (err, token) => {
      return err ? reject(err) : resolve(token)
    })
  })
}

function authenticate (jwt) {
  let key = jwtOpts.secret || jwtOpts.publicKey
  if (!jwtOpts || !key) return Promise.resolve()
  return new Promise((resolve, reject) => {
    jsonwebtoken.verify(jwt, key, jwtOpts, (err, d = {}) => {
      return err ? reject(err) : resolve(d)
    })
  })
}

// helper: find resource
function find (resource, id, params) {
  if (!id && id !== 0) return Promise.reject(noIdErr())
  params.id_array = [id]
  let firstRecord = (d) => Promise.resolve(d[0])
  return callPgFunc(`${pgPrefix}${resource}_read`, params).then(firstRecord)
}

// helper: find set of resources
function findAll (resource, params) {
  Object.keys(params).forEach((k) => {
    if (!Array.isArray(params[k])) return
    params[`${k}_array`] = params[k]
    delete params[k]
  })
  return callPgFunc(`${pgPrefix}${resource}_search`, params)
}

// helper: create resource
function create (resource, params) {
  let firstRecord = (d) => Promise.resolve(d[0])
  return callPgFunc(`${pgPrefix}${resource}_create`, params).then(firstRecord)
}

// helper: update resource
function save (resource, id, params) {
  if (!id && id !== 0) return Promise.reject(noIdErr())
  params.id = id
  let firstRecord = (d) => Promise.resolve(d[0])
  return callPgFunc(`${pgPrefix}${resource}_update`, params).then(firstRecord)
}

// helper: delete resource
function destroy (resource, id, params) {
  if (!id && id !== 0) return Promise.reject(noIdErr())
  params.id = id
  return callPgFunc(`${pgPrefix}${resource}_delete`, params)
}

// default handler for all resource methods
function actionHandler (req, res, name, action) {
  let bq = resources[name].beforeQuery || {} // (req, res)
  if (typeof bq !== 'function') bq = bq[action]
  let bs = resources[name].beforeSend || {} // (req, res, data)
  if (typeof bs !== 'function') bs = bs[action]
  let act = () => handlers[action](name, req)
  let send = (d) => sendData(res, d)
  let finish = (d) => bs ? bs(req, res, d).then((d) => send(d)) : send(d)
  let run = () => bq ? bq(req, res).then(act).then(finish) : act().then(finish)
  return run().catch((e) => sendErr(res, e))
}
<|endoftext|>


<commit_before>/*global define*/
/*jslint white: true*/
define([
    'bluebird',
    'uuid',
    'kb_common_html',
    'kb_service_workspace',
    'kb_service_userAndJobState',
    'kb_dataview_easyTree',
    'kb_service_utils',
    'kb/widget/bases/dataWidget',
], function (Promise, uuid, html, Workspace, UserAndJobState, EasyTree, serviceUtils, DataWidget) {
    'use strict';

    function makeObjectRef(obj) {
        return serviceUtils.makeWorkspaceObjectRef(obj.workspaceId, obj.objectId, obj.objectVersion);
    }

    function factory(config) {
        var defaultWidth = 1045,
            defaultHeight = 600;
        return DataWidget.make({
            runtime: config.runtime,
            title: 'Tree Data View',
            on: {
                initialContent: function () {
                    return html.loading('Loading tree...');
                },
                fetch: function () {
                    var workspaceClient = new Workspace(this.runtime.getConfig('services.workspace.url'), {
                        token: this.runtime.service('session').getAuthToken()
                    }),
                        ujsClient = new UserAndJobState(this.runtime.getConfig('services.ujs.url'), {
                            token: this.runtime.service('session').getAuthToken()
                        }),
                        ref = makeObjectRef(this.get('params')),
                        // these thread through and are build in the data api calls.
                        treeObject,
                        refList = [],
                        refToInfoMap = {};

                    return workspaceClient.get_objects([{ref: ref}])
                        .then(function (data) {
                            if (data.length === 1) {
                                treeObject = data[0];
                                treeObject.objectInfo = serviceUtils.object_info_to_object(treeObject.info);
                                return treeObject;
                            } else {
                                throw new Error('Invalid results');
                            }
                        })
                        .then(function (data) {
                                var treeRef = makeObjectRef({
                                    workspaceId: data.objectInfo.wsid,
                                    objectId: data.objectInfo.id,
                                    objectVersion: data.objectInfo.version
                                }),
                                tree = data.data;
                            if (tree.ws_refs) {
                                refList = Object.keys(tree.ws_refs).map(function (key) {
                                    return {ref: tree.ws_refs[key].g[0]};
                                });
                            }
                            return workspaceClient.get_object_info_new({objects: refList});
                        })
                        .then(function (objectInfoList) {
                            var i;
                            for (i = 0; i < objectInfoList.length; i += 1) {
                                refToInfoMap[refList[i].ref] = objectInfoList[i];
                            }

                            this.set('data', {
                                tree: treeObject,
                                refList: refList,
                                refToInfoMap: refToInfoMap,
                            });
                        })
                },
                attach: function (container) {
                    var containerId = html.genId(),
                        canvasId = html.genId(),
                        div = html.tag('div'),
                        canvas = html.tag('canvas'),
                        layout = div({id: containerId}, [
                            canvas({id: canvasId, style: {maxHeight: (config.height || defaultHeight) - 85, overflow: 'scroll'}})
                        ]);
                    container.innerHTML = layout;
                },
                render: function () {
                    var data = this.get('data');
                    return 'Wow, I finally got all that!, e.g.: ' + data.tree.objectInfo.id;

                }
            }
        });
    }

    return {
        make: function (config) {
            return factory(config);
        }
    };
});<commit_msg>porting trees widget over<commit_after>/*global define*/
/*jslint white: true*/
define([
    'bluebird',
    'uuid',
    'kb_common_html',
    'kb_service_workspace',
    'kb_service_userAndJobState',
    'kb_dataview_easyTree',
    'kb_service_utils',
    'kb/widget/bases/dataWidget',
], function (Promise, uuid, html, Workspace, UserAndJobState, EasyTree, serviceUtils, DataWidget) {
    'use strict';

    function makeObjectRef(obj) {
        return serviceUtils.makeWorkspaceObjectRef(obj.workspaceId, obj.objectId, obj.objectVersion);
    }

    function factory(config) {
        var defaultWidth = 1045,
            defaultHeight = 600;
        return DataWidget.make({
            runtime: config.runtime,
            title: 'Tree Data View',
            on: {
                initialContent: function () {
                    return html.loading('Loading tree...');
                },
                fetch: function () {
                    var workspaceClient = new Workspace(this.runtime.getConfig('services.workspace.url'), {
                        token: this.runtime.service('session').getAuthToken()
                    }),
                        ujsClient = new UserAndJobState(this.runtime.getConfig('services.ujs.url'), {
                            token: this.runtime.service('session').getAuthToken()
                        }),
                        ref = makeObjectRef(this.get('params')),
                        // these thread through and are build in the data api calls.
                        treeObject,
                        refList = [],
                        refToInfoMap = {};

                    return workspaceClient.get_objects([{ref: ref}])
                        .then(function (data) {
                            if (data.length === 1) {
                                treeObject = data[0];
                                treeObject.objectInfo = serviceUtils.object_info_to_object(treeObject.info);
                                return treeObject;
                            } else {
                                throw new Error('Invalid results');
                            }
                        })
                        .then(function (data) {
                                var treeRef = makeObjectRef({
                                    workspaceId: data.objectInfo.wsid,
                                    objectId: data.objectInfo.id,
                                    objectVersion: data.objectInfo.version
                                }),
                                tree = data.data;
                            if (tree.ws_refs) {
                                refList = Object.keys(tree.ws_refs).map(function (key) {
                                    return {ref: tree.ws_refs[key].g[0]};
                                });
                            }
                            return workspaceClient.get_object_info_new({objects: refList});
                        })
                        .then(function (objectInfoList) {
                            var i;
                            for (i = 0; i < objectInfoList.length; i += 1) {
                                refToInfoMap[refList[i].ref] = objectInfoList[i];
                            }

                            this.set('data', {
                                tree: treeObject,
                                refList: refList,
                                refToInfoMap: refToInfoMap,
                            });
                        }.bind(this));
                },
                attach: function (container) {
                    var containerId = html.genId(),
                        canvasId = html.genId(),
                        div = html.tag('div'),
                        canvas = html.tag('canvas'),
                        layout = div({id: containerId}, [
                            canvas({id: canvasId, style: {maxHeight: (config.height || defaultHeight) - 85, overflow: 'scroll'}})
                        ]);
                    container.innerHTML = layout;
                },
                render: function () {
                    var data = this.get('data');
                    return 'Wow, I finally got all that!, e.g.: ' + data.tree.objectInfo.id;

                }
            }
        });
    }

    return {
        make: function (config) {
            return factory(config);
        }
    };
});<|endoftext|>


<commit_before>var yo = require('../../../lib/plugin/out/yo.js'),
    nock = require('nock');

describe('output plugin: yo', function(){
  it('should be Yo successful.', function(done){
    nock("http://api.justyo.co").post('/yoall/').reply(200);

    var args = {
      "api_token": "foobar"
    };

    yo.output(args, "test", function(err, output){
      err.should.be.false;
      done();
    });
  });

  it('should be Yo fail.', function(done){
    nock("http://api.justyo.co").post('/yoall/').reply(201);

    var args = {
      "api_token": "foobar"
    };

    yo.output(args, "test", function(err, output){
      err.should.be.true;
      done();
    });
  });

});
<commit_msg>Fix Yo-pluging test.<commit_after>var yo = require('../../../lib/plugin/out/yo.js'),
    nock = require('nock');

describe('output plugin: yo', function(){
  it('should be Yo successful.', function(done){
    nock("http://api.justyo.co").post('/yoall/').reply(200);

    var args = {
      "api_token": "foobar"
    };

    yo.output(args, "test", function(err, output){
      err.should.be.false;
      done();
    });
  });

  it('should be Yo fail.', function(done){
    nock("http://api.justyo.co").post('/yoall/').reply(400);

    var args = {
      "api_token": "foobar"
    };

    yo.output(args, "test", function(err, output){
      err.should.be.true;
      done();
    });
  });

});
<|endoftext|>


<commit_before>/*global describe, it, beforeEach */

var Router, config, should, express, _;

should = require('should');
Router = require('../../server/router');
express = require('express');
_ = require('underscore');

config = {
  paths: {
    entryPath: __dirname + "/../fixtures"
  }
};

function shouldMatchRoute(actual, expected) {
  actual.should.be.an.instanceOf(Array);
  actual.slice(0, 2).should.eql(expected);
  actual[2].should.be.an.instanceOf(Function);
}

describe("server/router", function() {

  beforeEach(function() {
    this.router = new Router(config);
  });

  describe("route", function() {
    it("should add basic route definitions", function() {
      var route;
      route = this.router.route("test", "test#index");
      shouldMatchRoute(route, [
        '/test', {
          controller: 'test',
          action: 'index'
        }
      ]);
    });

    it("should support leading slash in pattern", function() {
      var route;

      route = this.router.route("/test", "test#index");
      return shouldMatchRoute(route, [
        '/test', {
          controller: 'test',
          action: 'index'
        }
      ]);
    });

    it("should support object as second argument", function() {
      var route;

      route = this.router.route("/test", {
        controller: 'test',
        action: 'index',
        role: 'admin'
      });
      shouldMatchRoute(route, [
        '/test', {
          controller: 'test',
          action: 'index',
          role: 'admin'
        }
      ]);
    });

    it("should support string as second argument, object as third argument", function() {
      var route;

      route = this.router.route("/test", "test#index", {
        role: 'admin'
      });
      shouldMatchRoute(route, [
        '/test', {
          controller: 'test',
          action: 'index',
          role: 'admin'
        }
      ]);

    });
  });

  describe("routes", function() {
    it("should return the aggregated routes", function() {
      var routes;

      this.router.route("users/:id", "users#show");
      routes = this.router.routes();
      routes.length.should.eql(1);
      shouldMatchRoute(routes[0], [
        '/users/:id', {
          controller: 'users',
          action: 'show'
        }
      ]);
      this.router.route("users/login", "users#login");
      routes = this.router.routes();
      routes.length.should.eql(2);
      shouldMatchRoute(routes[0], [
        '/users/:id', {
          controller: 'users',
          action: 'show'
        }
      ]);
      shouldMatchRoute(routes[1], [
        '/users/login', {
          controller: 'users',
          action: 'login'
        }
      ]);
    });

    it("should return a copy of the routes, not a reference", function() {
      var routes;

      this.router.route("users/:id", "users#show");
      routes = this.router.routes();

      // Modify the routes array
      routes.push('foo');
      this.router.routes().length.should.eql(1);

      // Also modify an individual route element
      this.router.routes()[0].length.should.eql(3);
      this.router.routes()[0].shift();
      this.router.routes()[0].length.should.eql(3);
    });

    it("should not throw error without routes", function() {
      this.router.routes().length.should.eql(0);
    });
  });

  describe("buildRoutes", function() {
    it("should build route definitions based on routes file", function() {
      var routes;

      this.router.buildRoutes();
      routes = this.router.routes();
      routes.length.should.eql(3);
      shouldMatchRoute(routes[0], [
        '/users/login', {
          controller: 'users',
          action: 'login'
        }
      ]);
      shouldMatchRoute(routes[1], [
        '/users/:id', {
          controller: 'users',
          action: 'show'
        }
      ]);
      shouldMatchRoute(routes[2], [
        '/test', {
          controller: 'test',
          action: 'index'
        }
      ]);
    });
  });

  describe("match", function() {
    it("should return the route info for a matched path, no leading slash", function() {
      var route;

      this.router.route("/users/:id", "users#show");
      route = this.router.match('users/1234');
      shouldMatchRoute(route, [
        '/users/:id', {
          controller: 'users',
          action: 'show'
        }
      ]);
    });

    it("should return the route info for a matched path, with leading slash", function() {
      var route;

      this.router.route("/users/:id", "users#show");
      route = this.router.match('/users/1234');
      shouldMatchRoute(route, [
        '/users/:id', {
          controller: 'users',
          action: 'show'
        }
      ]);
    });

    it.skip("should return the route info for a matched full URL", function() {
      var route;

      this.router.route("/users/:id", "users#show");
      route = this.router.match('https://www.example.org/users/1234');
      shouldMatchRoute(route, [
        '/users/:id', {
          controller: 'users',
          action: 'show'
        }
      ]);
    });

    it("should return null if no match", function() {
      should.not.exist(this.router.match('abcd1234xyz'));
    });

    it("should match in the right order", function() {
      var route;

      this.router.route("/users/login", "users#login");
      this.router.route("/users/:id", "users#show");
      route = this.router.match('users/thisisaparam');
      shouldMatchRoute(route, [
        '/users/:id', {
          controller: 'users',
          action: 'show'
        }
      ]);
      route = this.router.match('users/login');
      shouldMatchRoute(route, [
        '/users/login', {
          controller: 'users',
          action: 'login'
        }
      ]);
    });
  });

  describe("getParams", function() {
    beforeEach(function() {
      this.req = express.request;

      resetProperties(this.req, {
        query: {},
        route: {keys: [], params: {}}
      });
      this.router.getParams(this.req).should.eql({});
    });

    it("should return basic query params", function() {
      this.req.__defineGetter__('query', function() {
        return {foo: 'bar', bam: 'baz'};
      });
      this.router.getParams(this.req).should.eql({foo: 'bar', bam: 'baz'});
    });

    it("should support route params", function() {
      this.req.__defineGetter__('route', function() {
        return {
          keys: [{name: 'id'}, {name: 'login'}],
        };
      });
      this.req.__defineGetter__('params', function() {
        return {
          id: 'id-value',
          login: 'login-value'
        }
      });
      this.router.getParams(this.req).should.eql({
        id: 'id-value',
        login: 'login-value'
      });
    });

    it("should support both together", function() {
      this.req.__defineGetter__('query', function() {
        return {foo: 'bar', bam: 'baz'};
      });

      this.req.__defineGetter__('route', function() {
        return {
          keys: [{name: 'id'}, {name: 'login'}],
        };
      });
      this.req.__defineGetter__('params', function() {
        return {
          id: 'id-value',
          login: 'login-value'
        }
      });

      this.router.getParams(this.req).should.eql({
        foo: 'bar',
        bam: 'baz',
        id: 'id-value',
        login: 'login-value'
      });
    });

    it("should XSS sanitize params", function() {
      this.req.__defineGetter__('query', function() {
        return {foo: '<script>alert("foo")</script>'};
      });

      this.router.getParams(this.req).should.eql({
        foo: '[removed]alert("foo")[removed]'
      });
    });
  });
});

function resetProperties(obj, properties) {
  _.each(properties, function(value, key) {
    obj.__defineGetter__(key, function() {
      return value;
    });
  });
}
<commit_msg>Removing pending test for feature that was removed<commit_after>/*global describe, it, beforeEach */

var Router, config, should, express, _;

should = require('should');
Router = require('../../server/router');
express = require('express');
_ = require('underscore');

config = {
  paths: {
    entryPath: __dirname + "/../fixtures"
  }
};

function shouldMatchRoute(actual, expected) {
  actual.should.be.an.instanceOf(Array);
  actual.slice(0, 2).should.eql(expected);
  actual[2].should.be.an.instanceOf(Function);
}

describe("server/router", function() {

  beforeEach(function() {
    this.router = new Router(config);
  });

  describe("route", function() {
    it("should add basic route definitions", function() {
      var route;
      route = this.router.route("test", "test#index");
      shouldMatchRoute(route, [
        '/test', {
          controller: 'test',
          action: 'index'
        }
      ]);
    });

    it("should support leading slash in pattern", function() {
      var route;

      route = this.router.route("/test", "test#index");
      return shouldMatchRoute(route, [
        '/test', {
          controller: 'test',
          action: 'index'
        }
      ]);
    });

    it("should support object as second argument", function() {
      var route;

      route = this.router.route("/test", {
        controller: 'test',
        action: 'index',
        role: 'admin'
      });
      shouldMatchRoute(route, [
        '/test', {
          controller: 'test',
          action: 'index',
          role: 'admin'
        }
      ]);
    });

    it("should support string as second argument, object as third argument", function() {
      var route;

      route = this.router.route("/test", "test#index", {
        role: 'admin'
      });
      shouldMatchRoute(route, [
        '/test', {
          controller: 'test',
          action: 'index',
          role: 'admin'
        }
      ]);

    });
  });

  describe("routes", function() {
    it("should return the aggregated routes", function() {
      var routes;

      this.router.route("users/:id", "users#show");
      routes = this.router.routes();
      routes.length.should.eql(1);
      shouldMatchRoute(routes[0], [
        '/users/:id', {
          controller: 'users',
          action: 'show'
        }
      ]);
      this.router.route("users/login", "users#login");
      routes = this.router.routes();
      routes.length.should.eql(2);
      shouldMatchRoute(routes[0], [
        '/users/:id', {
          controller: 'users',
          action: 'show'
        }
      ]);
      shouldMatchRoute(routes[1], [
        '/users/login', {
          controller: 'users',
          action: 'login'
        }
      ]);
    });

    it("should return a copy of the routes, not a reference", function() {
      var routes;

      this.router.route("users/:id", "users#show");
      routes = this.router.routes();

      // Modify the routes array
      routes.push('foo');
      this.router.routes().length.should.eql(1);

      // Also modify an individual route element
      this.router.routes()[0].length.should.eql(3);
      this.router.routes()[0].shift();
      this.router.routes()[0].length.should.eql(3);
    });

    it("should not throw error without routes", function() {
      this.router.routes().length.should.eql(0);
    });
  });

  describe("buildRoutes", function() {
    it("should build route definitions based on routes file", function() {
      var routes;

      this.router.buildRoutes();
      routes = this.router.routes();
      routes.length.should.eql(3);
      shouldMatchRoute(routes[0], [
        '/users/login', {
          controller: 'users',
          action: 'login'
        }
      ]);
      shouldMatchRoute(routes[1], [
        '/users/:id', {
          controller: 'users',
          action: 'show'
        }
      ]);
      shouldMatchRoute(routes[2], [
        '/test', {
          controller: 'test',
          action: 'index'
        }
      ]);
    });
  });

  describe("match", function() {
    it("should return the route info for a matched path, no leading slash", function() {
      var route;

      this.router.route("/users/:id", "users#show");
      route = this.router.match('users/1234');
      shouldMatchRoute(route, [
        '/users/:id', {
          controller: 'users',
          action: 'show'
        }
      ]);
    });

    it("should return the route info for a matched path, with leading slash", function() {
      var route;

      this.router.route("/users/:id", "users#show");
      route = this.router.match('/users/1234');
      shouldMatchRoute(route, [
        '/users/:id', {
          controller: 'users',
          action: 'show'
        }
      ]);
    });

    it("should return null if no match", function() {
      should.not.exist(this.router.match('abcd1234xyz'));
    });

    it("should match in the right order", function() {
      var route;

      this.router.route("/users/login", "users#login");
      this.router.route("/users/:id", "users#show");
      route = this.router.match('users/thisisaparam');
      shouldMatchRoute(route, [
        '/users/:id', {
          controller: 'users',
          action: 'show'
        }
      ]);
      route = this.router.match('users/login');
      shouldMatchRoute(route, [
        '/users/login', {
          controller: 'users',
          action: 'login'
        }
      ]);
    });
  });

  describe("getParams", function() {
    beforeEach(function() {
      this.req = express.request;

      resetProperties(this.req, {
        query: {},
        route: {keys: [], params: {}}
      });
      this.router.getParams(this.req).should.eql({});
    });

    it("should return basic query params", function() {
      this.req.__defineGetter__('query', function() {
        return {foo: 'bar', bam: 'baz'};
      });
      this.router.getParams(this.req).should.eql({foo: 'bar', bam: 'baz'});
    });

    it("should support route params", function() {
      this.req.__defineGetter__('route', function() {
        return {
          keys: [{name: 'id'}, {name: 'login'}],
        };
      });
      this.req.__defineGetter__('params', function() {
        return {
          id: 'id-value',
          login: 'login-value'
        }
      });
      this.router.getParams(this.req).should.eql({
        id: 'id-value',
        login: 'login-value'
      });
    });

    it("should support both together", function() {
      this.req.__defineGetter__('query', function() {
        return {foo: 'bar', bam: 'baz'};
      });

      this.req.__defineGetter__('route', function() {
        return {
          keys: [{name: 'id'}, {name: 'login'}],
        };
      });
      this.req.__defineGetter__('params', function() {
        return {
          id: 'id-value',
          login: 'login-value'
        }
      });

      this.router.getParams(this.req).should.eql({
        foo: 'bar',
        bam: 'baz',
        id: 'id-value',
        login: 'login-value'
      });
    });

    it("should XSS sanitize params", function() {
      this.req.__defineGetter__('query', function() {
        return {foo: '<script>alert("foo")</script>'};
      });

      this.router.getParams(this.req).should.eql({
        foo: '[removed]alert("foo")[removed]'
      });
    });
  });
});

function resetProperties(obj, properties) {
  _.each(properties, function(value, key) {
    obj.__defineGetter__(key, function() {
      return value;
    });
  });
}
<|endoftext|>


<commit_before>// var server = require('../../app.js');
var chai = require('chai');
var chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);

var should = chai.should();
var fs = require('fs');

describe('server', function() {
  xit('should pass a test', function(done) {
    request(`http://localhost:9999`, function(error, res, body) {
      expect(res.statusCode).to.equal(200);
      done();
    });
  });

  xdescribe('#get()', function () {

    it('should get an image', function (done) {
      request('http://127.0.0.1:9999/api/images/yosemite1.jpg', function (err, response, body) {
        should.not.exist(err);
        response.statusCode.should.equal(200);
        should.exist(body);
        done();
      });
    });

    it('should get 404 when the image not exists', function (done) {
      request('http://127.0.0.1:9999/api/images/redwoods.png', function (err, response, body) {
        should.not.exist(err);
        response.statusCode.should.equal(404);
        done();
      });
    });

    it('should get all images', function (done) {
      request('http://127.0.0.1:9999/api/images', function (err, response, body) {
        should.not.exist(err);
        response.statusCode.should.equal(200);
        JSON.parse(body).files.should.have.length(8);
        done();
      });
    });
  });

  xdescribe('#post()', function () {

    before(function (done) {
      var boundary = Math.random();
      boundary = '----WebKitFormBoundaryIY5LjARPb2dO0B4Q';

      var options = {
        url: 'http://127.0.0.1:9999/api/images',
        method: 'POST',
        headers: {
          'Content-Type': 'multipart/form-data; boundary=' + boundary,

        }
      };
      var doSomething = function() {
        var stream = fs.createReadStream('./test/server/bigsur2.jpg');
        stream.pipe(request.post(options));
      };
      doSomething().should.eventually.equal('').notify(done);

      setTimeout(function() {
        console.log('done executed'); done();
      }, 1000);
      // stream.pipe(request.post(options, function(err, res) {
      //   console.log('On pipe stream request ', err, res);
      //   done();
      // }));

    });

    it('should get the image', function (done) {
      request('http://127.0.0.1:9999/api/images/yosemite1.jpg', function (err, response, body) {
        should.not.exist(err);
        response.statusCode.should.equal(200);
        should.exist(body);
        done();
      });
    });
  });

});
<commit_msg>Bringing up server before tests<commit_after>var server = require('../../app.js');
var chai = require('chai');
var chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);

var should = chai.should();
var fs = require('fs');

describe('server', function() {
  xit('should pass a test', function(done) {
    request(`http://localhost:9999`, function(error, res, body) {
      expect(res.statusCode).to.equal(200);
      done();
    });
  });

  xdescribe('#get()', function () {

    it('should get an image', function (done) {
      request('http://127.0.0.1:9999/api/images/yosemite1.jpg', function (err, response, body) {
        should.not.exist(err);
        response.statusCode.should.equal(200);
        should.exist(body);
        done();
      });
    });

    it('should get 404 when the image not exists', function (done) {
      request('http://127.0.0.1:9999/api/images/redwoods.png', function (err, response, body) {
        should.not.exist(err);
        response.statusCode.should.equal(404);
        done();
      });
    });

    it('should get all images', function (done) {
      request('http://127.0.0.1:9999/api/images', function (err, response, body) {
        should.not.exist(err);
        response.statusCode.should.equal(200);
        JSON.parse(body).files.should.have.length(8);
        done();
      });
    });
  });

  xdescribe('#post()', function () {

    before(function (done) {
      var boundary = Math.random();
      boundary = '----WebKitFormBoundaryIY5LjARPb2dO0B4Q';

      var options = {
        url: 'http://127.0.0.1:9999/api/images',
        method: 'POST',
        headers: {
          'Content-Type': 'multipart/form-data; boundary=' + boundary,

        }
      };
      var doSomething = function() {
        var stream = fs.createReadStream('./test/server/bigsur2.jpg');
        stream.pipe(request.post(options));
      };
      doSomething().should.eventually.equal('').notify(done);

      setTimeout(function() {
        console.log('done executed'); done();
      }, 1000);
      // stream.pipe(request.post(options, function(err, res) {
      //   console.log('On pipe stream request ', err, res);
      //   done();
      // }));

    });

    it('should get the image', function (done) {
      request('http://127.0.0.1:9999/api/images/yosemite1.jpg', function (err, response, body) {
        should.not.exist(err);
        response.statusCode.should.equal(200);
        should.exist(body);
        done();
      });
    });
  });

});
<|endoftext|>


<commit_before>import { getMountPoint } from 'substance-test'
import { platform } from 'substance'
import {
  InternalArticleDocument, InternalArticleSchema,
  createJatsImporter, createJatsExporter, createEmptyJATS
} from '../../index'

export { test, spy, wait, getMountPoint, testAsync } from 'substance-test'

export function promisify (fn) {
  return new Promise((resolve, reject) => {
    fn((err, result) => {
      if (err) reject(err)
      else resolve(result)
    })
  })
}

export class DOMEvent {
  constructor (props) {
    Object.assign(this, props)
  }
  stopPropagation () {}
  preventDefault () {}
}

export class ClipboardEventData {
  constructor () {
    this.data = {}
  }

  getData (format) {
    return this.data[format]
  }

  setData (format, data) {
    this.data[format] = data
  }

  get types () {
    return Object.keys(this.data)
  }
}

export class ClipboardEvent {
  constructor () {
    this.clipboardData = new ClipboardEventData()
  }
  preventDefault () {}
  stopPropagation () {}
}

export function diff (actual, expected) {
  let colors = require('colors')
  let jsdiff = require('diff')
  return jsdiff.diffChars(expected, actual).map(part => {
    // green for additions, red for deletions
    // grey for common parts
    let color = colors.grey
    let str = part.value
    if (part.added) {
      color = colors.green
    } else if (part.removed) {
      color = colors.red
    } else {
      let lines = str.split(/\r?\n/)
      let L = lines.length
      if (L > 5) {
        str = [lines[0], '...', lines[L - 1]].join('\n')
      }
    }
    return color(str)
  }).join('')
}

export function injectStyle (t, style) {
  let sandbox = getMountPoint(t)
  sandbox.insertAt(0, sandbox.createElement('style').text(style))
}

export function importElement (el) {
  let doc = InternalArticleDocument.createEmptyArticle(InternalArticleSchema)
  let importer = createJatsImporter(doc)
  return importer.convertElement(el)
}

export function exportNode (node) {
  let jats = createEmptyJATS()
  let exporter = createJatsExporter(jats, node.getDocument())
  return exporter.convertNode(node)
}

export function doesNotThrowInNodejs (t, fn, descr) {
  if (platform.inNodeJS) {
    t.doesNotThrow(fn, descr)
  } else {
    fn()
  }
}
<commit_msg>Improve test helper.<commit_after>import { getMountPoint } from 'substance-test'
import { platform } from 'substance'
import {
  InternalArticleDocument, InternalArticleSchema,
  createJatsImporter, createJatsExporter, createEmptyJATS
} from '../../index'

export { test, spy, wait, getMountPoint, testAsync } from 'substance-test'

export function promisify (fn) {
  return new Promise((resolve, reject) => {
    fn((err, result) => {
      if (err) reject(err)
      else resolve(result)
    })
  })
}

export class DOMEvent {
  constructor (props) {
    Object.assign(this, props)
  }
  stopPropagation () {}
  preventDefault () {}
}

export class ClipboardEventData {
  constructor () {
    this.data = {}
  }

  getData (format) {
    return this.data[format]
  }

  setData (format, data) {
    this.data[format] = data
  }

  get types () {
    return Object.keys(this.data)
  }
}

export class ClipboardEvent {
  constructor () {
    this.clipboardData = new ClipboardEventData()
  }
  preventDefault () {}
  stopPropagation () {}
}

export function diff (actual, expected) {
  let colors = require('colors')
  let jsdiff = require('diff')
  return jsdiff.diffChars(expected, actual).map(part => {
    // green for additions, red for deletions
    // grey for common parts
    let color = colors.grey
    let str = part.value
    if (part.added) {
      color = colors.green
    } else if (part.removed) {
      color = colors.red
    } else {
      let lines = str.split(/\r?\n/)
      let L = lines.length
      if (L > 5) {
        str = [lines[0], '...', lines[L - 1]].join('\n')
      }
    }
    return color(str)
  }).join('')
}

export function injectStyle (t, style) {
  let sandbox = getMountPoint(t)
  sandbox.insertAt(0, sandbox.createElement('style').text(style))
}

export function importElement (el) {
  let doc = InternalArticleDocument.createEmptyArticle(InternalArticleSchema)
  let importer = createJatsImporter(doc)
  return importer.convertElement(el)
}

export function exportNode (node) {
  let jats = createEmptyJATS()
  let exporter = createJatsExporter(jats, node.getDocument())
  return exporter.convertNode(node)
}

export function doesNotThrowInNodejs (t, fn, descr) {
  if (platform.inNodeJS) {
    t.doesNotThrow(fn, descr)
  } else {
    let success = false
    try {
      fn()
      success = true
    } finally {
      t.ok(success, descr)
    }
  }
}
<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict';

require('log-timestamp');

var express = require('express');
var taskist = require('taskist');
var sugar = require('object-sugar');

var config = require('./config');
var schemas = require('./schemas')({
    cdns: config.cdns
});
var api = require('./api')(sugar, config.cdns, schemas.object);
var tasks = require('./tasks')({
    sugar: sugar,
    request: require('request'),
    url: config.syncUrl,
    cdns: config.cdns,
    schemas: schemas.object
});
var purgeCache = require('./lib/purge')(config.maxcdn);

if(require.main === module) {
    main();
}

module.exports = main;
function main(cb) {
    cb = cb || noop;

    console.log('Connecting to database');

    sugar.connect('db', function(err) {
        if(err) {
            return console.error('Failed to connect to database', err);
        }

        console.log('Connected to database');

        console.log('Initializing tasks');
        initTasks();

        console.log('Starting server');
        serve(cb);
    });
}

function initTasks() {
    taskist(config.tasks, tasks, {
        instant: function(err) {
            if(err) {
                return console.error(err);
            }

            console.log('Purging cache');

            purgeCache(function(err) {
                if(err) {
                    return console.error(err);
                }

                console.log('Cache purged');
            });
        }
    });
}

function serve(cb) {
    cb = cb || noop;

    var app = express();
    var port = config.port;

    app.configure(function() {
        app.set('port', port);

        app.disable('etag');

        app.use(express.logger('dev'));

        app.use(app.router);
    });

    app.configure('development', function() {
        app.use(express.errorHandler());
    });

    api(app);

    process.on('exit', terminator);

    ['SIGHUP', 'SIGINT', 'SIGQUIT', 'SIGILL', 'SIGTRAP', 'SIGABRT', 'SIGBUS',
    'SIGFPE', 'SIGUSR1', 'SIGSEGV', 'SIGUSR2', 'SIGPIPE', 'SIGTERM'
    ].forEach(function(element) {
        process.on(element, function() { terminator(element); });
    });

    app.listen(port, function() {
        console.log('Node (version: %s) %s started on %d ...', process.version, process.argv[1], port);

        cb(null);
    });
}

function terminator(sig) {
    if(typeof sig === 'string') {
        console.log('%s: Received %s - terminating Node server ...',
            Date(Date.now()), sig);

        process.exit(1);
    }

    console.log('%s: Node server stopped.', Date(Date.now()) );
}

function noop() {}

<commit_msg>Show purge error in a nicer way<commit_after>#!/usr/bin/env node
'use strict';

require('log-timestamp');

var express = require('express');
var taskist = require('taskist');
var sugar = require('object-sugar');

var config = require('./config');
var schemas = require('./schemas')({
    cdns: config.cdns
});
var api = require('./api')(sugar, config.cdns, schemas.object);
var tasks = require('./tasks')({
    sugar: sugar,
    request: require('request'),
    url: config.syncUrl,
    cdns: config.cdns,
    schemas: schemas.object
});
var purgeCache = require('./lib/purge')(config.maxcdn);

if(require.main === module) {
    main();
}

module.exports = main;
function main(cb) {
    cb = cb || noop;

    console.log('Connecting to database');

    sugar.connect('db', function(err) {
        if(err) {
            return console.error('Failed to connect to database', err);
        }

        console.log('Connected to database');

        console.log('Initializing tasks');
        initTasks();

        console.log('Starting server');
        serve(cb);
    });
}

function initTasks() {
    taskist(config.tasks, tasks, {
        instant: function(err) {
            if(err) {
                return console.error(err);
            }

            console.log('Purging cache');

            purgeCache(function(err) {
                if(err) {
                    return console.dir(err);
                }

                console.log('Cache purged');
            });
        }
    });
}

function serve(cb) {
    cb = cb || noop;

    var app = express();
    var port = config.port;

    app.configure(function() {
        app.set('port', port);

        app.disable('etag');

        app.use(express.logger('dev'));

        app.use(app.router);
    });

    app.configure('development', function() {
        app.use(express.errorHandler());
    });

    api(app);

    process.on('exit', terminator);

    ['SIGHUP', 'SIGINT', 'SIGQUIT', 'SIGILL', 'SIGTRAP', 'SIGABRT', 'SIGBUS',
    'SIGFPE', 'SIGUSR1', 'SIGSEGV', 'SIGUSR2', 'SIGPIPE', 'SIGTERM'
    ].forEach(function(element) {
        process.on(element, function() { terminator(element); });
    });

    app.listen(port, function() {
        console.log('Node (version: %s) %s started on %d ...', process.version, process.argv[1], port);

        cb(null);
    });
}

function terminator(sig) {
    if(typeof sig === 'string') {
        console.log('%s: Received %s - terminating Node server ...',
            Date(Date.now()), sig);

        process.exit(1);
    }

    console.log('%s: Node server stopped.', Date(Date.now()) );
}

function noop() {}

<|endoftext|>


<commit_before>/**
 * This is the setup module.
 * It is supposed to help you create the correct environment to start the app.
 * For more information on how to use this script or on how to start the application,
 * please read README.md.
 *
 * @mdoule setup
 * @author Sören Gade
 * */

/* Our requirements */
var exec = require('child_process').exec;
var fs = require('fs');

/** ========== ========== ==========
 * Helpers
 *  ========== ========== ==========
 * */

/**
 * Copies a file synchronioulsy.
 * @param {String} src - The source path of the file that should be copied.
 * @param {String} dest - The destiation path of the copy.
 * */
function copyFileSync(src, dest) {
  var data = fs.readFileSync(src); // read all the data from the file
  fs.writeFileSync(dest, data); // write the data into the new file
}
/**
 * Checks if the given command line application is installed.
 * @param {String} app - The command that should be installed.
 * @param {SuccessCallback} callback - A callback that defines whether the tool is installed.
 * */
function isInstalled(app, callback) {
  var cmd = "which " + app; // use 'which' to determine path => it then is installed
  exec(cmd, function(err, stdout, stderr) {
    var isInstalled = !err;
    callback(isInstalled);
  });
}

/** ========== ========== ==========
 * Executed commands
 *  ========== ========== ==========
 * */
/**
 * Executes 'npm install'.
 * @param {ErrorCallback} callback - A callback that is called once the operation finished.
 * */
function npmInstall(callback) {
  exec("npm install", function(err, stdout, stderr) {
    callback(err);
  });
}
/**
 * Executes 'bower install'.
 * @param {ErrorCallback} callback - A callback that is called once the operation finished.
 * */
function bowerInstall(callback) {
  exec("bower install", function(err, stdout, stderr) {
    callback(err);
  });
}

function ensureGrunt(callback) {
  callback = callback || function() {};
  isInstalled("grunt", function(isInstalled) {
    if ( !isInstalled ) {
      exec("npm install -g grunt-cli", function(err, stdout, stderr) {
        callback(err);
      });
    } else {
      callback();
    }
  });
}
function ensureBower(callback) {
  callback = callback || function() {};
  isInstalled("bower", function(isInstalled) {
    if ( !isInstalled ) {
      exec("npm install -g bower", function(err, stdout, stderr) {
        callback(err);
      });
    } else {
      callback();
    }
  });
}

// First, check if there is a config.json
if ( !fs.existsSync('config.json') ) {
  console.log("You need to create a config.json file that tells the application your preferences.");
  console.log("Copying file for you...");
  copyFileSync('config.example.json', 'config.json');
  console.log("Done.");
} else {
  console.log("Good. You already have a config file for the application.");
}

console.log("We are installing dependencies, just to be sure...");
console.log("You need npm and bower installed.");
console.log("----- npm install -----");
npmInstall(function(err) {

  console.log("Installing grunt...");
  ensureGrunt(function(err2) {
    console.log("Installing bower...");
    ensureBower(function(err3) {

      console.log("----- bower install -----");
      bowerInstall(function(err4) {
        console.log("All done.");
      });

    });
  });

});
<commit_msg>Added more docs to setup.<commit_after>/**
 * This is the setup module.
 * It is supposed to help you create the correct environment to start the app.
 * For more information on how to use this script or on how to start the application,
 * please read README.md.
 *
 * @mdoule setup
 * @author Sören Gade
 * */

/* Our requirements */
var exec = require('child_process').exec;
var fs = require('fs');

/** ========== ========== ==========
 * Helpers
 *  ========== ========== ==========
 * */

/**
 * Copies a file synchronioulsy.
 * @param {String} src - The source path of the file that should be copied.
 * @param {String} dest - The destiation path of the copy.
 * */
function copyFileSync(src, dest) {
  var data = fs.readFileSync(src); // read all the data from the file
  fs.writeFileSync(dest, data); // write the data into the new file
}
/**
 * Checks if the given command line application is installed.
 * @param {String} app - The command that should be installed.
 * @param {SuccessCallback} callback - A callback that defines whether the tool is installed.
 * */
function isInstalled(app, callback) {
  var cmd = "which " + app; // use 'which' to determine path => it then is installed
  exec(cmd, function(err, stdout, stderr) {
    var isInstalled = !err;
    callback(isInstalled);
  });
}

/** ========== ========== ==========
 * Executed commands
 *  ========== ========== ==========
 * */
/**
 * Executes 'npm install'.
 * @param {ErrorCallback} callback - A callback that is called once the operation finished.
 * */
function npmInstall(callback) {
  exec("npm install", function(err, stdout, stderr) {
    callback(err);
  });
}
/**
 * Executes 'bower install'.
 * @param {ErrorCallback} callback - A callback that is called once the operation finished.
 * */
function bowerInstall(callback) {
  exec("bower install", function(err, stdout, stderr) {
    callback(err);
  });
}

/**
 * Ensures that grunt is installed.
 * @param {ErrorCallback} callback - A callback that is called once the operation finished.
 * */
function ensureGrunt(callback) {
  callback = callback || function() {};
  isInstalled("grunt", function(isInstalled) {
    if ( !isInstalled ) {
      exec("npm install -g grunt-cli", function(err, stdout, stderr) {
        callback(err);
      });
    } else {
      callback();
    }
  });
}
/**
 * Ensures that bower is installed.
 * @param {ErrorCallback} callback - A callback that is called once the operation finished.
 * */
function ensureBower(callback) {
  callback = callback || function() {};
  isInstalled("bower", function(isInstalled) {
    if ( !isInstalled ) {
      exec("npm install -g bower", function(err, stdout, stderr) {
        callback(err);
      });
    } else {
      callback();
    }
  });
}

// First, check if there is a config.json
if ( !fs.existsSync('config.json') ) {
  console.log("You need to create a config.json file that tells the application your preferences.");
  console.log("Copying file for you...");
  copyFileSync('config.example.json', 'config.json');
  console.log("Done.");
} else {
  console.log("Good. You already have a config file for the application.");
}

console.log("We are installing dependencies, just to be sure...");
console.log("You need npm and bower installed.");
console.log("----- npm install -----");
npmInstall(function(err) {

  console.log("Installing grunt...");
  ensureGrunt(function(err2) {
    console.log("Installing bower...");
    ensureBower(function(err3) {

      console.log("----- bower install -----");
      bowerInstall(function(err4) {
        console.log("All done.");
      });

    });
  });

});
<|endoftext|>


<commit_before>sagecell.makeSagecell( {

	inputLocation: '.sagemathcell',
	autoeval: true,
	hide: ['editor','evalButton','permalink']

} );

function resetIframes() {

    if ( /(iPad|iPhone|iPod)/g.test( navigator.userAgent ) ) {

        var scenes = document.getElementsByTagName( 'iframe' );

        for ( var i=0 ; i < scenes.length ; i++ ) {

//            scenes[i].style.width = getComputedStyle( scenes[i] ).width;
//            scenes[i].style.height = getComputedStyle( scenes[i] ).height;
    	    scenes[i].srcdoc = scenes[i].srcdoc;
            scenes[i].setAttribute( 'scrolling', 'no' );

        }
    }

}

function accept() {

	var buttons = document.getElementsByClassName( 'ui-dialog-buttonset' );
	if ( buttons.length > 0 ) buttons[0].firstChild.click();

}
<commit_msg>Update setup<commit_after>sagecell.makeSagecell( {

	inputLocation: '.sagemathcell',
	autoeval: true,
	hide: ['editor','evalButton','permalink']

} );

function resetIframes() {

    if ( /(iPad|iPhone|iPod)/g.test( navigator.userAgent ) ) {

        var scenes = document.getElementsByTagName( 'iframe' );

        for ( var i=0 ; i < scenes.length ; i++ ) {

//            scenes[i].style.width = getComputedStyle( scenes[i] ).width;
//            scenes[i].style.height = getComputedStyle( scenes[i] ).height;
    	    scenes[i].srcdoc = scenes[i].srcdoc;
//            scenes[i].setAttribute( 'scrolling', 'no' );

        }
    }

}

function accept() {

	var buttons = document.getElementsByClassName( 'ui-dialog-buttonset' );
	if ( buttons.length > 0 ) buttons[0].firstChild.click();

}
<|endoftext|>


<commit_before>/* @flow */
import type { UsersState, Action } from '../types';
import {
  APP_REFRESH,
  LOGOUT,
  LOGIN_SUCCESS,
  ACCOUNT_SWITCH,
  EVENT_PRESENCE,
  PRESENCE_RESPONSE,
} from '../actionConstants';
import { NULL_OBJECT } from '../nullObjects';

const initialState: Object = NULL_OBJECT;

export default (state: UsersState = initialState, action: Action): UsersState => {
  switch (action.type) {
    case APP_REFRESH:
    case LOGOUT:
    case LOGIN_SUCCESS:
    case ACCOUNT_SWITCH:
      return initialState;

    case PRESENCE_RESPONSE:
      return {
        ...state,
        ...action.presence,
      };

    case EVENT_PRESENCE:
      return {
        ...state,
        [action.email]: action.presence,
      };

    default:
      return state;
  }
};
<commit_msg>Set presence from initial realm data (#1577)<commit_after>/* @flow */
import type { UsersState, Action } from '../types';
import {
  APP_REFRESH,
  LOGOUT,
  LOGIN_SUCCESS,
  ACCOUNT_SWITCH,
  EVENT_PRESENCE,
  PRESENCE_RESPONSE,
  REALM_INIT,
} from '../actionConstants';
import { NULL_OBJECT } from '../nullObjects';

const initialState: Object = NULL_OBJECT;

export default (state: UsersState = initialState, action: Action): UsersState => {
  switch (action.type) {
    case APP_REFRESH:
    case LOGOUT:
    case LOGIN_SUCCESS:
    case ACCOUNT_SWITCH:
      return initialState;

    case REALM_INIT:
      return action.data.presences;

    case PRESENCE_RESPONSE:
      return {
        ...state,
        ...action.presence,
      };

    case EVENT_PRESENCE:
      return {
        ...state,
        [action.email]: action.presence,
      };

    default:
      return state;
  }
};
<|endoftext|>


<commit_before>var hookshot = require('hookshot'),
	fs         = require('fs'),
	sh         = require('execSync'),
	request    = require('request');

var config      = require('../config.json'),
		sh_commands = require('./sh-commands.js')

function verifyAccount(incoming_repo){
	if (incoming_repo == config.github_listener.account_name) return true;
	return false;
}
function checkIfCommitterIsDeployer(members, committer){
	members.some(function(member){
		return member.name === committer;
	})
}
function verifyCommitter(last_commit, cb){
	// You only need to verify the deployer if you're using teams, otherwise disable it and always allow anyone pushing to that repo to deploy.
	if (!config.verify_committer.enabled){
		cb(true);
	}else{
		var committer = last_commit.committer.username;
		request('https://api.github.com/teams/' + config.verify_committer.team_id + '/members?access_token=' + config.verify_committer.access_token, function (error, response, body) {
		  if (!error && response.statusCode == 200) {
		  	var committer_is_deployer = checkIfCommitterIsDeployer(JSON.parse(body), committer);
		    cb(committer_is_deployer);
		  }
		})
	}
}

function createDirGitInit(info){
	var repo_name = info.repository.name;
	fs.mkdirSync('./' + repo_name);

	var create_statement = sh_commands.createGitRepoAndRemotes(repo_name, info.repository.url, config.archive);
  sh.run(create_statement);
}
function pullLatest(info){
	var repo_name = info.repository.name;

	if (!fs.existsSync('./' + repo_name)){
		createDirGitInit(info);
	}

	var fetch_statement = sh_commands.fetchLatest(repo_name, config.archive);
	sh.run(fetch_statement);
}
function checkForDeployMsg(last_commit){
	var commit_msg = last_commit.message,
	    cp_deploy_regx   = new RegExp(config.s3.hard_deploy_trigger),
	    sync_deploy_regx = new RegExp(config.s3.sync_deploy_trigger);

	if (config.s3.hard_deploy_trigger.enabled && cp_deploy_regx.exec(commit_msg)) return 'cp';
	if (sync_deploy_regx.exec(commit_msg)) return 'sync';
	return false;
}
function deployToS3(deploy_type, info){
	var repo_name = info.repository.name,
	    path      = (config.s3.path) ? config.s3.path : '';

	var deploy_statement = sh_commands.deploy(deploy_type, repo_name, config.s3.bucket_name, path, config.s3.exclude_from_sync);
	var deploy_result = sh.exec(deploy_statement);
	// var deploy_result = sh.exec('aws s3 sync '+repo_name+' s3://'+config.bucket_name+'/'+path+repo_name+'/ --exclude ".git/*" --exclude ".*"');
	console.log(deploy_result.stdout);
}

hookshot('refs/heads/master', function(info){
	// The last commit in the array is the most recent
	var most_recent_commit  = info.commits[info.commits.length - 1];

	var is_account_verified = verifyAccount(info.repository.owner.name),
	    deploy_status       = checkForDeployMsg(most_recent_commit);

	// Is this coming from the whitelisted GitHub account?
	if (is_account_verified){
		pullLatest(info);

		// Are we deploying? Has that option been enabled and does the commit have the appropriate message?
		if (config.s3.enabled && deploy_status){
			verifyCommitter(most_recent_commit, function(committer_approved){

				// Does the committer have deploy? privileges?
				if (committer_approved) deployToS3(deploy_status, info);

			});
		}

	}
}).listen(config.github_listener.port);

console.log('Listening on port... ' + config.github_listener.port);	<commit_msg>add repositories<commit_after>var hookshot = require('hookshot'),
	fs         = require('fs'),
	sh         = require('execSync'),
	request    = require('request');

var config      = require('../config.json'),
		sh_commands = require('./sh-commands.js')

function verifyAccount(incoming_repo){
	if (incoming_repo == config.github_listener.account_name) return true;
	return false;
}
function checkIfCommitterIsDeployer(members, committer){
	members.some(function(member){
		return member.name === committer;
	})
}
function verifyCommitter(last_commit, cb){
	// You only need to verify the deployer if you're using teams, otherwise disable it and always allow anyone pushing to that repo to deploy.
	if (!config.verify_committer.enabled){
		cb(true);
	}else{
		var committer = last_commit.committer.username;
		request('https://api.github.com/teams/' + config.verify_committer.team_id + '/members?access_token=' + config.verify_committer.access_token, function (error, response, body) {
		  if (!error && response.statusCode == 200) {
		  	var committer_is_deployer = checkIfCommitterIsDeployer(JSON.parse(body), committer);
		    cb(committer_is_deployer);
		  }
		})
	}
}

function createDirGitInit(info){
	var repo_name = info.repository.name;
	fs.mkdirSync('./repositories/' + repo_name);

	var create_statement = sh_commands.createGitRepoAndRemotes(repo_name, info.repository.url, config.archive);
  sh.run(create_statement);
}
function pullLatest(info){
	var repo_name = info.repository.name;

	if (!fs.existsSync('./' + repo_name)){
		createDirGitInit(info);
	}

	var fetch_statement = sh_commands.fetchLatest(repo_name, config.archive);
	sh.run(fetch_statement);
}
function checkForDeployMsg(last_commit){
	var commit_msg = last_commit.message,
	    cp_deploy_regx   = new RegExp(config.s3.hard_deploy_trigger),
	    sync_deploy_regx = new RegExp(config.s3.sync_deploy_trigger);

	if (config.s3.hard_deploy_trigger.enabled && cp_deploy_regx.exec(commit_msg)) return 'cp';
	if (sync_deploy_regx.exec(commit_msg)) return 'sync';
	return false;
}
function deployToS3(deploy_type, info){
	var repo_name = info.repository.name,
	    path      = (config.s3.path) ? config.s3.path : '';

	var deploy_statement = sh_commands.deploy(deploy_type, repo_name, config.s3.bucket_name, path, config.s3.exclude_from_sync);
	var deploy_result = sh.exec(deploy_statement);
	// var deploy_result = sh.exec('aws s3 sync '+repo_name+' s3://'+config.bucket_name+'/'+path+repo_name+'/ --exclude ".git/*" --exclude ".*"');
	console.log(deploy_result.stdout);
}

hookshot('refs/heads/master', function(info){
	// The last commit in the array is the most recent
	var most_recent_commit  = info.commits[info.commits.length - 1];

	var is_account_verified = verifyAccount(info.repository.owner.name),
	    deploy_status       = checkForDeployMsg(most_recent_commit);

	// Is this coming from the whitelisted GitHub account?
	if (is_account_verified){
		pullLatest(info);

		// Are we deploying? Has that option been enabled and does the commit have the appropriate message?
		if (config.s3.enabled && deploy_status){
			verifyCommitter(most_recent_commit, function(committer_approved){

				// Does the committer have deploy? privileges?
				if (committer_approved) deployToS3(deploy_status, info);

			});
		}

	}
}).listen(config.github_listener.port);

console.log('Listening on port... ' + config.github_listener.port);	<|endoftext|>


<commit_before>'use strict';

import {workToJSON} from '../requestTypeIdentifier.js';

export default (params, context) => {
  if (!params.q) {
    return new Promise({statusCode: 400,
                    error: 'missing q parameter'});
  }

  let agency = context.opensearch.agency;
  let profile = context.opensearch.profile;
  let q = params.q.replace(/</g, '<');
  let sort = (params.sort || '').replace(/</g, '<');
  let offset = 1 + (parseInt(params.offset, 10) || 0);
  let limit = parseInt(params.limit, 10) || 10;

  let soap = `<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://oss.dbc.dk/ns/opensearch">
  <SOAP-ENV:Body>
    <ns1:searchRequest>
      <ns1:query>${q}</ns1:query>
      <ns1:agency>${agency}</ns1:agency>
      <ns1:profile>${profile}</ns1:profile>
      <ns1:start>${offset}</ns1:start>
      <ns1:stepValue>${limit}</ns1:stepValue>
      ${sort?'<ns1:sort>' + sort + '</ns1:sort>' : ''}
      <ns1:collectionType>work-1</ns1:collectionType>
      <ns1:allObjects>1</ns1:allObjects>
      <ns1:objectFormat>briefDisplay</ns1:objectFormat>
      <ns1:objectFormat>dkabm</ns1:objectFormat>
      <ns1:outputType>json</ns1:outputType>
    </ns1:searchRequest>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
`;

  return context.call('opensearch', soap).then(body => {
    body = JSON.parse(body).searchResponse.result;
    // let more = body.more.$; // this could be used for paging info later
    let searchResult = body.searchResult || [];
    let result = [];
    searchResult.forEach(o => { // eslint-disable-line no-loop-func
      let collection = o.collection.object.map(obj => obj.identifier.$);
      let dkabm = o.collection.object[0].record;
      dkabm = workToJSON(dkabm);
      let briefDisplays =
        o.formattedCollection.briefDisplay.manifestation.map(briefDisplay => {
          delete briefDisplay.fedoraPid;
          return workToJSON(briefDisplay, 'bd');
        });
      // here we would call getObject or moreInfo if needed...
      result.push(Object.assign({
        collection: collection,
        collectionDetails: briefDisplays
      }, dkabm, briefDisplays[0]));
    });
    return {statusCode: 200, data: result};
  });
};
<commit_msg>fix #223<commit_after>'use strict';

import {workToJSON} from '../requestTypeIdentifier.js';

export default (params, context) => {
  if (!params.q) {
    return Promise.resolve({statusCode: 400, error: 'missing q parameter'});
  }

  let agency = context.opensearch.agency;
  let profile = context.opensearch.profile;
  let q = params.q.replace(/</g, '<');
  let sort = (params.sort || '').replace(/</g, '<');
  let offset = 1 + (parseInt(params.offset, 10) || 0);
  let limit = parseInt(params.limit, 10) || 10;

  let soap = `<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://oss.dbc.dk/ns/opensearch">
  <SOAP-ENV:Body>
    <ns1:searchRequest>
      <ns1:query>${q}</ns1:query>
      <ns1:agency>${agency}</ns1:agency>
      <ns1:profile>${profile}</ns1:profile>
      <ns1:start>${offset}</ns1:start>
      <ns1:stepValue>${limit}</ns1:stepValue>
      ${sort?'<ns1:sort>' + sort + '</ns1:sort>' : ''}
      <ns1:collectionType>work-1</ns1:collectionType>
      <ns1:allObjects>1</ns1:allObjects>
      <ns1:objectFormat>briefDisplay</ns1:objectFormat>
      <ns1:objectFormat>dkabm</ns1:objectFormat>
      <ns1:outputType>json</ns1:outputType>
    </ns1:searchRequest>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
`;

  return context.call('opensearch', soap).then(body => {
    body = JSON.parse(body).searchResponse.result;
    // let more = body.more.$; // this could be used for paging info later
    let searchResult = body.searchResult || [];
    let result = [];
    searchResult.forEach(o => { // eslint-disable-line no-loop-func
      let collection = o.collection.object.map(obj => obj.identifier.$);
      let dkabm = o.collection.object[0].record;
      dkabm = workToJSON(dkabm);
      let briefDisplays =
        o.formattedCollection.briefDisplay.manifestation.map(briefDisplay => {
          delete briefDisplay.fedoraPid;
          return workToJSON(briefDisplay, 'bd');
        });
      // here we would call getObject or moreInfo if needed...
      result.push(Object.assign({
        collection: collection,
        collectionDetails: briefDisplays
      }, dkabm, briefDisplays[0]));
    });
    return {statusCode: 200, data: result};
  });
};
<|endoftext|>