@opra/elastic 1.21.0 → 1.22.1

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.
Files changed (31) hide show
  1. package/{esm/elastic-collection-service.js → elastic-collection-service.js} +12 -0
  2. package/{esm/elastic-entity-service.js → elastic-entity-service.js} +23 -2
  3. package/{esm/elastic-service.js → elastic-service.js} +11 -0
  4. package/package.json +10 -26
  5. package/cjs/adapter-utils/prepare-filter.js +0 -130
  6. package/cjs/adapter-utils/prepare-patch.js +0 -35
  7. package/cjs/adapter-utils/prepare-projection.js +0 -69
  8. package/cjs/adapter-utils/prepare-sort.js +0 -16
  9. package/cjs/elastic-adapter.js +0 -126
  10. package/cjs/elastic-collection-service.js +0 -409
  11. package/cjs/elastic-entity-service.js +0 -536
  12. package/cjs/elastic-service.js +0 -64
  13. package/cjs/index.js +0 -7
  14. package/cjs/package.json +0 -3
  15. package/esm/package.json +0 -3
  16. package/types/index.d.cts +0 -4
  17. /package/{types/adapter-utils → adapter-utils}/prepare-filter.d.ts +0 -0
  18. /package/{esm/adapter-utils → adapter-utils}/prepare-filter.js +0 -0
  19. /package/{types/adapter-utils → adapter-utils}/prepare-patch.d.ts +0 -0
  20. /package/{esm/adapter-utils → adapter-utils}/prepare-patch.js +0 -0
  21. /package/{types/adapter-utils → adapter-utils}/prepare-projection.d.ts +0 -0
  22. /package/{esm/adapter-utils → adapter-utils}/prepare-projection.js +0 -0
  23. /package/{types/adapter-utils → adapter-utils}/prepare-sort.d.ts +0 -0
  24. /package/{esm/adapter-utils → adapter-utils}/prepare-sort.js +0 -0
  25. /package/{types/elastic-adapter.d.ts → elastic-adapter.d.ts} +0 -0
  26. /package/{esm/elastic-adapter.js → elastic-adapter.js} +0 -0
  27. /package/{types/elastic-collection-service.d.ts → elastic-collection-service.d.ts} +0 -0
  28. /package/{types/elastic-entity-service.d.ts → elastic-entity-service.d.ts} +0 -0
  29. /package/{types/elastic-service.d.ts → elastic-service.d.ts} +0 -0
  30. /package/{types/index.d.ts → index.d.ts} +0 -0
  31. /package/{esm/index.js → index.js} +0 -0
@@ -1,536 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ElasticEntityService = void 0;
4
- const common_1 = require("@opra/common");
5
- const valgen_1 = require("valgen");
6
- const elastic_adapter_js_1 = require("./elastic-adapter.js");
7
- const elastic_service_js_1 = require("./elastic-service.js");
8
- /**
9
- * @class ElasticEntityService
10
- * @template T - The type of the documents in the collection.
11
- */
12
- class ElasticEntityService extends elastic_service_js_1.ElasticService {
13
- /**
14
- * Constructs a new instance
15
- *
16
- * @param {Type | string} dataType - The data type of the array elements.
17
- * @param {ElasticEntityService.Options} [options] - The options for the array service.
18
- * @constructor
19
- */
20
- constructor(dataType, options) {
21
- super(options);
22
- this._inputCodecs = {};
23
- this._outputCodecs = {};
24
- this._dataType_ = dataType;
25
- if (options?.indexName)
26
- this.indexName = options?.indexName;
27
- else {
28
- if (typeof dataType === 'string')
29
- this.indexName = dataType;
30
- if (typeof dataType === 'function') {
31
- const metadata = Reflect.getMetadata(common_1.DATATYPE_METADATA, dataType);
32
- if (metadata)
33
- this.indexName = metadata.name;
34
- }
35
- }
36
- this.resourceName = options?.resourceName;
37
- this.idGenerator = options?.idGenerator;
38
- }
39
- /**
40
- * Retrieves the index name.
41
- *
42
- * @protected
43
- * @returns The index name.
44
- * @throws {Error} If the index name is not defined.
45
- */
46
- getIndexName() {
47
- const out = typeof this.indexName === 'function'
48
- ? this.indexName(this)
49
- : this.indexName;
50
- if (out)
51
- return out;
52
- throw new Error('indexName is not defined');
53
- }
54
- /**
55
- * Retrieves the resource name.
56
- *
57
- * @protected
58
- * @returns {string} The resource name.
59
- * @throws {Error} If the resource name is not defined.
60
- */
61
- getResourceName() {
62
- const out = typeof this.resourceName === 'function'
63
- ? this.resourceName(this)
64
- : this.resourceName || this.getIndexName();
65
- if (out)
66
- return out;
67
- throw new Error('resourceName is not defined');
68
- }
69
- /**
70
- * Retrieves the OPRA data type
71
- *
72
- * @throws {NotAcceptableError} If the data type is not a ComplexType.
73
- */
74
- get dataType() {
75
- if (this._dataType && this._dataTypeScope !== this.scope)
76
- this._dataType = undefined;
77
- if (!this._dataType)
78
- this._dataType = this.context.__docNode.getComplexType(this._dataType_);
79
- this._dataTypeScope = this.scope;
80
- return this._dataType;
81
- }
82
- /**
83
- * Adds a JSON document to the specified data stream or index and makes it searchable.
84
- * If the target is an index and the document already exists,
85
- * the request updates the document and increments its version.
86
- *
87
- * @param {ElasticEntityService.CreateCommand} command
88
- * @protected
89
- */
90
- async _create(command) {
91
- const input = command.input;
92
- (0, valgen_1.isNotNullish)(input, { label: 'input' });
93
- (0, valgen_1.isNotNullish)(input._id, { label: 'input._id' });
94
- const inputCodec = this._getInputCodec('create');
95
- const doc = inputCodec(input);
96
- delete doc._id;
97
- const { options } = command;
98
- const request = {
99
- ...options?.request,
100
- index: this.getIndexName(),
101
- id: input._id,
102
- document: doc,
103
- };
104
- const r = await this.__create(request, options);
105
- /* istanbul ignore next */
106
- if (!(r._id && (r.result === 'created' || r.result === 'updated'))) {
107
- throw new common_1.InternalServerError(`Unknown error while creating document for "${this.getResourceName()}"`);
108
- }
109
- return r;
110
- }
111
- async __create(request, options) {
112
- const client = this.getClient();
113
- return options?.replaceIfExists
114
- ? await client.index(request, options?.transport)
115
- : await client.create(request, options?.transport);
116
- }
117
- /**
118
- * Returns the count of documents in the collection based on the provided options.
119
- *
120
- * @param {ElasticEntityService.CountCommand} command
121
- * @protected
122
- */
123
- async _count(command) {
124
- const { options } = command;
125
- const filterQuery = elastic_adapter_js_1.ElasticAdapter.prepareFilter([
126
- options?.filter,
127
- options?.request?.query,
128
- ]);
129
- let query = {
130
- ...options?.request?.query,
131
- ...filterQuery,
132
- };
133
- if (!Object.keys(query).length)
134
- query = undefined;
135
- const request = {
136
- index: this.getIndexName(),
137
- ...options?.request,
138
- query,
139
- };
140
- return this.__count(request, options);
141
- }
142
- __count(request, options) {
143
- const client = this.getClient();
144
- return client.count(request, options?.transport);
145
- }
146
- /**
147
- * Deletes a document from the collection.
148
- *
149
- * @param {ElasticEntityService.DeleteCommand} command
150
- * @protected
151
- */
152
- async _delete(command) {
153
- (0, valgen_1.isNotNullish)(command.documentId, { label: 'documentId' });
154
- const { options } = command;
155
- const filterQuery = elastic_adapter_js_1.ElasticAdapter.prepareFilter([
156
- { ids: { values: [command.documentId] } },
157
- options?.filter,
158
- options?.request?.query,
159
- ]);
160
- let query = {
161
- ...options?.request?.query,
162
- ...filterQuery,
163
- };
164
- if (!Object.keys(query).length)
165
- query = { match_all: {} };
166
- const request = {
167
- index: this.getIndexName(),
168
- ...options?.request,
169
- query,
170
- };
171
- return this.__delete(request, options);
172
- }
173
- /**
174
- * Deletes multiple documents from the collection that meet the specified filter criteria.
175
- *
176
- * @param {ElasticEntityService.DeleteManyCommand} command
177
- * @protected
178
- */
179
- async _deleteMany(command) {
180
- const { options } = command;
181
- const filterQuery = elastic_adapter_js_1.ElasticAdapter.prepareFilter([
182
- options?.filter,
183
- options?.request?.query,
184
- ]);
185
- let query = {
186
- ...options?.request?.query,
187
- ...filterQuery,
188
- };
189
- if (!Object.keys(query).length)
190
- query = { match_all: {} };
191
- const request = {
192
- ...options?.request,
193
- index: this.getIndexName(),
194
- query,
195
- };
196
- return await this.__delete(request, options);
197
- }
198
- async __delete(request, options) {
199
- const client = this.getClient();
200
- return client.deleteByQuery(request, options?.transport);
201
- }
202
- /**
203
- * Returns search hits that match the query defined in the request
204
- *
205
- * @param {ElasticEntityService.FindManyCommand} command
206
- */
207
- async _findMany(command) {
208
- const { options } = command;
209
- const filterQuery = elastic_adapter_js_1.ElasticAdapter.prepareFilter([
210
- command.documentId
211
- ? { ids: { values: [command.documentId] } }
212
- : undefined,
213
- options?.filter,
214
- // options?.request?.query,
215
- ]);
216
- let query = this._mergeQueries(options?.request?.query, filterQuery);
217
- if (!(query && Object.keys(query).length))
218
- query = { match_all: {} };
219
- const request = {
220
- from: options?.skip,
221
- size: options?.limit,
222
- sort: options?.sort
223
- ? elastic_adapter_js_1.ElasticAdapter.prepareSort(options?.sort)
224
- : undefined,
225
- _source: elastic_adapter_js_1.ElasticAdapter.prepareProjection(this.dataType, options?.projection, this._dataTypeScope),
226
- index: this.getIndexName(),
227
- ...options?.request,
228
- query,
229
- };
230
- const r = await this.__findMany(request, options);
231
- if (options?.noDecode)
232
- return r;
233
- if (r.hits.hits?.length) {
234
- const outputCodec = this.getOutputCodec('find');
235
- r.hits.hits = r.hits.hits.map((x) => ({
236
- ...x,
237
- _source: {
238
- _id: x._id,
239
- ...outputCodec(x._source),
240
- },
241
- }));
242
- }
243
- return r;
244
- }
245
- async __findMany(request, options) {
246
- const client = this.getClient();
247
- return client.search(request, options?.transport);
248
- }
249
- /**
250
- * Executes a search operation on the Elasticsearch index using the provided search command.
251
- *
252
- * @param {ElasticEntityService.SearchCommand} command - The search command containing the request configuration and optional transport settings.
253
- * @return {Promise<ElasticEntityService.SearchResponse>} A promise resolving to the search response from Elasticsearch.
254
- */
255
- async _searchRaw(command) {
256
- const { options } = command;
257
- const request = {
258
- index: this.getIndexName(),
259
- ...command.request,
260
- };
261
- const client = this.getClient();
262
- const r = await client.search(request, options?.transport);
263
- if (r.hits.hits?.length) {
264
- const outputCodec = this.getOutputCodec('find');
265
- r.hits.hits = r.hits.hits.map((x) => ({
266
- ...x,
267
- _source: {
268
- _id: x._id,
269
- ...outputCodec(x._source),
270
- },
271
- }));
272
- }
273
- return r;
274
- }
275
- /**
276
- * Updates multiple documents in the collection based on the specified input and options.
277
- *
278
- * @param {ElasticEntityService.UpdateCommand<T>} command
279
- */
280
- async _updateMany(command) {
281
- if (command.byId)
282
- (0, valgen_1.isNotNullish)(command.documentId, { label: 'documentId' });
283
- const { options } = command;
284
- const input = command.input;
285
- const requestScript = command.options?.request?.script;
286
- let script;
287
- const inputKeysLen = Object.keys(input).length;
288
- (0, valgen_1.isNotNullish)(inputKeysLen || script, { label: 'input' });
289
- if (requestScript) {
290
- if (typeof requestScript === 'string')
291
- script = { source: requestScript };
292
- else if (requestScript.source || requestScript.id)
293
- script = { ...requestScript };
294
- else
295
- script = { source: requestScript };
296
- script.lang = script.lang || 'painless';
297
- if (inputKeysLen > 0 && script.lang !== 'painless') {
298
- throw new TypeError(`You cannot provide 'input' and 'script' arguments at the same time unless the script lang is 'painless'`);
299
- }
300
- }
301
- if (inputKeysLen) {
302
- delete input._id;
303
- const inputCodec = this._getInputCodec('update');
304
- const doc = inputCodec(input);
305
- const scr = elastic_adapter_js_1.ElasticAdapter.preparePatch(doc);
306
- if (script) {
307
- script.source =
308
- (script.source ? script.source + '\n' + script.source : '') +
309
- scr.source;
310
- script.params = { ...script.params, ...scr.params };
311
- }
312
- else
313
- script = scr;
314
- }
315
- script.source = script?.source || 'return;';
316
- const filterQuery = elastic_adapter_js_1.ElasticAdapter.prepareFilter([
317
- command.byId ? { ids: { values: [command.documentId] } } : undefined,
318
- options?.filter,
319
- options?.request?.query,
320
- ]);
321
- let query = {
322
- ...options?.request?.query,
323
- ...filterQuery,
324
- };
325
- if (!Object.keys(query).length)
326
- query = { match_all: {} };
327
- const request = {
328
- ...options?.request,
329
- index: this.getIndexName(),
330
- script,
331
- query,
332
- };
333
- return await this.__update(request, options);
334
- }
335
- async __update(request, options) {
336
- const client = this.getClient();
337
- return client.updateByQuery(request, options?.transport);
338
- }
339
- /**
340
- * Generates an ID.
341
- *
342
- * @protected
343
- * @returns The generated ID.
344
- */
345
- _generateId(command) {
346
- return typeof this.idGenerator === 'function'
347
- ? this.idGenerator(command, this)
348
- : undefined;
349
- }
350
- /**
351
- * Retrieves the codec for the specified operation.
352
- *
353
- * @param operation - The operation to retrieve the encoder for. Valid values are 'create' and 'update'.
354
- */
355
- _getInputCodec(operation) {
356
- const dataType = this.dataType;
357
- const cacheKey = operation + (this._dataTypeScope ? ':' + this._dataTypeScope : '');
358
- let validator = this._inputCodecs[cacheKey];
359
- if (validator)
360
- return validator;
361
- const options = {
362
- projection: '*',
363
- scope: this._dataTypeScope,
364
- };
365
- if (operation === 'update') {
366
- options.partial = 'deep';
367
- options.keepKeyFields = true;
368
- }
369
- validator = dataType.generateCodec('decode', options);
370
- this._inputCodecs[cacheKey] = validator;
371
- return validator;
372
- }
373
- /**
374
- * Retrieves the codec.
375
- */
376
- getOutputCodec(operation) {
377
- const cacheKey = operation + (this._dataTypeScope ? ':' + this._dataTypeScope : '');
378
- let validator = this._outputCodecs[cacheKey];
379
- if (validator)
380
- return validator;
381
- const options = {
382
- projection: '*',
383
- partial: 'deep',
384
- scope: this._dataTypeScope,
385
- };
386
- const dataType = this.dataType;
387
- validator = dataType.generateCodec('decode', options);
388
- this._outputCodecs[cacheKey] = validator;
389
- return validator;
390
- }
391
- async _executeCommand(command, commandFn) {
392
- try {
393
- const result = await super._executeCommand(command, async () => {
394
- /** Call before[X] hooks */
395
- if (command.crud === 'create')
396
- await this._beforeCreate(command);
397
- else if (command.crud === 'update' && command.byId) {
398
- await this._beforeUpdate(command);
399
- }
400
- else if (command.crud === 'update' && !command.byId) {
401
- await this._beforeUpdateMany(command);
402
- }
403
- else if (command.crud === 'delete' && command.byId) {
404
- await this._beforeDelete(command);
405
- }
406
- else if (command.crud === 'delete' && !command.byId) {
407
- await this._beforeDeleteMany(command);
408
- }
409
- /** Call command function */
410
- return commandFn();
411
- });
412
- /** Call after[X] hooks */
413
- if (command.crud === 'create')
414
- await this._afterCreate(command, result);
415
- else if (command.crud === 'update' && command.byId) {
416
- await this._afterUpdate(command, result);
417
- }
418
- else if (command.crud === 'update' && !command.byId) {
419
- await this._afterUpdateMany(command, result);
420
- }
421
- else if (command.crud === 'delete' && command.byId) {
422
- await this._afterDelete(command, result);
423
- }
424
- else if (command.crud === 'delete' && !command.byId) {
425
- await this._afterDeleteMany(command, result);
426
- }
427
- return result;
428
- }
429
- catch (e) {
430
- Error.captureStackTrace(e, this._executeCommand);
431
- await this.onError?.(e, this);
432
- throw e;
433
- }
434
- }
435
- _mergeQueries(requestQuery, filterQuery) {
436
- if (requestQuery) {
437
- let subQuery = false;
438
- if (requestQuery.function_score) {
439
- subQuery = true;
440
- if (Array.isArray(requestQuery.function_score)) {
441
- requestQuery.function_score.forEach(item => {
442
- item.filter = this._mergeQueries(item.filter, filterQuery);
443
- });
444
- }
445
- else {
446
- requestQuery.function_score.query = this._mergeQueries(requestQuery.function_score.query, filterQuery);
447
- }
448
- }
449
- if (requestQuery.dis_max) {
450
- subQuery = true;
451
- requestQuery.dis_max.queries?.map(q => this._mergeQueries(q, filterQuery));
452
- }
453
- if (requestQuery.constant_score) {
454
- subQuery = true;
455
- requestQuery.constant_score.filter = this._mergeQueries(requestQuery.constant_score.filter, filterQuery);
456
- }
457
- if (requestQuery.has_child) {
458
- subQuery = true;
459
- requestQuery.has_child.query = this._mergeQueries(requestQuery.has_child.query, filterQuery);
460
- }
461
- if (requestQuery.has_parent) {
462
- subQuery = true;
463
- requestQuery.has_parent.query = this._mergeQueries(requestQuery.has_parent.query, filterQuery);
464
- }
465
- if (requestQuery.script_score) {
466
- subQuery = true;
467
- requestQuery.script_score.query = this._mergeQueries(requestQuery.script_score.query, filterQuery);
468
- }
469
- return subQuery
470
- ? requestQuery
471
- : elastic_adapter_js_1.ElasticAdapter.prepareFilter([requestQuery, filterQuery]);
472
- }
473
- return filterQuery;
474
- }
475
- async _beforeCreate(
476
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
477
- command) {
478
- // Do nothing
479
- }
480
- async _beforeUpdate(
481
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
482
- command) {
483
- // Do nothing
484
- }
485
- async _beforeUpdateMany(
486
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
487
- command) {
488
- // Do nothing
489
- }
490
- async _beforeDelete(
491
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
492
- command) {
493
- // Do nothing
494
- }
495
- async _beforeDeleteMany(
496
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
497
- command) {
498
- // Do nothing
499
- }
500
- async _afterCreate(
501
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
502
- command,
503
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
504
- result) {
505
- // Do nothing
506
- }
507
- async _afterUpdate(
508
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
509
- command,
510
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
511
- result) {
512
- // Do nothing
513
- }
514
- async _afterUpdateMany(
515
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
516
- command,
517
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
518
- affected) {
519
- // Do nothing
520
- }
521
- async _afterDelete(
522
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
523
- command,
524
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
525
- affected) {
526
- // Do nothing
527
- }
528
- async _afterDeleteMany(
529
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
530
- command,
531
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
532
- affected) {
533
- // Do nothing
534
- }
535
- }
536
- exports.ElasticEntityService = ElasticEntityService;
@@ -1,64 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ElasticService = void 0;
4
- const core_1 = require("@opra/core");
5
- /**
6
- * Class representing a ElasticSearch service for interacting with a collection.
7
- * @extends ServiceBase
8
- * @template T - The type of the documents in the collection.
9
- */
10
- class ElasticService extends core_1.ServiceBase {
11
- /**
12
- * Constructs a new instance
13
- *
14
- * @param [options] - The options for the service
15
- * @constructor
16
- */
17
- constructor(options) {
18
- super();
19
- this.interceptor = options?.interceptor;
20
- this.client = options?.client;
21
- this.onError = options?.onError;
22
- }
23
- /**
24
- * Retrieves the ElasticSearch client.
25
- *
26
- * @protected
27
- *
28
- * @throws {Error} If the context or client is not set.
29
- */
30
- getClient() {
31
- // @ts-ignore
32
- const db = typeof this.client === 'function'
33
- ? this.client(this)
34
- : this.client;
35
- if (!db)
36
- throw new Error(`Client not set!`);
37
- return db;
38
- }
39
- async _executeCommand(command, commandFn) {
40
- let proto;
41
- const next = async () => {
42
- proto = proto ? Object.getPrototypeOf(proto) : this;
43
- while (proto) {
44
- if (proto.interceptor &&
45
- Object.prototype.hasOwnProperty.call(proto, 'interceptor')) {
46
- return await proto.interceptor.call(this, next, command, this);
47
- }
48
- proto = Object.getPrototypeOf(proto);
49
- if (!(proto instanceof ElasticService))
50
- break;
51
- }
52
- return commandFn();
53
- };
54
- try {
55
- return await next();
56
- }
57
- catch (e) {
58
- Error.captureStackTrace(e, this._executeCommand);
59
- await this.onError?.(e, this);
60
- throw e;
61
- }
62
- }
63
- }
64
- exports.ElasticService = ElasticService;
package/cjs/index.js DELETED
@@ -1,7 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./elastic-adapter.js"), exports);
5
- tslib_1.__exportStar(require("./elastic-collection-service.js"), exports);
6
- tslib_1.__exportStar(require("./elastic-entity-service.js"), exports);
7
- tslib_1.__exportStar(require("./elastic-service.js"), exports);
package/cjs/package.json DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "type": "commonjs"
3
- }
package/esm/package.json DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "type": "module"
3
- }
package/types/index.d.cts DELETED
@@ -1,4 +0,0 @@
1
- export * from './elastic-adapter.js';
2
- export * from './elastic-collection-service.js';
3
- export * from './elastic-entity-service.js';
4
- export * from './elastic-service.js';
File without changes
File without changes
File without changes