@opra/elastic 1.0.0-alpha.32 → 1.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,14 +4,31 @@ exports.default = prepareFilter;
4
4
  /* eslint-disable camelcase */
5
5
  require("@opra/core");
6
6
  const common_1 = require("@opra/common");
7
- const isNil = (v) => v == null;
8
- function prepareFilter(ast, negative) {
9
- if (!ast)
7
+ function prepareFilter(filters) {
8
+ const filtersArray = Array.isArray(filters) ? filters : [filters];
9
+ if (!filtersArray.length)
10
10
  return;
11
- if (ast instanceof common_1.OpraFilter.QualifiedIdentifier) {
12
- return ast.value;
11
+ const out = [];
12
+ for (const filter of filtersArray) {
13
+ if (!filter)
14
+ continue;
15
+ let x = filter;
16
+ if (typeof filter === 'string')
17
+ x = prepareFilterAst(common_1.OpraFilter.parse(filter));
18
+ else if (filter instanceof common_1.OpraFilter.Expression)
19
+ x = prepareFilterAst(filter);
20
+ out.push(x);
13
21
  }
14
- if (ast instanceof common_1.OpraFilter.NumberLiteral ||
22
+ if (out.length > 1) {
23
+ return { bool: { must: [...out] } };
24
+ }
25
+ return out[0] ? out[0] : undefined;
26
+ }
27
+ function prepareFilterAst(ast, negative) {
28
+ if (!ast)
29
+ return;
30
+ if (ast instanceof common_1.OpraFilter.QualifiedIdentifier ||
31
+ ast instanceof common_1.OpraFilter.NumberLiteral ||
15
32
  ast instanceof common_1.OpraFilter.StringLiteral ||
16
33
  ast instanceof common_1.OpraFilter.BooleanLiteral ||
17
34
  ast instanceof common_1.OpraFilter.NullLiteral ||
@@ -20,86 +37,77 @@ function prepareFilter(ast, negative) {
20
37
  return ast.value;
21
38
  }
22
39
  if (ast instanceof common_1.OpraFilter.ArrayExpression) {
23
- return ast.items.map(x => prepareFilter(x, negative)).filter(x => !isNil(x));
40
+ return ast.items.map(x => prepareFilterAst(x, negative));
24
41
  }
25
42
  if (ast instanceof common_1.OpraFilter.NegativeExpression) {
26
- return prepareFilter(ast.expression, !negative);
43
+ return prepareFilterAst(ast.expression, !negative);
27
44
  }
28
45
  if (ast instanceof common_1.OpraFilter.LogicalExpression) {
29
- const v = ast.items.map(x => prepareFilter(x)).filter(x => !isNil(x));
30
- if (ast.op === 'and') {
31
- return {
32
- bool: {
33
- [negative ? 'must_not' : 'must']: v,
34
- },
35
- };
36
- }
37
- return wrapNot({
38
- bool: { should: v },
39
- }, negative);
46
+ const items = ast.items
47
+ .map(x => prepareFilterAst(x))
48
+ /** Filter nullish items */
49
+ .filter(x => x != null);
50
+ const k = (ast.op === 'or' ? 'should' : 'must') + (negative ? '_not' : '');
51
+ return { bool: { [k]: items } };
40
52
  }
41
53
  if (ast instanceof common_1.OpraFilter.ParenthesizedExpression) {
42
- return prepareFilter(ast.expression, negative);
43
- }
44
- if (ast instanceof common_1.OpraFilter.ComparisonExpression)
45
- return _transformComparisonExpression(ast, !!negative);
46
- throw new Error(`${ast.kind} is not implemented yet`);
47
- }
48
- function _transformComparisonExpression(ast, negative) {
49
- const left = prepareFilter(ast.left, negative);
50
- if (ast.right instanceof common_1.OpraFilter.QualifiedIdentifier) {
51
- throw new TypeError('not implemented yet');
54
+ return prepareFilterAst(ast.expression, negative);
52
55
  }
53
- const right = prepareFilter(ast.right);
54
- if (right == null) {
55
- const op = ast.op === '=' ? (negative ? '!=' : '=') : negative ? '=' : '!=';
56
- if (op === '=')
57
- return { bool: { must_not: { exists: { field: left } } } };
58
- if (op === '!=')
59
- return { bool: { exists: { field: left } } };
60
- }
61
- switch (ast.op) {
62
- case '=':
63
- return wrapNot({ term: { [left]: right } }, negative);
64
- case '!=':
65
- return wrapNot({ term: { [left]: right } }, !negative);
66
- case '>':
67
- return wrapNot({ range: { [left]: { gt: right } } }, negative);
68
- case '>=':
69
- return wrapNot({ range: { [left]: { gte: right } } }, negative);
70
- case '<':
71
- return wrapNot({ range: { [left]: { lt: right } } }, negative);
72
- case '<=':
73
- return wrapNot({ range: { [left]: { lte: right } } }, negative);
74
- case 'in':
75
- return wrapNot({ terms: { [left]: Array.isArray(right) ? right : [right] } }, negative);
76
- case '!in':
77
- return wrapNot({ terms: { [left]: Array.isArray(right) ? right : [right] } }, !negative);
78
- case 'like':
79
- return wrapNot({ wildcard: { [left]: String(right) } }, negative);
80
- case '!like':
81
- return wrapNot({ wildcard: { [left]: String(right) } }, !negative);
82
- case 'ilike':
83
- return wrapNot({
84
- wildcard: {
85
- [left]: {
86
- value: String(right),
87
- case_insensitive: true,
88
- },
89
- },
90
- }, negative);
91
- case '!ilike':
92
- return wrapNot({
93
- wildcard: {
94
- [left]: {
95
- value: String(right),
96
- case_insensitive: true,
97
- },
98
- },
99
- }, !negative);
100
- default:
101
- break;
56
+ if (ast instanceof common_1.OpraFilter.ComparisonExpression) {
57
+ if (!(ast.left instanceof common_1.OpraFilter.QualifiedIdentifier)) {
58
+ throw new Error('Left side of ComparisonExpression must be a QualifiedIdentifier');
59
+ }
60
+ const left = prepareFilterAst(ast.left);
61
+ const right = prepareFilterAst(ast.right);
62
+ let out;
63
+ if (right == null) {
64
+ negative = !negative;
65
+ out = { exists: { field: left } };
66
+ }
67
+ else {
68
+ switch (ast.op) {
69
+ case '!=':
70
+ case '=':
71
+ case 'in':
72
+ case '!in': {
73
+ out = { match: { [left]: right } };
74
+ break;
75
+ }
76
+ case '>': {
77
+ out = { range: { [left]: { gt: right } } };
78
+ break;
79
+ }
80
+ case '>=': {
81
+ out = { range: { [left]: { gte: right } } };
82
+ break;
83
+ }
84
+ case '<': {
85
+ out = { range: { [left]: { lt: right } } };
86
+ break;
87
+ }
88
+ case '<=': {
89
+ out = { range: { [left]: { lte: right } } };
90
+ break;
91
+ }
92
+ case '!like':
93
+ case 'like': {
94
+ out = { wildcard: { [left]: { value: String(right).replace(/%/g, '*') } } };
95
+ break;
96
+ }
97
+ case '!ilike':
98
+ case 'ilike': {
99
+ out = { wildcard: { [left]: { value: String(right).replace(/%/g, '*'), case_insensitive: true } } };
100
+ break;
101
+ }
102
+ default:
103
+ /* istanbul ignore next */
104
+ throw new TypeError(`Unknown ComparisonExpression operation (${ast.op})`);
105
+ }
106
+ }
107
+ if ((ast.op.startsWith('!') && !negative) || (!ast.op.startsWith('!') && negative)) {
108
+ return { bool: { must_not: { ...out } } };
109
+ }
110
+ return out;
102
111
  }
103
- throw new Error(`ComparisonExpression operator (${ast.op}) not implemented yet`);
112
+ throw new Error(`${ast.kind} is not implemented yet`);
104
113
  }
105
- const wrapNot = (o, negative) => (negative ? { bool: { must_not: o } } : o);
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = preparePatch;
4
+ function preparePatch(doc) {
5
+ const script = [];
6
+ const params = {};
7
+ _preparePatch(doc, script, params, '');
8
+ return {
9
+ source: script.join('\n'),
10
+ params,
11
+ lang: 'painless',
12
+ };
13
+ }
14
+ function _preparePatch(src, script, params, path) {
15
+ let f;
16
+ let field;
17
+ for (const [k, v] of Object.entries(src)) {
18
+ f = k.startsWith('*') ? k.substring(1) : k;
19
+ field = path ? path + '.' + f : f;
20
+ if (v == null) {
21
+ script.push(`ctx._source.remove('${field}');`);
22
+ continue;
23
+ }
24
+ if (v &&
25
+ typeof v === 'object' &&
26
+ !Array.isArray(v) &&
27
+ /** If field name starts with "*", do "replace" operation except "merge" */
28
+ !k.startsWith('*')) {
29
+ _preparePatch(v, script, params, field);
30
+ continue;
31
+ }
32
+ script.push(`ctx._source['${field}'] = params['${field}'];`);
33
+ params[field] = v;
34
+ }
35
+ }
@@ -1,109 +1,66 @@
1
1
  "use strict";
2
- // import { ApiField, ComplexType, FieldsProjection, omitNullish, parseFieldsProjection } from '@opra/common';
3
- // import mongodb, { Document } from 'mongodb';
4
- //
5
- // export default function prepareProjection(
6
- // dataType: ComplexType,
7
- // projection?: string | string[] | Document,
8
- // ): mongodb.Document | undefined {
9
- // if (projection && typeof projection === 'object' && !Array.isArray(projection)) return projection;
10
- // const out: Record<string, boolean> = {};
11
- // const projection_ =
12
- // typeof projection === 'string' || Array.isArray(projection) ? parseFieldsProjection(projection) : projection;
13
- // // const exclusionProjection = !pick && !!omit;
14
- // prepare(dataType, out, projection_);
15
- // return Object.keys(out).length ? out : undefined;
16
- // }
17
- //
18
- // export function prepare(dataType: ComplexType, target: mongodb.Document, projection?: FieldsProjection) {
19
- // const defaultFields = !projection || !Object.values(projection).find(p => !p.sign);
20
- // const projectionKeys = projection && Object.keys(projection).map(x => x.toLowerCase());
21
- // const projectionKeysSet = new Set(projectionKeys);
22
- // let fieldName: string;
23
- // let field: ApiField;
24
- // let k: string;
25
- // /** Add fields from data type */
26
- // for (field of dataType.fields.values()) {
27
- // fieldName = field.name;
28
- // k = fieldName.toLowerCase();
29
- // projectionKeysSet.delete(k);
30
- // const p = projection?.[k];
31
- // if (
32
- // /** Ignore if field is omitted */
33
- // p?.sign === '-' ||
34
- // /** Ignore if default fields and field is not in projection */
35
- // (!defaultFields && !p) ||
36
- // /** Ignore if default fields enabled and fields is exclusive */
37
- // (defaultFields && field.exclusive && !p)
38
- // ) {
39
- // continue;
40
- // }
41
- //
42
- // if (field.type instanceof ComplexType && typeof p?.projection === 'object') {
43
- // target[fieldName] = {};
44
- // prepare(field.type, target[fieldName], p.projection);
45
- // continue;
46
- // }
47
- // target[fieldName] = 1;
48
- // }
49
- // /** Add additional fields */
50
- // if (dataType.additionalFields) {
51
- // for (k of projectionKeysSet.values()) {
52
- // const n = projectionKeysSet[k];
53
- // if (n?.sign !== '-') target[k] = 1;
54
- // }
55
- // }
56
- // }
57
- //
58
- // // function __prepareProjection(
59
- // // dataType: ComplexType,
60
- // // args: {
61
- // // pick?: string[];
62
- // // omit?: string[];
63
- // // include?: string[];
64
- // // },
65
- // // ): any {
66
- // // let includes: string[] | undefined;
67
- // // let excludes: string[] | undefined;
68
- // //
69
- // // if (args.include && !args.pick) {
70
- // // includes = includes || [];
71
- // // for (const [k, f] of dataType.fields) {
72
- // // if (f.exclusive) continue;
73
- // // if (f.type instanceof ComplexType) includes.push(k + '.*');
74
- // // else includes.push(k);
75
- // // }
76
- // // }
77
- // //
78
- // // if (args.pick) {
79
- // // includes = includes || [];
80
- // // for (const k of args.pick) {
81
- // // const f = dataType.getField(k);
82
- // // if (f.type instanceof ComplexType) includes.push(k + '.*');
83
- // // else includes.push(k);
84
- // // }
85
- // // }
86
- // //
87
- // // if (args.include) {
88
- // // includes = includes || [];
89
- // // for (const k of args.include) {
90
- // // const f = dataType.getField(k);
91
- // // if (f.type instanceof ComplexType) includes.push(k + '.*');
92
- // // else includes.push(k);
93
- // // }
94
- // // }
95
- // //
96
- // // if (args.omit) {
97
- // // excludes = excludes || [];
98
- // // for (const k of args.omit) {
99
- // // const f = dataType.getField(k);
100
- // // if (f.type instanceof ComplexType) excludes.push(k + '.*');
101
- // // else excludes.push(k);
102
- // // }
103
- // // }
104
- // //
105
- // // return omitNullish({
106
- // // includes,
107
- // // excludes,
108
- // // });
109
- // // }
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = prepareProjection;
4
+ exports.prepare = prepare;
5
+ const common_1 = require("@opra/common");
6
+ function prepareProjection(dataType, projection) {
7
+ const out = {};
8
+ const includes = [];
9
+ const excludes = [];
10
+ const projection_ = typeof projection === 'string' || Array.isArray(projection) ? (0, common_1.parseFieldsProjection)(projection) : projection;
11
+ prepare(dataType, includes, excludes, '', projection_);
12
+ if (includes.length)
13
+ out.includes = includes;
14
+ if (excludes.length)
15
+ out.excludes = excludes;
16
+ return includes.length || excludes.length ? out : undefined;
17
+ }
18
+ function getNeedIncludes(projection) {
19
+ return !!(projection && Object.values(projection).find(p => !p.sign));
20
+ }
21
+ function prepare(dataType, includes, excludes, curPath, projection) {
22
+ const needIncludes = getNeedIncludes(projection);
23
+ const projectionKeys = projection && Object.keys(projection);
24
+ const projectionKeysSet = new Set(projectionKeys);
25
+ let fieldName;
26
+ let fieldPath;
27
+ let field;
28
+ let k;
29
+ /** Add fields from data type */
30
+ for (field of dataType.fields.values()) {
31
+ fieldName = field.name;
32
+ fieldPath = curPath + (curPath ? '.' : '') + fieldName;
33
+ k = fieldName.toLowerCase();
34
+ projectionKeysSet.delete(k);
35
+ const p = projection?.[k];
36
+ if (
37
+ /** if field is omitted */
38
+ p?.sign === '-' ||
39
+ /** if no projection defined for this field and includeDefaultFields is true and the field is exclusive */
40
+ (!p && field.exclusive)) {
41
+ if (!needIncludes)
42
+ excludes.push(fieldPath);
43
+ continue;
44
+ }
45
+ if (needIncludes && p && !includes.includes(fieldPath)) {
46
+ if (!getNeedIncludes(p?.projection)) {
47
+ includes.push(fieldPath);
48
+ }
49
+ }
50
+ if (field.type instanceof common_1.ComplexType && typeof p?.projection === 'object') {
51
+ prepare(field.type, includes, excludes, fieldPath, p.projection);
52
+ }
53
+ }
54
+ if (dataType.additionalFields) {
55
+ for (k of projectionKeysSet.values()) {
56
+ const n = projection?.[k];
57
+ fieldPath = curPath + (curPath ? '.' : '') + k;
58
+ if (n?.sign === '-') {
59
+ if (!needIncludes)
60
+ excludes.push(fieldPath);
61
+ }
62
+ else
63
+ includes.push(fieldPath);
64
+ }
65
+ }
66
+ }
@@ -1,17 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.default = prepareSort;
4
+ const SIGN_PATTERN = /^([+-])?(.+)$/;
4
5
  function prepareSort(sort) {
5
6
  if (!(sort && sort.length))
6
7
  return;
7
8
  const out = [];
8
9
  sort.forEach(k => {
9
- if (k.startsWith('-'))
10
- out.push({ [k.substring(1)]: 'desc' });
11
- else if (k.startsWith('+'))
12
- out.push(k.substring(1));
13
- else
14
- out.push(k);
10
+ const m = SIGN_PATTERN.exec(k);
11
+ if (m) {
12
+ out.push({ [m[2]]: { order: m[1] === '-' ? 'desc' : 'asc' } });
13
+ }
15
14
  });
16
15
  return out;
17
16
  }
@@ -2,18 +2,15 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ElasticAdapter = void 0;
4
4
  const tslib_1 = require("tslib");
5
- // import { SearchRequest } from '@elastic/elasticsearch/lib/api/types';
6
- // import { TransportRequestOptions } from '@elastic/transport';
7
- // import { omitNullish } from '@opra/common';
8
5
  const prepare_filter_js_1 = tslib_1.__importDefault(require("./adapter-utils/prepare-filter.js"));
9
- const prepare_key_values_js_1 = tslib_1.__importDefault(require("./adapter-utils/prepare-key-values.js"));
10
- // import _prepareProjection from './adapter-utils/prepare-projection.js';
6
+ const prepare_patch_js_1 = tslib_1.__importDefault(require("./adapter-utils/prepare-patch.js"));
7
+ const prepare_projection_js_1 = tslib_1.__importDefault(require("./adapter-utils/prepare-projection.js"));
11
8
  const prepare_sort_js_1 = tslib_1.__importDefault(require("./adapter-utils/prepare-sort.js"));
12
9
  var ElasticAdapter;
13
10
  (function (ElasticAdapter) {
14
11
  ElasticAdapter.prepareFilter = prepare_filter_js_1.default;
15
- ElasticAdapter.prepareKeyValues = prepare_key_values_js_1.default;
16
- // export const prepareProjection = _prepareProjection;
12
+ ElasticAdapter.preparePatch = prepare_patch_js_1.default;
13
+ ElasticAdapter.prepareProjection = prepare_projection_js_1.default;
17
14
  ElasticAdapter.prepareSort = prepare_sort_js_1.default;
18
15
  async function parseRequest(context) {
19
16
  const { operation } = context;