New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

orchestrate

Package Overview
Dependencies
Maintainers
4
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

orchestrate - npm Package Compare versions

Comparing version 0.4.6 to 0.4.7

2

lib/client.js

@@ -136,3 +136,3 @@ // Copyright 2013 Bowery Software, LLC

* @param {Object} data
* @param {string|boolean}
* @param {string|boolean} match
* @return {Promise}

@@ -139,0 +139,0 @@ */

@@ -9,2 +9,3 @@ // Copyright 2013 Bowery Software, LLC

var assert = require('assert')
var util = require('util')
var Builder = require('./builder')

@@ -19,3 +20,3 @@

require('util').inherits(GraphBuilder, Builder)
util.inherits(GraphBuilder, Builder)

@@ -44,2 +45,27 @@

/**
* Set graph data.
* @param {Object} data
* @return {GraphBuilder}
*/
GraphBuilder.prototype.data = function (data) {
assert(data, 'Data required.')
this.data = data
return this
}
/**
* Set "If-Match" header to the given ref value.
* @param {String|boolean} ref. String ref for conditional update, or false
* for insert-if-absent (ie fail create if already present)
* @return {GraphBuilder}
*/
GraphBuilder.prototype.ref = function (ref) {
assert(typeof ref === 'string' || typeof ref === 'boolean', 'Ref required.')
this.ref = ref
return this
}
/**
* Delete a relationship.

@@ -76,5 +102,28 @@ * @return {GraphBuilder}

this.kind = Array.prototype.slice.call(arguments, 0)
// Hoist the kind argument into an array.
if (util.isArray(kind)) {
this.kind = kind;
} else {
this.kind = Array.prototype.slice.call(arguments, 0)
}
if (!this.write) return this._execute(this._method)
// Make sure that the kind array is non-empty, and that its elements are non-empty strings.
assert(this.kind.length > 0, 'Kind of relation required.')
for (var i = 0; i < this.kind.length; i++) {
var k = this.kind[i];
assert(typeof(k) === "string" && k.length > 0, 'Kind must be a non-empty string')
}
// Call the execute method in any of these scenarios:
// (1) This is a read-only GraphBuilder, with toCollection & toKey empty. The execute
// function will list (GET) all related items for the collection & key.
// (2) This is a read-only GraphBuilder, with toCollection & toKey non-empty. The
// execute function will retrieve (GET) the data of a specific relationship.
// (3) This is a write-only GraphBuilder, with toCollection & toKey non-empty. The
// execute function will submit (PUT) a new relationship.
if (!this.write || (this.toCollection && this.toKey)) {
return this._execute(this._method)
}
// Without toCollection and toKey on this write-only GraphBuilder, just return
// the builder, since there are still missing params.
return this

@@ -94,3 +143,9 @@ }

this.toKey = toKey
return this._execute(this._method)
// Call the execute method only if the relationship kind has already been set.
// Otherwise, just return the builder, since there ae still missing params.
if (this.kind) {
return this._execute(this._method)
}
return this
}

@@ -105,3 +160,3 @@

GraphBuilder.prototype.limit = function (limit) {
assert(limit, 'Limit required.')
assert(limit || limit == 0, 'Limit required.')
this.limit_value = limit

@@ -125,2 +180,13 @@ return this

/**
* Quote the provided string if not already quoted.
* @param {string} str
* @return {string}
* @protected
*/
GraphBuilder.prototype._quote = function (str) {
return str.charAt(0) == '"' ? str : '"' + str + '"'
}
/**
* Execute graph read/write.

@@ -132,14 +198,30 @@ * @param {string} method

GraphBuilder.prototype._execute = function (method) {
var relation = this.write ? 'relation' : 'relations'
// Make sure we have a from item key
assert(this.collection && this.key, "'from' collection and key required.")
// Make sure that the kind array is non-empty, and that its elements are non-empty strings.
assert(this.kind && this.kind.length > 0, 'Kind of relation required.')
for (var i = 0; i < this.kind.length; i++) {
var k = this.kind[i];
assert(typeof(k) === "string" && k.length > 0, 'Kind must be a non-empty string')
}
// Create an array of path components.
var pathArgs = []
pathArgs.push(this.collection)
pathArgs.push(this.key)
pathArgs.push(relation)
// The 'relation' path component is used for creating and retrieving individual relations.
// The 'relations' path component is used for traversing single-hop or multi-hop relationships.
if (this.write || (this._method === "GET" && this.toCollection && this.toKey)) {
pathArgs.push('relation')
} else {
pathArgs.push('relations')
}
pathArgs = pathArgs.concat(this.kind)
pathArgs.push(this.toCollection)
pathArgs.push(this.toKey)
pathArgs = pathArgs.filter(function (i) {
return i != undefined
})
// Destination collection and key are only mandatory during PUT and (non-listing) GET.
if (this.toCollection) pathArgs.push(this.toCollection)
if (this.toKey) pathArgs.push(this.toKey)
// Build the querystring
var query = {}

@@ -150,4 +232,13 @@ if (this._method == 'del') query['purge'] = true

var url = this.getDelegate() && this.getDelegate().generateApiUrl(pathArgs, query)
return this.getDelegate()['_' + this._method](url)
// Build headers
var header = {}
if (typeof(this.ref) === 'string') {
header['If-Match'] = this._quote(this.ref)
} else if (typeof(this.ref) === 'boolean' && this.ref === false) {
header['If-None-Match'] = '"*"'
}
// Build the URL and return a callable delegate for this request
var url = this.getDelegate() && this.getDelegate().generateApiUrl(pathArgs, query)
return this.getDelegate()['_' + this._method](url, this.data, header)
}

@@ -154,0 +245,0 @@

@@ -28,3 +28,3 @@ {

},
"version": "0.4.6",
"version": "0.4.7",
"main": "index",

@@ -31,0 +31,0 @@ "tags": [

@@ -383,3 +383,49 @@ # orchestrate.js [![Build Status](https://travis-ci.org/orchestrate-io/orchestrate.js.png)](https://travis-ci.org/orchestrate-io/orchestrate.js) [![Coverage Status](https://coveralls.io/repos/orchestrate-io/orchestrate.js/badge.png)](https://coveralls.io/r/orchestrate-io/orchestrate.js)

We can optionally include a JSON object representing the properties of the relationship -- which are distinct from the properties of the two items connected by the relationship -- like this:
```javascript
db.newGraphBuilder()
.create()
.data({ "rating" : "5 Stars" })
.from('users', 'Steve')
.related('likes')
.to('movies', 'Superbad')
```
We can use [conditional put statements](https://orchestrate.io/docs/api/#key/value/put-(create/update)) to determine whether or not the store operation will occur. If a ref value is provided an `update` will occur if there is a valid match, if false is provided, a `create` will occur if there is no match.
```javascript
// update if ref matches
db.newGraphBuilder()
.create()
.data({ "rating" : "4 Stars" })
.ref('cbb48f9464612f20')
.from('users', 'Steve')
.related('likes')
.to('movies', 'Superbad')
// create if no previous relationship
db.newGraphBuilder()
.create()
.data({ "rating" : "4 Stars" })
.ref(false)
.from('users', 'Steve')
.related('likes')
.to('movies', 'Superbad')
```
After storing this relationship, we can retrieve its properties like this:
```javascript
db.newGraphReader()
.get()
.from('users', 'Steve')
.related('likes')
.to('movies', 'Superbad')
```
We can then look up all the different items Steve likes:
```javascript

@@ -393,2 +439,3 @@ db.newGraphReader()

We can even take this another step further:
```javascript

@@ -400,5 +447,7 @@ db.newGraphReader()

```
This will return all of the things that friends of Steve have liked. This assumes a friend relation has previously been defined between Steve and another user.
Orchestrate supports offsets and limits for graph relationships as well. To set those values:
```javascript

@@ -414,2 +463,3 @@ db.newGraphReader()

If we want to delete a graph relationship:
```javascript

@@ -427,2 +477,3 @@ db.newGraphBuilder()

Creating an event:
```javascript

@@ -437,2 +488,3 @@ db.newEventBuilder()

Creating an event at a specified time:
```javascript

@@ -448,2 +500,3 @@ db.newEventBuilder()

Listing events:
```javascript

@@ -450,0 +503,0 @@ db.newEventReader()

@@ -13,10 +13,28 @@ // Copyright 2014 Orchestrate, Inc.

var r = function(collection, from, to, kind) {
return db.newGraphBuilder()
.create()
var createRelation = function(collection, from, to, kind, data, ref) {
var builder = db.newGraphBuilder().create();
if (data) builder.data(data);
if (ref) builder.ref(ref);
return builder.from(collection, from)
.to(collection, to)
.related(kind);
};
var getRelation = function(collection, from, to, kind) {
return db.newGraphReader()
.get()
.from(collection, from)
.related(kind)
.to(collection, to);
.to(collection, to)
.related(kind);
};
var listRelations = function(collection, from, kinds) {
return db.newGraphReader()
.get()
.from(collection, from)
.related(kinds);
};
suite('Graph', function () {

@@ -34,4 +52,6 @@ suiteSetup(function (done) {

test('Create graph relationships', function(done) {
var relations = [r(users.collection, users.steve.email, users.kelsey.email, "friend"),
r(users.collection, users.kelsey.email, users.david.email, "friend")];
var relations = [
createRelation(users.collection, users.steve.email, users.kelsey.email, "friend"),
createRelation(users.collection, users.kelsey.email, users.david.email, "friend")
]

@@ -51,7 +71,90 @@ Q.all(relations)

test('Create graph relationship with properties', function(done) {
var properties = [
{ "foo" : "bar" },
{ "bing" : "bong" }
];
var relations = [
createRelation(users.collection, users.steve.email, users.kelsey.email, "likes", properties[0]),
createRelation(users.collection, users.kelsey.email, users.david.email, "likes", properties[1])
];
Q.all(relations)
.then(function (res) {
assert.equal(2, res.length);
// Test that each of the requests succeeded
for (var i in res) {
assert.equal(201, res[i].statusCode);
}
// Retrieve each of the relations and make sure they contain the correct properties
checkRelationProperties(users.collection, users.steve.email, users.kelsey.email, "likes", properties[0], done);
checkRelationProperties(users.collection, users.kelsey.email, users.david.email, "likes", properties[1], done);
done();
})
.fail(function (res) {
done(res);
});
});
test('Conditionally create (if-match) graph relationship with properties', function(done) {
var kind = "coworkers"
var properties = [
{ "foo" : "bar" },
{ "fizz" : "buzz" },
{ "bing" : "bong" }
];
var properties2 = [
{ "foo2" : "bar2" },
{ "fizz2" : "buzz2" },
{ "bing2" : "bong2" }
];
// For starters, only create the relationship if it doesn't already exist
var relations = [
createRelation(users.collection, users.steve.email, users.david.email, kind, properties[0], false),
createRelation(users.collection, users.steve.email, users.kelsey.email, kind, properties[1], false),
createRelation(users.collection, users.kelsey.email, users.david.email, kind, properties[2], false)
];
Q.all(relations)
.then(function (res) {
assert.equal(3, res.length);
// Test that each of the requests succeeded, and retrieve their etags.
var etags = [];
for (var i in res) {
assert.equal(201, res[i].statusCode);
etags.push(res[i].etag);
}
// Update both relationships.
// The first one, using if-none-match again, even though the item already exists, should fail.
// The second one, using if-match with a bogus etag, should also fail.
// The third one, using its previous etag to implement if-match, should succeed.
var updates = [
createRelation(users.collection, users.steve.email, users.david.email, kind, properties2[0], false),
createRelation(users.collection, users.steve.email, users.kelsey.email, kind, properties2[1], '"nonsense"'),
createRelation(users.collection, users.kelsey.email, users.david.email, kind, properties2[2], etags[2])
];
// Process the updates
Q.all(updates)
.fin(function() {
// Retrieve each of the relations and make sure they contain the correct properties.
// Only the third one should have been updated, but the other two should contain the original json.
checkRelationProperties(users.collection, users.steve.email, users.david.email, kind, properties[0]),
checkRelationProperties(users.collection, users.steve.email, users.kelsey.email, kind, properties[1]),
checkRelationProperties(users.collection, users.kelsey.email, users.david.email, kind, properties2[2])
done();
});
})
.fail(function (res) {
done(res);
});
});
test('Traverse graph relationship', function(done) {
db.newGraphReader()
.get()
.from(users.collection, users.steve.email)
.related('friend', 'friend')
listRelations(users.collection, users.steve.email, [ 'friend', 'friend' ])
.then(function (res) {

@@ -90,2 +193,14 @@ assert.equal(200, res.statusCode);

function checkRelationProperties(collection, key, toCollection, toKey, kind, properties, done) {
var promise = getRelation(collection, key, toCollection, toKey, kind);
Q.all(promise)
.then(function(res) {
assert.equal(res.body, properties);
done();
})
.fail(function (res) {
done(res);
});
}
});

@@ -12,2 +12,3 @@ // Copyright 2014 Orchestrate, Inc.

var util = require('util');
var misc = require('./misc');

@@ -71,3 +72,3 @@ suite('Key-Value', function () {

assert.deepEqual(users.david, res.body.results[0].value);
assert.equal('/v0/'+users.collection+'?limit=1&afterKey=byrd@bowery.io', res.body.next);
misc.assertUrlsEqual(res.body.next, '/v0/'+users.collection+'?limit=1&afterKey=byrd@bowery.io');
return db.list(users.collection, {limit:1, afterKey:users.david.email});

@@ -74,0 +75,0 @@ })

@@ -11,3 +11,20 @@ // Copyright 2014 Orchestrate, Inc.

var util = require('util');
var url = require('url');
function assertUrlsEqual(a, b) {
var aUrl = url.parse(a);
var bUrl = url.parse(b);
assert.equal(aUrl.hostname, bUrl.hostname);
assert.equal(aUrl.port, bUrl.port);
assert.equal(aUrl.hash, bUrl.hash);
var aUrlQueryParts = aUrl.query.split("&");
var bUrlQueryParts = bUrl.query.split("&");
assert.equal(aUrlQueryParts.length, bUrlQueryParts.length);
aUrlQueryParts.sort();
bUrlQueryParts.sort();
for (var i = 0; i < aUrlQueryParts.length; i++) {
assert.equal(aUrlQueryParts[i], bUrlQueryParts[i]);
}
}
suite('Misc', function () {

@@ -27,1 +44,3 @@ test('Service ping', function(done) {

});
module.exports.assertUrlsEqual = assertUrlsEqual;

@@ -12,3 +12,3 @@ // Copyright 2014 Orchestrate, Inc.

var collection = 'patch.test'
var collection = 'patch.test_' + process.version;
var key = 'test-key-1'

@@ -15,0 +15,0 @@ // example doc used in all tests. it is reset every before each test.

@@ -12,2 +12,3 @@ // Copyright 2014 Orchestrate, Inc.

var util = require('util');
var misc = require('./misc');

@@ -70,3 +71,3 @@ suite('Search', function () {

assert.equal(1, res.body.count);
assert.equal(res.body.next, '/v0/'+users.collection+'?limit=1&query=*&offset=2');
misc.assertUrlsEqual(res.body.next, '/v0/'+users.collection+'?limit=1&query=*&offset=2');
done();

@@ -73,0 +74,0 @@ })

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc