@naturalcycles/db-lib 8.34.1 → 8.36.0
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.
- package/dist/adapter/cachedb/cache.db.d.ts +9 -9
- package/dist/adapter/cachedb/cache.db.js +3 -1
- package/dist/adapter/cachedb/cache.db.model.d.ts +5 -3
- package/dist/adapter/file/file.db.d.ts +2 -2
- package/dist/adapter/inmemory/inMemory.db.d.ts +2 -2
- package/dist/adapter/inmemory/inMemory.db.js +6 -3
- package/dist/base.common.db.d.ts +2 -2
- package/dist/common.db.d.ts +3 -3
- package/dist/commondao/common.dao.d.ts +21 -21
- package/dist/commondao/common.dao.js +24 -22
- package/dist/commondao/common.dao.model.d.ts +22 -22
- package/dist/db.model.d.ts +2 -17
- package/dist/index.d.ts +4 -5
- package/dist/index.js +2 -4
- package/dist/pipeline/dbPipelineBackup.js +1 -2
- package/dist/pipeline/dbPipelineCopy.js +1 -2
- package/dist/pipeline/dbPipelineRestore.js +1 -2
- package/dist/query/dbQuery.d.ts +6 -6
- package/dist/validation/index.d.ts +3 -3
- package/package.json +1 -2
- package/src/adapter/cachedb/cache.db.model.ts +8 -7
- package/src/adapter/cachedb/cache.db.ts +20 -17
- package/src/adapter/file/file.db.ts +2 -2
- package/src/adapter/inmemory/inMemory.db.ts +9 -5
- package/src/base.common.db.ts +2 -2
- package/src/common.db.ts +7 -3
- package/src/commondao/common.dao.model.ts +31 -24
- package/src/commondao/common.dao.ts +78 -76
- package/src/db.model.ts +2 -18
- package/src/index.ts +2 -22
- package/src/pipeline/dbPipelineBackup.ts +9 -3
- package/src/pipeline/dbPipelineCopy.ts +2 -3
- package/src/pipeline/dbPipelineRestore.ts +2 -2
- package/src/query/dbQuery.ts +8 -7
- package/dist/adapter/inmemory/index.d.ts +0 -3
- package/dist/adapter/inmemory/index.js +0 -8
- package/dist/getDB.d.ts +0 -19
- package/dist/getDB.js +0 -32
- package/src/adapter/inmemory/index.ts +0 -9
- package/src/getDB.ts +0 -50
|
@@ -59,49 +59,60 @@ const isCI = !!process.env['CI']
|
|
|
59
59
|
* TM = Transport model (optimized to be sent over the wire)
|
|
60
60
|
*/
|
|
61
61
|
export class CommonDao<
|
|
62
|
-
BM extends Partial<ObjectWithId
|
|
63
|
-
DBM extends ObjectWithId = Saved<BM>,
|
|
62
|
+
BM extends Partial<ObjectWithId<ID>>,
|
|
63
|
+
DBM extends ObjectWithId<ID> = Saved<BM>,
|
|
64
64
|
TM = BM,
|
|
65
|
+
ID extends string | number = DBM['id'],
|
|
65
66
|
> {
|
|
66
|
-
constructor(public cfg: CommonDaoCfg<BM, DBM, TM>) {
|
|
67
|
+
constructor(public cfg: CommonDaoCfg<BM, DBM, TM, ID>) {
|
|
67
68
|
this.cfg = {
|
|
68
69
|
// Default is to NOT log in AppEngine and in CI,
|
|
69
70
|
// otherwise to log Operations
|
|
70
71
|
// e.g in Dev (local machine), Test - it will log operations (useful for debugging)
|
|
71
72
|
logLevel: isGAE || isCI ? CommonDaoLogLevel.NONE : CommonDaoLogLevel.OPERATIONS,
|
|
73
|
+
idType: 'string',
|
|
74
|
+
createId: true,
|
|
72
75
|
created: true,
|
|
73
76
|
updated: true,
|
|
74
77
|
logger: console,
|
|
75
78
|
...cfg,
|
|
76
79
|
hooks: {
|
|
77
|
-
createId: () => stringId(),
|
|
78
80
|
parseNaturalId: () => ({}),
|
|
79
81
|
beforeCreate: bm => bm as BM,
|
|
80
82
|
beforeDBMValidate: dbm => dbm,
|
|
81
83
|
beforeDBMToBM: dbm => dbm as any,
|
|
82
84
|
beforeBMToDBM: bm => bm as any,
|
|
83
|
-
beforeTMToBM: tm => tm
|
|
85
|
+
beforeTMToBM: tm => tm,
|
|
84
86
|
beforeBMToTM: bm => bm as any,
|
|
85
87
|
anonymize: dbm => dbm,
|
|
86
88
|
onValidationError: err => err,
|
|
87
89
|
...cfg.hooks,
|
|
88
90
|
},
|
|
89
91
|
}
|
|
92
|
+
|
|
93
|
+
if (this.cfg.createId) {
|
|
94
|
+
_assert(
|
|
95
|
+
this.cfg.idType === 'string',
|
|
96
|
+
'db-lib: automatic generation of non-string ids is not supported',
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
this.cfg.hooks!.createId ||= () => stringId() as ID
|
|
100
|
+
} else {
|
|
101
|
+
delete this.cfg.hooks!.createId
|
|
102
|
+
}
|
|
90
103
|
}
|
|
91
104
|
|
|
92
105
|
// CREATE
|
|
93
106
|
create(part: Partial<BM> = {}, opt: CommonDaoOptions = {}): Saved<BM> {
|
|
94
107
|
let bm = this.cfg.hooks!.beforeCreate!(part) as BM
|
|
95
108
|
bm = this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)
|
|
96
|
-
|
|
97
|
-
// If no SCHEMA - return as is
|
|
98
109
|
return this.assignIdCreatedUpdated(bm, opt)
|
|
99
110
|
}
|
|
100
111
|
|
|
101
112
|
// GET
|
|
102
113
|
async getById(id: undefined, opt?: CommonDaoOptions): Promise<null>
|
|
103
|
-
async getById(id?:
|
|
104
|
-
async getById(id?:
|
|
114
|
+
async getById(id?: ID, opt?: CommonDaoOptions): Promise<Saved<BM> | null>
|
|
115
|
+
async getById(id?: ID, opt: CommonDaoOptions = {}): Promise<Saved<BM> | null> {
|
|
105
116
|
if (!id) return null
|
|
106
117
|
const op = `getById(${id})`
|
|
107
118
|
const table = opt.table || this.cfg.table
|
|
@@ -126,22 +137,14 @@ export class CommonDao<
|
|
|
126
137
|
return bm || null
|
|
127
138
|
}
|
|
128
139
|
|
|
129
|
-
async getByIdOrEmpty(
|
|
130
|
-
id: string,
|
|
131
|
-
part: Partial<BM> = {},
|
|
132
|
-
opt?: CommonDaoOptions,
|
|
133
|
-
): Promise<Saved<BM>> {
|
|
140
|
+
async getByIdOrEmpty(id: ID, part: Partial<BM> = {}, opt?: CommonDaoOptions): Promise<Saved<BM>> {
|
|
134
141
|
const bm = await this.getById(id, opt)
|
|
135
142
|
if (bm) return bm
|
|
136
143
|
|
|
137
144
|
return this.create({ ...part, id }, opt)
|
|
138
145
|
}
|
|
139
146
|
|
|
140
|
-
async getByIdAsDBMOrEmpty(
|
|
141
|
-
id: string,
|
|
142
|
-
part: Partial<BM> = {},
|
|
143
|
-
opt?: CommonDaoOptions,
|
|
144
|
-
): Promise<DBM> {
|
|
147
|
+
async getByIdAsDBMOrEmpty(id: ID, part: Partial<BM> = {}, opt?: CommonDaoOptions): Promise<DBM> {
|
|
145
148
|
const dbm = await this.getByIdAsDBM(id, opt)
|
|
146
149
|
if (dbm) return dbm
|
|
147
150
|
|
|
@@ -150,8 +153,8 @@ export class CommonDao<
|
|
|
150
153
|
}
|
|
151
154
|
|
|
152
155
|
async getByIdAsDBM(id: undefined, opt?: CommonDaoOptions): Promise<null>
|
|
153
|
-
async getByIdAsDBM(id?:
|
|
154
|
-
async getByIdAsDBM(id?:
|
|
156
|
+
async getByIdAsDBM(id?: ID, opt?: CommonDaoOptions): Promise<DBM | null>
|
|
157
|
+
async getByIdAsDBM(id?: ID, opt: CommonDaoOptions = {}): Promise<DBM | null> {
|
|
155
158
|
if (!id) return null
|
|
156
159
|
const op = `getByIdAsDBM(${id})`
|
|
157
160
|
const table = opt.table || this.cfg.table
|
|
@@ -165,8 +168,8 @@ export class CommonDao<
|
|
|
165
168
|
}
|
|
166
169
|
|
|
167
170
|
async getByIdAsTM(id: undefined, opt?: CommonDaoOptions): Promise<null>
|
|
168
|
-
async getByIdAsTM(id?:
|
|
169
|
-
async getByIdAsTM(id?:
|
|
171
|
+
async getByIdAsTM(id?: ID, opt?: CommonDaoOptions): Promise<TM | null>
|
|
172
|
+
async getByIdAsTM(id?: ID, opt: CommonDaoOptions = {}): Promise<TM | null> {
|
|
170
173
|
if (!id) return null
|
|
171
174
|
const op = `getByIdAsTM(${id})`
|
|
172
175
|
const table = opt.table || this.cfg.table
|
|
@@ -182,7 +185,7 @@ export class CommonDao<
|
|
|
182
185
|
return tm || null
|
|
183
186
|
}
|
|
184
187
|
|
|
185
|
-
async getByIds(ids:
|
|
188
|
+
async getByIds(ids: ID[], opt: CommonDaoOptions = {}): Promise<Saved<BM>[]> {
|
|
186
189
|
const op = `getByIds ${ids.length} id(s) (${_truncate(ids.slice(0, 10).join(', '), 50)})`
|
|
187
190
|
const table = opt.table || this.cfg.table
|
|
188
191
|
const started = this.logStarted(op, table)
|
|
@@ -192,7 +195,7 @@ export class CommonDao<
|
|
|
192
195
|
return bms
|
|
193
196
|
}
|
|
194
197
|
|
|
195
|
-
async getByIdsAsDBM(ids:
|
|
198
|
+
async getByIdsAsDBM(ids: ID[], opt: CommonDaoOptions = {}): Promise<DBM[]> {
|
|
196
199
|
const op = `getByIdsAsDBM ${ids.length} id(s) (${_truncate(ids.slice(0, 10).join(', '), 50)})`
|
|
197
200
|
const table = opt.table || this.cfg.table
|
|
198
201
|
const started = this.logStarted(op, table)
|
|
@@ -201,7 +204,7 @@ export class CommonDao<
|
|
|
201
204
|
return dbms
|
|
202
205
|
}
|
|
203
206
|
|
|
204
|
-
async requireById(id:
|
|
207
|
+
async requireById(id: ID, opt: CommonDaoOptions = {}): Promise<Saved<BM>> {
|
|
205
208
|
const r = await this.getById(id, opt)
|
|
206
209
|
if (!r) {
|
|
207
210
|
this.throwRequiredError(id, opt)
|
|
@@ -209,7 +212,7 @@ export class CommonDao<
|
|
|
209
212
|
return r
|
|
210
213
|
}
|
|
211
214
|
|
|
212
|
-
async requireByIdAsDBM(id:
|
|
215
|
+
async requireByIdAsDBM(id: ID, opt: CommonDaoOptions = {}): Promise<DBM> {
|
|
213
216
|
const r = await this.getByIdAsDBM(id, opt)
|
|
214
217
|
if (!r) {
|
|
215
218
|
this.throwRequiredError(id, opt)
|
|
@@ -217,7 +220,7 @@ export class CommonDao<
|
|
|
217
220
|
return r
|
|
218
221
|
}
|
|
219
222
|
|
|
220
|
-
private throwRequiredError(id:
|
|
223
|
+
private throwRequiredError(id: ID, opt: CommonDaoOptions): never {
|
|
221
224
|
const table = opt.table || this.cfg.table
|
|
222
225
|
throw new AppError(`DB row required, but not found: ${table}.${id}`, {
|
|
223
226
|
code: DBLibError.DB_ROW_REQUIRED,
|
|
@@ -267,8 +270,8 @@ export class CommonDao<
|
|
|
267
270
|
/**
|
|
268
271
|
* Pass `table` to override table
|
|
269
272
|
*/
|
|
270
|
-
query(table?: string): RunnableDBQuery<BM, DBM, TM> {
|
|
271
|
-
return new RunnableDBQuery<BM, DBM, TM>(this, table)
|
|
273
|
+
query(table?: string): RunnableDBQuery<BM, DBM, TM, ID> {
|
|
274
|
+
return new RunnableDBQuery<BM, DBM, TM, ID>(this, table)
|
|
272
275
|
}
|
|
273
276
|
|
|
274
277
|
async runQuery(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<Saved<BM>[]> {
|
|
@@ -514,18 +517,18 @@ export class CommonDao<
|
|
|
514
517
|
)
|
|
515
518
|
}
|
|
516
519
|
|
|
517
|
-
async queryIds(q: DBQuery<DBM>, opt: CommonDaoOptions = {}): Promise<
|
|
520
|
+
async queryIds(q: DBQuery<DBM>, opt: CommonDaoOptions = {}): Promise<ID[]> {
|
|
518
521
|
q.table = opt.table || q.table
|
|
519
522
|
const { rows } = await this.cfg.db.runQuery(q.select(['id']), opt)
|
|
520
523
|
return rows.map(r => r.id)
|
|
521
524
|
}
|
|
522
525
|
|
|
523
|
-
streamQueryIds(q: DBQuery<DBM>, opt: CommonDaoStreamOptions = {}): ReadableTyped<
|
|
526
|
+
streamQueryIds(q: DBQuery<DBM>, opt: CommonDaoStreamOptions = {}): ReadableTyped<ID> {
|
|
524
527
|
q.table = opt.table || q.table
|
|
525
528
|
opt.errorMode ||= ErrorMode.SUPPRESS
|
|
526
529
|
|
|
527
530
|
return this.cfg.db.streamQuery<DBM>(q.select(['id']), opt).pipe(
|
|
528
|
-
transformMapSimple<
|
|
531
|
+
transformMapSimple<DBM, ID>(objectWithId => objectWithId.id, {
|
|
529
532
|
errorMode: ErrorMode.SUPPRESS, // cause .pipe() cannot propagate errors
|
|
530
533
|
}),
|
|
531
534
|
)
|
|
@@ -533,8 +536,8 @@ export class CommonDao<
|
|
|
533
536
|
|
|
534
537
|
async streamQueryIdsForEach(
|
|
535
538
|
q: DBQuery<DBM>,
|
|
536
|
-
mapper: AsyncMapper<
|
|
537
|
-
opt: CommonDaoStreamForEachOptions<
|
|
539
|
+
mapper: AsyncMapper<ID, void>,
|
|
540
|
+
opt: CommonDaoStreamForEachOptions<ID> = {},
|
|
538
541
|
): Promise<void> {
|
|
539
542
|
q.table = opt.table || q.table
|
|
540
543
|
opt.errorMode = opt.errorMode || ErrorMode.SUPPRESS
|
|
@@ -545,9 +548,9 @@ export class CommonDao<
|
|
|
545
548
|
|
|
546
549
|
await _pipeline([
|
|
547
550
|
this.cfg.db.streamQuery<DBM>(q.select(['id']), opt),
|
|
548
|
-
transformMapSimple<
|
|
551
|
+
transformMapSimple<DBM, ID>(objectWithId => objectWithId.id),
|
|
549
552
|
transformTap(() => count++),
|
|
550
|
-
transformMap<
|
|
553
|
+
transformMap<ID, void>(mapper, {
|
|
551
554
|
...opt,
|
|
552
555
|
predicate: _passthroughPredicate,
|
|
553
556
|
}),
|
|
@@ -573,18 +576,14 @@ export class CommonDao<
|
|
|
573
576
|
assignIdCreatedUpdated(obj: DBM | BM, opt: CommonDaoOptions = {}): DBM | Saved<BM> {
|
|
574
577
|
const now = Math.floor(Date.now() / 1000)
|
|
575
578
|
|
|
576
|
-
obj.id
|
|
579
|
+
obj.id ||= this.cfg.hooks!.createId?.(obj)
|
|
577
580
|
|
|
578
581
|
if (this.cfg.created) {
|
|
579
|
-
|
|
580
|
-
created: (obj as any).created || (obj as any).updated || now,
|
|
581
|
-
})
|
|
582
|
+
obj['created'] ||= obj['updated'] || now
|
|
582
583
|
}
|
|
583
584
|
|
|
584
585
|
if (this.cfg.updated) {
|
|
585
|
-
|
|
586
|
-
updated: opt.preserveUpdatedCreated && (obj as any).updated ? (obj as any).updated : now,
|
|
587
|
-
})
|
|
586
|
+
obj['updated'] = opt.preserveUpdatedCreated && obj['updated'] ? obj['updated'] : now
|
|
588
587
|
}
|
|
589
588
|
|
|
590
589
|
return obj as any
|
|
@@ -601,7 +600,7 @@ export class CommonDao<
|
|
|
601
600
|
const dbm = await this.bmToDBM(bm, opt)
|
|
602
601
|
const table = opt.table || this.cfg.table
|
|
603
602
|
if (opt.ensureUniqueId && idWasGenerated) await this.ensureUniqueId(table, dbm)
|
|
604
|
-
if (this.cfg.immutable) await this.
|
|
603
|
+
if (this.cfg.immutable) await this.ensureImmutableDontExist(table, [dbm.id])
|
|
605
604
|
const op = `save(${dbm.id})`
|
|
606
605
|
const started = this.logSaveStarted(op, bm, table)
|
|
607
606
|
await this.cfg.db.saveBatch(table, [dbm], {
|
|
@@ -613,12 +612,11 @@ export class CommonDao<
|
|
|
613
612
|
return bm as any
|
|
614
613
|
}
|
|
615
614
|
|
|
616
|
-
private async
|
|
617
|
-
await this.throwIfObjectExists(table,
|
|
615
|
+
private async ensureImmutableDontExist(table: string, ids: ID[]): Promise<void> {
|
|
616
|
+
await this.throwIfObjectExists(table, ids, [
|
|
618
617
|
DBLibError.OBJECT_IS_IMMUTABLE,
|
|
619
618
|
{
|
|
620
619
|
code: DBLibError.OBJECT_IS_IMMUTABLE,
|
|
621
|
-
id: dbm.id,
|
|
622
620
|
table,
|
|
623
621
|
},
|
|
624
622
|
])
|
|
@@ -626,23 +624,27 @@ export class CommonDao<
|
|
|
626
624
|
|
|
627
625
|
private async ensureUniqueId(table: string, dbm: DBM): Promise<void> {
|
|
628
626
|
// todo: retry N times
|
|
629
|
-
await this.throwIfObjectExists(
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
627
|
+
await this.throwIfObjectExists(
|
|
628
|
+
table,
|
|
629
|
+
[dbm.id],
|
|
630
|
+
[
|
|
631
|
+
DBLibError.OBJECT_IS_IMMUTABLE,
|
|
632
|
+
{
|
|
633
|
+
code: DBLibError.OBJECT_IS_IMMUTABLE,
|
|
634
|
+
table,
|
|
635
|
+
},
|
|
636
|
+
],
|
|
637
|
+
)
|
|
637
638
|
}
|
|
638
639
|
|
|
639
640
|
private async throwIfObjectExists(
|
|
640
641
|
table: string,
|
|
641
|
-
|
|
642
|
+
ids: ID[],
|
|
642
643
|
errorMeta: [DBLibError, any],
|
|
643
644
|
): Promise<void> {
|
|
644
|
-
const
|
|
645
|
-
if (existing
|
|
645
|
+
const existing = await this.cfg.db.getByIds<DBM>(table, ids)
|
|
646
|
+
if (existing.length > 0)
|
|
647
|
+
throw new AppError(errorMeta[0], { ...errorMeta[1], ids: existing.map(i => i.id) })
|
|
646
648
|
}
|
|
647
649
|
|
|
648
650
|
/**
|
|
@@ -653,11 +655,7 @@ export class CommonDao<
|
|
|
653
655
|
*
|
|
654
656
|
* Convenience method to replace 3 operations (loading+patching+saving) with one.
|
|
655
657
|
*/
|
|
656
|
-
async patch(
|
|
657
|
-
id: string,
|
|
658
|
-
patch: Partial<BM>,
|
|
659
|
-
opt: CommonDaoSaveOptions<DBM> = {},
|
|
660
|
-
): Promise<Saved<BM>> {
|
|
658
|
+
async patch(id: ID, patch: Partial<BM>, opt: CommonDaoSaveOptions<DBM> = {}): Promise<Saved<BM>> {
|
|
661
659
|
return await this.save(
|
|
662
660
|
{
|
|
663
661
|
...(await this.getByIdOrEmpty(id, patch, opt)),
|
|
@@ -667,11 +665,7 @@ export class CommonDao<
|
|
|
667
665
|
)
|
|
668
666
|
}
|
|
669
667
|
|
|
670
|
-
async patchAsDBM(
|
|
671
|
-
id: string,
|
|
672
|
-
patch: Partial<DBM>,
|
|
673
|
-
opt: CommonDaoSaveOptions<DBM> = {},
|
|
674
|
-
): Promise<DBM> {
|
|
668
|
+
async patchAsDBM(id: ID, patch: Partial<DBM>, opt: CommonDaoSaveOptions<DBM> = {}): Promise<DBM> {
|
|
675
669
|
const dbm =
|
|
676
670
|
(await this.getByIdAsDBM(id, opt)) ||
|
|
677
671
|
(this.create({ ...patch, id } as Partial<BM>, opt) as any as DBM)
|
|
@@ -696,7 +690,7 @@ export class CommonDao<
|
|
|
696
690
|
this.assignIdCreatedUpdated(dbm, opt) // mutates
|
|
697
691
|
dbm = this.anyToDBM(dbm, opt)
|
|
698
692
|
if (opt.ensureUniqueId && idWasGenerated) await this.ensureUniqueId(table, dbm)
|
|
699
|
-
if (this.cfg.immutable) await this.
|
|
693
|
+
if (this.cfg.immutable) await this.ensureImmutableDontExist(table, [dbm.id])
|
|
700
694
|
}
|
|
701
695
|
const op = `saveAsDBM(${dbm.id})`
|
|
702
696
|
const started = this.logSaveStarted(op, dbm, table)
|
|
@@ -715,7 +709,11 @@ export class CommonDao<
|
|
|
715
709
|
const dbms = await this.bmsToDBM(bms, opt)
|
|
716
710
|
if (opt.ensureUniqueId) throw new AppError('ensureUniqueId is not supported in saveBatch')
|
|
717
711
|
if (this.cfg.immutable)
|
|
718
|
-
|
|
712
|
+
await this.ensureImmutableDontExist(
|
|
713
|
+
table,
|
|
714
|
+
dbms.map(dbm => dbm.id),
|
|
715
|
+
)
|
|
716
|
+
|
|
719
717
|
const op = `saveBatch ${dbms.length} row(s) (${_truncate(
|
|
720
718
|
dbms
|
|
721
719
|
.slice(0, 10)
|
|
@@ -742,7 +740,11 @@ export class CommonDao<
|
|
|
742
740
|
dbms.forEach(dbm => this.assignIdCreatedUpdated(dbm, opt)) // mutates
|
|
743
741
|
dbms = this.anyToDBMs(dbms, opt)
|
|
744
742
|
if (opt.ensureUniqueId) throw new AppError('ensureUniqueId is not supported in saveBatch')
|
|
745
|
-
if (this.cfg.immutable)
|
|
743
|
+
if (this.cfg.immutable)
|
|
744
|
+
await this.ensureImmutableDontExist(
|
|
745
|
+
table,
|
|
746
|
+
dbms.map(dbm => dbm.id),
|
|
747
|
+
)
|
|
746
748
|
}
|
|
747
749
|
const op = `saveBatchAsDBM ${dbms.length} row(s) (${_truncate(
|
|
748
750
|
dbms
|
|
@@ -767,8 +769,8 @@ export class CommonDao<
|
|
|
767
769
|
* @returns number of deleted items
|
|
768
770
|
*/
|
|
769
771
|
async deleteById(id: undefined, opt?: CommonDaoOptions): Promise<0>
|
|
770
|
-
async deleteById(id?:
|
|
771
|
-
async deleteById(id?:
|
|
772
|
+
async deleteById(id?: ID, opt?: CommonDaoOptions): Promise<number>
|
|
773
|
+
async deleteById(id?: ID, opt: CommonDaoOptions = {}): Promise<number> {
|
|
772
774
|
if (!id) return 0
|
|
773
775
|
this.requireWriteAccess()
|
|
774
776
|
if (!opt.allowMutability) this.requireObjectMutability()
|
|
@@ -780,7 +782,7 @@ export class CommonDao<
|
|
|
780
782
|
return ids
|
|
781
783
|
}
|
|
782
784
|
|
|
783
|
-
async deleteByIds(ids:
|
|
785
|
+
async deleteByIds(ids: ID[], opt: CommonDaoOptions = {}): Promise<number> {
|
|
784
786
|
this.requireWriteAccess()
|
|
785
787
|
if (!opt.allowMutability) this.requireObjectMutability()
|
|
786
788
|
const op = `deleteByIds(${ids.join(', ')})`
|
|
@@ -812,7 +814,7 @@ export class CommonDao<
|
|
|
812
814
|
|
|
813
815
|
await _pipeline([
|
|
814
816
|
this.cfg.db.streamQuery<DBM>(q.select(['id']), opt),
|
|
815
|
-
transformMapSimple<
|
|
817
|
+
transformMapSimple<DBM, ID>(objectWithId => objectWithId.id, {
|
|
816
818
|
errorMode: ErrorMode.SUPPRESS,
|
|
817
819
|
}),
|
|
818
820
|
transformBuffer<string>({ batchSize }),
|
package/src/db.model.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { AnyObjectWithId, ObjectWithId } from '@naturalcycles/js-lib'
|
|
2
|
-
import { CommonDB } from './common.db'
|
|
3
2
|
|
|
4
3
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
5
4
|
export interface CommonDBOptions {}
|
|
@@ -16,8 +15,9 @@ export type CommonDBStreamOptions = CommonDBOptions
|
|
|
16
15
|
|
|
17
16
|
export interface CommonDBCreateOptions extends CommonDBOptions {
|
|
18
17
|
/**
|
|
19
|
-
* @default false
|
|
20
18
|
* Caution! If set to true - will actually DROP the table!
|
|
19
|
+
*
|
|
20
|
+
* @default false
|
|
21
21
|
*/
|
|
22
22
|
dropIfExists?: boolean
|
|
23
23
|
}
|
|
@@ -51,19 +51,3 @@ export enum DBModelType {
|
|
|
51
51
|
BM = 'BM',
|
|
52
52
|
TM = 'TM',
|
|
53
53
|
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Interface for a module (lib) that implements CommonDB.
|
|
57
|
-
*
|
|
58
|
-
* Example:
|
|
59
|
-
*
|
|
60
|
-
* const lib: CommonDBModule = require('mysql-lib')
|
|
61
|
-
* const db = lib.getDB()
|
|
62
|
-
*/
|
|
63
|
-
export interface CommonDBAdapter {
|
|
64
|
-
/**
|
|
65
|
-
* @param cfg was read from SECRET_DB${i} by secret('SECRET_DB${i}') method and passed there.
|
|
66
|
-
* It's a string that can contain e.g JSON.stringified configuration object (depends on the adapter).
|
|
67
|
-
*/
|
|
68
|
-
getDBAdapter(cfg?: string): CommonDB
|
|
69
|
-
}
|
package/src/index.ts
CHANGED
|
@@ -6,25 +6,16 @@ import { DBLibError } from './cnst'
|
|
|
6
6
|
import { CommonDB } from './common.db'
|
|
7
7
|
import { CommonDao } from './commondao/common.dao'
|
|
8
8
|
import {
|
|
9
|
-
CommonDaoAnonymizeHook,
|
|
10
|
-
CommonDaoBeforeBMToDBMHook,
|
|
11
|
-
CommonDaoBeforeBMToTMHook,
|
|
12
|
-
CommonDaoBeforeCreateHook,
|
|
13
|
-
CommonDaoBeforeDBMToBMHook,
|
|
14
|
-
CommonDaoBeforeDBMValidateHook,
|
|
15
|
-
CommonDaoBeforeTMToBMHook,
|
|
16
9
|
CommonDaoCfg,
|
|
17
|
-
CommonDaoCreateIdHook,
|
|
18
10
|
CommonDaoCreateOptions,
|
|
19
11
|
CommonDaoLogLevel,
|
|
20
12
|
CommonDaoOptions,
|
|
21
|
-
CommonDaoParseNaturalIdHook,
|
|
22
13
|
CommonDaoSaveOptions,
|
|
23
14
|
CommonDaoStreamForEachOptions,
|
|
24
15
|
CommonDaoStreamOptions,
|
|
16
|
+
CommonDaoHooks,
|
|
25
17
|
} from './commondao/common.dao.model'
|
|
26
18
|
import {
|
|
27
|
-
CommonDBAdapter,
|
|
28
19
|
CommonDBCreateOptions,
|
|
29
20
|
CommonDBOptions,
|
|
30
21
|
CommonDBSaveOptions,
|
|
@@ -36,7 +27,6 @@ import {
|
|
|
36
27
|
DBSaveBatchOperation,
|
|
37
28
|
RunQueryResult,
|
|
38
29
|
} from './db.model'
|
|
39
|
-
import { getDB } from './getDB'
|
|
40
30
|
import { CommonKeyValueDao, CommonKeyValueDaoCfg } from './kv/commonKeyValueDao'
|
|
41
31
|
import { CommonKeyValueDB, KeyValueDBTuple } from './kv/commonKeyValueDB'
|
|
42
32
|
import {
|
|
@@ -69,6 +59,7 @@ export type {
|
|
|
69
59
|
CommonDaoSaveOptions,
|
|
70
60
|
CommonDaoStreamForEachOptions,
|
|
71
61
|
CommonDaoStreamOptions,
|
|
62
|
+
CommonDaoHooks,
|
|
72
63
|
CommonDBOptions,
|
|
73
64
|
CommonDBSaveOptions,
|
|
74
65
|
CommonDBStreamOptions,
|
|
@@ -76,21 +67,11 @@ export type {
|
|
|
76
67
|
CommonDB,
|
|
77
68
|
RunQueryResult,
|
|
78
69
|
CommonDaoCfg,
|
|
79
|
-
CommonDaoCreateIdHook,
|
|
80
|
-
CommonDaoParseNaturalIdHook,
|
|
81
|
-
CommonDaoBeforeCreateHook,
|
|
82
|
-
CommonDaoBeforeDBMValidateHook,
|
|
83
|
-
CommonDaoBeforeDBMToBMHook,
|
|
84
|
-
CommonDaoBeforeBMToDBMHook,
|
|
85
|
-
CommonDaoBeforeTMToBMHook,
|
|
86
|
-
CommonDaoBeforeBMToTMHook,
|
|
87
|
-
CommonDaoAnonymizeHook,
|
|
88
70
|
InMemoryDBCfg,
|
|
89
71
|
InMemoryKeyValueDBCfg,
|
|
90
72
|
DBPipelineBackupOptions,
|
|
91
73
|
DBPipelineRestoreOptions,
|
|
92
74
|
DBPipelineCopyOptions,
|
|
93
|
-
CommonDBAdapter,
|
|
94
75
|
DBOperation,
|
|
95
76
|
DBSaveBatchOperation,
|
|
96
77
|
DBDeleteByIdsOperation,
|
|
@@ -117,7 +98,6 @@ export {
|
|
|
117
98
|
dbPipelineBackup,
|
|
118
99
|
dbPipelineRestore,
|
|
119
100
|
dbPipelineCopy,
|
|
120
|
-
getDB,
|
|
121
101
|
DBLibError,
|
|
122
102
|
BaseCommonDB,
|
|
123
103
|
DBTransaction,
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { createGzip, ZlibOptions } from 'zlib'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
AppError,
|
|
4
|
+
AsyncMapper,
|
|
5
|
+
ErrorMode,
|
|
6
|
+
pMap,
|
|
7
|
+
_passthroughMapper,
|
|
8
|
+
localTime,
|
|
9
|
+
} from '@naturalcycles/js-lib'
|
|
3
10
|
import {
|
|
4
11
|
NDJsonStats,
|
|
5
12
|
transformLogProgress,
|
|
@@ -11,7 +18,6 @@ import {
|
|
|
11
18
|
_pipeline,
|
|
12
19
|
} from '@naturalcycles/nodejs-lib'
|
|
13
20
|
import { boldWhite, dimWhite, grey, yellow } from '@naturalcycles/nodejs-lib/dist/colors'
|
|
14
|
-
import { dayjs } from '@naturalcycles/time-lib'
|
|
15
21
|
import * as fs from 'fs-extra'
|
|
16
22
|
import { CommonDB } from '../common.db'
|
|
17
23
|
import { DBQuery } from '../index'
|
|
@@ -144,7 +150,7 @@ export async function dbPipelineBackup(opt: DBPipelineBackupOptions): Promise<ND
|
|
|
144
150
|
|
|
145
151
|
let { tables } = opt
|
|
146
152
|
|
|
147
|
-
const sinceUpdatedStr = sinceUpdated ? ' since ' + grey(
|
|
153
|
+
const sinceUpdatedStr = sinceUpdated ? ' since ' + grey(localTime(sinceUpdated).toPretty()) : ''
|
|
148
154
|
|
|
149
155
|
console.log(
|
|
150
156
|
`>> ${dimWhite('dbPipelineBackup')} started in ${grey(outputDirPath)}...${sinceUpdatedStr}`,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AsyncMapper, ErrorMode, pMap, _passthroughMapper } from '@naturalcycles/js-lib'
|
|
1
|
+
import { AsyncMapper, ErrorMode, pMap, _passthroughMapper, localTime } from '@naturalcycles/js-lib'
|
|
2
2
|
import {
|
|
3
3
|
NDJsonStats,
|
|
4
4
|
transformBuffer,
|
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
_pipeline,
|
|
12
12
|
} from '@naturalcycles/nodejs-lib'
|
|
13
13
|
import { boldWhite, dimWhite, grey, yellow } from '@naturalcycles/nodejs-lib/dist/colors'
|
|
14
|
-
import { dayjs } from '@naturalcycles/time-lib'
|
|
15
14
|
import { CommonDB } from '../common.db'
|
|
16
15
|
import { CommonDBSaveOptions } from '../db.model'
|
|
17
16
|
import { DBQuery } from '../query/dbQuery'
|
|
@@ -103,7 +102,7 @@ export async function dbPipelineCopy(opt: DBPipelineCopyOptions): Promise<NDJson
|
|
|
103
102
|
|
|
104
103
|
let { tables } = opt
|
|
105
104
|
|
|
106
|
-
const sinceUpdatedStr = sinceUpdated ? ' since ' + grey(
|
|
105
|
+
const sinceUpdatedStr = sinceUpdated ? ' since ' + grey(localTime(sinceUpdated).toPretty()) : ''
|
|
107
106
|
|
|
108
107
|
console.log(`>> ${dimWhite('dbPipelineCopy')} started...${sinceUpdatedStr}`)
|
|
109
108
|
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
_mapValues,
|
|
8
8
|
_passthroughMapper,
|
|
9
9
|
SavedDBEntity,
|
|
10
|
+
localTime,
|
|
10
11
|
} from '@naturalcycles/js-lib'
|
|
11
12
|
import {
|
|
12
13
|
NDJsonStats,
|
|
@@ -24,7 +25,6 @@ import {
|
|
|
24
25
|
_pipeline,
|
|
25
26
|
} from '@naturalcycles/nodejs-lib'
|
|
26
27
|
import { boldWhite, dimWhite, grey, yellow } from '@naturalcycles/nodejs-lib/dist/colors'
|
|
27
|
-
import { dayjs } from '@naturalcycles/time-lib'
|
|
28
28
|
import * as fs from 'fs-extra'
|
|
29
29
|
import { CommonDB } from '../common.db'
|
|
30
30
|
import { CommonDBSaveOptions } from '../index'
|
|
@@ -133,7 +133,7 @@ export async function dbPipelineRestore(opt: DBPipelineRestoreOptions): Promise<
|
|
|
133
133
|
const strict = errorMode !== ErrorMode.SUPPRESS
|
|
134
134
|
const onlyTables = opt.tables && new Set(opt.tables)
|
|
135
135
|
|
|
136
|
-
const sinceUpdatedStr = sinceUpdated ? ' since ' + grey(
|
|
136
|
+
const sinceUpdatedStr = sinceUpdated ? ' since ' + grey(localTime(sinceUpdated).toPretty()) : ''
|
|
137
137
|
|
|
138
138
|
console.log(
|
|
139
139
|
`>> ${dimWhite('dbPipelineRestore')} started in ${grey(inputDirPath)}...${sinceUpdatedStr}`,
|
package/src/query/dbQuery.ts
CHANGED
|
@@ -216,14 +216,15 @@ export class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
|
|
|
216
216
|
* DBQuery that has additional method to support Fluent API style.
|
|
217
217
|
*/
|
|
218
218
|
export class RunnableDBQuery<
|
|
219
|
-
BM extends Partial<ObjectWithId
|
|
220
|
-
DBM extends ObjectWithId
|
|
219
|
+
BM extends Partial<ObjectWithId<ID>>,
|
|
220
|
+
DBM extends ObjectWithId<ID>,
|
|
221
221
|
TM,
|
|
222
|
+
ID extends string | number,
|
|
222
223
|
> extends DBQuery<DBM> {
|
|
223
224
|
/**
|
|
224
225
|
* Pass `table` to override table.
|
|
225
226
|
*/
|
|
226
|
-
constructor(public dao: CommonDao<BM, DBM, TM>, table?: string) {
|
|
227
|
+
constructor(public dao: CommonDao<BM, DBM, TM, ID>, table?: string) {
|
|
227
228
|
super(table || dao.cfg.table)
|
|
228
229
|
}
|
|
229
230
|
|
|
@@ -281,17 +282,17 @@ export class RunnableDBQuery<
|
|
|
281
282
|
return this.dao.streamQueryAsDBM(this, opt)
|
|
282
283
|
}
|
|
283
284
|
|
|
284
|
-
async queryIds(opt?: CommonDaoOptions): Promise<
|
|
285
|
+
async queryIds(opt?: CommonDaoOptions): Promise<ID[]> {
|
|
285
286
|
return await this.dao.queryIds(this, opt)
|
|
286
287
|
}
|
|
287
288
|
|
|
288
|
-
streamQueryIds(opt?: CommonDaoStreamOptions): ReadableTyped<
|
|
289
|
+
streamQueryIds(opt?: CommonDaoStreamOptions): ReadableTyped<ID> {
|
|
289
290
|
return this.dao.streamQueryIds(this, opt)
|
|
290
291
|
}
|
|
291
292
|
|
|
292
293
|
async streamQueryIdsForEach(
|
|
293
|
-
mapper: AsyncMapper<
|
|
294
|
-
opt?: CommonDaoStreamForEachOptions<
|
|
294
|
+
mapper: AsyncMapper<ID, void>,
|
|
295
|
+
opt?: CommonDaoStreamForEachOptions<ID>,
|
|
295
296
|
): Promise<void> {
|
|
296
297
|
await this.dao.streamQueryIdsForEach(this, mapper, opt)
|
|
297
298
|
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getDBAdapter = void 0;
|
|
4
|
-
const inMemory_db_1 = require("./inMemory.db");
|
|
5
|
-
function getDBAdapter() {
|
|
6
|
-
return new inMemory_db_1.InMemoryDB();
|
|
7
|
-
}
|
|
8
|
-
exports.getDBAdapter = getDBAdapter;
|
package/dist/getDB.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { CommonDB } from './common.db';
|
|
2
|
-
/**
|
|
3
|
-
* Returns pre-configured DB
|
|
4
|
-
*
|
|
5
|
-
* @param index defaults to 1
|
|
6
|
-
*
|
|
7
|
-
* Requires process.env.DB${index} to be set to the name of the adapter, e.g `mysql-lib` or `db-lib/adapter/inmemory`.
|
|
8
|
-
* Requires (by most adapters) process.env.SECRET_DB${index} to contain a "connection string" to that DB. Usually a JSON.stringified object,
|
|
9
|
-
* but depends on the adapter.
|
|
10
|
-
*/
|
|
11
|
-
export declare function getDB(index?: number): CommonDB;
|
|
12
|
-
declare global {
|
|
13
|
-
namespace NodeJS {
|
|
14
|
-
interface ProcessEnv {
|
|
15
|
-
DB1?: string;
|
|
16
|
-
DB2?: string;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
package/dist/getDB.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getDB = void 0;
|
|
4
|
-
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
|
-
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
6
|
-
const colors_1 = require("@naturalcycles/nodejs-lib/dist/colors");
|
|
7
|
-
/**
|
|
8
|
-
* Returns pre-configured DB
|
|
9
|
-
*
|
|
10
|
-
* @param index defaults to 1
|
|
11
|
-
*
|
|
12
|
-
* Requires process.env.DB${index} to be set to the name of the adapter, e.g `mysql-lib` or `db-lib/adapter/inmemory`.
|
|
13
|
-
* Requires (by most adapters) process.env.SECRET_DB${index} to contain a "connection string" to that DB. Usually a JSON.stringified object,
|
|
14
|
-
* but depends on the adapter.
|
|
15
|
-
*/
|
|
16
|
-
function getDB(index = 1) {
|
|
17
|
-
return _getDB(index);
|
|
18
|
-
}
|
|
19
|
-
exports.getDB = getDB;
|
|
20
|
-
// Extra function to provide index=1 as default (since memo doesn't work well with default arguments)
|
|
21
|
-
const _getDB = (0, js_lib_1._memoFn)((index) => {
|
|
22
|
-
const libName = process.env[`DB${index}`];
|
|
23
|
-
if (!libName) {
|
|
24
|
-
throw new Error(`getDB(${(0, colors_1.yellow)(index)}), but process.env.${(0, colors_1.white)('DB' + index)} is not defined!`);
|
|
25
|
-
}
|
|
26
|
-
const lib = require(libName);
|
|
27
|
-
if (!lib.getDBAdapter) {
|
|
28
|
-
throw new Error(`DB${index}=${libName}, but require('${libName}').getDBAdapter() is not defined`);
|
|
29
|
-
}
|
|
30
|
-
const cfg = (0, nodejs_lib_1.secretOptional)(`SECRET_DB${index}`);
|
|
31
|
-
return lib.getDBAdapter(cfg);
|
|
32
|
-
});
|