Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

decypher

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

decypher - npm Package Compare versions

Comparing version 0.4.0 to 0.5.0

2

index.js

@@ -14,3 +14,3 @@ /**

Object.defineProperty(loader, 'version', {
value: '0.4.0'
value: '0.5.0'
});

@@ -17,0 +17,0 @@

{
"name": "decypher",
"version": "0.4.0",
"version": "0.5.0",
"description": "A handful of cypher utilities for Node.js",

@@ -31,2 +31,3 @@ "main": "index.js",

"dependencies": {
"escape-regexp": "0.0.1",
"lodash.assign": "^3.2.0",

@@ -33,0 +34,0 @@ "lodash.isplainobject": "^3.2.0"

@@ -12,2 +12,7 @@ [![Build Status](https://travis-ci.org/Yomguithereal/decypher.svg)](https://travis-ci.org/Yomguithereal/decypher)

* Miscellaneous [helpers](#helpers).
* [escapeIdentifier](#identifier)
* [escapeLiteralMap](#literal-map)
* [nodePattern](#node-pattern)
* [relationshipPattern](#relationship-pattern)
* [searchPattern](#search-pattern)

@@ -176,3 +181,3 @@ ## Installation

*Escaping identifiers*
<em id="identifier">Escaping identifiers</em>

@@ -186,3 +191,3 @@ ```js

*Escaping literal maps*
<em id="literal-map">Escaping literal maps</em>

@@ -206,3 +211,3 @@ ```js

*Building node patterns*
<em id="node-pattern">Building node patterns</em>

@@ -223,2 +228,5 @@ ```js

helpers.nodePattern('n');
>>> '(n)'
helpers.nodePattern({

@@ -251,3 +259,3 @@ identifier: 'n',

*Building relationship patterns*
<em id="relationship-pattern">Building relationship patterns</em>

@@ -265,2 +273,4 @@ ```js

// * `paramKeys`: will be passed to escapeLiteralMap when stringifying data
// * `source`: the source node (passed to the `nodePattern` function)
// * `target`: the target node (passed to the `nodePattern` function)

@@ -270,2 +280,5 @@ helpers.relationshipPattern();

helpers.relationshipPattern('r');
>>> '-[r]-'
helpers.relationshipPattern({

@@ -296,4 +309,36 @@ direction: 'out',

>>> '-[:KNOWS {since: 1975}]-'
helpers.relationshipPattern({
direction: 'out',
predicate: 'PLAYED_IN',
source: 'a',
target: {
identifier: 'm',
label: 'Movie'
}
});
>>> '(a)-[:PLAYED_IN]->(m:Movie)'
```
<em id="search-pattern">Building search patterns</em>
Note that it will escape for query for regular expression use through the [`escape-regexp`](https://www.npmjs.com/package/escape-regexp) module.
```js
var helpers = require('decypher').helpers;
// Possible options are:
// * `flags` [`'ius'`]: Flags for the regular expression.
// * `partial` [`true`]: Should the match be partial (wrapped in `.*query.*`)?
helpers.searchPattern('john');
>>> '(?ius).*john.*'
helpers.searchPattern('john', {flags: 'im'});
>>> '(?im).*john.*'
helpers.searchPattern('john', {flags: null, partial: false});
>>> 'john'
```
## Contribution

@@ -300,0 +345,0 @@

@@ -13,13 +13,8 @@ /**

var escapeIdentifier = helpers.escapeIdentifier,
nodePattern = helpers.nodePattern,
relationshipPattern = helpers.relationshipPattern;
// TODO: RETURN rather object for nodes?
/**
* Helpers.
*/
function isInternal(id) {
return /^i/.test('' + id);
}
function buildObject(key, value) {

@@ -34,5 +29,42 @@ if (!key)

function validData(o) {
return o && !!Object.keys(o).length;
}
/**
* Class.
* Handler classes.
*/
function Node(batch, id, data, labels) {
var external = id || id === 0;
// Properties
this.batch = batch;
this.id = id || null;
this.identifier = 'N' + (!external ? 'i' + (batch.nodesCounter++) : 'e' + id);
this.param = 'p' + this.identifier;
this.data = data || null;
this.labels = labels;
this.external = external;
}
function Edge(batch, id, source, predicate, target, data) {
var external = id || id === 0;
// Properties
this.batch = batch;
this.id = id || null;
this.identifier = 'R' + (!external ? 'i' + (batch.edgesCounter++) : 'e' + id);
this.param = 'p' + this.identifier;
this.source = source;
this.target = target;
this.predicate = predicate;
this.data = data || null;
this.external = external;
}
/**
* Main class.
*/
function Batch() {

@@ -42,2 +74,3 @@

this.nodesCounter = 0;
this.edgesCounter = 0;
this.nodes = {};

@@ -52,12 +85,10 @@ this.externalNodes = {};

*/
Batch.prototype._externalNode = function(id, data) {
var identifier = 'e' + id;
Batch.prototype._externalNode = function(id) {
if (typeof id !== 'string' && typeof id !== 'number')
throw Error('decypher.Batch: invalid node. Should be either a node handler or a raw Neo4j id.');
if (!this.externalNodes[identifier])
this.externalNodes[identifier] = {id: identifier};
if (!this.externalNodes[id])
this.externalNodes[id] = new Node(this, id, {});
if (data)
this.externalNodes[identifier].data = data;
return this.externalNodes[identifier];
return this.externalNodes[id];
};

@@ -80,27 +111,19 @@

// Giving an id to the created node
var id = 'i' + (this.nodesCounter++);
var node = new Node(this, null, data, labels);
this.nodes[node.identifier] = node;
this.nodes[id] = {data: data, labels: labels};
return id;
return node;
}
// Updating a node
Batch.prototype.update = function(id, data) {
Batch.prototype.update = function(node, data) {
if (!isPlainObject(data))
throw Error('decypher.Batch.update: provided data is not an object.');
if (isInternal(id)) {
var node = this.nodes[id];
if (!(node instanceof Node))
node = this._externalNode(node);
if (!node)
throw Error('decypher.Batch.update: the given internal node id is not defined.');
node.data = assign({}, node.data, data);
node.data = assign({}, node.data, data);
}
else {
this._externalNode(id, data);
}
return this;
return node;
};

@@ -119,60 +142,30 @@

// Relate two nodes
Batch.prototype.relate = function(a, predicate, b, data) {
Batch.prototype.relate = function(source, predicate, target, data) {
data = data || null;
if (!isInternal(a)) {
var node = this._externalNode(a);
a = node.id;
}
else {
var node = this.nodes[a];
if (!(source instanceof Node))
source = this._externalNode(source);
if (!node)
throw Error('decypher.Batch.relate: the given internal node id for the source is not defined.');
}
if (!(target instanceof Node))
target = this._externalNode(target);
if (!isInternal(b)) {
var node = this._externalNode(b);
b = node.id;
}
else {
var node = this.nodes[b];
var edge = new Edge(this, null, source, predicate, target, data);
if (!node)
throw Error('decypher.Batch.relate: the given internal node id for the target is not defined.');
}
this.edges.push(edge);
this.edges.push({from: a, to: b, predicate: predicate, data: data});
// TODO: Return the edge id?
return this;
return edge;
};
// Unrelate two nodes
Batch.prototype.unrelate = function(a, predicate, b) {
// TODO: how to delete a relation strictly
Batch.prototype.unrelate = function(source, predicate, target) {
if (!isInternal(a)) {
var node = this._externalNode(a);
a = node.id;
}
else {
var node = this.nodes[a];
if (!(source instanceof Node))
source = this._externalNode(source);
if (!node)
throw Error('decypher.Batch.unrelate: the given internal node id for the source is not defined.');
}
if (!(target instanceof Node))
target = this._externalNode(target);
if (!isInternal(b)) {
var node = this._externalNode(b);
b = node.id;
}
else {
var node = this.nodes[b];
if (!node)
throw Error('decypher.Batch.unrelate: the given internal node id for the target is not defined.');
}
this.unlinks.push({from: a, to: b, predicate: predicate});
return this;
this.unlinks.push({source: source, target: target, predicate: predicate});
return;
};

@@ -185,17 +178,17 @@

Batch.prototype.query = function() {
var query = new Query();
var query = new Query(),
matchSegment = query.segment(),
createSegment = query.segment();
var matches = [],
lines = [];
//-- External nodes
//-- Registering external nodes
Object.keys(this.externalNodes).forEach(function(k) {
var node = this.externalNodes[k],
name = 'n' + k,
propName = 'p' + k;
var node = this.externalNodes[k];
matches.push({name: name, id: node.id});
matchSegment
.match(nodePattern({identifier: node.identifier}))
.where('id(' + node.identifier + ') = ' + node.id);
if (node.data)
lines.push({type: 'update', name: name, propName: propName, data: node.data});
if (validData(node.data))
query.set(node.identifier + ' += {' + node.param + '}', buildObject(node.param, node.data));
}, this);

@@ -205,11 +198,12 @@

Object.keys(this.nodes).forEach(function(k) {
var node = this.nodes[k],
name = 'n' + k,
propName = 'p' + k;
var node = this.nodes[k];
lines.push({type: 'create', name: name, propName: propName, data: node.data});
createSegment
.create(nodePattern({identifier: node.identifier, data: node.param}), buildObject(node.param, node.data));
node.labels.forEach(function(label) {
lines.push({type: 'label', name: name, label: label});
var labels = node.labels.map(function(label) {
return node.identifier + ':' + escapeIdentifier(label);
});
query.set(labels);
}, this);

@@ -219,64 +213,29 @@

this.unlinks.forEach(function(unlink, i) {
matches.push({
from: unlink.from,
predicate: unlink.predicate,
to: unlink.to,
index: i
});
matchSegment
.match(relationshipPattern({
direction: 'out',
identifier: 'U' + i,
predicate: unlink.predicate,
source: unlink.source.identifier,
target: unlink.target.identifier
}));
lines.push({type: 'unrelate', index: i});
query.delete('U' + i);
});
//-- Edges
this.edges.forEach(function(edge) {
lines.push({
type: 'relate',
from: edge.from,
to: edge.to,
predicate: edge.predicate
});
});
//-- Building the query
matches.forEach(function(match) {
if (match.from) {
var pattern = relationshipPattern({
this.edges.forEach(function(edge, i) {
createSegment
.create(relationshipPattern({
direction: 'out',
identifier: 'r' + match.index,
predicate: match.predicate
});
predicate: edge.predicate,
data: edge.data ? edge.param : null,
source: edge.source.identifier,
target: edge.target.identifier
}));
query.match('(n' + match.from + ')' + pattern + '(n' + match.to + ')');
}
else {
query.match('(' + match.name + ')');
query.where('id(' + match.name + ') = ' + match.id);
}
if (validData(edge.data))
query.params(buildObject(edge.param, edge.data));
});
lines.forEach(function(line) {
var p = buildObject(line.propName, line.data);
if (line.type === 'update') {
query.set(line.name + ' += {' + line.propName + '}', p);
}
else if (line.type === 'create') {
query.create('(' + line.name + ' {' + line.propName + '})', p);
}
else if (line.type === 'label') {
query.set(line.name + ':`' + escapeIdentifier(line.label) + '`');
}
else if (line.type === 'relate') {
var pattern = relationshipPattern({
direction: 'out',
predicate: line.predicate
});
query.create('(n' + line.from + ')' + pattern + '(n' + line.to + ')');
}
else if (line.type === 'unrelate') {
query.delete('r' + line.index);
}
});
return query;

@@ -283,0 +242,0 @@ };

@@ -7,5 +7,8 @@ /**

*/
var isPlainObject = require('lodash.isplainobject');
var isPlainObject = require('lodash.isplainobject'),
escapeRegexp = require('escape-regexp'),
syntax = require('./syntax.js');
var KEYWORDS = require('./syntax.js').KEYWORDS;
var KEYWORDS = syntax.KEYWORDS,
REGEX_FLAGS = syntax.REGEX_FLAGS;

@@ -48,2 +51,5 @@ // Escaping an identifier

if (typeof opts === 'string')
return nodePattern({identifier: opts});
if (!isPlainObject(opts))

@@ -77,2 +83,5 @@ throw Error('decypher.helpers.nodePattern: given options should be a plain object.');

if (typeof opts === 'string')
return relationshipPattern({identifier: opts});
if (!isPlainObject(opts))

@@ -83,2 +92,5 @@ throw Error('decypher.helpers.relationshipPattern: given options should be a plain object.');

if (opts.source)
pattern += nodePattern(opts.source);
if (opts.direction === 'in')

@@ -118,5 +130,41 @@ pattern += '<-';

if (opts.target)
pattern += nodePattern(opts.target);
return pattern;
}
// Creating a search pattern
function searchPattern(query, opts) {
opts = opts || {};
if (typeof query !== 'string')
throw Error('decypher.helpers.searchPattern: given query should be a string.');
var flags = 'flags' in opts ? opts.flags : 'ius',
partial = opts.partial !== false;
if (typeof flags === 'string') {
if (flags.split('').some(function(flag) {
return !REGEX_FLAGS[flag];
}))
throw Error('decypher.helpers.searchPattern: invalid flags "' + flags + '".');
}
var pattern = '';
if (flags)
pattern += '(?' + flags + ')';
if (partial)
pattern += '.*';
pattern += escapeRegexp(query);
if (partial)
pattern += '.*';
return pattern;
}
module.exports = {

@@ -126,3 +174,4 @@ escapeIdentifier: escapeIdentifier,

nodePattern: nodePattern,
relationshipPattern: relationshipPattern
relationshipPattern: relationshipPattern,
searchPattern: searchPattern
};

@@ -8,2 +8,17 @@ /**

*/
var flags = [
'i',
'x',
'm',
's',
'u',
'd'
];
var REGEX_FLAGS = {};
flags.forEach(function(flag) {
REGEX_FLAGS[flag] = true;
});
var STATEMENTS = [

@@ -50,2 +65,3 @@ 'ASSERT',

'ASC',
'CONTAINS',
'DESC',

@@ -68,3 +84,4 @@ 'ENDS',

exports.REGEX_FLAGS = REGEX_FLAGS;
exports.STATEMENTS = STATEMENTS;
exports.KEYWORDS = KEYWORDS;
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