@samet-it/be-db-common 1.0.11

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.
@@ -0,0 +1,924 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.DbRepo = void 0;
13
+ const node_crypto_1 = require("node:crypto");
14
+ const query_1 = require("@leyyo/query");
15
+ const type_1 = require("@leyyo/type");
16
+ const error_1 = require("../error");
17
+ // noinspection JSUnusedGlobalSymbols
18
+ /**
19
+ * DB repository abstract class
20
+ * */
21
+ class DbRepo {
22
+ // endregion protected-property
23
+ constructor(conn, opt) {
24
+ /**
25
+ * Option of in-body usage in place of constructor param
26
+ * */
27
+ this._opt = {};
28
+ if (!(0, type_1.isObjectFilled)(conn)) {
29
+ throw new error_1.DbInvalidValueError('Connection', typeof conn, 'DbRepo', 'constructor');
30
+ }
31
+ if (!(0, type_1.isObjectBare)(this._opt)) {
32
+ this._opt = {};
33
+ }
34
+ if ((0, type_1.isObjectBare)(opt)) {
35
+ this._opt = Object.assign(Object.assign({}, this._opt), opt);
36
+ }
37
+ // handle invalid cache
38
+ if (!this._opt.cache) {
39
+ this._opt.cache = { isConnected: false };
40
+ }
41
+ if (this._opt.useVersion) {
42
+ if (typeof this._opt.version !== 'number') {
43
+ throw new error_1.DbInvalidValueError('Model version', typeof conn, 'DbRepo', 'constructor');
44
+ }
45
+ }
46
+ else {
47
+ this._opt.version = undefined;
48
+ }
49
+ if (typeof this._opt.urnDelimiter !== 'string') {
50
+ this._opt.urnDelimiter = ',';
51
+ }
52
+ else {
53
+ this._opt.urnDelimiter = this._opt.urnDelimiter.trim();
54
+ if (![',', '|', ';', '/'].includes(this._opt.urnDelimiter)) {
55
+ this._opt.urnDelimiter = ',';
56
+ }
57
+ }
58
+ if (typeof this._opt.urnPrefix !== 'string') {
59
+ this._opt.urnPrefix = undefined;
60
+ }
61
+ else {
62
+ this._opt.urnPrefix = this._opt.urnPrefix.trim();
63
+ if (!this._opt.urnPrefix) {
64
+ this._opt.urnPrefix = undefined;
65
+ }
66
+ }
67
+ if (!this._opt.urnPrefix) {
68
+ throw new error_1.DbInvalidValueError('Urn prefix', typeof conn, 'DbRepo', 'constructor');
69
+ }
70
+ this._opt.forbiddenSet = this._checkForbiddenList(this._opt.forbiddenSet, ['id', '_urn', '_trashId', 'createdAt', 'createdBy']);
71
+ this._opt.forbiddenUnset = this._checkForbiddenList(this._opt.forbiddenUnset, ['id', '_urn', '_trashId', 'createdAt', 'createdBy', 'updatedAt', 'updatedBy']);
72
+ this._props = Object.assign({ conn }, this._opt);
73
+ delete this._opt;
74
+ }
75
+ // region protected-method
76
+ _removeFieldForForbidden(fields, flag, field) {
77
+ if (this._opt[flag] !== true) {
78
+ const index = fields.indexOf(field);
79
+ if (index >= 0) {
80
+ fields.splice(index, 0);
81
+ }
82
+ }
83
+ }
84
+ _checkForbiddenList(given, def) {
85
+ if (!Array.isArray(given)) {
86
+ given = [];
87
+ }
88
+ else {
89
+ given = given.filter(v => (0, type_1.isText)(v));
90
+ }
91
+ if (given.length < 1) {
92
+ given.push(...def);
93
+ }
94
+ this._removeFieldForForbidden(given, 'useSoftDelete', '_trashId');
95
+ this._removeFieldForForbidden(given, 'useCreatedAt', 'createdAt');
96
+ this._removeFieldForForbidden(given, 'useCreatedBy', 'createdBy');
97
+ this._removeFieldForForbidden(given, 'useUpdatedAt', 'updatedAt');
98
+ this._removeFieldForForbidden(given, 'useUpdatedBy', 'updatedBy');
99
+ this._removeFieldForForbidden(given, 'useRevision', '_rev');
100
+ this._removeFieldForForbidden(given, 'useVersion', '_ver');
101
+ return given;
102
+ }
103
+ get _now() {
104
+ const { useIsoDate } = this._props;
105
+ return useIsoDate ? new Date().toISOString() : Date.now();
106
+ }
107
+ get _randomIndexName() {
108
+ return 'idx_' + (0, node_crypto_1.randomUUID)().match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
109
+ .map(s => s.toLowerCase())
110
+ .join('_');
111
+ }
112
+ _indexName(name) {
113
+ if (typeof name !== 'string') {
114
+ return this._randomIndexName;
115
+ }
116
+ name = name.trim();
117
+ if (name === '') {
118
+ return this._randomIndexName;
119
+ }
120
+ name = name.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
121
+ .map(s => s.toLowerCase())
122
+ .join('_');
123
+ name = name.replace(/^_+|_+$/g, '');
124
+ if (name === '') {
125
+ return this._randomIndexName;
126
+ }
127
+ if (!name.startsWith('idx_')) {
128
+ name = 'idx_' + name;
129
+ }
130
+ if (name.length > 30) {
131
+ name = name.substring(0, 30);
132
+ }
133
+ return name;
134
+ }
135
+ /**
136
+ * Fetch urn from doc as doc._urn
137
+ * */
138
+ _urnFromDoc(doc, method) {
139
+ const { path } = this._props;
140
+ (0, type_1.assertObject)(doc, () => {
141
+ return { field: 'doc', where: 'DbRepo', path, method };
142
+ });
143
+ const urn = doc._urn;
144
+ (0, type_1.assertObject)(urn, () => {
145
+ return { field: 'urn', where: 'DbRepo', path, method };
146
+ });
147
+ return urn;
148
+ }
149
+ _checkKey(value) {
150
+ const { useNumericId } = this._props;
151
+ let id;
152
+ switch (typeof value) {
153
+ case "string":
154
+ const str = value.trim();
155
+ if (str) {
156
+ if (this._isUrn(str)) {
157
+ return [str, '_urn'];
158
+ }
159
+ else {
160
+ if (useNumericId) {
161
+ try {
162
+ id = parseInt(str);
163
+ }
164
+ catch (e) {
165
+ // nothing
166
+ }
167
+ if (id !== undefined) {
168
+ return [id, 'id'];
169
+ }
170
+ }
171
+ else {
172
+ return [str, 'id'];
173
+ }
174
+ }
175
+ }
176
+ break;
177
+ case "number":
178
+ if (useNumericId) {
179
+ return [value, 'id'];
180
+ }
181
+ else {
182
+ return [value.toString(10), 'id'];
183
+ }
184
+ case "object":
185
+ if (!value) {
186
+ return [undefined, undefined];
187
+ }
188
+ const obj = value;
189
+ if (obj.id !== undefined) {
190
+ return this._checkKey(obj.id);
191
+ }
192
+ if (obj.urn !== undefined) {
193
+ return this._checkKey(obj.urn);
194
+ }
195
+ if (obj._urn !== undefined) {
196
+ return this._checkKey(obj._urn);
197
+ }
198
+ break;
199
+ }
200
+ return [undefined, undefined];
201
+ }
202
+ /**
203
+ * Check array keys as id list or urn list
204
+ * */
205
+ _checkKeys(keys) {
206
+ const result = { urns: [], ids: [], ordered: [] };
207
+ if (!keys || !Array.isArray(keys) || keys.length < 1) {
208
+ return result;
209
+ }
210
+ for (const item of keys) {
211
+ const [key, field] = this._checkKey(item);
212
+ if (field) {
213
+ if ((field === '_urn') && !result.urns.includes(key)) {
214
+ result.urns.push(key);
215
+ result.ordered.push([key, field]);
216
+ }
217
+ else if ((field === 'id') && !result.ids.includes(key)) {
218
+ result.ids.push(key);
219
+ result.ordered.push([key, field]);
220
+ }
221
+ }
222
+ }
223
+ return result;
224
+ }
225
+ _isUrn(key) {
226
+ const { urnPrefix } = this._props;
227
+ return (typeof key === 'string') && key.startsWith(urnPrefix + ':');
228
+ }
229
+ // endregion protected-method
230
+ // region getter
231
+ /** @inheritDoc */
232
+ get props() {
233
+ return this._props;
234
+ }
235
+ /** @inheritDoc */
236
+ get $def() {
237
+ return this;
238
+ }
239
+ /** @inheritDoc */
240
+ $cast() {
241
+ return this;
242
+ }
243
+ // endregion getter
244
+ // region urn
245
+ _keyToUrn(key) {
246
+ const { urnPrefix } = this._props;
247
+ return `${urnPrefix}:${key}`;
248
+ }
249
+ /** @inheritDoc */
250
+ toUrn(urnRec) {
251
+ const { urnPrefix, urnDelimiter } = this._props;
252
+ return `${urnPrefix}:${this.$toUrnTuple(urnRec).join(urnDelimiter)}`;
253
+ }
254
+ /** @inheritDoc */
255
+ $toUrnTuple(urnRec) {
256
+ return [urnRec['id']];
257
+ }
258
+ // endregion urn
259
+ // region get
260
+ /** @inheritDoc */
261
+ get(k1, p1) {
262
+ return __awaiter(this, void 0, void 0, function* () {
263
+ const [key, field] = this._checkKey(k1);
264
+ switch (field) {
265
+ case "_urn":
266
+ return this.getByPrimary(key, p1, true);
267
+ case "id":
268
+ return this.getBySecondary(key, p1, true);
269
+ default:
270
+ (0, type_1.assertMessage)('Invalid key', { field: 'key', value: k1, where: 'DbRepo', method: 'get' });
271
+ }
272
+ });
273
+ }
274
+ /** @inheritDoc */
275
+ getByPrimary(key, p1, ignoreCheck) {
276
+ return __awaiter(this, void 0, void 0, function* () {
277
+ const { cache } = this._props;
278
+ if (!ignoreCheck) {
279
+ (0, type_1.assertText)(key, { field: 'key', where: 'DbRepo', method: 'getByPrimary' });
280
+ }
281
+ let found;
282
+ if (cache.props.isConnected) {
283
+ try {
284
+ found = (yield cache.getByPrimary(key))[0];
285
+ }
286
+ catch (e) {
287
+ this.logger.warn(`getByPrimary.cache.getByPrimary <${e.name}> ${e.message}`);
288
+ }
289
+ if (found) {
290
+ return found;
291
+ }
292
+ }
293
+ found = yield this.$getByPrimary(key, p1, true);
294
+ if (found && cache.props.isConnected) {
295
+ cache.ingestDoc(found)
296
+ .then()
297
+ .catch(e => this.logger.warn(`getByPrimary.cache.ingestDoc <${e.name}> ${e.message}`));
298
+ }
299
+ return found;
300
+ });
301
+ }
302
+ /** @inheritDoc */
303
+ getBySecondary(key, p1, ignoreCheck) {
304
+ return __awaiter(this, void 0, void 0, function* () {
305
+ const { cache, useNumericId, idSame } = this._props;
306
+ if (!ignoreCheck) {
307
+ if (useNumericId) {
308
+ (0, type_1.assertInteger)(key, { field: 'key', where: 'DbRepo', method: 'getBySecondary' });
309
+ }
310
+ else {
311
+ (0, type_1.assertText)(key, { field: 'key', where: 'DbRepo', method: 'getBySecondary' });
312
+ }
313
+ }
314
+ if (idSame) {
315
+ return this.getByPrimary(this._keyToUrn(key), p1, true);
316
+ }
317
+ let found;
318
+ if (cache.props.isConnected) {
319
+ try {
320
+ found = (yield cache.getBySecondary(key))[0];
321
+ if (found) {
322
+ return found;
323
+ }
324
+ }
325
+ catch (e) {
326
+ this.logger.warn(`getBySecondary.cache.getBySecondary <${e.name}> ${e.message}`);
327
+ }
328
+ }
329
+ found = yield this.$getBySecondary(key, p1, true);
330
+ if (found && cache.props.isConnected) {
331
+ cache.ingestDoc(found)
332
+ .then()
333
+ .catch(e => this.logger.warn(`getBySecondary.cache.ingestDoc <${e.name}> ${e.message}`));
334
+ }
335
+ return found;
336
+ });
337
+ }
338
+ // endregion get
339
+ // region exists
340
+ /** @inheritDoc */
341
+ exists(k1, p1) {
342
+ return __awaiter(this, void 0, void 0, function* () {
343
+ const [key, field] = this._checkKey(k1);
344
+ switch (field) {
345
+ case "_urn":
346
+ return this.existsByPrimary(key, p1, true);
347
+ case "id":
348
+ return this.existsBySecondary(key, p1, true);
349
+ default:
350
+ (0, type_1.assertMessage)('Invalid key', { field: 'key', value: k1, where: 'DbRepo', method: 'exists' });
351
+ break;
352
+ }
353
+ });
354
+ }
355
+ /** @inheritDoc */
356
+ existsByPrimary(key, p1, ignoreCheck) {
357
+ return __awaiter(this, void 0, void 0, function* () {
358
+ const { cache } = this._props;
359
+ if (!ignoreCheck) {
360
+ (0, type_1.assertText)(key, { field: 'key', where: 'DbRepo', method: 'existsByPrimary' });
361
+ }
362
+ if (cache.props.isConnected) {
363
+ try {
364
+ const found = (yield cache.getByPrimary(key))[0];
365
+ if (found) {
366
+ return true;
367
+ }
368
+ }
369
+ catch (e) {
370
+ this.logger.warn(`existsByPrimary.cache.existsByPrimary <${e.name}> ${e.message}`);
371
+ }
372
+ }
373
+ return this.$existsByPrimary(key, p1, true);
374
+ });
375
+ }
376
+ /** @inheritDoc */
377
+ existsBySecondary(key, p1, ignoreCheck) {
378
+ return __awaiter(this, void 0, void 0, function* () {
379
+ const { cache, useNumericId, idSame } = this._props;
380
+ if (!ignoreCheck) {
381
+ if (useNumericId) {
382
+ (0, type_1.assertInteger)(key, { field: 'key', where: 'DbRepo', method: 'existsBySecondary' });
383
+ }
384
+ else {
385
+ (0, type_1.assertText)(key, { field: 'key', where: 'DbRepo', method: 'existsBySecondary' });
386
+ }
387
+ }
388
+ if (!idSame) {
389
+ return this.existsByPrimary(this._keyToUrn(key));
390
+ }
391
+ if (cache.props.isConnected) {
392
+ try {
393
+ const found = (yield cache.getBySecondary(key))[0];
394
+ if (found) {
395
+ return true;
396
+ }
397
+ }
398
+ catch (e) {
399
+ this.logger.warn(`existsBySecondary.cache.existsBySecondary <${e.name}> ${e.message}`);
400
+ }
401
+ }
402
+ return this.$existsBySecondary(key, p1, true);
403
+ });
404
+ }
405
+ // endregion exists
406
+ // region list
407
+ /** @inheritDoc */
408
+ list(keys, p1, ignoreCheck) {
409
+ return __awaiter(this, void 0, void 0, function* () {
410
+ if (!ignoreCheck) {
411
+ (0, type_1.assertArray)(keys, { field: 'keys', where: 'DbRepo', method: 'list' });
412
+ }
413
+ const { conn, cache } = this._props;
414
+ const opt = conn.buildOpt(p1, 'list');
415
+ const result = this._checkKeys(keys);
416
+ if (result.ordered.length < 1) {
417
+ return [];
418
+ }
419
+ const docs = [];
420
+ let founds = [];
421
+ if (result.urns.length > 0) {
422
+ if (cache.props.isConnected) {
423
+ try {
424
+ founds = yield cache.getByPrimary(...result.urns);
425
+ }
426
+ catch (e) {
427
+ this.logger.warn(`list.cache.getByPrimary <${e.name}> ${e.message}`);
428
+ }
429
+ founds.forEach(val => {
430
+ const index = result.urns.indexOf(val._urn);
431
+ if (index >= 0) {
432
+ result.urns.splice(index, 1);
433
+ }
434
+ });
435
+ docs.push(...founds);
436
+ }
437
+ if (result.urns.length > 0) {
438
+ founds = yield this.$listByPrimary(result.urns, opt, true);
439
+ if (founds.length > 0) {
440
+ if (cache.props.isConnected) {
441
+ founds.forEach(found => cache.ingestDoc(found)
442
+ .then()
443
+ .catch(e => this.logger.warn(`list.cache.ingestDoc <${e.name}> ${e.message}`)));
444
+ }
445
+ docs.push(...founds);
446
+ }
447
+ }
448
+ }
449
+ if (result.ids.length > 0) {
450
+ if (cache.props.isConnected) {
451
+ try {
452
+ founds = yield cache.getBySecondary(...result.ids);
453
+ }
454
+ catch (e) {
455
+ this.logger.warn(`list.cache.getBySecondary <${e.name}> ${e.message}`);
456
+ }
457
+ founds.forEach(val => {
458
+ const index = result.ids.indexOf(val.id);
459
+ if (index >= 0) {
460
+ result.ids.splice(index, 1);
461
+ }
462
+ });
463
+ docs.push(...founds);
464
+ }
465
+ if (result.ids.length > 0) {
466
+ founds = yield this.$listBySecondary(result.ids, opt, true);
467
+ if (founds.length > 0) {
468
+ if (cache.props.isConnected) {
469
+ founds.forEach(found => cache.ingestDoc(found)
470
+ .then()
471
+ .catch(e => this.logger.warn(`list.cache.ingestDoc <${e.name}> ${e.message}`)));
472
+ }
473
+ docs.push(...founds);
474
+ }
475
+ }
476
+ }
477
+ return result.ordered.map(o => docs.find(d => d[o[1]] === o[0]));
478
+ });
479
+ }
480
+ // endregion list
481
+ // region filter
482
+ /** @inheritDoc */
483
+ filter(query, p1) {
484
+ return __awaiter(this, void 0, void 0, function* () {
485
+ const { conn } = this._props;
486
+ const opt = conn.buildOpt(p1, 'filter');
487
+ return this.$filter(query_1.queryParser.exec(query, [], opt.name), opt);
488
+ });
489
+ }
490
+ // endregion filter
491
+ // region insert
492
+ /** @inheritDoc */
493
+ insert(doc, p1, ignoreCheck) {
494
+ return __awaiter(this, void 0, void 0, function* () {
495
+ const { useCreatedAt, useNumericId, useCreatedBy, useUpdatedAt, useUpdatedBy } = this._props;
496
+ if (!ignoreCheck) {
497
+ (0, type_1.assertObject)(doc, { field: 'doc', where: 'DbRepo', method: 'insert' });
498
+ if (useNumericId) {
499
+ (0, type_1.assertInteger)(doc.id, { field: 'doc.id', where: 'DbRepo', method: 'insert' });
500
+ }
501
+ else {
502
+ (0, type_1.assertText)(doc.id, { field: 'doc.id', where: 'DbRepo', method: 'insert' });
503
+ }
504
+ (0, type_1.assertText)(doc._urn, { field: 'doc._urn', where: 'DbRepo', method: 'insert' });
505
+ }
506
+ if (!doc._trashId !== undefined) {
507
+ delete doc._trashId;
508
+ }
509
+ if (useCreatedAt) {
510
+ doc.createdAt = this._now;
511
+ }
512
+ if (useCreatedBy) {
513
+ // todo
514
+ }
515
+ if (useUpdatedAt) {
516
+ doc.updatedAt = this._now;
517
+ }
518
+ if (useUpdatedBy) {
519
+ // todo
520
+ }
521
+ return this.$insert(doc, p1);
522
+ });
523
+ }
524
+ /** @inheritDoc */
525
+ inserts(docs, p1, ignoreCheck) {
526
+ return __awaiter(this, void 0, void 0, function* () {
527
+ if (!ignoreCheck) {
528
+ (0, type_1.assertArray)(docs, { field: 'docs', where: 'DbRepo', method: 'inserts' });
529
+ }
530
+ const insertedIds = [];
531
+ for (const doc of docs) {
532
+ insertedIds.push(yield this.insert(doc, p1, true));
533
+ }
534
+ return insertedIds;
535
+ });
536
+ }
537
+ // endregion insert
538
+ // region replace
539
+ /** @inheritDoc */
540
+ replace(doc, p1, ignoreCheck) {
541
+ return __awaiter(this, void 0, void 0, function* () {
542
+ const { cache, useNumericId, useUpdatedAt, useUpdatedBy } = this._props;
543
+ if (!ignoreCheck) {
544
+ (0, type_1.assertObject)(doc, { field: 'doc', where: 'DbRepo', method: 'replace' });
545
+ (0, type_1.assertText)(doc._urn, { field: 'doc._urn', where: 'DbRepo', method: 'replace' });
546
+ if (useNumericId) {
547
+ (0, type_1.assertInteger)(doc.id, { field: 'doc.id', where: 'DbRepo', method: 'insert' });
548
+ }
549
+ else {
550
+ (0, type_1.assertText)(doc.id, { field: 'doc.id', where: 'DbRepo', method: 'insert' });
551
+ }
552
+ }
553
+ if (doc._trashId !== undefined) {
554
+ delete doc._trashId;
555
+ }
556
+ if (useUpdatedAt) {
557
+ doc.updatedAt = this._now;
558
+ }
559
+ if (useUpdatedBy) {
560
+ // todo
561
+ }
562
+ const replacedId = yield this.$replace(doc, p1, true);
563
+ if (cache.props.isConnected) {
564
+ cache.clearDoc(replacedId)
565
+ .then()
566
+ .catch(e => this.logger.warn(`replace.cache.clearDoc <${e.name}> ${e.message}`));
567
+ }
568
+ return replacedId;
569
+ });
570
+ }
571
+ // endregion replace
572
+ // region update
573
+ /** @inheritDoc */
574
+ update(k1, doc, p1, ignoreCheck) {
575
+ return __awaiter(this, void 0, void 0, function* () {
576
+ if (!ignoreCheck) {
577
+ (0, type_1.assertObject)(doc, { field: 'doc', where: 'DbRepo', method: 'update' });
578
+ }
579
+ const [key, field] = this._checkKey(k1);
580
+ switch (field) {
581
+ case "_urn":
582
+ return this.updateByPrimary(key, doc, p1, true);
583
+ case "id":
584
+ return this.updateBySecondary(key, doc, p1, true);
585
+ default:
586
+ (0, type_1.assertMessage)('Invalid key', { field: 'key', value: k1, where: 'DbRepo', method: 'update' });
587
+ }
588
+ });
589
+ }
590
+ /** @inheritDoc */
591
+ updateByPrimary(key, doc, p1, ignoreCheck) {
592
+ return __awaiter(this, void 0, void 0, function* () {
593
+ const { forbiddenSet, cache, useUpdatedAt, useUpdatedBy } = this._props;
594
+ if (!ignoreCheck) {
595
+ (0, type_1.assertText)(key, { field: 'key', where: 'DbRepo', method: 'updateByPrimary' });
596
+ (0, type_1.assertObject)(doc, { field: 'doc', where: 'DbRepo', method: 'updateByPrimary' });
597
+ }
598
+ if (doc._trashId !== undefined) {
599
+ delete doc._trashId;
600
+ }
601
+ forbiddenSet.forEach(f => {
602
+ if (doc[f] !== undefined) {
603
+ delete doc[f];
604
+ }
605
+ });
606
+ if (useUpdatedAt) {
607
+ doc.updatedAt = this._now;
608
+ }
609
+ if (useUpdatedBy) {
610
+ // todo
611
+ }
612
+ const updatedKey = yield this.$updateByPrimary(key, doc, p1, true);
613
+ if (updatedKey && cache.props.isConnected) {
614
+ cache.clearDoc(updatedKey)
615
+ .then()
616
+ .catch(e => this.logger.warn(`updateByPrimary.cache.clearDoc <${e.name}> ${e.message}`));
617
+ }
618
+ return updatedKey;
619
+ });
620
+ }
621
+ /** @inheritDoc */
622
+ updateBySecondary(key, doc, p1, ignoreCheck) {
623
+ return __awaiter(this, void 0, void 0, function* () {
624
+ const { forbiddenSet, cache, useNumericId, idSame, useUpdatedAt, useUpdatedBy } = this._props;
625
+ if (!ignoreCheck) {
626
+ if (useNumericId) {
627
+ (0, type_1.assertInteger)(key, { field: 'key', where: 'DbRepo', method: 'getBySecondary' });
628
+ }
629
+ else {
630
+ (0, type_1.assertText)(key, { field: 'key', where: 'DbRepo', method: 'getBySecondary' });
631
+ }
632
+ (0, type_1.assertObject)(doc, { field: 'doc', where: 'DbRepo', method: 'getBySecondary' });
633
+ }
634
+ if (idSame) {
635
+ return this.updateBySecondary(this._keyToUrn(key), doc, p1, true);
636
+ }
637
+ if (doc._trashId !== undefined) {
638
+ delete doc._trashId;
639
+ }
640
+ forbiddenSet.forEach(f => {
641
+ if (doc[f] !== undefined) {
642
+ delete doc[f];
643
+ }
644
+ });
645
+ if (useUpdatedAt) {
646
+ doc.updatedAt = this._now;
647
+ }
648
+ if (useUpdatedBy) {
649
+ // todo
650
+ }
651
+ const updatedKey = yield this.$updateBySecondary(key, doc, p1, true);
652
+ if (updatedKey && cache.props.isConnected) {
653
+ cache.clearDoc(updatedKey)
654
+ .then()
655
+ .catch(e => this.logger.warn(`updateBySecondary.cache.clearDoc <${e.name}> ${e.message}`));
656
+ }
657
+ return updatedKey;
658
+ });
659
+ }
660
+ // endregion update
661
+ // region set
662
+ /** @inheritDoc */
663
+ set(key, doc, p1, ignoreCheck) {
664
+ return __awaiter(this, void 0, void 0, function* () {
665
+ if (!ignoreCheck) {
666
+ (0, type_1.assertObject)(doc, { field: 'doc', where: 'DbRepo', method: 'set' });
667
+ }
668
+ for (const [f, v] of Object.entries(doc)) {
669
+ if (v === undefined) { // dont allow undefined
670
+ delete doc[f];
671
+ }
672
+ }
673
+ return this.update(key, doc, p1, false);
674
+ });
675
+ }
676
+ /** @inheritDoc */
677
+ unset(key, fields, p1, ignoreCheck) {
678
+ return __awaiter(this, void 0, void 0, function* () {
679
+ if (!ignoreCheck) {
680
+ (0, type_1.assertArray)(fields, { field: 'fields', where: 'DbRepo', method: 'unset' });
681
+ fields.forEach((field, index) => {
682
+ (0, type_1.assertText)(field, { field: field, where: 'DbRepo', method: 'unset', index });
683
+ });
684
+ }
685
+ const { forbiddenUnset } = this._props;
686
+ const doc = {};
687
+ fields.forEach(f => {
688
+ if (!forbiddenUnset.includes(f)) {
689
+ doc[f] = undefined;
690
+ }
691
+ });
692
+ return this.update(key, doc, p1, false);
693
+ });
694
+ }
695
+ // endregion set
696
+ // region remove
697
+ /** @inheritDoc */
698
+ remove(k1, p1) {
699
+ return __awaiter(this, void 0, void 0, function* () {
700
+ const [key, field] = this._checkKey(k1);
701
+ switch (field) {
702
+ case "_urn":
703
+ return this.removeByPrimary(key, p1, true);
704
+ case "id":
705
+ return this.removeBySecondary(key, p1, true);
706
+ default:
707
+ (0, type_1.assertMessage)('Invalid key', { field: 'key', value: k1, where: 'DbRepo', method: 'remove' });
708
+ }
709
+ });
710
+ }
711
+ /** @inheritDoc */
712
+ removeByPrimary(key, p1, ignoreCheck) {
713
+ return __awaiter(this, void 0, void 0, function* () {
714
+ const { cache } = this._props;
715
+ if (!ignoreCheck) {
716
+ (0, type_1.assertText)(key, { field: 'key', where: 'DbRepo', method: 'removeByPrimary' });
717
+ }
718
+ const removedKey = yield this.$removeByPrimary(key, p1, true);
719
+ if (removedKey && cache.props.isConnected) {
720
+ cache.clearDoc(removedKey)
721
+ .then()
722
+ .catch(e => this.logger.warn(`removeByPrimary.cache.clearDoc <${e.name}> ${e.message}`));
723
+ }
724
+ return removedKey;
725
+ });
726
+ }
727
+ /** @inheritDoc */
728
+ removeBySecondary(key, p1, ignoreCheck) {
729
+ return __awaiter(this, void 0, void 0, function* () {
730
+ const { cache, useNumericId, idSame } = this._props;
731
+ if (useNumericId) {
732
+ (0, type_1.assertInteger)(key, { field: 'key', where: 'DbRepo', method: 'removeBySecondary' });
733
+ }
734
+ else {
735
+ (0, type_1.assertText)(key, { field: 'key', where: 'DbRepo', method: 'removeBySecondary' });
736
+ }
737
+ if (idSame) {
738
+ return this.removeByPrimary(this._keyToUrn(key), p1, ignoreCheck);
739
+ }
740
+ const removedKey = yield this.$removeBySecondary(key, p1, true);
741
+ if (removedKey && cache.props.isConnected) {
742
+ cache.clearDoc(removedKey)
743
+ .then()
744
+ .catch(e => this.logger.warn(`removeBySecondary.cache.clearDoc <${e.name}> ${e.message}`));
745
+ }
746
+ return removedKey;
747
+ });
748
+ }
749
+ // endregion remove
750
+ // region trash
751
+ /** @inheritDoc */
752
+ trash(k1, p1) {
753
+ return __awaiter(this, void 0, void 0, function* () {
754
+ const [key, field] = this._checkKey(k1);
755
+ switch (field) {
756
+ case "_urn":
757
+ return this.trashByPrimary(key, p1, true);
758
+ case "id":
759
+ return this.trashBySecondary(key, p1, true);
760
+ default:
761
+ (0, type_1.assertMessage)('Invalid key', { field: 'key', value: k1, where: 'DbRepo', method: 'trash' });
762
+ }
763
+ });
764
+ }
765
+ /** @inheritDoc */
766
+ trashByPrimary(key, p1, ignoreCheck) {
767
+ return __awaiter(this, void 0, void 0, function* () {
768
+ const { useSoftDelete, conn, cache } = this._props;
769
+ if (!useSoftDelete) {
770
+ throw new error_1.DbNotSupportedError('Soft delete', 'DbRepo', 'trashByPrimary');
771
+ }
772
+ if (!ignoreCheck) {
773
+ (0, type_1.assertText)(key, { field: 'urn', where: 'DbRepo', method: 'trashByPrimary' });
774
+ }
775
+ const opt = conn.buildOpt(p1, 'trashByPrimary');
776
+ if (!(0, type_1.isText)(opt.trashId)) {
777
+ opt.trashId = (0, node_crypto_1.randomUUID)();
778
+ }
779
+ const trashedKey = yield this.$trashByPrimary(key, opt, true);
780
+ if (trashedKey && cache.props.isConnected) {
781
+ cache.clearDoc(trashedKey)
782
+ .then()
783
+ .catch(e => this.logger.warn(`trashByPrimary.cache.clearDoc <${e.name}> ${e.message}`));
784
+ }
785
+ return trashedKey;
786
+ });
787
+ }
788
+ /** @inheritDoc */
789
+ trashBySecondary(key, p1, ignoreCheck) {
790
+ return __awaiter(this, void 0, void 0, function* () {
791
+ const { useSoftDelete, useNumericId, idSame, conn, cache } = this._props;
792
+ if (!useSoftDelete) {
793
+ throw new error_1.DbNotSupportedError('Soft delete', 'DbRepo', 'trashBySecondary');
794
+ }
795
+ if (useNumericId) {
796
+ (0, type_1.assertInteger)(key, { field: 'key', where: 'DbRepo', method: 'trashBySecondary' });
797
+ }
798
+ else {
799
+ (0, type_1.assertText)(key, { field: 'key', where: 'DbRepo', method: 'trashBySecondary' });
800
+ }
801
+ if (idSame) {
802
+ return this.trashByPrimary(this._keyToUrn(key), p1, ignoreCheck);
803
+ }
804
+ const opt = conn.buildOpt(p1, 'trashBySecondary');
805
+ if (!(0, type_1.isText)(opt.trashId)) {
806
+ opt.trashId = (0, node_crypto_1.randomUUID)();
807
+ }
808
+ const trashedKey = yield this.$trashBySecondary(key, opt, true);
809
+ if (trashedKey && cache.props.isConnected) {
810
+ cache.clearDoc(trashedKey)
811
+ .then()
812
+ .catch(e => this.logger.warn(`trashBySecondary.cache.clearDoc <${e.name}> ${e.message}`));
813
+ }
814
+ return trashedKey;
815
+ });
816
+ }
817
+ // endregion trash
818
+ // region dim
819
+ /** @inheritDoc */
820
+ $toDim(doc, dim) {
821
+ return __awaiter(this, void 0, void 0, function* () {
822
+ if (!doc) {
823
+ return undefined;
824
+ }
825
+ switch (dim) {
826
+ case "portion":
827
+ return yield this.$toPortion(doc);
828
+ case "view":
829
+ return yield this.$toView(doc);
830
+ case "pair":
831
+ return yield this.$toPair(doc);
832
+ default:
833
+ return yield this.$toPortion(doc);
834
+ }
835
+ });
836
+ }
837
+ /** @inheritDoc */
838
+ getDim(key, dim) {
839
+ return __awaiter(this, void 0, void 0, function* () {
840
+ const doc = yield this.get(key, { name: `getDim/${dim !== null && dim !== void 0 ? dim : 'def'}` });
841
+ return doc ? this.$toDim(doc, dim) : undefined;
842
+ });
843
+ }
844
+ /** @inheritDoc */
845
+ listDims(keys, dim, ignoreCheck) {
846
+ return __awaiter(this, void 0, void 0, function* () {
847
+ const docs = yield this.list(keys, { name: `listDims/${dim !== null && dim !== void 0 ? dim : 'def'}` }, ignoreCheck);
848
+ if (docs.length < 1) {
849
+ return [];
850
+ }
851
+ const items = [];
852
+ for (const doc of docs) {
853
+ items.push(yield this.$toDim(doc, dim));
854
+ }
855
+ return items;
856
+ });
857
+ }
858
+ // endregion dim
859
+ // region pair
860
+ /** @inheritDoc */
861
+ $toPair(doc) {
862
+ return __awaiter(this, void 0, void 0, function* () {
863
+ if (!doc) {
864
+ return undefined;
865
+ }
866
+ return { id: doc === null || doc === void 0 ? void 0 : doc.id, name: doc === null || doc === void 0 ? void 0 : doc.name };
867
+ });
868
+ }
869
+ /** @inheritDoc */
870
+ getPair(key) {
871
+ return __awaiter(this, void 0, void 0, function* () {
872
+ return this.getDim(key, 'pair');
873
+ });
874
+ }
875
+ /** @inheritDoc */
876
+ listPairs(keys, ignoreCheck) {
877
+ return __awaiter(this, void 0, void 0, function* () {
878
+ return this.listDims(keys, 'pair', ignoreCheck);
879
+ });
880
+ }
881
+ // endregion pair
882
+ // region view
883
+ $toView(doc) {
884
+ return __awaiter(this, void 0, void 0, function* () {
885
+ return doc;
886
+ });
887
+ }
888
+ /** @inheritDoc */
889
+ getView(identifier) {
890
+ return __awaiter(this, void 0, void 0, function* () {
891
+ return this.getDim(identifier, 'view');
892
+ });
893
+ }
894
+ /** @inheritDoc */
895
+ listViews(identifiers, ignoreCheck) {
896
+ return __awaiter(this, void 0, void 0, function* () {
897
+ return this.listDims(identifiers, 'view', ignoreCheck);
898
+ });
899
+ }
900
+ // endregion view
901
+ // region portion
902
+ /** @inheritDoc */
903
+ $toPortion(doc) {
904
+ return __awaiter(this, void 0, void 0, function* () {
905
+ if (!doc) {
906
+ return undefined;
907
+ }
908
+ return { id: doc === null || doc === void 0 ? void 0 : doc.id };
909
+ });
910
+ }
911
+ /** @inheritDoc */
912
+ getPortion(identifier) {
913
+ return __awaiter(this, void 0, void 0, function* () {
914
+ return this.getDim(identifier, 'portion');
915
+ });
916
+ }
917
+ /** @inheritDoc */
918
+ listPortions(identifiers, ignoreCheck) {
919
+ return __awaiter(this, void 0, void 0, function* () {
920
+ return this.listDims(identifiers, 'portion', ignoreCheck);
921
+ });
922
+ }
923
+ }
924
+ exports.DbRepo = DbRepo;