UNPKG

neode

Version:
787 lines (639 loc) 24.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.mode = void 0; var _Match = _interopRequireDefault(require("./Match")); var _Order = _interopRequireDefault(require("./Order")); var _Statement = _interopRequireDefault(require("./Statement")); var _Property = _interopRequireDefault(require("./Property")); var _WhereStatement = _interopRequireDefault(require("./WhereStatement")); var _Where = _interopRequireWildcard(require("./Where")); var _WhereBetween = _interopRequireDefault(require("./WhereBetween")); var _WhereId = _interopRequireDefault(require("./WhereId")); var _WhereRaw = _interopRequireDefault(require("./WhereRaw")); var _WithStatement = _interopRequireDefault(require("./WithStatement")); var _WithDistinctStatement = _interopRequireDefault(require("./WithDistinctStatement")); var _neo4jDriver = _interopRequireDefault(require("neo4j-driver")); function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } var mode = { READ: "READ", WRITE: "WRITE" }; exports.mode = mode; var Builder = /*#__PURE__*/function () { function Builder(neode) { _classCallCheck(this, Builder); this._neode = neode; this._params = {}; this._statements = []; this._current; this._where; this._set_count = 0; } /** * Start a new Query segment and set the current statement * * @return {Builder} */ _createClass(Builder, [{ key: "statement", value: function statement(prefix) { if (this._current) { this._statements.push(this._current); } this._current = new _Statement["default"](prefix); return this; } /** * Start a new Where Segment * * @return {Builder} */ }, { key: "whereStatement", value: function whereStatement(prefix) { if (this._where) { this._current.where(this._where); } this._where = new _WhereStatement["default"](prefix); return this; } /** * Match a Node by a definition * * @param {String} alias Alias in query * @param {Model|String} model Model definition * @param {Object|null} properties Inline Properties * @return {Builder} Builder */ }, { key: "match", value: function match(alias, model, properties) { this.whereStatement('WHERE'); this.statement(); this._current.match(new _Match["default"](alias, model, this._convertPropertyMap(alias, properties))); return this; } }, { key: "optionalMatch", value: function optionalMatch(alias, model) { this.whereStatement('WHERE'); this.statement('OPTIONAL MATCH'); this._current.match(new _Match["default"](alias, model)); return this; } /** * Add a 'with' statement to the query * * @param {...String} args Variables/aliases to carry through * @return {Builder} */ }, { key: "with", value: function _with() { this.whereStatement('WHERE'); this.statement(); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } this._statements.push(_construct(_WithStatement["default"], args)); return this; } /** * Add a 'with distinct' statement to the query * * @param {...String} args Variables/aliases to carry through * @return {Builder} */ }, { key: "withDistinct", value: function withDistinct() { this.whereStatement('WHERE'); this.statement(); for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } this._statements.push(_construct(_WithDistinctStatement["default"], args)); return this; } /** * Create a new WhereSegment * @param {...mixed} args * @return {Builder} */ }, { key: "or", value: function or() { this.whereStatement('OR'); return this.where.apply(this, arguments); } /** * Generate a unique key and add the value to the params object * * @param {String} key * @param {Mixed} value */ }, { key: "_addWhereParameter", value: function _addWhereParameter(key, value) { var attempt = 1; var base = "where_".concat(key.replace(/[^a-z0-9]+/g, '_')); // Try to create a unique key var variable = base; while (typeof this._params[variable] != "undefined") { attempt++; variable = "".concat(base, "_").concat(attempt); } this._params[variable] = value; return variable; } /** * Add a where condition to the current statement. * * @param {...mixed} args Arguments * @return {Builder} */ }, { key: "where", value: function where() { var _this = this; for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } if (!args.length || !args[0]) return this; // If 2 character length, it should be straight forward where if (args.length == 2) { args = [args[0], _Where.OPERATOR_EQUALS, args[1]]; } // If only one argument, treat it as a single string if (args.length == 1) { var _args = args, _args2 = _slicedToArray(_args, 1), arg = _args2[0]; if (Array.isArray(arg)) { arg.forEach(function (inner) { _this.where.apply(_this, _toConsumableArray(inner)); }); } else if (_typeof(arg) == 'object') { Object.keys(arg).forEach(function (key) { _this.where(key, arg[key]); }); } else { this._where.append(new _WhereRaw["default"](args[0])); } } else { var _args3 = args, _args4 = _slicedToArray(_args3, 3), left = _args4[0], operator = _args4[1], value = _args4[2]; var right = this._addWhereParameter(left, value); this._params[right] = value; this._where.append(new _Where["default"](left, operator, "$".concat(right))); } return this; } /** * Query on Internal ID * * @param {String} alias * @param {Int} value * @return {Builder} */ }, { key: "whereId", value: function whereId(alias, value) { var param = this._addWhereParameter("".concat(alias, "_id"), _neo4jDriver["default"]["int"](value)); this._where.append(new _WhereId["default"](alias, param)); return this; } /** * Add a raw where clause * * @param {String} clause * @return {Builder} */ }, { key: "whereRaw", value: function whereRaw(clause) { this._where.append(new _WhereRaw["default"](clause)); return this; } /** * A negative where clause * * @param {*} args * @return {Builder} */ }, { key: "whereNot", value: function whereNot() { this.where.apply(this, arguments); this._where.last().setNegative(); return this; } /** * Between clause * * @param {String} alias * @param {Mixed} floor * @param {Mixed} ceiling * @return {Builder} */ }, { key: "whereBetween", value: function whereBetween(alias, floor, ceiling) { var floor_alias = this._addWhereParameter("".concat(alias, "_floor"), floor); var ceiling_alias = this._addWhereParameter("".concat(alias, "_ceiling"), ceiling); this._where.append(new _WhereBetween["default"](alias, floor_alias, ceiling_alias)); return this; } /** * Negative Between clause * * @param {String} alias * @param {Mixed} floor * @param {Mixed} ceiling * @return {Builder} */ }, { key: "whereNotBetween", value: function whereNotBetween(alias, floor, ceiling) { this.whereBetween(alias, floor, ceiling); this._where.last().setNegative(); return this; } /** * Set Delete fields * * @param {...mixed} args * @return {Builder} */ }, { key: "delete", value: function _delete() { var _this$_current; (_this$_current = this._current)["delete"].apply(_this$_current, arguments); return this; } /** * Set Detach Delete fields * * @param {...mixed} args * @return {Builder} */ }, { key: "detachDelete", value: function detachDelete() { var _this$_current2; (_this$_current2 = this._current).detachDelete.apply(_this$_current2, arguments); return this; } /** * Start a Create Statement by alias/definition * * @param {String} alias Alias in query * @param {Model|String} model Model definition * @param {Object|null} properties Inline Properties * @return {Builder} Builder */ }, { key: "create", value: function create(alias, model, properties) { this.whereStatement('WHERE'); this.statement('CREATE'); this._current.match(new _Match["default"](alias, model, this._convertPropertyMap(alias, properties))); return this; } /** * Convert a map of properties into an Array of * * @param {Object|null} properties */ }, { key: "_convertPropertyMap", value: function _convertPropertyMap(alias, properties) { var _this2 = this; if (properties) { return Object.keys(properties).map(function (key) { var property_alias = "".concat(alias, "_").concat(key); _this2._params[property_alias] = properties[key]; return new _Property["default"](key, property_alias); }); } return []; } /** * Start a Merge Statement by alias/definition * * @param {String} alias Alias in query * @param {Model|String} model Model definition * @param {Object|null} properties Inline Properties * @return {Builder} Builder */ }, { key: "merge", value: function merge(alias, model, properties) { this.whereStatement('WHERE'); this.statement('MERGE'); this._current.match(new _Match["default"](alias, model, this._convertPropertyMap(alias, properties))); return this; } /** * Set a property * * @param {String|Object} property Property in {alias}.{property} format * @param {Mixed} value Value * @param {String} operator Operator */ }, { key: "set", value: function set(property, value) { var _this3 = this; var operator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '='; // Support a map of properties if (!value && property instanceof Object) { Object.keys(property).forEach(function (key) { _this3.set(key, property[key]); }); } else { if (value !== undefined) { var alias = "set_".concat(this._set_count); this._params[alias] = value; this._set_count++; this._current.set(property, alias, operator); } else { this._current.setRaw(property); } } return this; } /** * Set a property * * @param {String|Object} property Property in {alias}.{property} format * @param {Mixed} value Value * @param {String} operator Operator */ }, { key: "onCreateSet", value: function onCreateSet(property, value) { var _this4 = this; var operator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '='; // Support a map of properties if (value === undefined && property instanceof Object) { Object.keys(property).forEach(function (key) { _this4.onCreateSet(key, property[key]); }); } else { var alias = "set_".concat(this._set_count); this._params[alias] = value; this._set_count++; this._current.onCreateSet(property, alias, operator); } return this; } /** * Set a property * * @param {String|Object} property Property in {alias}.{property} format * @param {Mixed} value Value * @param {String} operator Operator */ }, { key: "onMatchSet", value: function onMatchSet(property, value) { var _this5 = this; var operator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '='; // Support a map of properties if (value === undefined && property instanceof Object) { Object.keys(property).forEach(function (key) { _this5.onMatchSet(key, property[key]); }); } else { var alias = "set_".concat(this._set_count); this._params[alias] = value; this._set_count++; this._current.onMatchSet(property, alias, operator); } return this; } /** * Remove properties or labels in {alias}.{property} * or {alias}:{Label} format * * @param {[String]} items */ }, { key: "remove", value: function remove() { for (var _len4 = arguments.length, items = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { items[_key4] = arguments[_key4]; } this._current.remove(items); return this; } /** * Set Return fields * * @param {...mixed} args * @return {Builder} */ }, { key: "return", value: function _return() { var _this$_current3; (_this$_current3 = this._current)["return"].apply(_this$_current3, arguments); return this; } /** * Set Record Limit * * @param {Int} limit * @return {Builder} */ }, { key: "limit", value: function limit(_limit) { this._current.limit(_limit); return this; } /** * Set Records to Skip * * @param {Int} skip * @return {Builder} */ }, { key: "skip", value: function skip(_skip) { this._current.skip(_skip); return this; } /** * Add an order by statement * * @param {...String|object} args Order by statements * @return {Builder} */ }, { key: "orderBy", value: function orderBy() { var _this6 = this; for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { args[_key5] = arguments[_key5]; } var order_by; if (args.length == 2) { // Assume orderBy(what, how) order_by = new _Order["default"](args[0], args[1]); } else if (Array.isArray(args[0])) { // Handle array of where's args[0].forEach(function (arg) { _this6.orderBy(arg); }); } // TODO: Ugly, stop supporting this else if (_typeof(args[0]) == 'object' && args[0].field) { // Assume orderBy(args[0].field, args[0].order) order_by = new _Order["default"](args[0].field, args[0].order); } else if (_typeof(args[0]) == 'object') { // Assume {key: order} Object.keys(args[0]).forEach(function (key) { _this6.orderBy(key, args[0][key]); }); } else if (args[0]) { // Assume orderBy(what, 'ASC') order_by = new _Order["default"](args[0]); } if (order_by) { this._current.order(order_by); } return this; } /** * Add a relationship to the query * * @param {String|RelationshipType} relationship Relationship name or RelationshipType object * @param {String} direction Direction of relationship DIRECTION_IN, DIRECTION_OUT * @param {String|null} alias Relationship alias * @param {Int|String} degrees Number of traversdegreesals (1, "1..2", "0..2", "..3") * @return {Builder} */ }, { key: "relationship", value: function relationship(_relationship, direction, alias, degrees) { this._current.relationship(_relationship, direction, alias, degrees); return this; } /** * Complete a relationship * @param {String} alias Alias * @param {Model} model Model definition * @param {Object} properties Properties * @return {Builder} */ }, { key: "to", value: function to(alias, model, properties) { this._current.match(new _Match["default"](alias, model, this._convertPropertyMap(alias, properties))); return this; } /** * Complete the relationship statement to point to anything * * @return {Builder} */ }, { key: "toAnything", value: function toAnything() { this._current.match(new _Match["default"]()); return this; } /** * Build the pattern without any keywords * * @return {String} */ }, { key: "pattern", value: function pattern() { this.whereStatement(); this.statement(); return this._statements.map(function (statement) { return statement.toString(false); }).join('\n'); } /** * Build the Query * * @param {...String} output References to output * @return {Object} Object containing `query` and `params` property */ }, { key: "build", value: function build() { // Append Statement to Statements this.whereStatement(); this.statement(); var query = this._statements.map(function (statement) { return statement.toString(); }).join('\n'); return { query: query, params: this._params }; } /** * Execute the query * * @param {String} query_mode * @return {Promise} */ }, { key: "execute", value: function execute() { var query_mode = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : mode.WRITE; var _this$build = this.build(), query = _this$build.query, params = _this$build.params; var session; switch (query_mode) { case mode.WRITE: session = this._neode.writeSession(); return session.writeTransaction(function (tx) { return tx.run(query, params); }).then(function (res) { session.close(); return res; }); default: session = this._neode.readSession(); return session.readTransaction(function (tx) { return tx.run(query, params); }).then(function (res) { session.close(); return res; }); } } }]); return Builder; }(); exports["default"] = Builder;