<commit_before>var fs = require('fs')
  , test = require('tape')
  , cv = null

test("Smoke tests / Can Import", function(t){
  cv = require('../lib/opencv')
  t.ok(cv, "imported fine")
  t.ok(cv.version, "version is there:" + cv.version)
  t.ok(cv.Point, "point is there")
  t.ok(cv.Matrix, "matrix is there")
  t.end()
})

test('importing library multiple times is ok', function(t){
  var cv1 = require('../lib/opencv')
    , cv2 = require('../lib/opencv')
    cv1.readImage('./examples/files/mona.png', function(err, im){
      t.error(err)
      cv2.readImage('./examples/files/mona.png', function(err, im){
        t.error(err)
        t.end();
      });
    });
})

test('Point', function(t){

  t.ok(new cv.Point(1, 2))
  t.throws(function () { cv.Point(1, 2)}, TypeError, "cannot call without new")

  t.equal(new cv.Point(1, 2).x, 1)
  t.equal(new cv.Point(1, 2).y, 2)
  t.equal(Math.round(new cv.Point(1.1, 2).x * 100), 110)
  t.equal(Math.round(new cv.Point(1.2, 2.75).y *100), 275)

  t.throws(function () {new cv.Point(1.1, 2).x = 5}, Error, "Points are immutable")
  t.throws(function () {new cv.Point(1.1, 2).y = 5}, Error, "Points are immutable")

  var p1 = new cv.Point(3, 6)
    , p2 = new cv.Point(5, 7)

  t.ok(p1.dot);
  t.equal(p1.dot(p2), 57);

  t.end()
})

test('Matrix constructor', function(assert){
  assert.ok(cv.Matrix);
  assert.ok(new cv.Matrix);
  assert.ok(new cv.Matrix(1, 2));
  assert.ok(new cv.Matrix(1, 2, cv.Constants.CV_8U));
  assert.ok(new cv.Matrix(1, 2, cv.Constants.CV_8U, [1]));
  assert.end()
})

test('Matrix accessors', function(assert){
  var mat = new cv.Matrix(1, 2);
  mat.set(0,0,3)
  mat.set(0,1,5000)
  assert.deepEqual(mat.row(0), [3,5000]);

  mat = new cv.Matrix(1,2);
  assert.equal(mat.set(0,0,3), undefined);
  assert.equal(mat.get(0,0), 3);

  mat = new cv.Matrix(6,7);
  assert.equal(mat.width(), 7);

  mat = new cv.Matrix(6,7);
  assert.equal(mat.height(), 6);

  mat = new cv.Matrix(6,7);
  assert.deepEqual(mat.size(), [6, 7]);

  mat = new cv.Matrix(6,7);
  assert.equal(mat.width(), 7);
  mat.resize(8,9);
  assert.equal(mat.width(), 8);

  mat = new cv.Matrix.Eye(4,4)
  assert.deepEqual(mat.row(1), [0,1,0,0])
  assert.deepEqual(mat.row(2), [0,0,1,0])

  mat = new cv.Matrix.Eye(4,4);
  assert.deepEqual(mat.col(1), [0,1,0,0])
  assert.deepEqual(mat.col(2), [0,0,1,0])

  assert.equal(new cv.Matrix().empty(), true);

  mat = new cv.Matrix(1, 2, cv.Constants.CV_8UC3, [1, 2, 3]);
  assert.deepEqual(mat.pixelRow(0), [1, 2, 3, 1, 2, 3]);

  assert.end()
})

test('Matrix functions', function(assert) {
  // convertTo
  var mat = new cv.Matrix(75, 75, cv.Constants.CV_32F, [2.0]);
  var matNew = new cv.Matrix(75, 75, cv.Constants.CV_8U);
  mat.convertTo(matNew, cv.Constants.CV_8U, 2, 1);
  assert.equal(matNew.pixel(0, 0), 5);

  // reshape
  mat = new cv.Matrix(75, 75, cv.Constants.CV_8UC1);
  matNew = mat.reshape(1, 1);
  assert.equal(matNew.height(), 1);
  assert.equal(matNew.width(), 5625);

  // GetRotationMatrix2D
  mat = cv.Matrix.getRotationMatrix2D(0, 0, 90, 1.0);
  assert.deepEqual(mat.size(), [2,3], 'GetRotationMatrix2D');

  assert.end();
})

test(".norm", function(assert){
  cv.readImage("./examples/files/coin1.jpg", function(err, im) {
    cv.readImage("./examples/files/coin2.jpg", function(err, im2){
      assert.ok(im);
      assert.ok(im2);

      var errorL2 = im.norm(im2, cv.Constants.NORM_L2);
      assert.equal(errorL2, 7295.591339980605);

      errorL2 = im.norm(im, cv.Constants.NORM_L2);
      assert.equal(errorL2, 0);
      assert.end();
    });
  });
})

test("Matrix toBuffer", function(assert){
  var buf = fs.readFileSync('./examples/files/mona.png')

  cv.readImage(buf.slice(0), function(err, mat){
    var buf0 = mat.toBuffer()
    assert.ok(buf0);
    assert.end()
  })
})

test("Matrix toBuffer Async", function(assert){
  var buf = fs.readFileSync('./examples/files/mona.png')

  cv.readImage(buf.slice(0), function(err, mat){
    mat.toBuffer(function(err, buff){
      assert.error(err)
      assert.ok(buf)
      assert.ok(buf.length > 100)

      assert.end()
    })
  })
})

test("detectObject", function(assert){
  cv.readImage("./examples/files/mona.png", function(err, im){
    im.detectObject(cv.FACE_CASCADE, {}, function(err, faces){
      assert.error(err)
      assert.ok(faces)
      assert.equal(faces.length, 1)
      assert.end()
    })
  })
})

test(".absDiff and .countNonZero", function(assert){
  cv.readImage("./examples/files/mona.png", function(err, im) {
    cv.readImage("./examples/files/mona.png", function(err, im2){
      assert.ok(im);
      assert.ok(im2);

      var diff = new cv.Matrix(im.width(), im.height());
      diff.absDiff(im, im2);

      diff.convertGrayscale();
      assert.equal(diff.countNonZero(), 0);
      assert.end()
    });
  });
})

test(".bitwiseXor", function(assert){
  var mat1 = new cv.Matrix(1,1);
  mat1.set(0,0, 1);

  var mat2 = new cv.Matrix(1,1);
  mat2.set(0,0, 1);

  var xored = new cv.Matrix(1,1);
  xored.bitwiseXor(mat1, mat2);

  assert.equal(xored.get(0,0), 0);

  assert.end()
})

test("Image read from file", function(assert){
  cv.readImage("./examples/files/opencv.png", function(err, im){
    assert.ok(im);
    assert.equal(im.width(), 82);
    assert.equal(im.height(), 99);
    assert.equal(im.channels(), 4);
    assert.equal(im.empty(), false);
    assert.end();
  })
})

test("read Image from buffer", function(assert){
  cv.readImage(fs.readFileSync('./examples/files/opencv.png'), function(err, im){
    assert.ok(im);
    assert.equal(im.width(), 82);
    assert.equal(im.height(), 99);
    assert.equal(im.channels(), 4);
    assert.equal(im.empty(), false);
    assert.end();
  })
})

test("Cascade Classifier", function(assert){
  assert.ok(new cv.CascadeClassifier("./data/haarcascade_frontalface_alt.xml"), 'test constructor')

  cv.readImage("./examples/files/mona.png", function(err, im){
    cascade = new cv.CascadeClassifier("./data/haarcascade_frontalface_alt.xml");
    cascade.detectMultiScale(im, function(err, faces){//, 1.1, 2, [30, 30]);
      assert.error(err);
      assert.equal(typeof faces, typeof []);
      assert.equal(faces.length, 1)
      assert.end()
    })
  })
})

test("ImageDataStream", function(assert){
  var s = new cv.ImageDataStream()
  s.on('load', function(im){
    assert.ok(im)
    assert.equal(im.empty(), false);
    assert.end()
  })

  fs.createReadStream('./examples/files/mona.png').pipe(s);

})

test("ImageStream", function(assert){
  var s = new cv.ImageStream()
    , im = fs.readFileSync('./examples/files/mona.png')

  s.on('data', function(mat){
    assert.deepEqual(mat.size(), [756,500])
    assert.end()
  })
  s.write(im);
})

test("CamShift", function(assert){
  cv.readImage('./examples/files/coin1.jpg', function(e, im){
    cv.readImage('./examples/files/coin2.jpg', function(e, im2){
      var tracked = new cv.TrackedObject(im, [420, 110, 490, 170], {channel: 'v'});
      assert.ok(tracked);
      var res = tracked.track(im2)
      assert.ok(res);
      assert.ok(res[0]  < 396)
      assert.ok(res[0]  > 376)
      assert.ok(res[1]  < 122)
      assert.ok(res[1]  > 102)
      assert.ok(res[2]  < 469)
      assert.ok(res[2]  > 449)
      assert.ok(res[3]  < 176)
      assert.ok(res[3]  > 156)
      assert.end()
    })
  })
})

test("fonts", function(t) {

  function rnd() {
    return Math.round(Math.random() * 255);
  };

  cv.readImage("./examples/files/coin1.jpg", function(e, im){
    var y = 0;
    var scale = 1;

    ([
      "HERSEY_SIMPLEX",
      "HERSEY_PLAIN",
      "HERSEY_DUPLEX",
      "HERSEY_COMPLEX",
      "HERSEY_TRIPLEX",
      "HERSEY_COMPLEX_SMALL",
      "HERSEY_SCRIPT_SIMPLEX",
      "HERSEY_SCRIPT_COMPLEX",
      "HERSEY_SCRIPT_SIMPLEX"
    ]).forEach(function(font) {
      im.putText("Some text", 0, y += 20, font, [rnd(), rnd(), rnd()], 2, scale++);
    });

    t.ok(im, "image is ok");
    im.save("./examples/tmp/coin1-with-text.jpg");
    t.end();
  });
})

test('LDA Wrap', function(assert) {
  if (cv.LDA === undefined) {
    console.log('TODO: Please port LDAWrap.cc to OpenCV 3')
    assert.end();
    return;
  }

  // subspaceProject
  var mat = cv.LDA.subspaceProject(new cv.Matrix(1, 2, cv.Constants.CV_64F), new cv.Matrix(), new cv.Matrix(2, 1, cv.Constants.CV_8UC1));
  assert.deepEqual(mat.size(), [2,2], 'subspaceProject');

  // subspaceReconstruct
  mat = cv.LDA.subspaceReconstruct(new cv.Matrix(1, 2, cv.Constants.CV_64F), new cv.Matrix(), new cv.Matrix(1, 2, cv.Constants.CV_8UC1));
  assert.deepEqual(mat.size(), [1,1], 'subspaceReconstruct');

  assert.end();
})

test('Native Matrix', function(assert) {
  var nativemat = require('../build/Release/test_nativemat.node');
  var mat = new cv.Matrix(42, 8);

  assert.deepEqual(mat.size(), nativemat.size(mat), 'nativemat');
  assert.end();
})

test('Subtract', function(assert) {
  var a = new cv.Matrix.Zeros(1,1);
  a.set(0, 0, 3);
  var b = new cv.Matrix.Zeros(1,1);
  b.set(0, 0, 1);
  a.subtract(b);
  assert.deepEqual(a.get(0, 0), 2);
  assert.end();
});

test('Mean', function(assert) {
  var a = new cv.Matrix.Zeros(2, 2, cv.Constants.CV_8UC3);

  // Set [0, 0] element to 1 for all three channels
  a.set(0, 0, 1, 0);
  a.set(0, 0, 1, 1);
  a.set(0, 0, 1, 2);

  var means = a.mean();
  assert.deepEqual(means, [0.25, 0.25, 0.25, 0]);
  assert.end();
});

// Test the examples folder.
require('./examples')()

<commit_msg>Add Unit test to method<commit_after>var fs = require('fs')
  , test = require('tape')
  , cv = null

test("Smoke tests / Can Import", function(t){
  cv = require('../lib/opencv')
  t.ok(cv, "imported fine")
  t.ok(cv.version, "version is there:" + cv.version)
  t.ok(cv.Point, "point is there")
  t.ok(cv.Matrix, "matrix is there")
  t.end()
})

test('importing library multiple times is ok', function(t){
  var cv1 = require('../lib/opencv')
    , cv2 = require('../lib/opencv')
    cv1.readImage('./examples/files/mona.png', function(err, im){
      t.error(err)
      cv2.readImage('./examples/files/mona.png', function(err, im){
        t.error(err)
        t.end();
      });
    });
})

test('Point', function(t){

  t.ok(new cv.Point(1, 2))
  t.throws(function () { cv.Point(1, 2)}, TypeError, "cannot call without new")

  t.equal(new cv.Point(1, 2).x, 1)
  t.equal(new cv.Point(1, 2).y, 2)
  t.equal(Math.round(new cv.Point(1.1, 2).x * 100), 110)
  t.equal(Math.round(new cv.Point(1.2, 2.75).y *100), 275)

  t.throws(function () {new cv.Point(1.1, 2).x = 5}, Error, "Points are immutable")
  t.throws(function () {new cv.Point(1.1, 2).y = 5}, Error, "Points are immutable")

  var p1 = new cv.Point(3, 6)
    , p2 = new cv.Point(5, 7)

  t.ok(p1.dot);
  t.equal(p1.dot(p2), 57);

  t.end()
})

test('Matrix constructor', function(assert){
  assert.ok(cv.Matrix);
  assert.ok(new cv.Matrix);
  assert.ok(new cv.Matrix(1, 2));
  assert.ok(new cv.Matrix(1, 2, cv.Constants.CV_8U));
  assert.ok(new cv.Matrix(1, 2, cv.Constants.CV_8U, [1]));
  assert.end()
})

test('Matrix accessors', function(assert){
  var mat = new cv.Matrix(1, 2);
  mat.set(0,0,3)
  mat.set(0,1,5000)
  assert.deepEqual(mat.row(0), [3,5000]);

  mat = new cv.Matrix(1,2);
  assert.equal(mat.set(0,0,3), undefined);
  assert.equal(mat.get(0,0), 3);

  mat = new cv.Matrix(6,7);
  assert.equal(mat.width(), 7);

  mat = new cv.Matrix(6,7);
  assert.equal(mat.height(), 6);

  mat = new cv.Matrix(6,7);
  assert.deepEqual(mat.size(), [6, 7]);

  mat = new cv.Matrix(6,7);
  assert.equal(mat.width(), 7);
  mat.resize(8,9);
  assert.equal(mat.width(), 8);

  mat = new cv.Matrix.Eye(4,4)
  assert.deepEqual(mat.row(1), [0,1,0,0])
  assert.deepEqual(mat.row(2), [0,0,1,0])

  mat = new cv.Matrix.Eye(4,4);
  assert.deepEqual(mat.col(1), [0,1,0,0])
  assert.deepEqual(mat.col(2), [0,0,1,0])

  assert.equal(new cv.Matrix().empty(), true);

  mat = new cv.Matrix(1, 2, cv.Constants.CV_8UC3, [1, 2, 3]);
  assert.deepEqual(mat.pixelRow(0), [1, 2, 3, 1, 2, 3]);

  assert.end()
})

test('Matrix functions', function(assert) {
  // convertTo
  var mat = new cv.Matrix(75, 75, cv.Constants.CV_32F, [2.0]);
  var matNew = new cv.Matrix(75, 75, cv.Constants.CV_8U);
  mat.convertTo(matNew, cv.Constants.CV_8U, 2, 1);
  assert.equal(matNew.pixel(0, 0), 5);

  // reshape
  mat = new cv.Matrix(75, 75, cv.Constants.CV_8UC1);
  matNew = mat.reshape(1, 1);
  assert.equal(matNew.height(), 1);
  assert.equal(matNew.width(), 5625);

  // GetRotationMatrix2D
  mat = cv.Matrix.getRotationMatrix2D(0, 0, 90, 1.0);
  assert.deepEqual(mat.size(), [2,3], 'GetRotationMatrix2D');

  assert.end();
})

test(".norm", function(assert){
  cv.readImage("./examples/files/coin1.jpg", function(err, im) {
    cv.readImage("./examples/files/coin2.jpg", function(err, im2){
      assert.ok(im);
      assert.ok(im2);

      var errorL2 = im.norm(im2, cv.Constants.NORM_L2);
      assert.equal(errorL2, 7295.591339980605);

      errorL2 = im.norm(im, cv.Constants.NORM_L2);
      assert.equal(errorL2, 0);
      assert.end();
    });
  });
})

test("Matrix toBuffer", function(assert){
  var buf = fs.readFileSync('./examples/files/mona.png')

  cv.readImage(buf.slice(0), function(err, mat){
    var buf0 = mat.toBuffer()
    assert.ok(buf0);
    assert.end()
  })
})

test("Matrix toBuffer Async", function(assert){
  var buf = fs.readFileSync('./examples/files/mona.png')

  cv.readImage(buf.slice(0), function(err, mat){
    mat.toBuffer(function(err, buff){
      assert.error(err)
      assert.ok(buf)
      assert.ok(buf.length > 100)

      assert.end()
    })
  })
})

test("detectObject", function(assert){
  cv.readImage("./examples/files/mona.png", function(err, im){
    im.detectObject(cv.FACE_CASCADE, {}, function(err, faces){
      assert.error(err)
      assert.ok(faces)
      assert.equal(faces.length, 1)
      assert.end()
    })
  })
})

test(".absDiff and .countNonZero", function(assert){
  cv.readImage("./examples/files/mona.png", function(err, im) {
    cv.readImage("./examples/files/mona.png", function(err, im2){
      assert.ok(im);
      assert.ok(im2);

      var diff = new cv.Matrix(im.width(), im.height());
      diff.absDiff(im, im2);

      diff.convertGrayscale();
      assert.equal(diff.countNonZero(), 0);
      assert.end()
    });
  });
})

test(".bitwiseXor", function(assert){
  var mat1 = new cv.Matrix(1,1);
  mat1.set(0,0, 1);

  var mat2 = new cv.Matrix(1,1);
  mat2.set(0,0, 1);

  var xored = new cv.Matrix(1,1);
  xored.bitwiseXor(mat1, mat2);

  assert.equal(xored.get(0,0), 0);

  assert.end()
})

test("Image read from file", function(assert){
  cv.readImage("./examples/files/opencv.png", function(err, im){
    assert.ok(im);
    assert.equal(im.width(), 82);
    assert.equal(im.height(), 99);
    assert.equal(im.channels(), 4);
    assert.equal(im.empty(), false);
    assert.end();
  })
})

test("read Image from buffer", function(assert){
  cv.readImage(fs.readFileSync('./examples/files/opencv.png'), function(err, im){
    assert.ok(im);
    assert.equal(im.width(), 82);
    assert.equal(im.height(), 99);
    assert.equal(im.channels(), 4);
    assert.equal(im.empty(), false);
    assert.end();
  })
})

test("Cascade Classifier", function(assert){
  assert.ok(new cv.CascadeClassifier("./data/haarcascade_frontalface_alt.xml"), 'test constructor')

  cv.readImage("./examples/files/mona.png", function(err, im){
    cascade = new cv.CascadeClassifier("./data/haarcascade_frontalface_alt.xml");
    cascade.detectMultiScale(im, function(err, faces){//, 1.1, 2, [30, 30]);
      assert.error(err);
      assert.equal(typeof faces, typeof []);
      assert.equal(faces.length, 1)
      assert.end()
    })
  })
})

test("ImageDataStream", function(assert){
  var s = new cv.ImageDataStream()
  s.on('load', function(im){
    assert.ok(im)
    assert.equal(im.empty(), false);
    assert.end()
  })

  fs.createReadStream('./examples/files/mona.png').pipe(s);

})

test("ImageStream", function(assert){
  var s = new cv.ImageStream()
    , im = fs.readFileSync('./examples/files/mona.png')

  s.on('data', function(mat){
    assert.deepEqual(mat.size(), [756,500])
    assert.end()
  })
  s.write(im);
})

test("CamShift", function(assert){
  cv.readImage('./examples/files/coin1.jpg', function(e, im){
    cv.readImage('./examples/files/coin2.jpg', function(e, im2){
      var tracked = new cv.TrackedObject(im, [420, 110, 490, 170], {channel: 'v'});
      assert.ok(tracked);
      var res = tracked.track(im2)
      assert.ok(res);
      assert.ok(res[0]  < 396)
      assert.ok(res[0]  > 376)
      assert.ok(res[1]  < 122)
      assert.ok(res[1]  > 102)
      assert.ok(res[2]  < 469)
      assert.ok(res[2]  > 449)
      assert.ok(res[3]  < 176)
      assert.ok(res[3]  > 156)
      assert.end()
    })
  })
})

test("fonts", function(t) {

  function rnd() {
    return Math.round(Math.random() * 255);
  };

  cv.readImage("./examples/files/coin1.jpg", function(e, im){
    var y = 0;
    var scale = 1;

    ([
      "HERSEY_SIMPLEX",
      "HERSEY_PLAIN",
      "HERSEY_DUPLEX",
      "HERSEY_COMPLEX",
      "HERSEY_TRIPLEX",
      "HERSEY_COMPLEX_SMALL",
      "HERSEY_SCRIPT_SIMPLEX",
      "HERSEY_SCRIPT_COMPLEX",
      "HERSEY_SCRIPT_SIMPLEX"
    ]).forEach(function(font) {
      im.putText("Some text", 0, y += 20, font, [rnd(), rnd(), rnd()], 2, scale++);
    });

    t.ok(im, "image is ok");
    im.save("./examples/tmp/coin1-with-text.jpg");
    t.end();
  });
})

test('LDA Wrap', function(assert) {
  if (cv.LDA === undefined) {
    console.log('TODO: Please port LDAWrap.cc to OpenCV 3')
    assert.end();
    return;
  }

  // subspaceProject
  var mat = cv.LDA.subspaceProject(new cv.Matrix(1, 2, cv.Constants.CV_64F), new cv.Matrix(), new cv.Matrix(2, 1, cv.Constants.CV_8UC1));
  assert.deepEqual(mat.size(), [2,2], 'subspaceProject');

  // subspaceReconstruct
  mat = cv.LDA.subspaceReconstruct(new cv.Matrix(1, 2, cv.Constants.CV_64F), new cv.Matrix(), new cv.Matrix(1, 2, cv.Constants.CV_8UC1));
  assert.deepEqual(mat.size(), [1,1], 'subspaceReconstruct');

  assert.end();
})

test('Native Matrix', function(assert) {
  var nativemat = require('../build/Release/test_nativemat.node');
  var mat = new cv.Matrix(42, 8);

  assert.deepEqual(mat.size(), nativemat.size(mat), 'nativemat');
  assert.end();
})

test('Subtract', function(assert) {
  var a = new cv.Matrix.Zeros(1,1);
  a.set(0, 0, 3);
  var b = new cv.Matrix.Zeros(1,1);
  b.set(0, 0, 1);
  a.subtract(b);
  assert.deepEqual(a.get(0, 0), 2);
  assert.end();
});

test('Mean', function(assert) {
  var a = new cv.Matrix.Zeros(2, 2, cv.Constants.CV_8UC3);

  // Set [0, 0] element to 1 for all three channels
  a.set(0, 0, 1, 0);
  a.set(0, 0, 1, 1);
  a.set(0, 0, 1, 2);

  var means = a.mean();
  assert.deepEqual(means, [0.25, 0.25, 0.25, 0]);
  assert.end();
});

test('MatchTemplateByMatrix', function(assert) {
  var cv = require('../lib/opencv');
  cv.readImage("./examples/files/car1.jpg", function(err, target){
    cv.readImage("./examples/files/car1_template.jpg", function(err, template){
      var res = target.matchTemplateByMatrix(template, cv.Constants.TM_CCORR_NORMED);
      var minMax = res.minMaxLoc();
      var topLeft = minMax.maxLoc;
      assert.ok(topLeft, "Found Match");
      console.log(topLeft.x === 717);
      assert.equal(topLeft.x, 717, "match location x === 717");
      assert.equal(topLeft.y, 0, "match location y === 717");
      assert.end();
    });
  })
});

// Test the examples folder.
require('./examples')()
<|endoftext|>


<commit_before>"use strict";
require('es6-shim');
require('prfun');

var program = require('commander');
var json = require('../package.json');

var fs = require('fs');
var Pusher = require('pusher-client');
var url = require('url');

var p = require('./p');
var request = require('./retry-request');

var CHILD_IGNORE = { childOptions: { stdio: 'ignore' } };
var readFile = Promise.promisify(fs.readFile, false, fs);

program
	.version(json.version)
	.usage('[options] [github project]')
	.option(
		'--travis-api <url>',
		'Travis API endpoint [https://api.travis-ci.org]',
		'https://api.travis-ci.org'
	).option(
		'-j, --job <n>',
		'Only follow the specified job (job numbers start at 1)'
	);

program.parse(process.argv);

if (program.args.length > 1) {
	console.error('Too many arguments.');
	return 1;
}

var getUserAgent = function(repo) {
	return json.name + '/' + json.version + ' (' +
		'node ' + process.version + ' ' + process.platform + ' ' + process.arch +
		') ' + repo;
};

var gitRemoteRegex =
	/Push\s+URL:\s+(?:https?:\/\/github.com\/|git@github.com:)([^\/]+)\/([^\/]+?)(?:\.git)?\s/;

var getRepoName = function() {
	return Promise.resolve(program.args[0]).then(function(reponame) {
		if (reponame) { return reponame; }
		// look in .git/config for 'github' remote
		return p.execFile('git', ['remote','show','github']).then(function(out){
			var m = gitRemoteRegex.exec(out.stdout);
			if (m) {
				return m[1] + '/' + m[2];
			}
		});
	}).catch(function(e) { /* ignore */ }).then(function(reponame) {
		if (reponame) { return reponame; }
		// look in .git/config for 'origin' remote
		return p.execFile('git', ['remote','show','origin']).then(function(out){
			var m = gitRemoteRegex.exec(out.stdout);
			if (m) {
				return m[1] + '/' + m[2];
			}
		});
	}).catch(function(e) { /* ignore */ }).then(function(reponame) {
		if (reponame) { return reponame; }
		// look in ./package.json
		return readFile(
			'./package.json', { encoding: 'utf8' }
		).then(function(data) {
			var json = JSON.parse(data);
			if (json.repository && json.repository.type === 'git') {
				var m =
					/^(https?:\/\/github.com\/)?([^\/]+)\/([^\/]+?)(\.git)?$/.
					exec(json.repository.url || '');
				if (m) {
					return m[2] + '/' + m[3];
				}
			}
		});
	}).catch(function(e) { /* ignore */ }).then(function(reponame) {
		if (reponame) { return reponame; }
		throw new Error("Can't determine github repo name.");
	});
};

// ensure that there is a github remote, named 'github'
var ensureRemote = function(repo) {
	return p.spawn('git', ['remote', 'show', 'github'], CHILD_IGNORE).then(function() {
		/* ok, github already exists */
	}, function(e) {
		/* doesn't exist, create it! */
		return p.spawn('git', ['remote','add','github','git@github.com:'+repo]);
	});
};

// get the hash of HEAD
var getGitHead = function() {
	return p.execFile('git', ['rev-parse', 'HEAD']).then(function(out) {
		return out.stdout.trim();
	});
};

// create the new branch name
var getBranchName = function(hash) {
	return json.name + '-' + hash.slice(0, 8);
};

// push to github
var ensureBranch = function(repo, branchname) {
	return ensureRemote(repo).then(function() {
		return p.spawn('git', ['push', 'github', 'HEAD:'+branchname], CHILD_IGNORE);
	});
};

var deleteBranch = function(repo, branchname) {
	return ensureRemote(repo).then(function() {
		return p.spawn('git', ['push', 'github', ':'+branchname], {
			timeout: 60*1000,
			childOptions: CHILD_IGNORE.childOptions
		});
	});
};

var apiRequest = function(path, opts) {
	opts = opts || {};
	var apiURL = url.resolve(program.travisApi, path);
	var mimeType = 'application/vnd.travis-ci.2+json';
	if (opts.chunked) {
		mimeType += '; chunked=true';
	}
	return request({
		url: apiURL,
		encoding: 'utf8',
		pool: false,
		headers: {
			'User-Agent': getUserAgent(),
			'Accept': mimeType
		},
		retries: opts.retries,
		delay: opts.delay,
		timeout: opts.timeout
	}).then(function(resp) {
		if (resp.response.statusCode !== 200) {
			throw new Error("Bad status: "+resp.response.statusCode);
		}
		return opts.raw ? resp.body : JSON.parse(resp.body);
	});
};

var getTravisConfig = function() {
	return apiRequest('/config').get('config');
};

var getTravisBuild = function(repo, branch, retry) {
	return apiRequest('/repos/'+repo+'/branches/'+branch, {
		timeout: 30 * 1000,
		delay:   5 * 1000, /* check every 5 seconds */
		retries: retry ? 3 * 12 : 0 /* for up to 3 minutes */
	}).get('branch');
};

var getTravisJob = function(job_id) {
	return apiRequest('/jobs/'+job_id).get('job');
};

var getTravisLog = function(log_id, chunked) {
	return apiRequest('/logs/'+log_id, {
		chunked: chunked,
	}).get('log');
};

var Log = function() {
	this.chunks = [];
	this.next = 1;
	this._last = -1;
};
Log.prototype.add = function(n, data) {
	this.chunks[n] = data;
	this.advance();
	return (n === this._last);
};
Log.prototype.advance = function() {
	while (this.chunks[this.next] !== undefined) {
		process.stdout.write(this.chunks[this.next++]);
	}
};
Log.prototype.last = function(n) {
	this._last = n;
};

var doit = function() {
	var state = {}, pusher;
	var initState = function() {
		return Promise.all([
			getTravisConfig().then(function(config) {
				state.config = config;
				pusher = new Pusher(state.config.pusher.key);
				if (false) { /* debugging */
					pusher.connection.on('message', function(message) {
						console.log('GOT PUSHER MESSAGE', message);
					});
				}
			}),
			getGitHead().then(function(hash) {
				state.githash = hash;
				state.branch = getBranchName(hash);
			}),
			getRepoName().then(function(repo) {
				state.repo = repo;
			})
		]).then(function() {
			// check to see if builds on this branch already exist
			return getTravisBuild(state.repo, state.branch, false).catch(function(e) {
				// doesn't yet exist; push to github and then retry query until
				// we see the build show up in travis.
				return ensureBranch(state.repo, state.branch).then(function() {
					return getTravisBuild(state.repo, state.branch, true);
				});
			});
		}).then(function(build) {
			// ok, we've got a build on this branch!
			state.build = build;
			console.log(
				'==> Travis build',
				state.build.number,
				'(',
				'https://'+state.config.host+'/'+state.repo+'/builds/'+state.build.id,
				')'
			);
			return state;
		});
	};
	var watchJob = function(job_num) {
		return Promise.resolve().then(function() {
			state.job_num = job_num;
			state.job_id = state.build.job_ids[state.job_num - 1];
			console.log(
				'==> Travis job',
				state.build.number+'.'+state.job_num,
				'(',
				'https://'+state.config.host+'/'+state.repo+'/jobs/'+state.job_id,
				')'
			);
			// check job #
			if (!state.job_id) {
				throw new Error(
					"Bad job number: " + state.job_num +
						" ("+state.build.job_ids.length+" jobs)"
				);
			}
			return getTravisJob(state.job_id);
		}).then(function(job) {
			state.job = job;
			var log = new Log();
			if (/^(passed|failed)$/.test(state.job.state || '')) {
				// fetch all the logs, easy-peasy
				return getTravisLog(state.job.log_id, false/*not chunked*/).then(function(resp_log) {
					log.last(1);
					log.add(1, resp_log.body);
				});
			}
			// hm, we need to stream the logs.
			var channelName = 'job-' + state.job_id;
			var channel = pusher.subscribe(channelName);
			var streamResolve;
			var handleChunk = function(data) {
				var content = data._log !== undefined ? data._log : data.content;
				if (data.final) {
					log.last(data.number + 1); // weird!
				}
				var last = log.add(data.number, content);
				if (last) { streamResolve(); }
			};
			return Promise.all([
				// fetch chunked log to fill in gaps
				new Promise(function(resolve, reject) {
					channel.bind('pusher:subscription_succeeded', function() {
						getTravisLog(state.job.log_id, true /* chunked */).then(function(resp_log) {
							resp_log.parts.forEach(handleChunk);
						}).then(resolve, reject);
					});
				}),
				// tail log for this job
				new Promise(function(resolve, reject) {
					streamResolve = resolve;
					channel.bind('job:log', handleChunk);
					channel.bind('job:finished', streamResolve);
				}).then(function() {
					pusher.unsubscribe(channelName);
				})
			]);
		}).then(function() {
			return getTravisJob(state.job_id);
		}).then(function(job) {
			state.job = job;
			return state.job.state;
		});
	};
	var cleanup = function() {
		return Promise.resolve().then(function() {
			pusher.disconnect();
			return getTravisBuild(state.repo, state.branch, false);
		}).then(function(build) {
			state.build = build;
			// if build is complete (all jobs), we can clean up the branch
			if (/^(passed|failed)$/.test(state.build.state || '')) {
				return deleteBranch(state.repo, state.branch).catch(function(e) {
					/* ignore failure, maybe already deleted */
				});
			}
		});
	};

	// ok, put all the pieces together
	return initState().then(function() {
		if (program.job !== undefined) {
			// watch one particular job
			return watchJob((+program.job));
		}
		// watch all jobs
		return Promise.reduce(state.build.job_ids, function(_,jid,index) {
			return watchJob(index + 1);
		}, null);
	}).then(function() {
		return cleanup();
	}).then(function() {
		if (program.job !== undefined) {
			// return our job status
			return state.job.state;
		}
		// return our build status
		return state.build.state;
	});
};

doit().then(function(status) {
	console.log('==> ' + json.name + ': '+ status);
	if (status !== 'passed') {
		process.exit(1);
	} else {
		process.exit(0);
	}
}).done();
<commit_msg>Add `--remote` CLI option to customize git remote name.<commit_after>"use strict";
require('es6-shim');
require('prfun');

var program = require('commander');
var json = require('../package.json');

var fs = require('fs');
var Pusher = require('pusher-client');
var url = require('url');

var p = require('./p');
var request = require('./retry-request');

var CHILD_IGNORE = { childOptions: { stdio: 'ignore' } };
var readFile = Promise.promisify(fs.readFile, false, fs);

program
	.version(json.version)
	.usage('[options] [github user/project]')
	.option(
		'--travis-api <url>',
		'Travis API endpoint [https://api.travis-ci.org]',
		'https://api.travis-ci.org'
	).option(
		'--remote <name>',
		'Use the specified git remote for push [github]',
		'github'
	).option(
		'-j, --job <n>',
		'Only follow the specified job (job numbers start at 1)'
	);

program.parse(process.argv);

if (program.args.length > 1) {
	console.error('Too many arguments.');
	return 1;
}

var getUserAgent = function(repo) {
	return json.name + '/' + json.version + ' (' +
		'node ' + process.version + ' ' + process.platform + ' ' + process.arch +
		') ' + repo;
};

var gitRemoteRegex =
	/Push\s+URL:\s+(?:https?:\/\/github.com\/|git@github.com:)([^\/]+)\/([^\/]+?)(?:\.git)?\s/;

var getRepoName = function() {
	return Promise.resolve(program.args[0]).then(function(reponame) {
		if (reponame) { return reponame; }
		// look in .git/config for 'github' remote
		return p.execFile('git', ['remote','show',program.remote]).then(function(out){
			var m = gitRemoteRegex.exec(out.stdout);
			if (m) {
				return m[1] + '/' + m[2];
			}
		});
	}).catch(function(e) { /* ignore */ }).then(function(reponame) {
		if (reponame) { return reponame; }
		// look in .git/config for 'origin' remote
		return p.execFile('git', ['remote','show','origin']).then(function(out){
			var m = gitRemoteRegex.exec(out.stdout);
			if (m) {
				return m[1] + '/' + m[2];
			}
		});
	}).catch(function(e) { /* ignore */ }).then(function(reponame) {
		if (reponame) { return reponame; }
		// look in ./package.json
		return readFile(
			'./package.json', { encoding: 'utf8' }
		).then(function(data) {
			var json = JSON.parse(data);
			if (json.repository && json.repository.type === 'git') {
				var m =
					/^(https?:\/\/github.com\/)?([^\/]+)\/([^\/]+?)(\.git)?$/.
					exec(json.repository.url || '');
				if (m) {
					return m[2] + '/' + m[3];
				}
			}
		});
	}).catch(function(e) { /* ignore */ }).then(function(reponame) {
		if (reponame) { return reponame; }
		throw new Error("Can't determine github repo name.");
	});
};

// ensure that there is a github remote, named 'github'
var ensureRemote = function(repo) {
	return p.spawn('git', ['remote', 'show', program.remote], CHILD_IGNORE).then(function() {
		/* ok, github already exists */
	}, function(e) {
		/* doesn't exist, create it! */
		return p.spawn('git', ['remote','add',program.remote,'git@github.com:'+repo]);
	});
};

// get the hash of HEAD
var getGitHead = function() {
	return p.execFile('git', ['rev-parse', 'HEAD']).then(function(out) {
		return out.stdout.trim();
	});
};

// create the new branch name
var getBranchName = function(hash) {
	return json.name + '-' + hash.slice(0, 8);
};

// push to github
var ensureBranch = function(repo, branchname) {
	return ensureRemote(repo).then(function() {
		return p.spawn('git', ['push', program.remote, 'HEAD:'+branchname], CHILD_IGNORE);
	});
};

var deleteBranch = function(repo, branchname) {
	return ensureRemote(repo).then(function() {
		return p.spawn('git', ['push', program.remote, ':'+branchname], {
			timeout: 60*1000,
			childOptions: CHILD_IGNORE.childOptions
		});
	});
};

var apiRequest = function(path, opts) {
	opts = opts || {};
	var apiURL = url.resolve(program.travisApi, path);
	var mimeType = 'application/vnd.travis-ci.2+json';
	if (opts.chunked) {
		mimeType += '; chunked=true';
	}
	return request({
		url: apiURL,
		encoding: 'utf8',
		pool: false,
		headers: {
			'User-Agent': getUserAgent(),
			'Accept': mimeType
		},
		retries: opts.retries,
		delay: opts.delay,
		timeout: opts.timeout
	}).then(function(resp) {
		if (resp.response.statusCode !== 200) {
			throw new Error("Bad status: "+resp.response.statusCode);
		}
		return opts.raw ? resp.body : JSON.parse(resp.body);
	});
};

var getTravisConfig = function() {
	return apiRequest('/config').get('config');
};

var getTravisBuild = function(repo, branch, retry) {
	return apiRequest('/repos/'+repo+'/branches/'+branch, {
		timeout: 30 * 1000,
		delay:   5 * 1000, /* check every 5 seconds */
		retries: retry ? 3 * 12 : 0 /* for up to 3 minutes */
	}).get('branch');
};

var getTravisJob = function(job_id) {
	return apiRequest('/jobs/'+job_id).get('job');
};

var getTravisLog = function(log_id, chunked) {
	return apiRequest('/logs/'+log_id, {
		chunked: chunked,
	}).get('log');
};

var Log = function() {
	this.chunks = [];
	this.next = 1;
	this._last = -1;
};
Log.prototype.add = function(n, data) {
	this.chunks[n] = data;
	this.advance();
	return (n === this._last);
};
Log.prototype.advance = function() {
	while (this.chunks[this.next] !== undefined) {
		process.stdout.write(this.chunks[this.next++]);
	}
};
Log.prototype.last = function(n) {
	this._last = n;
};

var doit = function() {
	var state = {}, pusher;
	var initState = function() {
		return Promise.all([
			getTravisConfig().then(function(config) {
				state.config = config;
				pusher = new Pusher(state.config.pusher.key);
				if (false) { /* debugging */
					pusher.connection.on('message', function(message) {
						console.log('GOT PUSHER MESSAGE', message);
					});
				}
			}),
			getGitHead().then(function(hash) {
				state.githash = hash;
				state.branch = getBranchName(hash);
			}),
			getRepoName().then(function(repo) {
				state.repo = repo;
			})
		]).then(function() {
			// check to see if builds on this branch already exist
			return getTravisBuild(state.repo, state.branch, false).catch(function(e) {
				// doesn't yet exist; push to github and then retry query until
				// we see the build show up in travis.
				return ensureBranch(state.repo, state.branch).then(function() {
					return getTravisBuild(state.repo, state.branch, true);
				});
			});
		}).then(function(build) {
			// ok, we've got a build on this branch!
			state.build = build;
			console.log(
				'==> Travis build',
				state.build.number,
				'(',
				'https://'+state.config.host+'/'+state.repo+'/builds/'+state.build.id,
				')'
			);
			return state;
		});
	};
	var watchJob = function(job_num) {
		return Promise.resolve().then(function() {
			state.job_num = job_num;
			state.job_id = state.build.job_ids[state.job_num - 1];
			console.log(
				'==> Travis job',
				state.build.number+'.'+state.job_num,
				'(',
				'https://'+state.config.host+'/'+state.repo+'/jobs/'+state.job_id,
				')'
			);
			// check job #
			if (!state.job_id) {
				throw new Error(
					"Bad job number: " + state.job_num +
						" ("+state.build.job_ids.length+" jobs)"
				);
			}
			return getTravisJob(state.job_id);
		}).then(function(job) {
			state.job = job;
			var log = new Log();
			if (/^(passed|failed)$/.test(state.job.state || '')) {
				// fetch all the logs, easy-peasy
				return getTravisLog(state.job.log_id, false/*not chunked*/).then(function(resp_log) {
					log.last(1);
					log.add(1, resp_log.body);
				});
			}
			// hm, we need to stream the logs.
			var channelName = 'job-' + state.job_id;
			var channel = pusher.subscribe(channelName);
			var streamResolve;
			var handleChunk = function(data) {
				var content = data._log !== undefined ? data._log : data.content;
				if (data.final) {
					log.last(data.number + 1); // weird!
				}
				var last = log.add(data.number, content);
				if (last) { streamResolve(); }
			};
			return Promise.all([
				// fetch chunked log to fill in gaps
				new Promise(function(resolve, reject) {
					channel.bind('pusher:subscription_succeeded', function() {
						getTravisLog(state.job.log_id, true /* chunked */).then(function(resp_log) {
							resp_log.parts.forEach(handleChunk);
						}).then(resolve, reject);
					});
				}),
				// tail log for this job
				new Promise(function(resolve, reject) {
					streamResolve = resolve;
					channel.bind('job:log', handleChunk);
					channel.bind('job:finished', streamResolve);
				}).then(function() {
					pusher.unsubscribe(channelName);
				})
			]);
		}).then(function() {
			return getTravisJob(state.job_id);
		}).then(function(job) {
			state.job = job;
			return state.job.state;
		});
	};
	var cleanup = function() {
		return Promise.resolve().then(function() {
			pusher.disconnect();
			return getTravisBuild(state.repo, state.branch, false);
		}).then(function(build) {
			state.build = build;
			// if build is complete (all jobs), we can clean up the branch
			if (/^(passed|failed)$/.test(state.build.state || '')) {
				return deleteBranch(state.repo, state.branch).catch(function(e) {
					/* ignore failure, maybe already deleted */
				});
			}
		});
	};

	// ok, put all the pieces together
	return initState().then(function() {
		if (program.job !== undefined) {
			// watch one particular job
			return watchJob((+program.job));
		}
		// watch all jobs
		return Promise.reduce(state.build.job_ids, function(_,jid,index) {
			return watchJob(index + 1);
		}, null);
	}).then(function() {
		return cleanup();
	}).then(function() {
		if (program.job !== undefined) {
			// return our job status
			return state.job.state;
		}
		// return our build status
		return state.build.state;
	});
};

doit().then(function(status) {
	console.log('==> ' + json.name + ': '+ status);
	if (status !== 'passed') {
		process.exit(1);
	} else {
		process.exit(0);
	}
}).done();
<|endoftext|>


<commit_before>var files = window.__karma__.files;
var start = window.__karma__.start;
var tests = [];

Object.keys(files).forEach(function (file) {
  if (file.indexOf('/unit/') > -1) {
    tests.push(file);
  }
});

afterEach(function () {
  skate.destroy();
});

require(tests, start);
<commit_msg>Ensure beforeEach is called with an AMD version of skate.<commit_after>var files = window.__karma__.files;
var start = window.__karma__.start;
var tests = [];

Object.keys(files).forEach(function (file) {
  if (file.indexOf('/unit/') > -1) {
    tests.push(file);
  }
});

require(['/base/src/skate.js'], function (skate) {
  afterEach(skate.destroy);
  require(tests, start);
});
<|endoftext|>


<commit_before>export default {
  abc: 200,
  name: 'lu'
};
<commit_msg>add age<commit_after>export default {
  abc: 200,
  name: 'lu',
  age: 20
};
<|endoftext|>


<commit_before>"use strict";

// For generating the coverage badge
var path = require("path");
var downloader = require("./downloader");
var reportParser = require("./istanbulReportParser");
var defaultThresholds = require("./defaultThresholds");
var extend = require("xtend");

// exporting the plugin main function
module.exports = istanbulCoberturaBadger;

/**
 * Creates a code coverage badge based on the cobertura report generated by istanbul.
 *
 * @param {Object} opts is the set of properties provided to the api.
 * @param {Function} callback is the CPS function to get the results.
 */
function istanbulCoberturaBadger(opts, callback) {
  // Resolve the options
  opts = extend({
    // Setting the default coverage file generated by istanbul cobertura report.
    istanbulReportFile: "./coverage/cobertura-coverage.xml",
    // The default location for the destination being the coverage directory from istanbul.
    destinationDir: null,
    // The shields host to be used for retrieving the badge. https://github.com/badges/shields
    shieldsHost: process.env.SHIELDS_HOST || "https://img.shields.io",
    // The style of shield icon to generate (plastic, flat-square, flat)
    shieldStyle: "flat",
    // The name of the badge file to be generated
    badgeFileName: "coverage",
    // The thresholds to be used to give colors to the badge.
    thresholds: defaultThresholds
  }, opts);

  reportParser(opts.istanbulReportFile, function(err, report) {
    if (err) {
      return callback(err);
    }

    // The color depends on the fixed thresholds (RED: 0 >= % < 60) (YELLOW: 60 >= % < 90) (GREEN: % >= 90)
    var color = report.overallPercent >= opts.thresholds.excellent ? "brightgreen" :
      (report.overallPercent >= opts.thresholds.good ? "yellow" : "red");

    // The shields service that will give badges.
    var url = opts.shieldsHost + "/badge/coverage-" + report.overallPercent + "%-" + color + ".svg?style=" + opts.shieldStyle;

    // Save always as coverage image.
    var badgeFileName = path.join(opts.destinationDir, opts.badgeFileName + ".svg");

    downloader(url, badgeFileName, function(err, downloadResult) {
      if (err) {
        return callback(err);
      }

      report.url = url;
      report.badgeFile = downloadResult;
      report.color = color;

      return callback(null, report);
    });
  });
}
<commit_msg>Update index.js<commit_after>"use strict";

// For generating the coverage badge
var path = require("path");
var downloader = require("./downloader");
var reportParser = require("./istanbulReportParser");
var defaultThresholds = require("./defaultThresholds");
var extend = require("xtend");

// exporting the plugin main function
module.exports = istanbulCoberturaBadger;

/**
 * Creates a code coverage badge based on the cobertura report generated by istanbul.
 *
 * @param {Object} opts is the set of properties provided to the api.
 * @param {Function} callback is the CPS function to get the results.
 */
function istanbulCoberturaBadger(opts, callback) {
  // Resolve the options
  opts = extend({
    // Setting the default coverage file generated by istanbul cobertura report.
    istanbulReportFile: "./coverage/cobertura-coverage.xml",
    // The default location for the destination being the coverage directory from istanbul.
    destinationDir: null,
    // The shields host to be used for retrieving the badge. https://github.com/badges/shields
    shieldsHost: process.env.SHIELDS_HOST || "https://img.shields.io",
    // The style of shield icon to generate (plastic, flat-square, flat)
    shieldStyle: "flat",
    // The name of the badge file to be generated
    badgeFileName: "coverage",
    // The thresholds to be used to give colors to the badge.
    thresholds: defaultThresholds
  }, opts);

  reportParser(opts.istanbulReportFile, function(err, report) {
    if (err) {
      return callback(err);
    }

    // The color depends on the fixed thresholds (RED: 0 >= % < 60) (YELLOW: 60 >= % < 90) (GREEN: % >= 90)
    var color = report.overallPercent >= opts.thresholds.excellent ? "brightgreen" :
      (report.overallPercent >= opts.thresholds.good ? "yellow" : "red");

    // The shields service that will give badges.
    var url = opts.shieldsHost + "/badge/coverage-" + report.overallPercent;
    url += "%-" + color + ".svg?style=" + opts.shieldStyle;

    // Save always as coverage image.
    var badgeFileName = path.join(opts.destinationDir, opts.badgeFileName + ".svg");

    downloader(url, badgeFileName, function(err, downloadResult) {
      if (err) {
        return callback(err);
      }

      report.url = url;
      report.badgeFile = downloadResult;
      report.color = color;

      return callback(null, report);
    });
  });
}
<|endoftext|>


<commit_before>var sanitize_input = function(input) {
  // http://www.postgresql.org/docs/9.0/static/sql-syntax-lexical.html [4.1.2.1-4.1.2.2]
  // single quotes (') must be replaced with double single quotes ('')
  input = input.replace(/'/, '\'\'');
  // backslashes (\) must be replaced with double backslashes (\\)
  input = input.replace(/\\/, '\\\\');
  return input;
};

var to_string = function(input) {
  switch(typeof input) {
    case 'boolean':
    case 'number':
      return String(input);
    case 'string':
      return sanitize_input(input);
    default:
      return '';
  }
};

module.exports = {
  stringify: function (data, callback) {
    var hstore = Object.keys(data).map(function (key) {
      return '"'+key+'"=>"'+to_string(data[key])+'"';
    });
    callback(hstore.join());
  },

  parse: function(value, callback) {
    var result = {};
    var hstore = value.split(',').forEach(function(pair) {
      var split = pair.split('=>');
      var key = split[0].replace(/"/g, '').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
      var value = split[1].replace(/"/g, '');
      result[key] = value;
    });
    callback(result);
  }
};<commit_msg>add support for callback or stndrd return value<commit_after>var sanitize_input = function(input) {
  // http://www.postgresql.org/docs/9.0/static/sql-syntax-lexical.html [4.1.2.1-4.1.2.2]
  // single quotes (') must be replaced with double single quotes ('')
  input = input.replace(/'/, '\'\'');
  // backslashes (\) must be replaced with double backslashes (\\)
  input = input.replace(/\\/, '\\\\');
  return input;
};

var to_string = function(input) {
  switch(typeof input) {
    case 'boolean':
    case 'number':
      return String(input);
    case 'string':
      return sanitize_input(input);
    default:
      return '';
  }
};

module.exports = {
  stringify: function (data, callback) {
    var hstore = Object.keys(data).map(function (key) {
      return '"'+key+'"=>"'+to_string(data[key])+'"';
    });
    var joined = hstore.join();
    if (!callback || callback === null) return joined;
    callback(joined);
  },

  parse: function(value, callback) {
    var result = {};
    var hstore = value.split(',').forEach(function(pair) {
      var split = pair.split('=>');
      var key = split[0].replace(/"/g, '').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
      var value = split[1].replace(/"/g, '');
      result[key] = value;
    });
    if (!callback || callback === null) return result;
    callback(result);
  }
};<|endoftext|>


<commit_before>var $ = require('jquery');

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var Enemy = require("./enemies.js");
var Bluecifer = require('./bluecifer');

var bluecifer = new Bluecifer (150, 150, 50, 41);

var enemy = new Enemy();
var enemy2 = new Enemy();

function newEnemy () {
  enemy.draw(ctx);
  enemy.moveLeftRandom();
}

function newEnemy2 () {

  setTimeout(function() {
    enemy2.draw(ctx);
    enemy2.moveLeftRandom();
    return enemy2;
  }, 3000);

}

var fps = 30;

function repeat () {
  setTimeout(function() {
    requestAnimationFrame(repeat);
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    bluecifer.draw(ctx);
    bluecifer.gravity();
    newEnemy();
    newEnemy2();
    detectFloorCollision();
  }, 1000 / fps);

}

repeat();

// setInterval(function () {
//   requestAnimationFrame(repeat);
// }, 10000 / fps);

function detectFloorCollision () {
  if (bluecifer.y > 350) {
    console.log("game over!");
    bluecifer.y = 300;
  }
}

$(document).on('keydown', function (e) {
  var code = e.keyCode || e.which;
  if (code === 32) {
    bluecifer.moveUp();
    detectCeilingCollision();
  } else {
    return false;
  }
});

function detectCeilingCollision () {
  if (bluecifer.y < 0) {
    bluecifer.y = bluecifer.y + 10;
  }
}
<commit_msg>stopped the flashing of second enemy by putting enemy.draw() outside of setTimeout<commit_after>var $ = require('jquery');

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var Enemy = require("./enemies.js");
var Bluecifer = require('./bluecifer');

var bluecifer = new Bluecifer (150, 150, 50, 41);

var enemy = new Enemy();
var enemy2 = new Enemy();

function newEnemy () {
  enemy.draw(ctx);
  enemy.moveLeftRandom();
}

function newEnemy2 () {

  enemy2.draw(ctx);
  setTimeout(function() {
    enemy2.moveLeftRandom();
    return enemy2;
  }, 3000);

}

var fps = 30;

function repeat () {
  setTimeout(function() {
    requestAnimationFrame(repeat);
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    bluecifer.draw(ctx);
    bluecifer.gravity();
    newEnemy();
    newEnemy2();
    detectFloorCollision();
  }, 1000 / fps);

}

repeat();

// setInterval(function () {
//   requestAnimationFrame(repeat);
// }, 10000 / fps);

function detectFloorCollision () {
  if (bluecifer.y > 350) {
    console.log("game over!");
    bluecifer.y = 300;
  }
}

$(document).on('keydown', function (e) {
  var code = e.keyCode || e.which;
  if (code === 32) {
    bluecifer.moveUp();
    detectCeilingCollision();
  } else {
    return false;
  }
});

function detectCeilingCollision () {
  if (bluecifer.y < 0) {
    bluecifer.y = bluecifer.y + 10;
  }
}
<|endoftext|>


<commit_before>/* global fetch */
import LokkaTransport from 'lokka/transport';
// In some envionment like in ReactNative, we don't need fetch at all.
// Technically, this should be handle by 'isomorphic-fetch'.
// But it's not happening. So this is the fix

const isNode = new Function('try {return this===global;}catch(e){return false;}');

let fetchUrl;
if (typeof fetch === 'function') {
  // has a native fetch implementation
  fetchUrl = fetch;
} else if (isNode()) {
  // for Node.js
  fetchUrl = require('node-fetch');
  fetchUrl.Promise = Promise;
} else {
  // for the browser
  require('whatwg-fetch');
  fetchUrl = fetch;
}

// the default error handler
function handleErrors(errors) {
  const message = errors[0].message;
  const error = new Error(`GraphQL Error: ${message}`);
  error.rawError = errors;
  error.rawData = data;
  throw error;
}

export class Transport extends LokkaTransport {
  constructor(endpoint, options = {}) {
    if (!endpoint) {
      throw new Error('endpoint is required!');
    }

    super();
    this._httpOptions = {
      auth: options.auth,
      headers: options.headers || {},
      credentials: options.credentials,
    };
    this.endpoint = endpoint;
    this.handleErrors = options.handleErrors || handleErrors;
  }

  _buildOptions(payload) {
    const options = {
      method: 'post',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(payload),
      // To pass cookies to the server. (supports CORS as well)
      credentials: 'include',
    };

    // use delete property for backward compatibility
    if(this._httpOptions.credentials === false) delete options.credentials;

    Object.assign(options.headers, this._httpOptions.headers);
    return options;
  }

  send(query, variables, operationName) {
    const payload = {query, variables, operationName};
    const options = this._buildOptions(payload);

    return fetchUrl(this.endpoint, options).then(response => {
      // 200 is for success
      // 400 is for bad request
      if (response.status !== 200 && response.status !== 400) {
        throw new Error(`Invalid status code: ${response.status}`);
      }

      return response.json();
    }).then(({data, errors}) => {
      if (errors) {
        this.handleErrors(errors);
        return null;
      }

      return data;
    });
  }
}

export default Transport;
<commit_msg>Fix #18.<commit_after>/* global fetch */
import LokkaTransport from 'lokka/transport';
// In some envionment like in ReactNative, we don't need fetch at all.
// Technically, this should be handle by 'isomorphic-fetch'.
// But it's not happening. So this is the fix

const isNode = new Function('try {return this===global;}catch(e){return false;}');

let fetchUrl;
if (typeof fetch === 'function') {
  // has a native fetch implementation
  fetchUrl = fetch;
} else if (isNode()) {
  // for Node.js
  fetchUrl = require('node-fetch');
  fetchUrl.Promise = Promise;
} else {
  // for the browser
  require('whatwg-fetch');
  fetchUrl = fetch;
}

// the default error handler
function handleErrors(errors, data) {
  const message = errors[0].message;
  const error = new Error(`GraphQL Error: ${message}`);
  error.rawError = errors;
  error.rawData = data;
  throw error;
}

export class Transport extends LokkaTransport {
  constructor(endpoint, options = {}) {
    if (!endpoint) {
      throw new Error('endpoint is required!');
    }

    super();
    this._httpOptions = {
      auth: options.auth,
      headers: options.headers || {},
      credentials: options.credentials,
    };
    this.endpoint = endpoint;
    this.handleErrors = options.handleErrors || handleErrors;
  }

  _buildOptions(payload) {
    const options = {
      method: 'post',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(payload),
      // To pass cookies to the server. (supports CORS as well)
      credentials: 'include',
    };

    // use delete property for backward compatibility
    if (this._httpOptions.credentials === false) {
      delete options.credentials;
    }

    Object.assign(options.headers, this._httpOptions.headers);
    return options;
  }

  send(query, variables, operationName) {
    const payload = {query, variables, operationName};
    const options = this._buildOptions(payload);

    return fetchUrl(this.endpoint, options).then(response => {
      // 200 is for success
      // 400 is for bad request
      if (response.status !== 200 && response.status !== 400) {
        throw new Error(`Invalid status code: ${response.status}`);
      }

      return response.json();
    }).then(({data, errors}) => {
      if (errors) {
        this.handleErrors(errors, data);
        return null;
      }

      return data;
    });
  }
}

export default Transport;
<|endoftext|>


<commit_before><commit_msg>implemented bootstrapping testing code<commit_after>var requirejs = require('requirejs');

requirejs.config({
    //Pass the top-level main.js/index.js require
    //function to requirejs so that node modules
    //are loaded relative to the top-level JS file.
    nodeRequire: require
});

requirejs(['Board'], function (Board) {
    var b = Board.initBitBoard(2, 8, 8);

    b.printBoard();

});
<|endoftext|>


<commit_before>"use strict";

const validateSchema = require("./validators/schema");
const validateSpec = require("./validators/spec");
const normalizeArgs = require("json-schema-ref-parser/lib/normalize-args");
const util = require("./util");
const Options = require("./options");
const maybe = require("call-me-maybe");
const { ono } = require("ono");
const $RefParser = require("json-schema-ref-parser");
const dereference = require("json-schema-ref-parser/lib/dereference");

module.exports = SwaggerParser;

/**
 * This class parses a Swagger 2.0 or 3.0 API, resolves its JSON references and their resolved values,
 * and provides methods for traversing, dereferencing, and validating the API.
 *
 * @constructor
 * @extends $RefParser
 */
function SwaggerParser () {
  $RefParser.apply(this, arguments);
}

util.inherits(SwaggerParser, $RefParser);
SwaggerParser.YAML = $RefParser.YAML;
SwaggerParser.parse = $RefParser.parse;
SwaggerParser.resolve = $RefParser.resolve;
SwaggerParser.bundle = $RefParser.bundle;
SwaggerParser.dereference = $RefParser.dereference;

/**
 * Alias {@link $RefParser#schema} as {@link SwaggerParser#api}
 */
Object.defineProperty(SwaggerParser.prototype, "api", {
  configurable: true,
  enumerable: true,
  get () {
    return this.schema;
  }
});

/**
 * Parses the given Swagger API.
 * This method does not resolve any JSON references.
 * It just reads a single file in JSON or YAML format, and parse it as a JavaScript object.
 *
 * @param {string} [path] - The file path or URL of the JSON schema
 * @param {object} [api] - The Swagger API object. This object will be used instead of reading from `path`.
 * @param {ParserOptions} [options] - Options that determine how the API is parsed
 * @param {function} [callback] - An error-first callback. The second parameter is the parsed API object.
 * @returns {Promise} - The returned promise resolves with the parsed API object.
 */
SwaggerParser.prototype.parse = async function (path, api, options, callback) {
  let args = normalizeArgs(arguments);
  args.options = new Options(args.options);

  try {
    let schema = await $RefParser.prototype.parse.call(this, args.path, args.schema, args.options);

    if (schema.swagger) {
      // Verify that the parsed object is a Swagger API
      if (schema.swagger === undefined || schema.info === undefined || schema.paths === undefined) {
        throw ono.syntax(`${args.path || args.schema} is not a valid Swagger API definition`);
      }
      else if (typeof schema.swagger === "number") {
        // This is a very common mistake, so give a helpful error message
        throw ono.syntax('Swagger version number must be a string (e.g. "2.0") not a number.');
      }
      else if (typeof schema.info.version === "number") {
        // This is a very common mistake, so give a helpful error message
        throw ono.syntax('API version number must be a string (e.g. "1.0.0") not a number.');
      }
      else if (schema.swagger !== "2.0") {
        throw ono.syntax(`Unrecognized Swagger version: ${schema.swagger}. Expected 2.0`);
      }
    }
    else {
      let supportedVersions = ["3.0.0", "3.0.1", "3.0.2"];

      // Verify that the parsed object is a Openapi API
      if (schema.openapi === undefined || schema.info === undefined || schema.paths === undefined) {
        throw ono.syntax(`${args.path || args.schema} is not a valid Openapi API definition`);
      }
      else if (typeof schema.openapi === "number") {
        // This is a very common mistake, so give a helpful error message
        throw ono.syntax('Openapi version number must be a string (e.g. "3.0.0") not a number.');
      }
      else if (typeof schema.info.version === "number") {
        // This is a very common mistake, so give a helpful error message
        throw ono.syntax('API version number must be a string (e.g. "1.0.0") not a number.');
      }
      else if (supportedVersions.indexOf(schema.openapi) === -1) {
        throw ono.syntax(
          `Unsupported OpenAPI version: ${schema.openapi}. ` +
          `Swagger Parser only supports versions ${supportedVersions.join(", ")}`
        );
      }
    }

    // Looks good!
    return maybe(args.callback, Promise.resolve(schema));
  }
  catch (err) {
    return maybe(args.callback, Promise.reject(err));
  }
};

/**
 * Parses, dereferences, and validates the given Swagger API.
 * Depending on the options, validation can include JSON Schema validation and/or Swagger Spec validation.
 *
 * @param {string} [path] - The file path or URL of the JSON schema
 * @param {object} [api] - The Swagger API object. This object will be used instead of reading from `path`.
 * @param {ParserOptions} [options] - Options that determine how the API is parsed, dereferenced, and validated
 * @param {function} [callback] - An error-first callback. The second parameter is the parsed API object.
 * @returns {Promise} - The returned promise resolves with the parsed API object.
 */
SwaggerParser.validate = function (path, api, options, callback) {
  let Class = this; // eslint-disable-line consistent-this
  let instance = new Class();
  return instance.validate.apply(instance, arguments);
};

/**
 * Parses, dereferences, and validates the given Swagger API.
 * Depending on the options, validation can include JSON Schema validation and/or Swagger Spec validation.
 *
 * @param {string} [path] - The file path or URL of the JSON schema
 * @param {object} [api] - The Swagger API object. This object will be used instead of reading from `path`.
 * @param {ParserOptions} [options] - Options that determine how the API is parsed, dereferenced, and validated
 * @param {function} [callback] - An error-first callback. The second parameter is the parsed API object.
 * @returns {Promise} - The returned promise resolves with the parsed API object.
 */
SwaggerParser.prototype.validate = async function (path, api, options, callback) {
  let me = this;
  let args = normalizeArgs(arguments);
  args.options = new Options(args.options);

  // ZSchema doesn't support circular objects, so don't dereference circular $refs yet
  // (see https://github.com/zaggino/z-schema/issues/137)
  let circular$RefOption = args.options.dereference.circular;
  args.options.validate.schema && (args.options.dereference.circular = "ignore");

  try {
    await this.dereference(args.path, args.schema, args.options);

    // Restore the original options, now that we're done dereferencing
    args.options.dereference.circular = circular$RefOption;

    if (args.options.validate.schema) {
      // Validate the API against the Swagger schema
      // NOTE: This is safe to do, because we haven't dereferenced circular $refs yet
      validateSchema(me.api);

      if (me.$refs.circular) {
        if (circular$RefOption === true) {
          // The API has circular references,
          // so we need to do a second-pass to fully-dereference it
          dereference(me, args.options);
        }
        else if (circular$RefOption === false) {
          // The API has circular references, and they're not allowed, so throw an error
          throw ono.reference("The API contains circular references");
        }
      }
    }

    if (args.options.validate.spec) {
      // Validate the API against the Swagger spec
      validateSpec(me.api);
    }

    return maybe(args.callback, Promise.resolve(me.schema));
  }
  catch (err) {
    return maybe(args.callback, Promise.reject(err));
  }
};

/**
 * The Swagger object
 * https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#swagger-object
 *
 * @typedef {{swagger: string, info: {}, paths: {}}} SwaggerObject
 */
<commit_msg>Support 3.0.3<commit_after>"use strict";

const validateSchema = require("./validators/schema");
const validateSpec = require("./validators/spec");
const normalizeArgs = require("json-schema-ref-parser/lib/normalize-args");
const util = require("./util");
const Options = require("./options");
const maybe = require("call-me-maybe");
const { ono } = require("ono");
const $RefParser = require("json-schema-ref-parser");
const dereference = require("json-schema-ref-parser/lib/dereference");

module.exports = SwaggerParser;

/**
 * This class parses a Swagger 2.0 or 3.0 API, resolves its JSON references and their resolved values,
 * and provides methods for traversing, dereferencing, and validating the API.
 *
 * @constructor
 * @extends $RefParser
 */
function SwaggerParser () {
  $RefParser.apply(this, arguments);
}

util.inherits(SwaggerParser, $RefParser);
SwaggerParser.YAML = $RefParser.YAML;
SwaggerParser.parse = $RefParser.parse;
SwaggerParser.resolve = $RefParser.resolve;
SwaggerParser.bundle = $RefParser.bundle;
SwaggerParser.dereference = $RefParser.dereference;

/**
 * Alias {@link $RefParser#schema} as {@link SwaggerParser#api}
 */
Object.defineProperty(SwaggerParser.prototype, "api", {
  configurable: true,
  enumerable: true,
  get () {
    return this.schema;
  }
});

/**
 * Parses the given Swagger API.
 * This method does not resolve any JSON references.
 * It just reads a single file in JSON or YAML format, and parse it as a JavaScript object.
 *
 * @param {string} [path] - The file path or URL of the JSON schema
 * @param {object} [api] - The Swagger API object. This object will be used instead of reading from `path`.
 * @param {ParserOptions} [options] - Options that determine how the API is parsed
 * @param {function} [callback] - An error-first callback. The second parameter is the parsed API object.
 * @returns {Promise} - The returned promise resolves with the parsed API object.
 */
SwaggerParser.prototype.parse = async function (path, api, options, callback) {
  let args = normalizeArgs(arguments);
  args.options = new Options(args.options);

  try {
    let schema = await $RefParser.prototype.parse.call(this, args.path, args.schema, args.options);

    if (schema.swagger) {
      // Verify that the parsed object is a Swagger API
      if (schema.swagger === undefined || schema.info === undefined || schema.paths === undefined) {
        throw ono.syntax(`${args.path || args.schema} is not a valid Swagger API definition`);
      }
      else if (typeof schema.swagger === "number") {
        // This is a very common mistake, so give a helpful error message
        throw ono.syntax('Swagger version number must be a string (e.g. "2.0") not a number.');
      }
      else if (typeof schema.info.version === "number") {
        // This is a very common mistake, so give a helpful error message
        throw ono.syntax('API version number must be a string (e.g. "1.0.0") not a number.');
      }
      else if (schema.swagger !== "2.0") {
        throw ono.syntax(`Unrecognized Swagger version: ${schema.swagger}. Expected 2.0`);
      }
    }
    else {
      let supportedVersions = ["3.0.0", "3.0.1", "3.0.2", "3.0.3"];

      // Verify that the parsed object is a Openapi API
      if (schema.openapi === undefined || schema.info === undefined || schema.paths === undefined) {
        throw ono.syntax(`${args.path || args.schema} is not a valid Openapi API definition`);
      }
      else if (typeof schema.openapi === "number") {
        // This is a very common mistake, so give a helpful error message
        throw ono.syntax('Openapi version number must be a string (e.g. "3.0.0") not a number.');
      }
      else if (typeof schema.info.version === "number") {
        // This is a very common mistake, so give a helpful error message
        throw ono.syntax('API version number must be a string (e.g. "1.0.0") not a number.');
      }
      else if (supportedVersions.indexOf(schema.openapi) === -1) {
        throw ono.syntax(
          `Unsupported OpenAPI version: ${schema.openapi}. ` +
          `Swagger Parser only supports versions ${supportedVersions.join(", ")}`
        );
      }
    }

    // Looks good!
    return maybe(args.callback, Promise.resolve(schema));
  }
  catch (err) {
    return maybe(args.callback, Promise.reject(err));
  }
};

/**
 * Parses, dereferences, and validates the given Swagger API.
 * Depending on the options, validation can include JSON Schema validation and/or Swagger Spec validation.
 *
 * @param {string} [path] - The file path or URL of the JSON schema
 * @param {object} [api] - The Swagger API object. This object will be used instead of reading from `path`.
 * @param {ParserOptions} [options] - Options that determine how the API is parsed, dereferenced, and validated
 * @param {function} [callback] - An error-first callback. The second parameter is the parsed API object.
 * @returns {Promise} - The returned promise resolves with the parsed API object.
 */
SwaggerParser.validate = function (path, api, options, callback) {
  let Class = this; // eslint-disable-line consistent-this
  let instance = new Class();
  return instance.validate.apply(instance, arguments);
};

/**
 * Parses, dereferences, and validates the given Swagger API.
 * Depending on the options, validation can include JSON Schema validation and/or Swagger Spec validation.
 *
 * @param {string} [path] - The file path or URL of the JSON schema
 * @param {object} [api] - The Swagger API object. This object will be used instead of reading from `path`.
 * @param {ParserOptions} [options] - Options that determine how the API is parsed, dereferenced, and validated
 * @param {function} [callback] - An error-first callback. The second parameter is the parsed API object.
 * @returns {Promise} - The returned promise resolves with the parsed API object.
 */
SwaggerParser.prototype.validate = async function (path, api, options, callback) {
  let me = this;
  let args = normalizeArgs(arguments);
  args.options = new Options(args.options);

  // ZSchema doesn't support circular objects, so don't dereference circular $refs yet
  // (see https://github.com/zaggino/z-schema/issues/137)
  let circular$RefOption = args.options.dereference.circular;
  args.options.validate.schema && (args.options.dereference.circular = "ignore");

  try {
    await this.dereference(args.path, args.schema, args.options);

    // Restore the original options, now that we're done dereferencing
    args.options.dereference.circular = circular$RefOption;

    if (args.options.validate.schema) {
      // Validate the API against the Swagger schema
      // NOTE: This is safe to do, because we haven't dereferenced circular $refs yet
      validateSchema(me.api);

      if (me.$refs.circular) {
        if (circular$RefOption === true) {
          // The API has circular references,
          // so we need to do a second-pass to fully-dereference it
          dereference(me, args.options);
        }
        else if (circular$RefOption === false) {
          // The API has circular references, and they're not allowed, so throw an error
          throw ono.reference("The API contains circular references");
        }
      }
    }

    if (args.options.validate.spec) {
      // Validate the API against the Swagger spec
      validateSpec(me.api);
    }

    return maybe(args.callback, Promise.resolve(me.schema));
  }
  catch (err) {
    return maybe(args.callback, Promise.reject(err));
  }
};

/**
 * The Swagger object
 * https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#swagger-object
 *
 * @typedef {{swagger: string, info: {}, paths: {}}} SwaggerObject
 */
<|endoftext|>


<commit_before>"use strict"

var Q = require("q");

module.exports = function(){
  return Retain.extend();
};

module.exports.Retain = Retain;

function Retain()
{

}

Retain.extend = function()
{
  var __hasProp = {}.hasOwnProperty;
  var Child = function(){};

  for (var key in Retain)
  {
    if (__hasProp.call(Retain, key))
    {
      Child[key] = Retain[key];
    }
  }

  function ctor() {
    this.constructor = Child;
  }

  ctor.prototype = Retain.prototype;
  Child.prototype = new ctor();

  Child.__super__ = Retain.prototype;
  Child._init()

  return Child;
}

Retain._plugins = []
Retain._id_prop = "id";

Retain.use = function(proxy, config)
{
  var plugin = proxy();

  for (var prop in config)
  {
    plugin.config[prop] = config[prop];
  }

  this._plugins.push(proxy());
}

Retain.attrs = function(props)
{
  for(var key in props)
  {
    this._attrs[key] = props[key]
  }
}

Retain.new = function (callback)
{
  var key, record, value;

  record = new this;
  record._cid = this._records.length;
  record._keys = {};

  this._records.push(record);

  this._run_plugins("new", record, callback);

  return record;
}

Retain.prototype.set = function(props, callback)
{

  var args = 1 <= props.length ? [].slice.call(props, 0) : [];

  for(var prop in props)
  {
    this._validate_prop(prop, props[prop]);
  }

  this.constructor._run_plugins("set", this, callback);

  return this;
}

Retain.prototype.get = function(prop)
{
  return this._keys[prop];
}

Retain.find = function(id, callback)
{
  var found = null;

  // Search by ID
  for(var i = 0, total = this._records.length; i < total; i++)
  {
    if(this._records[i][this._id_prop] === id)
    {
      found = this._records[i];
    }
  }

  // Search by CID
  for(i = 0; i < total; i++)
  {
    if(this._records[i]["_cid"] === id && !found)
    {
      found = this._records[i];
    }
  }

  this._run_plugins("find", id, callback);
  return found;
}

Retain.all = function(callback)
{
  this._run_plugins("all", this._records, callback);
  return this._records;
}

Retain.prototype.remove = function(callback)
{
  var cid = this._cid;
  var record = null;

  for(var i = 0, total = this.constructor._records.length -1; i < total; i++)
  {
    record = this.constructor._records[i];

    if(record._cid === cid)
    {
      this.constructor._records.splice(i,1);
    }
  }

  this.constructor._run_plugins("remove", this, callback);
}

// Private

Retain._run_plugins = function(method, initialValue, callback)
{
  if(callback)
  {
    // Reference https://github.com/kriskowal/q#sequences
    var plugins = this._get_plugins(method);

    plugins.reduce(Q.when, Q(initialValue))
      .then(function(res)
      {
        callback(res,null);
      })
      .fail(function(err)
      {
          callback(null,err)
      });
  }
}

Retain._init = function()
{
  this._attrs = {}
  this._records = []
}

Retain._get_plugins = function(method)
{
  var promises = [];

  for(var i = 0, total = this._plugins.length; i < total; i++)
  {
    if(this._plugins[i][method])
    {
      promises.push(this._plugins[i][method].bind(this._plugins[i]));
    }
  }

  return promises;
}

Retain.prototype._keys = {}

Retain.prototype._cid = {}

Retain.prototype._validate_type = function(prop, val)
{
  var attr = this.constructor._attrs[prop];

  if(/native\scode/.test(attr))
  {
    switch(attr.toString().match(/function\s(\w+)/)[1])
    {
      case "String":
        return (typeof val === "string");
        break;
      case "Boolean":
        return (typeof val === "boolean");
        break;
      case "Number":
        return (typeof val === "number");
        break;
      case "Array":
      case "Object":
      case "Date":
        return (val instanceof attr);
        break;
    }
  }
}

Retain.prototype._validate_prop = function(prop, value)
{
  if(this.constructor._attrs[prop])
  {
    if(this._validate_type(prop, value))
    {
      this._keys[prop] = value;
    }
    else
    {
      throw new Error("Invalid type for property " + prop + " = " + value);
    }
  }
  else
  {
    this[prop] = value;
  }
}
<commit_msg>Hotfix 'find' method<commit_after>"use strict"

var Q = require("q");

module.exports = function(){
  return Retain.extend();
};

module.exports.Retain = Retain;

function Retain()
{

}

Retain.extend = function()
{
  var __hasProp = {}.hasOwnProperty;
  var Child = function(){};

  for (var key in Retain)
  {
    if (__hasProp.call(Retain, key))
    {
      Child[key] = Retain[key];
    }
  }

  function ctor() {
    this.constructor = Child;
  }

  ctor.prototype = Retain.prototype;
  Child.prototype = new ctor();

  Child.__super__ = Retain.prototype;
  Child._init()

  return Child;
}

Retain._plugins = []
Retain._id_prop = "id";

Retain.use = function(proxy, config)
{
  var plugin = proxy();

  for (var prop in config)
  {
    plugin.config[prop] = config[prop];
  }

  this._plugins.push(proxy());
}

Retain.attrs = function(props)
{
  for(var key in props)
  {
    this._attrs[key] = props[key]
  }
}

Retain.new = function (callback)
{
  var key, record, value;

  record = new this;
  record._cid = this._records.length;
  record._keys = {};

  this._records.push(record);

  this._run_plugins("new", record, callback);

  return record;
}

Retain.prototype.set = function(props, callback)
{

  var args = 1 <= props.length ? [].slice.call(props, 0) : [];

  for(var prop in props)
  {
    this._validate_prop(prop, props[prop]);
  }

  this.constructor._run_plugins("set", this, callback);

  return this;
}

Retain.prototype.get = function(prop)
{
  return this._keys[prop];
}

Retain.find = function(id, callback)
{
  var found = null;
  var record = {id:id};

  // Search by ID
  for(var i = 0, total = this._records.length; i < total; i++)
  {
    if(this._records[i][this._id_prop] === id)
    {
      found = this._records[i];
    }
  }

  // Search by CID
  for(i = 0; i < total; i++)
  {
    if(this._records[i]["_cid"] === id && !found)
    {
      found = this._records[i];
    }
  }

  if(found)
    record = found;

  this._run_plugins("find", record, callback);
  return found;
}

Retain.all = function(callback)
{
  this._run_plugins("all", this._records, callback);
  return this._records;
}

Retain.prototype.remove = function(callback)
{
  var cid = this._cid;
  var record = null;

  for(var i = 0, total = this.constructor._records.length -1; i < total; i++)
  {
    record = this.constructor._records[i];

    if(record._cid === cid)
    {
      this.constructor._records.splice(i,1);
    }
  }

  this.constructor._run_plugins("remove", this, callback);
}

// Private

Retain._run_plugins = function(method, initialValue, callback)
{
  if(callback)
  {
    // Reference https://github.com/kriskowal/q#sequences
    var plugins = this._get_plugins(method);

    plugins.reduce(Q.when, Q(initialValue))
      .then(function(res)
      {
        callback(res,null);
      })
      .fail(function(err)
      {
          callback(null,err)
      });
  }
}

Retain._init = function()
{
  this._attrs = {}
  this._records = []
}

Retain._get_plugins = function(method)
{
  var promises = [];

  for(var i = 0, total = this._plugins.length; i < total; i++)
  {
    if(this._plugins[i][method])
    {
      promises.push(this._plugins[i][method].bind(this._plugins[i]));
    }
  }

  return promises;
}

Retain.prototype._keys = {}

Retain.prototype._cid = {}

Retain.prototype._validate_type = function(prop, val)
{
  var attr = this.constructor._attrs[prop];

  if(/native\scode/.test(attr))
  {
    switch(attr.toString().match(/function\s(\w+)/)[1])
    {
      case "String":
        return (typeof val === "string");
        break;
      case "Boolean":
        return (typeof val === "boolean");
        break;
      case "Number":
        return (typeof val === "number");
        break;
      case "Array":
      case "Object":
      case "Date":
        return (val instanceof attr);
        break;
    }
  }
}

Retain.prototype._validate_prop = function(prop, value)
{
  if(this.constructor._attrs[prop])
  {
    if(this._validate_type(prop, value))
    {
      this._keys[prop] = value;
    }
    else
    {
      throw new Error("Invalid type for property " + prop + " = " + value);
    }
  }
  else
  {
    this[prop] = value;
  }
}
<|endoftext|>


<commit_before>
var integration = require('analytics.js-integration');

/**
 * Expose `Route` integration.
 */

var Route = module.exports = integration('Route')
  .global('_rq')
  .global('_route')
  .option('organizationId', '')
  .tag('<script id="rtracker" data-organization-id="{{ organizationId }}" src="//www.routecdn.com/tracker/route-tracker-min.js">');

/**
 * Initialize Route.
 *
 * @api public
 */

Route.prototype.initialize = function() {
  window._rq = window._rq || [];
  window._route = window._route || [];
  window._route.methods = ['identify', 'track', 'trackById'];
  window._route.factory = function(method) {
    return function() {
      var args = Array.prototype.slice.call(arguments);
      args.unshift(method);
      window._rq.push(args);
      return window._rq;
    };
  };
  for (var i = 0; i < window._route.methods.length; i++) {
    var key = window._route.methods[i];
    window._route[key] = window._route.factory(key);
  }
  this.load(this.ready);
};

/**
 * Has the Route library been loaded yet?
 *
 * @api private
 * @return {Boolean}
 */

Route.prototype.loaded = function() {
  return window._rq && window._rq.push !== Array.prototype.push;
};

/**
 * Identify a user.
 *
 * @api public
 * @param {Track} identify
 */

Route.prototype.identify = function(identify) {
  window._route.identify(identify.traits());
};

/**
 * Track an event.
 *
 * @api public
 * @param {Track} track
 */

Route.prototype.track = function(track) {
  window._route.track(track.event());
};
<commit_msg>Update index.js<commit_after>
var integration = require('analytics.js-integration');

/**
 * Expose `Route` integration.
 */

var Route = module.exports = integration('Route')
  .global('_rq')
  .global('_route')
  .option('organizationId', '')
  .tag('<script id="rtracker" data-organization-id="{{ organizationId }}" data-source="segment.com" src="//www.routecdn.com/tracker/route-tracker-min.js">');

/**
 * Initialize Route.
 *
 * @api public
 */

Route.prototype.initialize = function() {
  window._rq = window._rq || [];
  window._route = window._route || [];
  window._route.methods = ['identify', 'track', 'trackById'];
  window._route.factory = function(method) {
    return function() {
      var args = Array.prototype.slice.call(arguments);
      args.unshift(method);
      window._rq.push(args);
      return window._rq;
    };
  };
  for (var i = 0; i < window._route.methods.length; i++) {
    var key = window._route.methods[i];
    window._route[key] = window._route.factory(key);
  }
  this.load(this.ready);
};

/**
 * Has the Route library been loaded yet?
 *
 * @api private
 * @return {Boolean}
 */

Route.prototype.loaded = function() {
  return window._rq && window._rq.push !== Array.prototype.push;
};

/**
 * Identify a user.
 *
 * @api public
 * @param {Track} identify
 */

Route.prototype.identify = function(identify) {
  window._route.identify(identify.traits());
};

/**
 * Track an event.
 *
 * @api public
 * @param {Track} track
 */

Route.prototype.track = function(track) {
  window._route.track(track.event());
};
<|endoftext|>


<commit_before>'use strict';

const Async = require('async');
const Boom = require('boom');
const Joi = require('joi');
const Hoek = require('hoek');

const DENY = 0;
const PERMIT = 1;
const UNDETERMINED = 3;

const CONFIG_NONE = 'none';

const internals = {};
const schemas = {};
const defaults = {};

schemas.policyRetriever = Joi.func();
schemas.policy = Joi.object();

/**
 * Data retriever router object constructor.
 *
 * This object allows to register data retrieval handlers to obtain data form different sources.
 **/
const DataRetrievalRouter = function(options) {
    options = options || {};
    Joi.assert(options, schemas.DataRetrievalRouter_options);

    this.options = options;
    this.retrievers = {};
    this.parent = options.parent;
    this.context = options.context;
};
schemas.DataRetrievalRouter_options = Joi.object({
    override: Joi.boolean().optional(),
    parent: Joi.object().type(DataRetrievalRouter).optional(),
    context: Joi.object().optional()
}).unknown(false);

/**
 * Create a child DataRetrievalRouter inheriting the current object, applied for a certain data context
 **/
DataRetrievalRouter.prototype.createChild = function(context) {
    const options = Hoek.applyToDefaultsWithShallow(this.options, {
        parent: this,
        context: context
    }, ['parent', 'context']);

    return new DataRetrievalRouter(options);
};

/**
 * Register a data retriever.
 *
 * * handles - A string or array of strings specifying what this component retrieves (source of data, e.g. 'credentials')
 * * retriever - A function which returns data, according to a key. Function signature is (source:string, key:string, context:object) => String
 * * options - (optional) A JSON with the following options:
 *   * override - When true, overrides existent handler if exists. When false, throws an error when a repeated handler is used. (default: false)
 **/
DataRetrievalRouter.prototype.register = function (handles, retriever, options) {
    Joi.assert(handles, schemas.DataRetrievalRouter_register_handles);
    Joi.assert(retriever, schemas.DataRetrievalRouter_register_retriever);
    options = options || {};
    Joi.assert(options, schemas.DataRetrievalRouter_register_options);
    options = Hoek.applyToDefaults(defaults.DataRetrievalRouter_register_options, options);

    if(handles instanceof Array) {
        handles.forEach((source) => this._register(source, retriever, options));
    } else {
        this._register(handles, retriever, options);
    }

    return this;
};
schemas.DataRetrievalRouter_register_handles = Joi.alternatives().try(
    Joi.string().min(1),
    Joi.array().items(Joi.string().min(1))
);
schemas.DataRetrievalRouter_register_retriever = Joi.func().arity(3);
schemas.DataRetrievalRouter_register_options = Joi.object({
    override: Joi.boolean().optional()
}).unknown(false);

defaults.DataRetrievalRouter_register_options = {
    override: false
};

DataRetrievalRouter.prototype._register = function (handles, retriever, options) {
    if(this.retrievers[handles] && !options.override) {
        throw new Error('There is a data retriever already registered for the source: ' + handles);
    }

    this.retrievers[handles] = retriever;
};

/**
 * Obtain data from a retriever.
 *
 * * source - E.g. 'credentials' to obtain data from credentials document
 * * key - Key value from the source (e.g. 'username')
 * * context - Context object. Contains the request object.
 **/
DataRetrievalRouter.prototype.get = function (key, context) {
    Joi.assert(key, schemas.DataRetrievalRouter_get_key);
    let source, subkey;

    if(key.indexOf(':') === -1) {
        source = 'credentials'; // keep it backwards compatible
        subkey = key;
    } else {
        const split_key = key.split(':');
        source = split_key[0];
        subkey = split_key[1];
    }

    Joi.assert(subkey, schemas.DataRetrievalRouter_get_key);
    Joi.assert(source, schemas.DataRetrievalRouter_get_source);

    if(!this.retrievers[source]) {
        if(!this.parent) {
            return null;
        }
        return this.parent.get(key, context || this.context);
    }

    return this.retrievers[source](source, subkey, context || this.context);
};
schemas.DataRetrievalRouter_get_source = Joi.string().min(1);
schemas.DataRetrievalRouter_get_key = Joi.string().min(1);

// Default data retrievers
defaults.credentialsRetriever = function (source, key, context) {
    if(!context || !context.auth || !context.auth.credentials) {
        return null;
    }

    return context.auth.credentials[key];
};

defaults.connectionInfoRetriever = function (source, key, context) {
    if(!context || !context.info) {
        return null;
    }

    return context.info[key];
};

defaults.queryInfoRetriever = function (source, key, context) {
    if(!context || !context.query) {
        return null;
    }

    return context.query[key];
};

defaults.paramsInfoRetriever = function (source, key, context) {
    if(!context || !context.params) {
        return null;
    }

    return context.params[key];
};

defaults.stateInfoRetriever = function (source, key, context) {
    if(!context || !context.state) {
        return null;
    }

    return context.state[key];
};

defaults.requestInfoRetriever = function (source, key, context) {
    if(!context) {
        return null;
    }

    if(['method', 'path'].indexOf(key) === -1) {
        return null;
    }

    return context[key];
};

/**
 * Hapi register function
 **/
schemas.register_options = Joi.object({
    policy: Joi.alternatives().try(
            schemas.policyRetriever,
            schemas.policy
        ).optional(),
    dataRetrievers: Joi.array().items(
        Joi.object({
            handles: schemas.DataRetrievalRouter_register_handles.required()
        })
    ).optional()
});

exports.register = (server, options, next) => {

    Joi.assert(options, schemas.register_options);

    const dataRetriever = new DataRetrievalRouter();
    dataRetriever.register('credentials', defaults.credentialsRetriever);
    dataRetriever.register('connection', defaults.connectionInfoRetriever);
    dataRetriever.register('query', defaults.queryInfoRetriever);
    dataRetriever.register(['param','params'], defaults.paramsInfoRetriever);
    dataRetriever.register('request', defaults.requestInfoRetriever);

    server.ext('onPostAuth', (request, reply) => {

        let config = request.route.settings.plugins.rbac || options.policy;

        if (config && config !== CONFIG_NONE) {

            return internals.retrievePolicy(config, request, (err, policy) => {

                if (err) {
                    return reply(err);
                }

                if (!policy || policy === CONFIG_NONE) {
                    return reply.continue();
                }

                // Add context to data retriever's child
                const wrappedDataRetriever = dataRetriever.createChild(request);

                internals.evaluatePolicy(policy, wrappedDataRetriever, (err, result) => {

                    if (err) {
                        return reply(err);
                    }

                    if (result === DENY) {
                        return reply(Boom.unauthorized('No permissions to access this resource'));
                    }

                    if (result === UNDETERMINED) {
                        return reply(Boom.unauthorized('Could not evaluate access rights to resource'));
                    }

                    reply.continue();
                });
            });
        }

        reply.continue();
    });

    next();
};

exports.register.attributes = {
    pkg: require('../package.json')
};

/**
 * If the configuration is a function, then this function should retrieve the access policy (e.g.: from a database).
 * Otherwise, it is assumed that the configuration is the access policy itself.
 *
 * The callback signature is function (err, policy) {}
 **/
internals.retrievePolicy = (config, request, callback) => {

    if (config instanceof Function) {
        config(request, callback);
    }
    else {
        callback(null, config);
    }
};

/**
 * Evaluate a single Policy of PolicySet
 *
 **/
internals.evaluatePolicy = (item, dataRetriever, callback) => {

    if (!item) {
        return callback(Boom.badImplementation('RBAC configuration error: null item'));
    }

    if (!item.apply) {
        item.apply = 'permit-overrides';
    }

    if (!(item.apply instanceof Function)) {
        if (!internals.combineAlg[item.apply]) {
            return callback(Boom.badImplementation('RBAC error: combinatory algorithm does not exist: ' + item.apply));
        }

        item.apply = internals.combineAlg[item.apply];
    }

    internals.evaluateTarget(item.target, dataRetriever, (err, applies) => {

        if (err) {
            return callback(err);
        }

        if (!applies) {
            return callback(null, UNDETERMINED);
        }

        // Policy set
        if (item.policies) {

            return item.apply(item.policies, dataRetriever, internals.evaluatePolicy, callback);
        }

        // Policy
        if (item.rules) {

            return item.apply(item.rules, dataRetriever, internals.evaluateRule, callback);
        }

        // Rule
        internals.evaluateRule(item, dataRetriever, callback);
    });
};

/**
 * Evaluate a single rule.
 *
 * {
 *    'target': ['any-of', item1, ..., itemN],
 *    'effect': PERMIT, DENY
 * }
 **/
internals.evaluateRule = (rule, dataRetriever, callback) => {

    if (!rule) {
        return callback(Boom.badImplementation('RBAC rule is missing'));
    }

    internals.evaluateTarget(rule.target, dataRetriever, (err, applies) => {

        if (err) {
            return callback(err);
        }

        if (!applies) {
            return callback(null, UNDETERMINED);
        }

        switch (rule.effect) {
            case 'permit':
            case PERMIT:
                return callback(null, PERMIT);
            case 'deny':
            case DENY:
                return callback(null, DENY);
            default:
                return callback(Boom.badImplementation('RBAC rule error: invalid effect ' + rule.effect));
        }
    });
};

/**
 * Evaluate a target
 * ['any-of', {type: 'username', value:'francisco'}, {type: 'group', value:'admin'}]
 * ['all-of', {type: 'username', value:'francisco'}, {type: 'group', value:'admin'}]
 **/
internals.evaluateTarget = (target, dataRetriever, callback) => {

    if (!target) {
        // Applies by default, when no target is defined
        return callback(null, true);
    }

    if (!(target instanceof Array) || target.length < 2) {
        return callback(Boom.badImplementation('RBAC target error: invalid format. Should be an array with match type and items ["all-of", item1, item2, ..., itemN]'));
    }

    for (let i = 1; i < target.length; ++i) {
        const value = dataRetriever.get(target[i].type);

        const result = internals._targetApplies(target[i].value, value);

        if (result && target[0] === 'any-of') {
            return callback(null, true);
        }

        if (!result && target[0] === 'all-of') {
            return callback(null, false);
        }
    }

    return callback(null, target[0] === 'all-of');
};

internals._targetApplies = (target, value) => {

    if (target === value) {
        return true;
    }

    if (value instanceof Array) {
        if (value.indexOf(target) !== -1) {
            return true;
        }
    }

    return false;
};

/**
 * Combinator algorithms:
 *
 *   - permit-overrides - If at least one permit is evaluated, then permit
 *   - deny-overrides - If at least one deny is evaluated, then deny
 *   - only-one-applicable -
 *   - first-applicable - Only evaluate the first applicable rule
 **/
internals.combineAlg = {};

internals.combineAlg['permit-overrides'] = (items, information, fn, callback) => {

    if (!items || items.length === 0) {
        return callback(null, UNDETERMINED);
    }

    const tasks = [];

    for (let i = 0; i < items.length; ++i) {
        tasks.push(fn.bind(null, items[i], information));
    }

    Async.parallel(tasks, (err, results) => {

        if (err) {
            return callback(err);
        }

        for (let i = 0; i < results.length; ++i) {
            if (results[i] === PERMIT) {
                return callback(null, PERMIT);
            }
        }

        callback(null, DENY);
    });
};

internals.combineAlg['deny-overrides'] = (items, information, fn, callback) => {

    if (!items || items.length === 0) {
        return callback(null, UNDETERMINED);
    }

    const tasks = [];

    for (let i = 0; i < items.length; ++i) {
        tasks.push(fn.bind(null, items[i], information));
    }

    Async.parallel(tasks, (err, results) => {

        if (err) {
            return callback(err);
        }

        for (let i = 0; i < results.length; ++i) {
            if (results[i] === DENY) {
                return callback(null, DENY);
            }
        }

        callback(null, PERMIT);
    });
};

if (['test', 'development'].indexOf(process.env.NODE_ENV) !== -1) {

    // To run the lab tests
    exports.evaluateTarget = internals.evaluateTarget;
    exports.evaluatePolicy = internals.evaluatePolicy;
    exports.evaluateRule = internals.evaluateRule;

    exports.PERMIT = PERMIT;
    exports.DENY = DENY;
    exports.UNDETERMINED = UNDETERMINED;

    exports.DataRetrievalRouter = DataRetrievalRouter;
}
<commit_msg>Moved core to rbac-core module<commit_after>'use strict';

const Async = require('async');
const Boom = require('boom');
const Joi = require('joi');
const Hoek = require('hoek');
const RbacCore = require('rbac-core');
const DataRetrievalRouter = RbacCore.DataRetrievalRouter;

const CONFIG_NONE = 'none';

const internals = {};
const schemas = {};
const defaults = {};

schemas.policyRetriever = Joi.func();
schemas.policy = Joi.object();
schemas.DataRetrievalRouter_register_handles = Joi.alternatives().try(
    Joi.string().min(1),
    Joi.array().items(Joi.string().min(1))
);

/**
 * If the configuration is a function, then this function should retrieve the access policy (e.g.: from a database).
 * Otherwise, it is assumed that the configuration is the access policy itself.
 *
 * The callback signature is function (err, policy) {}
 **/
internals.retrievePolicy = (config, request, callback) => {

    if (config instanceof Function) {
        config(request, callback);
    }
    else {
        callback(null, config);
    }
};

// Default data retrievers
defaults.credentialsRetriever = function (source, key, context) {
    if(!context || !context.auth || !context.auth.credentials) {
        return null;
    }

    return context.auth.credentials[key];
};

defaults.connectionInfoRetriever = function (source, key, context) {
    if(!context || !context.info) {
        return null;
    }

    return context.info[key];
};

defaults.queryInfoRetriever = function (source, key, context) {
    if(!context || !context.query) {
        return null;
    }

    return context.query[key];
};

defaults.paramsInfoRetriever = function (source, key, context) {
    if(!context || !context.params) {
        return null;
    }

    return context.params[key];
};

defaults.stateInfoRetriever = function (source, key, context) {
    if(!context || !context.state) {
        return null;
    }

    return context.state[key];
};

defaults.requestInfoRetriever = function (source, key, context) {
    if(!context) {
        return null;
    }

    if(['method', 'path'].indexOf(key) === -1) {
        return null;
    }

    return context[key];
};

/**
 * Hapi register function
 **/
schemas.register_options = Joi.object({
    policy: Joi.alternatives().try(
            schemas.policyRetriever,
            schemas.policy
        ).optional(),
    dataRetrievers: Joi.array().items(
        Joi.object({
            handles: schemas.DataRetrievalRouter_register_handles.required()
        })
    ).optional()
});

exports.register = (server, options, next) => {

    Joi.assert(options, schemas.register_options);

    const dataRetriever = new DataRetrievalRouter();
    dataRetriever.register('credentials', defaults.credentialsRetriever);
    dataRetriever.register('connection', defaults.connectionInfoRetriever);
    dataRetriever.register('query', defaults.queryInfoRetriever);
    dataRetriever.register(['param','params'], defaults.paramsInfoRetriever);
    dataRetriever.register('request', defaults.requestInfoRetriever);

    server.ext('onPostAuth', (request, reply) => {

        let config = request.route.settings.plugins.rbac || options.policy;

        if (config && config !== CONFIG_NONE) {

            return internals.retrievePolicy(config, request, (err, policy) => {

                if (err) {
                    return reply(err);
                }

                if (!policy || policy === CONFIG_NONE) {
                    return reply.continue();
                }

                // Add context to data retriever's child
                const wrappedDataRetriever = dataRetriever.createChild(request);

                RbacCore.evaluatePolicy(policy, wrappedDataRetriever, (err, result) => {

                    if (err) {
                        return reply(err);
                    }

                    if (result === RbacCore.DENY) {
                        return reply(Boom.unauthorized('No permissions to access this resource'));
                    }

                    if (result === RbacCore.UNDETERMINED) {
                        return reply(Boom.unauthorized('Could not evaluate access rights to resource'));
                    }

                    reply.continue();
                });
            });
        }

        reply.continue();
    });

    next();
};

exports.register.attributes = {
    pkg: require('../package.json')
};
<|endoftext|>