1
0

index.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. "use strict";
  2. var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
  3. if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
  4. return cooked;
  5. };
  6. var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
  7. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  8. return new (P || (P = Promise))(function (resolve, reject) {
  9. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  10. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  11. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  12. step((generator = generator.apply(thisArg, _arguments || [])).next());
  13. });
  14. };
  15. var __generator = (this && this.__generator) || function (thisArg, body) {
  16. var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
  17. return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
  18. function verb(n) { return function (v) { return step([n, v]); }; }
  19. function step(op) {
  20. if (f) throw new TypeError("Generator is already executing.");
  21. while (_) try {
  22. if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
  23. if (y = 0, t) op = [op[0] & 2, t.value];
  24. switch (op[0]) {
  25. case 0: case 1: t = op; break;
  26. case 4: _.label++; return { value: op[1], done: false };
  27. case 5: _.label++; y = op[1]; op = [0]; continue;
  28. case 7: op = _.ops.pop(); _.trys.pop(); continue;
  29. default:
  30. if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
  31. if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
  32. if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
  33. if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
  34. if (t[2]) _.ops.pop();
  35. _.trys.pop(); continue;
  36. }
  37. op = body.call(thisArg, _);
  38. } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
  39. if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
  40. }
  41. };
  42. exports.__esModule = true;
  43. exports.search = exports.find = exports.count = exports.parseTerms = exports.parseSort = exports.parseFilter = exports.parseLimit = exports.operators = exports.operatorMap = exports.formatValue = exports.formatData = void 0;
  44. var arangojs_1 = require("arangojs");
  45. /** Format scalar or scalar array data for use in AQL. */
  46. var formatData = function (data) {
  47. return data instanceof Array ? "[".concat(data.map(exports.formatValue).join(','), "]") : (0, exports.formatValue)(data);
  48. };
  49. exports.formatData = formatData;
  50. /** Format scalar data for use in AQL. */
  51. var formatValue = function (data) {
  52. if (typeof data === 'string')
  53. return "\"".concat(data, "\"");
  54. if (data === null)
  55. return 'null';
  56. return "".concat(data);
  57. };
  58. exports.formatValue = formatValue;
  59. /** Map of search operator properties to AQL equivalents. */
  60. exports.operatorMap = {
  61. eq: '==',
  62. gt: '>',
  63. gte: '>=',
  64. "in": 'IN',
  65. like: 'LIKE',
  66. lt: '<',
  67. lte: '<=',
  68. neq: '!=',
  69. nin: 'NOT IN',
  70. nlike: 'NOT LIKE',
  71. nreg: '!~',
  72. reg: '=~'
  73. };
  74. /** Search operators. */
  75. exports.operators = Object.keys(exports.operatorMap);
  76. /**
  77. * Parse a search limit to a string AQL limit.
  78. *
  79. * Note: `LIMIT` is not prepended.
  80. */
  81. var parseLimit = function (l) { return l.length > 1 ? "".concat(l[0], ", ").concat(l[1]) : l[0]; };
  82. exports.parseLimit = parseLimit;
  83. /**
  84. * Parse a search filter to a string of AQL filters.
  85. *
  86. * Note: `FILTER` is not prepended.
  87. */
  88. var parseFilter = function (param, search) { return parseFilterOps(search)
  89. .map(function (_a) {
  90. var op = _a[0], data = _a[1];
  91. return "".concat(param, " ").concat(op, " ").concat((0, exports.formatData)(data));
  92. })
  93. .join(" ".concat(search.mode || 'AND', " ")); };
  94. exports.parseFilter = parseFilter;
  95. /** Parse search parameter object to FILTER statement(s). */
  96. var parseFilterOps = function (search) {
  97. return Object.keys(search).map(function (key) {
  98. if (key === 'mode' || search[key] === undefined)
  99. return undefined;
  100. if (exports.operatorMap[key] === undefined)
  101. throw new Error('unrecognised search operator');
  102. return [exports.operatorMap[key], search[key]];
  103. }).filter(Boolean);
  104. };
  105. /**
  106. * Parse query sort(s) to an array of string AQL sorts.
  107. *
  108. * Note: `SORT` is not prepended.
  109. */
  110. var parseSort = function (s, parent) {
  111. if (s[0] instanceof Array)
  112. return s.map(function (ss) { return "".concat(renderSortKey(ss, parent), " ").concat(ss[1]); });
  113. return ["".concat(parent, ".").concat(String(s[0]), " ").concat(s[1])];
  114. };
  115. exports.parseSort = parseSort;
  116. /**
  117. * Parse search terms to a flat array of search filters.
  118. * The `parent` argument refers to the current document, and is prefixed to each filter.
  119. */
  120. var parseTerms = function (s, parent) { return Object.keys(s)
  121. .reduce(function (filters, param) {
  122. var f = s[param];
  123. if (!f)
  124. return filters;
  125. if (Object.keys(f).find(function (k) { return k !== 'mode' && !exports.operators.includes(k); })) {
  126. // object is nested
  127. filters.push.apply(filters, (0, exports.parseTerms)(f, "".concat(parent, ".").concat(String(param))));
  128. }
  129. else {
  130. // object resembles a search parameter
  131. filters.push((0, exports.parseFilter)("".concat(parent, ".").concat(String(param)), f));
  132. }
  133. return filters;
  134. }, []); };
  135. exports.parseTerms = parseTerms;
  136. var renderSortKey = function (_a, parent) {
  137. var key = _a[0];
  138. if (key instanceof Object)
  139. return key.toAQL();
  140. return "".concat(parent, ".").concat(String(key));
  141. };
  142. /**
  143. * Build and execute a count query that matches documents in a single collection.
  144. * Returns the total number of matches.
  145. *
  146. * This example resembles the generated AQL query:
  147. *
  148. * ```aql
  149. * FOR {i} IN {c} {FILTER ...} COLLECT WITH COUNT INTO {n} RETURN {n}
  150. * ```
  151. */
  152. var count = function (db, c, i, n) {
  153. if (i === void 0) { i = 'i'; }
  154. if (n === void 0) { n = 'n'; }
  155. return function (terms, inject) { return __awaiter(void 0, void 0, void 0, function () {
  156. var filters, filterStr, l, countQuery;
  157. return __generator(this, function (_a) {
  158. switch (_a.label) {
  159. case 0:
  160. filters = terms && (0, exports.parseTerms)(terms, i);
  161. filterStr = arangojs_1.aql.literal(filters ? filters.map(function (f) { return "FILTER ".concat(f); }).join(' ') : '');
  162. l = { i: arangojs_1.aql.literal(i), n: arangojs_1.aql.literal(n) };
  163. countQuery = (0, arangojs_1.aql)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n FOR ", " IN ", "\n ", "\n ", "\n ", "\n ", "\n ", "\n COLLECT WITH COUNT INTO ", "\n RETURN ", "\n "], ["\n FOR ", " IN ", "\n ", "\n ", "\n ", "\n ", "\n ", "\n COLLECT WITH COUNT INTO ", "\n RETURN ", "\n "])), l.i, c, (inject === null || inject === void 0 ? void 0 : inject.beforeFilter) && arangojs_1.aql.literal(inject.beforeFilter), filterStr, (inject === null || inject === void 0 ? void 0 : inject.beforeSort) && arangojs_1.aql.literal(inject.beforeSort), (inject === null || inject === void 0 ? void 0 : inject.beforeLimit) && arangojs_1.aql.literal(inject.beforeLimit), (inject === null || inject === void 0 ? void 0 : inject.after) && arangojs_1.aql.literal(inject.after), l.n, l.n);
  164. return [4 /*yield*/, db.query(countQuery)];
  165. case 1: return [4 /*yield*/, (_a.sent()).next()];
  166. case 2: return [2 /*return*/, _a.sent()];
  167. }
  168. });
  169. }); };
  170. };
  171. exports.count = count;
  172. /**
  173. * Build and execute a find query that returns the first matching document in a single collection.
  174. *
  175. * This example resembles the generated AQL query:
  176. *
  177. * ```aql
  178. * FOR {i} IN {collection} {FILTER ...} {SORT ...} LIMIT 1 RETURN {i}
  179. * ```
  180. */
  181. var find = function (db, c, i) {
  182. if (i === void 0) { i = 'i'; }
  183. return function (terms, sort, inject) {
  184. if (sort === void 0) { sort = ['_key', 'ASC']; }
  185. return __awaiter(void 0, void 0, void 0, function () {
  186. var filters, filterStr, sortStr, l, query, data;
  187. return __generator(this, function (_a) {
  188. switch (_a.label) {
  189. case 0:
  190. filters = terms && (0, exports.parseTerms)(terms, 'i');
  191. filterStr = arangojs_1.aql.literal(filters ? filters.map(function (f) { return "FILTER ".concat(f); }).join(' ') : '');
  192. sortStr = arangojs_1.aql.literal(sort ? "SORT ".concat((0, exports.parseSort)(sort, 'i').join(', ')) : '');
  193. l = { i: arangojs_1.aql.literal(i) };
  194. query = (0, arangojs_1.aql)(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n FOR ", " IN ", "\n ", "\n ", "\n ", "\n ", "\n ", "\n ", "\n LIMIT 1\n RETURN ", "\n "], ["\n FOR ", " IN ", "\n ", "\n ", "\n ", "\n ", "\n ", "\n ", "\n LIMIT 1\n RETURN ", "\n "])), l.i, c, (inject === null || inject === void 0 ? void 0 : inject.beforeFilter) && arangojs_1.aql.literal(inject.beforeFilter), filterStr, (inject === null || inject === void 0 ? void 0 : inject.beforeSort) && arangojs_1.aql.literal(inject.beforeSort), sortStr, (inject === null || inject === void 0 ? void 0 : inject.beforeLimit) && arangojs_1.aql.literal(inject.beforeLimit), (inject === null || inject === void 0 ? void 0 : inject.after) && arangojs_1.aql.literal(inject.after), l.i);
  195. return [4 /*yield*/, db.query(query)];
  196. case 1: return [4 /*yield*/, (_a.sent()).next()];
  197. case 2:
  198. data = _a.sent();
  199. return [2 /*return*/, data];
  200. }
  201. });
  202. });
  203. };
  204. };
  205. exports.find = find;
  206. /**
  207. * Build and execute a search query across a single collection.
  208. * Returns a `SearchResult` tuple containing the total number of matches (ignoring limit), all matching documents
  209. * (respecting limit), and the AQL query.
  210. *
  211. * This example resembles the generated AQL query:
  212. *
  213. * ```aql
  214. * FOR {i} IN {collection} {FILTER ...} {SORT ...} {LIMIT ...} RETURN {i}
  215. * ```
  216. */
  217. var search = function (db, c, i, n) {
  218. if (i === void 0) { i = 'i'; }
  219. if (n === void 0) { n = 'n'; }
  220. return function (terms, limit, sort, inject) {
  221. if (sort === void 0) { sort = ['_rev', 'ASC']; }
  222. return __awaiter(void 0, void 0, void 0, function () {
  223. var filters, filterStr, limitStr, sortStr, l, count, countQuery, query, data;
  224. return __generator(this, function (_a) {
  225. switch (_a.label) {
  226. case 0:
  227. filters = terms && (0, exports.parseTerms)(terms, 'i');
  228. filterStr = arangojs_1.aql.literal(filters ? filters.map(function (f) { return "FILTER ".concat(f); }).join(' ') : '');
  229. limitStr = arangojs_1.aql.literal(limit ? "LIMIT ".concat((0, exports.parseLimit)(limit)) : '');
  230. sortStr = arangojs_1.aql.literal(sort ? "SORT ".concat((0, exports.parseSort)(sort, 'i').join(', ')) : '');
  231. l = { i: arangojs_1.aql.literal(i), n: arangojs_1.aql.literal(n) };
  232. count = 0;
  233. if (!limit) return [3 /*break*/, 3];
  234. countQuery = (0, arangojs_1.aql)(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n FOR ", " IN ", "\n ", "\n ", "\n ", "\n ", "\n ", "\n COLLECT WITH COUNT INTO ", "\n RETURN ", "\n "], ["\n FOR ", " IN ", "\n ", "\n ", "\n ", "\n ", "\n ", "\n COLLECT WITH COUNT INTO ", "\n RETURN ", "\n "])), l.i, c, (inject === null || inject === void 0 ? void 0 : inject.beforeFilter) && arangojs_1.aql.literal(inject.beforeFilter), filterStr, (inject === null || inject === void 0 ? void 0 : inject.beforeSort) && arangojs_1.aql.literal(inject.beforeSort), (inject === null || inject === void 0 ? void 0 : inject.beforeLimit) && arangojs_1.aql.literal(inject.beforeLimit), (inject === null || inject === void 0 ? void 0 : inject.after) && arangojs_1.aql.literal(inject.after), l.n, l.n);
  235. return [4 /*yield*/, db.query(countQuery)];
  236. case 1: return [4 /*yield*/, (_a.sent()).next()];
  237. case 2:
  238. count = _a.sent();
  239. _a.label = 3;
  240. case 3:
  241. query = (0, arangojs_1.aql)(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n FOR ", " IN ", "\n ", "\n ", "\n ", "\n ", "\n ", "\n ", "\n ", "\n RETURN ", "\n "], ["\n FOR ", " IN ", "\n ", "\n ", "\n ", "\n ", "\n ", "\n ", "\n ", "\n RETURN ", "\n "])), l.i, c, (inject === null || inject === void 0 ? void 0 : inject.beforeFilter) && arangojs_1.aql.literal(inject.beforeFilter), filterStr, (inject === null || inject === void 0 ? void 0 : inject.beforeSort) && arangojs_1.aql.literal(inject.beforeSort), sortStr, (inject === null || inject === void 0 ? void 0 : inject.beforeLimit) && arangojs_1.aql.literal(inject.beforeLimit), limitStr, (inject === null || inject === void 0 ? void 0 : inject.after) && arangojs_1.aql.literal(inject.after), l.i);
  242. return [4 /*yield*/, db.query(query)];
  243. case 4: return [4 /*yield*/, (_a.sent()).all()];
  244. case 5:
  245. data = _a.sent();
  246. if (data.length > count)
  247. count = data.length;
  248. return [2 /*return*/, [count, data, query]];
  249. }
  250. });
  251. });
  252. };
  253. };
  254. exports.search = search;
  255. exports["default"] = {
  256. count: exports.count,
  257. find: exports.find,
  258. formatData: exports.formatData,
  259. formatValue: exports.formatValue,
  260. operatorMap: exports.operatorMap,
  261. operators: exports.operators,
  262. parseFilter: exports.parseFilter,
  263. parseLimit: exports.parseLimit,
  264. parseSort: exports.parseSort,
  265. parseTerms: exports.parseTerms,
  266. search: exports.search
  267. };
  268. var templateObject_1, templateObject_2, templateObject_3, templateObject_4;