@naturalcycles/db-lib 8.11.0 → 8.13.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/CHANGELOG.md +29 -0
- package/dist/adapter/cachedb/cache.db.d.ts +3 -3
- package/dist/adapter/cachedb/cache.db.js +4 -4
- package/dist/adapter/file/file.db.d.ts +2 -2
- package/dist/adapter/file/file.db.js +20 -18
- package/dist/adapter/file/inMemory.persistence.plugin.js +1 -1
- package/dist/adapter/file/localFile.persistence.plugin.js +9 -9
- package/dist/adapter/inmemory/inMemory.db.d.ts +3 -4
- package/dist/adapter/inmemory/inMemory.db.js +25 -23
- package/dist/adapter/inmemory/queryInMemory.js +1 -1
- package/dist/base.common.db.d.ts +3 -3
- package/dist/base.common.db.js +10 -4
- package/dist/common.db.d.ts +3 -3
- package/dist/commondao/common.dao.d.ts +7 -7
- package/dist/commondao/common.dao.js +56 -48
- package/dist/commondao/common.dao.model.d.ts +20 -27
- package/dist/db.model.js +2 -2
- package/dist/getDB.js +3 -3
- package/dist/index.d.ts +2 -4
- package/dist/index.js +1 -5
- package/dist/kv/commonKeyValueDao.js +4 -4
- package/dist/model.util.js +2 -2
- package/dist/pipeline/dbPipelineBackup.d.ts +0 -1
- package/dist/pipeline/dbPipelineBackup.js +14 -25
- package/dist/pipeline/dbPipelineCopy.js +11 -11
- package/dist/pipeline/dbPipelineRestore.js +20 -20
- package/dist/query/dbQuery.js +2 -2
- package/dist/testing/daoTest.js +23 -23
- package/dist/testing/dbTest.js +17 -17
- package/dist/testing/keyValueDBTest.js +18 -14
- package/dist/testing/keyValueDaoTest.js +18 -14
- package/dist/testing/test.model.d.ts +4 -2
- package/dist/testing/test.model.js +39 -8
- package/dist/testing/timeSeriesTest.util.js +1 -1
- package/dist/transaction/dbTransaction.util.js +2 -2
- package/dist/validation/index.js +9 -9
- package/package.json +1 -1
- package/readme.md +5 -4
- package/src/adapter/cachedb/cache.db.ts +9 -5
- package/src/adapter/file/file.db.ts +7 -4
- package/src/adapter/inmemory/inMemory.db.ts +20 -7
- package/src/base.common.db.ts +10 -4
- package/src/common.db.ts +3 -3
- package/src/commondao/common.dao.model.ts +24 -29
- package/src/commondao/common.dao.ts +35 -24
- package/src/index.ts +0 -7
- package/src/pipeline/dbPipelineBackup.ts +2 -15
- package/src/pipeline/dbPipelineRestore.ts +1 -1
- package/src/testing/dbTest.ts +1 -1
- package/src/testing/keyValueDBTest.ts +10 -6
- package/src/testing/keyValueDaoTest.ts +10 -6
- package/src/testing/test.model.ts +38 -4
- package/dist/schema/common.schema.d.ts +0 -38
- package/dist/schema/common.schema.js +0 -18
- package/dist/schema/commonSchemaGenerator.d.ts +0 -35
- package/dist/schema/commonSchemaGenerator.js +0 -151
- package/src/schema/common.schema.ts +0 -49
- package/src/schema/commonSchemaGenerator.ts +0 -200
|
@@ -29,10 +29,10 @@ function mergeDBOperations(ops) {
|
|
|
29
29
|
}
|
|
30
30
|
});
|
|
31
31
|
const resultOps = [];
|
|
32
|
-
js_lib_1._stringMapEntries(saveMapByTable).forEach(([table, saveMap]) => {
|
|
32
|
+
(0, js_lib_1._stringMapEntries)(saveMapByTable).forEach(([table, saveMap]) => {
|
|
33
33
|
const rowsToSave = [];
|
|
34
34
|
const idsToDelete = [];
|
|
35
|
-
js_lib_1._stringMapEntries(saveMap).forEach(([id, r]) => {
|
|
35
|
+
(0, js_lib_1._stringMapEntries)(saveMap).forEach(([id, r]) => {
|
|
36
36
|
if (r === null) {
|
|
37
37
|
idsToDelete.push(id);
|
|
38
38
|
}
|
package/dist/validation/index.js
CHANGED
|
@@ -3,30 +3,30 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.dbQuerySchema = exports.dbQueryOrderSchema = exports.dbQueryFilterSchema = exports.dbQueryFilterOperatorSchema = exports.commonDBSaveOptionsSchema = exports.commonDBOptionsSchema = void 0;
|
|
4
4
|
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
5
5
|
const dbQuery_1 = require("../query/dbQuery");
|
|
6
|
-
exports.commonDBOptionsSchema = nodejs_lib_1.objectSchema({
|
|
6
|
+
exports.commonDBOptionsSchema = (0, nodejs_lib_1.objectSchema)({
|
|
7
7
|
onlyCache: nodejs_lib_1.booleanSchema.optional(),
|
|
8
8
|
skipCache: nodejs_lib_1.booleanSchema.optional(),
|
|
9
9
|
});
|
|
10
|
-
exports.commonDBSaveOptionsSchema = nodejs_lib_1.objectSchema({
|
|
11
|
-
excludeFromIndexes: nodejs_lib_1.arraySchema(nodejs_lib_1.stringSchema).optional(),
|
|
10
|
+
exports.commonDBSaveOptionsSchema = (0, nodejs_lib_1.objectSchema)({
|
|
11
|
+
excludeFromIndexes: (0, nodejs_lib_1.arraySchema)(nodejs_lib_1.stringSchema).optional(),
|
|
12
12
|
}).concat(exports.commonDBOptionsSchema);
|
|
13
13
|
exports.dbQueryFilterOperatorSchema = nodejs_lib_1.stringSchema.valid(...dbQuery_1.DBQueryFilterOperatorValues);
|
|
14
|
-
exports.dbQueryFilterSchema = nodejs_lib_1.objectSchema({
|
|
14
|
+
exports.dbQueryFilterSchema = (0, nodejs_lib_1.objectSchema)({
|
|
15
15
|
name: nodejs_lib_1.stringSchema,
|
|
16
16
|
op: exports.dbQueryFilterOperatorSchema,
|
|
17
17
|
val: nodejs_lib_1.anySchema,
|
|
18
18
|
});
|
|
19
|
-
exports.dbQueryOrderSchema = nodejs_lib_1.objectSchema({
|
|
19
|
+
exports.dbQueryOrderSchema = (0, nodejs_lib_1.objectSchema)({
|
|
20
20
|
name: nodejs_lib_1.stringSchema,
|
|
21
21
|
descending: nodejs_lib_1.booleanSchema.optional(),
|
|
22
22
|
});
|
|
23
|
-
exports.dbQuerySchema = nodejs_lib_1.objectSchema({
|
|
23
|
+
exports.dbQuerySchema = (0, nodejs_lib_1.objectSchema)({
|
|
24
24
|
table: nodejs_lib_1.stringSchema,
|
|
25
|
-
_filters: nodejs_lib_1.arraySchema(exports.dbQueryFilterSchema).optional(),
|
|
25
|
+
_filters: (0, nodejs_lib_1.arraySchema)(exports.dbQueryFilterSchema).optional(),
|
|
26
26
|
_limitValue: nodejs_lib_1.integerSchema.min(0).optional(),
|
|
27
27
|
_offsetValue: nodejs_lib_1.integerSchema.min(0).optional(),
|
|
28
|
-
_orders: nodejs_lib_1.arraySchema(exports.dbQueryOrderSchema).optional(),
|
|
28
|
+
_orders: (0, nodejs_lib_1.arraySchema)(exports.dbQueryOrderSchema).optional(),
|
|
29
29
|
_startCursor: nodejs_lib_1.stringSchema.optional(),
|
|
30
30
|
_endCursor: nodejs_lib_1.stringSchema.optional(),
|
|
31
|
-
_selectedFieldNames: nodejs_lib_1.arraySchema(nodejs_lib_1.stringSchema).optional(),
|
|
31
|
+
_selectedFieldNames: (0, nodejs_lib_1.arraySchema)(nodejs_lib_1.stringSchema).optional(),
|
|
32
32
|
});
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -216,19 +216,20 @@ await db.getTables()
|
|
|
216
216
|
|
|
217
217
|
###### getTableSchema
|
|
218
218
|
|
|
219
|
-
`getTableSchema(table: string): Promise<
|
|
219
|
+
`getTableSchema(table: string): Promise<JsonSchemaObject>`
|
|
220
220
|
|
|
221
221
|
```typescript
|
|
222
222
|
await db.getTableSchema('table1')
|
|
223
|
-
// todo: describe CommonSchema example
|
|
224
223
|
```
|
|
225
224
|
|
|
225
|
+
Returns a JsonSchema, generated from the table.
|
|
226
|
+
|
|
226
227
|
###### createTable
|
|
227
228
|
|
|
228
|
-
`createTable(schema:
|
|
229
|
+
`createTable(table: string, schema: JsonSchemaObject): Promise<void>`
|
|
229
230
|
|
|
230
231
|
Applicable to Relational DBs, like MySQL. Will invoke smth like `create table Table1 ... ;`. Takes a
|
|
231
|
-
`
|
|
232
|
+
`JsonSchema` as an argument.
|
|
232
233
|
|
|
233
234
|
# DBQuery
|
|
234
235
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { JsonSchemaObject } from '@naturalcycles/js-lib'
|
|
1
2
|
import { Debug, IDebugger } from '@naturalcycles/nodejs-lib'
|
|
2
3
|
import { Readable } from 'stream'
|
|
3
4
|
import { BaseCommonDB } from '../../base.common.db'
|
|
4
5
|
import { CommonDB } from '../../common.db'
|
|
5
6
|
import { ObjectWithId, RunQueryResult } from '../../db.model'
|
|
6
7
|
import { DBQuery } from '../../query/dbQuery'
|
|
7
|
-
import { CommonSchema } from '../../schema/common.schema'
|
|
8
8
|
import {
|
|
9
9
|
CacheDBCfg,
|
|
10
10
|
CacheDBCreateOptions,
|
|
@@ -45,17 +45,21 @@ export class CacheDB extends BaseCommonDB implements CommonDB {
|
|
|
45
45
|
|
|
46
46
|
override async getTableSchema<ROW extends ObjectWithId>(
|
|
47
47
|
table: string,
|
|
48
|
-
): Promise<
|
|
48
|
+
): Promise<JsonSchemaObject<ROW>> {
|
|
49
49
|
return await this.cfg.downstreamDB.getTableSchema<ROW>(table)
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
override async createTable(
|
|
52
|
+
override async createTable(
|
|
53
|
+
table: string,
|
|
54
|
+
schema: JsonSchemaObject,
|
|
55
|
+
opt: CacheDBCreateOptions = {},
|
|
56
|
+
): Promise<void> {
|
|
53
57
|
if (!opt.onlyCache && !this.cfg.onlyCache) {
|
|
54
|
-
await this.cfg.downstreamDB.createTable(schema, opt)
|
|
58
|
+
await this.cfg.downstreamDB.createTable(table, schema, opt)
|
|
55
59
|
}
|
|
56
60
|
|
|
57
61
|
if (!opt.skipCache && !this.cfg.skipCache) {
|
|
58
|
-
await this.cfg.cacheDB.createTable(schema, opt)
|
|
62
|
+
await this.cfg.cacheDB.createTable(table, schema, opt)
|
|
59
63
|
}
|
|
60
64
|
}
|
|
61
65
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
+
generateJsonSchemaFromData,
|
|
3
|
+
JsonSchemaObject,
|
|
2
4
|
pMap,
|
|
3
5
|
StringMap,
|
|
4
6
|
_by,
|
|
@@ -12,8 +14,6 @@ import {
|
|
|
12
14
|
import { Debug, readableCreate, ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
13
15
|
import { dimGrey } from '@naturalcycles/nodejs-lib/dist/colors'
|
|
14
16
|
import { BaseCommonDB, DBSaveBatchOperation, ObjectWithId, queryInMemory } from '../..'
|
|
15
|
-
import { CommonSchema } from '../..'
|
|
16
|
-
import { CommonSchemaGenerator } from '../..'
|
|
17
17
|
import { CommonDB } from '../../common.db'
|
|
18
18
|
import {
|
|
19
19
|
CommonDBOptions,
|
|
@@ -213,9 +213,12 @@ export class FileDB extends BaseCommonDB implements CommonDB {
|
|
|
213
213
|
|
|
214
214
|
override async getTableSchema<ROW extends ObjectWithId>(
|
|
215
215
|
table: string,
|
|
216
|
-
): Promise<
|
|
216
|
+
): Promise<JsonSchemaObject<ROW>> {
|
|
217
217
|
const rows = await this.loadFile(table)
|
|
218
|
-
return
|
|
218
|
+
return {
|
|
219
|
+
...generateJsonSchemaFromData(rows),
|
|
220
|
+
$id: `${table}.schema.json`,
|
|
221
|
+
} as JsonSchemaObject<ROW>
|
|
219
222
|
}
|
|
220
223
|
|
|
221
224
|
// wrapper, to handle logging
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
generateJsonSchemaFromData,
|
|
3
|
+
JsonSchemaObject,
|
|
4
|
+
pMap,
|
|
5
|
+
StringMap,
|
|
6
|
+
_by,
|
|
7
|
+
_since,
|
|
8
|
+
_sortObjectDeep,
|
|
9
|
+
} from '@naturalcycles/js-lib'
|
|
2
10
|
import {
|
|
3
11
|
bufferReviver,
|
|
4
12
|
Debug,
|
|
@@ -14,8 +22,6 @@ import * as fs from 'fs-extra'
|
|
|
14
22
|
import { Readable } from 'stream'
|
|
15
23
|
import { createGzip, createUnzip } from 'zlib'
|
|
16
24
|
import { CommonDB, DBTransaction, ObjectWithId, queryInMemory } from '../..'
|
|
17
|
-
import { CommonSchema } from '../..'
|
|
18
|
-
import { CommonSchemaGenerator } from '../..'
|
|
19
25
|
import {
|
|
20
26
|
CommonDBCreateOptions,
|
|
21
27
|
CommonDBOptions,
|
|
@@ -105,13 +111,20 @@ export class InMemoryDB implements CommonDB {
|
|
|
105
111
|
return Object.keys(this.data).filter(t => t.startsWith(this.cfg.tablesPrefix))
|
|
106
112
|
}
|
|
107
113
|
|
|
108
|
-
async getTableSchema<ROW extends ObjectWithId>(_table: string): Promise<
|
|
114
|
+
async getTableSchema<ROW extends ObjectWithId>(_table: string): Promise<JsonSchemaObject<ROW>> {
|
|
109
115
|
const table = this.cfg.tablesPrefix + _table
|
|
110
|
-
return
|
|
116
|
+
return {
|
|
117
|
+
...generateJsonSchemaFromData(Object.values(this.data[table] || {})),
|
|
118
|
+
$id: `${table}.schema.json`,
|
|
119
|
+
} as JsonSchemaObject<ROW>
|
|
111
120
|
}
|
|
112
121
|
|
|
113
|
-
async createTable(
|
|
114
|
-
|
|
122
|
+
async createTable(
|
|
123
|
+
_table: string,
|
|
124
|
+
_schema: JsonSchemaObject,
|
|
125
|
+
opt: CommonDBCreateOptions = {},
|
|
126
|
+
): Promise<void> {
|
|
127
|
+
const table = this.cfg.tablesPrefix + _table
|
|
115
128
|
if (opt.dropIfExists) {
|
|
116
129
|
this.data[table] = {}
|
|
117
130
|
} else {
|
package/src/base.common.db.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { JsonSchemaObject } from '@naturalcycles/js-lib'
|
|
1
2
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
2
3
|
import { Readable } from 'stream'
|
|
3
4
|
import { CommonDB } from './common.db'
|
|
4
5
|
import { CommonDBSaveOptions, ObjectWithId, RunQueryResult } from './db.model'
|
|
5
6
|
import { DBQuery } from './query/dbQuery'
|
|
6
|
-
import { CommonSchema } from './schema/common.schema'
|
|
7
7
|
import { DBTransaction } from './transaction/dbTransaction'
|
|
8
8
|
import { commitDBTransactionSimple } from './transaction/dbTransaction.util'
|
|
9
9
|
|
|
@@ -18,11 +18,17 @@ export class BaseCommonDB implements CommonDB {
|
|
|
18
18
|
return []
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
async getTableSchema<ROW>(table: string): Promise<
|
|
22
|
-
return {
|
|
21
|
+
async getTableSchema<ROW extends ObjectWithId>(table: string): Promise<JsonSchemaObject<ROW>> {
|
|
22
|
+
return {
|
|
23
|
+
$id: `${table}.schema.json`,
|
|
24
|
+
type: 'object',
|
|
25
|
+
additionalProperties: true,
|
|
26
|
+
properties: {} as any,
|
|
27
|
+
required: [],
|
|
28
|
+
}
|
|
23
29
|
}
|
|
24
30
|
|
|
25
|
-
async createTable(_schema:
|
|
31
|
+
async createTable(_table: string, _schema: JsonSchemaObject): Promise<void> {}
|
|
26
32
|
|
|
27
33
|
async deleteByIds(_table: string, _ids: string[]): Promise<number> {
|
|
28
34
|
return 0
|
package/src/common.db.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { JsonSchemaObject } from '@naturalcycles/js-lib'
|
|
1
2
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
2
3
|
import {
|
|
3
4
|
CommonDBCreateOptions,
|
|
@@ -8,7 +9,6 @@ import {
|
|
|
8
9
|
RunQueryResult,
|
|
9
10
|
} from './db.model'
|
|
10
11
|
import { DBQuery } from './query/dbQuery'
|
|
11
|
-
import { CommonSchema } from './schema/common.schema'
|
|
12
12
|
import { DBTransaction } from './transaction/dbTransaction'
|
|
13
13
|
|
|
14
14
|
export interface CommonDB {
|
|
@@ -25,13 +25,13 @@ export interface CommonDB {
|
|
|
25
25
|
*/
|
|
26
26
|
getTables(): Promise<string[]>
|
|
27
27
|
|
|
28
|
-
getTableSchema<ROW extends ObjectWithId>(table: string): Promise<
|
|
28
|
+
getTableSchema<ROW extends ObjectWithId>(table: string): Promise<JsonSchemaObject<ROW>>
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Will do like `create table ...` for mysql.
|
|
32
32
|
* Caution! dropIfExists defaults to false. If set to true - will actually DROP the table!
|
|
33
33
|
*/
|
|
34
|
-
createTable(schema:
|
|
34
|
+
createTable(table: string, schema: JsonSchemaObject, opt?: CommonDBCreateOptions): Promise<void>
|
|
35
35
|
|
|
36
36
|
// GET
|
|
37
37
|
/**
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { ErrorMode } from '@naturalcycles/js-lib'
|
|
2
2
|
import {
|
|
3
|
+
AjvSchema,
|
|
4
|
+
AjvValidationError,
|
|
3
5
|
JoiValidationError,
|
|
4
6
|
ObjectSchemaTyped,
|
|
5
7
|
TransformLogProgressOptions,
|
|
8
|
+
TransformMapOptions,
|
|
6
9
|
} from '@naturalcycles/nodejs-lib'
|
|
7
10
|
import { CommonDB } from '../common.db'
|
|
8
11
|
import {
|
|
@@ -16,11 +19,11 @@ import {
|
|
|
16
19
|
export type CommonDaoCreateIdHook<BM, DBM> = (obj: DBM | BM) => string
|
|
17
20
|
export type CommonDaoParseNaturalIdHook<DBM> = (id: string) => Partial<DBM>
|
|
18
21
|
export type CommonDaoBeforeCreateHook<BM> = (bm: Partial<BM>) => BM
|
|
19
|
-
export type CommonDaoBeforeDBMValidateHook<DBM> = (dbm: DBM) => DBM
|
|
20
|
-
export type CommonDaoBeforeDBMToBMHook<BM, DBM> = (dbm: DBM) => BM
|
|
21
|
-
export type CommonDaoBeforeBMToDBMHook<BM, DBM> = (bm: BM) => DBM
|
|
22
|
-
export type CommonDaoBeforeTMToBMHook<BM, TM> = (tm: TM) => BM
|
|
23
|
-
export type CommonDaoBeforeBMToTMHook<BM, TM> = (bm: BM) => TM
|
|
22
|
+
export type CommonDaoBeforeDBMValidateHook<DBM> = (dbm: Partial<DBM>) => Partial<DBM>
|
|
23
|
+
export type CommonDaoBeforeDBMToBMHook<BM, DBM> = (dbm: DBM) => Partial<BM>
|
|
24
|
+
export type CommonDaoBeforeBMToDBMHook<BM, DBM> = (bm: BM) => Partial<DBM>
|
|
25
|
+
export type CommonDaoBeforeTMToBMHook<BM, TM> = (tm: TM) => Partial<BM>
|
|
26
|
+
export type CommonDaoBeforeBMToTMHook<BM, TM> = (bm: BM) => Partial<TM>
|
|
24
27
|
export type CommonDaoAnonymizeHook<DBM> = (dbm: DBM) => DBM
|
|
25
28
|
|
|
26
29
|
interface CommonDaoHooks<BM, DBM, TM> {
|
|
@@ -33,6 +36,14 @@ interface CommonDaoHooks<BM, DBM, TM> {
|
|
|
33
36
|
beforeTMToBM: CommonDaoBeforeTMToBMHook<BM, TM>
|
|
34
37
|
beforeBMToTM: CommonDaoBeforeBMToTMHook<BM, TM>
|
|
35
38
|
anonymize: CommonDaoAnonymizeHook<DBM>
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* If hook is defined - allows to prevent or modify the error thrown.
|
|
42
|
+
* Return `false` to prevent throwing an error.
|
|
43
|
+
* Return original `err` to pass the error through (will be thrown in CommonDao).
|
|
44
|
+
* Return modified/new `Error` if needed.
|
|
45
|
+
*/
|
|
46
|
+
onValidationError: (err: JoiValidationError | AjvValidationError) => Error | false
|
|
36
47
|
}
|
|
37
48
|
|
|
38
49
|
export enum CommonDaoLogLevel {
|
|
@@ -48,9 +59,13 @@ export enum CommonDaoLogLevel {
|
|
|
48
59
|
export interface CommonDaoCfg<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId, TM> {
|
|
49
60
|
db: CommonDB
|
|
50
61
|
table: string
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Joi or AjvSchema are supported.
|
|
65
|
+
*/
|
|
66
|
+
dbmSchema?: ObjectSchemaTyped<DBM> | AjvSchema<DBM>
|
|
67
|
+
bmSchema?: ObjectSchemaTyped<BM> | AjvSchema<BM>
|
|
68
|
+
tmSchema?: ObjectSchemaTyped<TM> | AjvSchema<TM>
|
|
54
69
|
|
|
55
70
|
excludeFromIndexes?: string[]
|
|
56
71
|
|
|
@@ -70,22 +85,6 @@ export interface CommonDaoCfg<BM extends Partial<ObjectWithId>, DBM extends Obje
|
|
|
70
85
|
*/
|
|
71
86
|
logStarted?: boolean
|
|
72
87
|
|
|
73
|
-
/**
|
|
74
|
-
* @default false
|
|
75
|
-
*/
|
|
76
|
-
throwOnEntityValidationError?: boolean
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* @default to throwOnEntityValidationError setting
|
|
80
|
-
*/
|
|
81
|
-
throwOnDaoCreateObject?: boolean
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Called when validation error occurs.
|
|
85
|
-
* Called ONLY when error is NOT thrown (when throwOnEntityValidationError is off)
|
|
86
|
-
*/
|
|
87
|
-
onValidationError?: (err: JoiValidationError) => any
|
|
88
|
-
|
|
89
88
|
// Hooks are designed with inspiration from got/ky interface
|
|
90
89
|
hooks?: Partial<CommonDaoHooks<BM, DBM, TM>>
|
|
91
90
|
|
|
@@ -127,11 +126,6 @@ export interface CommonDaoOptions extends CommonDBOptions {
|
|
|
127
126
|
*/
|
|
128
127
|
raw?: boolean
|
|
129
128
|
|
|
130
|
-
/**
|
|
131
|
-
* @default inherited from CommonDaoCfg.throwOnEntityValidationError
|
|
132
|
-
*/
|
|
133
|
-
throwOnError?: boolean
|
|
134
|
-
|
|
135
129
|
/**
|
|
136
130
|
* @default false
|
|
137
131
|
*/
|
|
@@ -170,6 +164,7 @@ export interface CommonDaoSaveOptions extends CommonDaoOptions, CommonDBSaveOpti
|
|
|
170
164
|
|
|
171
165
|
export interface CommonDaoStreamForEachOptions<IN>
|
|
172
166
|
extends CommonDaoStreamOptions,
|
|
167
|
+
TransformMapOptions<IN, any>,
|
|
173
168
|
TransformLogProgressOptions<IN> {}
|
|
174
169
|
|
|
175
170
|
export interface CommonDaoStreamOptions extends CommonDaoOptions {
|
|
@@ -2,14 +2,18 @@ import {
|
|
|
2
2
|
AppError,
|
|
3
3
|
AsyncMapper,
|
|
4
4
|
ErrorMode,
|
|
5
|
+
JsonSchemaObject,
|
|
5
6
|
_filterNullishValues,
|
|
6
7
|
_passthroughPredicate,
|
|
7
8
|
_since,
|
|
8
9
|
_truncate,
|
|
9
10
|
} from '@naturalcycles/js-lib'
|
|
10
11
|
import {
|
|
12
|
+
AjvSchema,
|
|
13
|
+
AjvValidationError,
|
|
11
14
|
Debug,
|
|
12
15
|
getValidationResult,
|
|
16
|
+
JoiValidationError,
|
|
13
17
|
ObjectSchemaTyped,
|
|
14
18
|
ReadableTyped,
|
|
15
19
|
stringId,
|
|
@@ -24,7 +28,6 @@ import {
|
|
|
24
28
|
import { DBLibError } from '../cnst'
|
|
25
29
|
import { DBModelType, ObjectWithId, RunQueryResult, Saved } from '../db.model'
|
|
26
30
|
import { DBQuery, RunnableDBQuery } from '../query/dbQuery'
|
|
27
|
-
import { CommonSchema } from '../schema/common.schema'
|
|
28
31
|
import {
|
|
29
32
|
CommonDaoCfg,
|
|
30
33
|
CommonDaoCreateOptions,
|
|
@@ -66,6 +69,7 @@ export class CommonDao<
|
|
|
66
69
|
beforeTMToBM: tm => tm as any,
|
|
67
70
|
beforeBMToTM: bm => bm as any,
|
|
68
71
|
anonymize: dbm => dbm,
|
|
72
|
+
onValidationError: err => err,
|
|
69
73
|
...cfg.hooks,
|
|
70
74
|
},
|
|
71
75
|
}
|
|
@@ -73,10 +77,6 @@ export class CommonDao<
|
|
|
73
77
|
|
|
74
78
|
// CREATE
|
|
75
79
|
create(input: Partial<BM>, opt: CommonDaoOptions = {}): Saved<BM> {
|
|
76
|
-
if (opt.throwOnError === undefined) {
|
|
77
|
-
opt.throwOnError = this.cfg.throwOnDaoCreateObject
|
|
78
|
-
}
|
|
79
|
-
|
|
80
80
|
let bm = this.cfg.hooks!.beforeCreate!(input)
|
|
81
81
|
bm = this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)
|
|
82
82
|
|
|
@@ -804,7 +804,7 @@ export class CommonDao<
|
|
|
804
804
|
// tm = this.validateAndConvert(tm, this.cfg.tmSchema, DBModelType.TM, opt)
|
|
805
805
|
|
|
806
806
|
// TM > BM
|
|
807
|
-
const bm = this.cfg.hooks!.beforeTMToBM!(tm)
|
|
807
|
+
const bm = this.cfg.hooks!.beforeTMToBM!(tm) as BM
|
|
808
808
|
|
|
809
809
|
// Validate/convert BM
|
|
810
810
|
return this.validateAndConvert<BM>(bm, this.cfg.bmSchema, DBModelType.BM, opt)
|
|
@@ -818,11 +818,12 @@ export class CommonDao<
|
|
|
818
818
|
/**
|
|
819
819
|
* Returns *converted value*.
|
|
820
820
|
* Validates (unless `skipValidation=true` passed).
|
|
821
|
-
*
|
|
821
|
+
*
|
|
822
|
+
* Does NOT mutate the object.
|
|
822
823
|
*/
|
|
823
|
-
validateAndConvert<IN
|
|
824
|
+
validateAndConvert<IN, OUT = IN>(
|
|
824
825
|
obj: IN,
|
|
825
|
-
schema?: ObjectSchemaTyped<IN>,
|
|
826
|
+
schema?: ObjectSchemaTyped<IN> | AjvSchema<IN>,
|
|
826
827
|
modelType?: DBModelType,
|
|
827
828
|
opt: CommonDaoOptions = {},
|
|
828
829
|
): OUT {
|
|
@@ -844,32 +845,42 @@ export class CommonDao<
|
|
|
844
845
|
|
|
845
846
|
// This will Convert and Validate
|
|
846
847
|
const table = opt.table || this.cfg.table
|
|
847
|
-
const
|
|
848
|
+
const objectName = table + (modelType || '')
|
|
849
|
+
|
|
850
|
+
let error: JoiValidationError | AjvValidationError | undefined
|
|
851
|
+
let convertedValue: any
|
|
852
|
+
|
|
853
|
+
if (schema instanceof AjvSchema) {
|
|
854
|
+
// Ajv schema
|
|
855
|
+
convertedValue = obj // because Ajv mutates original object
|
|
856
|
+
|
|
857
|
+
error = schema.getValidationError(obj, {
|
|
858
|
+
objectName,
|
|
859
|
+
})
|
|
860
|
+
} else {
|
|
861
|
+
// Joi
|
|
862
|
+
const vr = getValidationResult<IN, OUT>(obj, schema, objectName)
|
|
863
|
+
error = vr.error
|
|
864
|
+
convertedValue = vr.value
|
|
865
|
+
}
|
|
848
866
|
|
|
849
867
|
// If we care about validation and there's an error
|
|
850
868
|
if (error && !opt.skipValidation) {
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
) {
|
|
855
|
-
throw error
|
|
856
|
-
} else {
|
|
857
|
-
// capture by Sentry and ignore the error
|
|
858
|
-
// It will still *convert* the value and return.
|
|
859
|
-
this.cfg.onValidationError?.(error)
|
|
860
|
-
}
|
|
869
|
+
const processedError = this.cfg.hooks!.onValidationError!(error)
|
|
870
|
+
|
|
871
|
+
if (processedError) throw processedError
|
|
861
872
|
}
|
|
862
873
|
|
|
863
|
-
return
|
|
874
|
+
return convertedValue
|
|
864
875
|
}
|
|
865
876
|
|
|
866
|
-
async getTableSchema(): Promise<
|
|
877
|
+
async getTableSchema(): Promise<JsonSchemaObject<DBM>> {
|
|
867
878
|
return await this.cfg.db.getTableSchema<DBM>(this.cfg.table)
|
|
868
879
|
}
|
|
869
880
|
|
|
870
|
-
async createTable(schema:
|
|
881
|
+
async createTable(schema: JsonSchemaObject<DBM>, opt?: CommonDaoCreateOptions): Promise<void> {
|
|
871
882
|
this.requireWriteAccess()
|
|
872
|
-
await this.cfg.db.createTable(schema, opt)
|
|
883
|
+
await this.cfg.db.createTable(this.cfg.table, schema as any, opt)
|
|
873
884
|
}
|
|
874
885
|
|
|
875
886
|
/**
|
package/src/index.ts
CHANGED
|
@@ -67,8 +67,6 @@ import {
|
|
|
67
67
|
DBQueryOrder,
|
|
68
68
|
RunnableDBQuery,
|
|
69
69
|
} from './query/dbQuery'
|
|
70
|
-
import { CommonSchema, CommonSchemaField, DATA_TYPE } from './schema/common.schema'
|
|
71
|
-
import { CommonSchemaGenerator, CommonSchemaGeneratorCfg } from './schema/commonSchemaGenerator'
|
|
72
70
|
import { DBTransaction, RunnableDBTransaction } from './transaction/dbTransaction'
|
|
73
71
|
import { commitDBTransactionSimple, mergeDBOperations } from './transaction/dbTransaction.util'
|
|
74
72
|
|
|
@@ -110,9 +108,6 @@ export type {
|
|
|
110
108
|
DBPipelineBackupOptions,
|
|
111
109
|
DBPipelineRestoreOptions,
|
|
112
110
|
DBPipelineCopyOptions,
|
|
113
|
-
CommonSchema,
|
|
114
|
-
CommonSchemaField,
|
|
115
|
-
CommonSchemaGeneratorCfg,
|
|
116
111
|
CommonDBAdapter,
|
|
117
112
|
DBOperation,
|
|
118
113
|
DBSaveBatchOperation,
|
|
@@ -143,7 +138,6 @@ export {
|
|
|
143
138
|
dbPipelineBackup,
|
|
144
139
|
dbPipelineRestore,
|
|
145
140
|
dbPipelineCopy,
|
|
146
|
-
DATA_TYPE,
|
|
147
141
|
getDB,
|
|
148
142
|
DBLibError,
|
|
149
143
|
BaseCommonDB,
|
|
@@ -151,6 +145,5 @@ export {
|
|
|
151
145
|
RunnableDBTransaction,
|
|
152
146
|
mergeDBOperations,
|
|
153
147
|
commitDBTransactionSimple,
|
|
154
|
-
CommonSchemaGenerator,
|
|
155
148
|
CommonKeyValueDao,
|
|
156
149
|
}
|
|
@@ -15,7 +15,6 @@ import * as fs from 'fs-extra'
|
|
|
15
15
|
import { createGzip, ZlibOptions } from 'zlib'
|
|
16
16
|
import { CommonDB } from '../common.db'
|
|
17
17
|
import { DBQuery } from '../index'
|
|
18
|
-
import { CommonSchemaGenerator } from '../schema/commonSchemaGenerator'
|
|
19
18
|
|
|
20
19
|
export interface DBPipelineBackupOptions extends TransformLogProgressOptions {
|
|
21
20
|
/**
|
|
@@ -102,7 +101,7 @@ export interface DBPipelineBackupOptions extends TransformLogProgressOptions {
|
|
|
102
101
|
* @default false
|
|
103
102
|
* If true - will use CommonSchemaGenerator to detect schema from input data.
|
|
104
103
|
*/
|
|
105
|
-
emitSchemaFromData?: boolean
|
|
104
|
+
// emitSchemaFromData?: boolean
|
|
106
105
|
|
|
107
106
|
/**
|
|
108
107
|
* @default false
|
|
@@ -140,7 +139,6 @@ export async function dbPipelineBackup(opt: DBPipelineBackupOptions): Promise<ND
|
|
|
140
139
|
transformMapOptions,
|
|
141
140
|
errorMode = ErrorMode.SUPPRESS,
|
|
142
141
|
emitSchemaFromDB = false,
|
|
143
|
-
emitSchemaFromData = false,
|
|
144
142
|
sortObjects = false,
|
|
145
143
|
} = opt
|
|
146
144
|
const strict = errorMode !== ErrorMode.SUPPRESS
|
|
@@ -193,10 +191,6 @@ export async function dbPipelineBackup(opt: DBPipelineBackupOptions): Promise<ND
|
|
|
193
191
|
console.log(`>> ${grey(schemaFilePath)} saved (generated from DB)`)
|
|
194
192
|
}
|
|
195
193
|
|
|
196
|
-
const schemaGen = emitSchemaFromData
|
|
197
|
-
? new CommonSchemaGenerator({ table, sortedFields: true })
|
|
198
|
-
: undefined
|
|
199
|
-
|
|
200
194
|
await _pipeline([
|
|
201
195
|
db.streamQuery(q),
|
|
202
196
|
transformLogProgress({
|
|
@@ -210,9 +204,8 @@ export async function dbPipelineBackup(opt: DBPipelineBackupOptions): Promise<ND
|
|
|
210
204
|
...transformMapOptions,
|
|
211
205
|
metric: table,
|
|
212
206
|
}),
|
|
213
|
-
transformTap(
|
|
207
|
+
transformTap(() => {
|
|
214
208
|
rows++
|
|
215
|
-
if (schemaGen) schemaGen.add(row)
|
|
216
209
|
}),
|
|
217
210
|
transformToNDJson({ strict, sortObjects }),
|
|
218
211
|
...(gzip ? [createGzip(zlibOptions)] : []), // optional gzip
|
|
@@ -229,12 +222,6 @@ export async function dbPipelineBackup(opt: DBPipelineBackupOptions): Promise<ND
|
|
|
229
222
|
|
|
230
223
|
console.log(`>> ${grey(filePath)}\n` + stats.toPretty())
|
|
231
224
|
|
|
232
|
-
if (schemaGen) {
|
|
233
|
-
const schema = schemaGen.generate()
|
|
234
|
-
await fs.writeJson(schemaFilePath, schema, { spaces: 2 })
|
|
235
|
-
console.log(`>> ${grey(schemaFilePath)} saved (generated from data)`)
|
|
236
|
-
}
|
|
237
|
-
|
|
238
225
|
statsPerTable[table] = stats
|
|
239
226
|
},
|
|
240
227
|
{ concurrency, errorMode },
|
|
@@ -179,7 +179,7 @@ export async function dbPipelineRestore(opt: DBPipelineRestoreOptions): Promise<
|
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
const schema = await fs.readJson(schemaFilePath)
|
|
182
|
-
await db.createTable(schema, { dropIfExists: true })
|
|
182
|
+
await db.createTable(table, schema, { dropIfExists: true })
|
|
183
183
|
})
|
|
184
184
|
}
|
|
185
185
|
|
package/src/testing/dbTest.ts
CHANGED
|
@@ -97,7 +97,7 @@ export function runCommonDBTest(
|
|
|
97
97
|
// CREATE TABLE, DROP
|
|
98
98
|
if (createTable) {
|
|
99
99
|
test('createTable, dropIfExists=true', async () => {
|
|
100
|
-
await db.createTable(getTestItemSchema(), { dropIfExists: true })
|
|
100
|
+
await db.createTable(TEST_TABLE, getTestItemSchema(), { dropIfExists: true })
|
|
101
101
|
})
|
|
102
102
|
}
|
|
103
103
|
|
|
@@ -41,8 +41,10 @@ export function runCommonKeyValueDBTest(db: CommonKeyValueDB): void {
|
|
|
41
41
|
|
|
42
42
|
test('streamIds limited', async () => {
|
|
43
43
|
const idsLimited = await readableToArray(db.streamIds(TEST_TABLE, 2))
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
// Order is non-deterministic, so, cannot compare values
|
|
45
|
+
// idsLimited.sort()
|
|
46
|
+
// expect(idsLimited).toEqual(testIds.slice(0, 2))
|
|
47
|
+
expect(idsLimited.length).toBe(2)
|
|
46
48
|
})
|
|
47
49
|
|
|
48
50
|
test('streamValues', async () => {
|
|
@@ -53,8 +55,9 @@ export function runCommonKeyValueDBTest(db: CommonKeyValueDB): void {
|
|
|
53
55
|
|
|
54
56
|
test('streamValues limited', async () => {
|
|
55
57
|
const valuesLimited = await readableToArray(db.streamValues(TEST_TABLE, 2))
|
|
56
|
-
valuesLimited.sort()
|
|
57
|
-
expect(valuesLimited).toEqual(testEntries.map(e => e[1]).slice(0, 2))
|
|
58
|
+
// valuesLimited.sort()
|
|
59
|
+
// expect(valuesLimited).toEqual(testEntries.map(e => e[1]).slice(0, 2))
|
|
60
|
+
expect(valuesLimited.length).toBe(2)
|
|
58
61
|
})
|
|
59
62
|
|
|
60
63
|
test('streamEntries', async () => {
|
|
@@ -65,8 +68,9 @@ export function runCommonKeyValueDBTest(db: CommonKeyValueDB): void {
|
|
|
65
68
|
|
|
66
69
|
test('streamEntries limited', async () => {
|
|
67
70
|
const entriesLimited = await readableToArray(db.streamEntries(TEST_TABLE, 2))
|
|
68
|
-
entriesLimited.sort()
|
|
69
|
-
expect(entriesLimited).toEqual(testEntries.slice(0, 2))
|
|
71
|
+
// entriesLimited.sort()
|
|
72
|
+
// expect(entriesLimited).toEqual(testEntries.slice(0, 2))
|
|
73
|
+
expect(entriesLimited.length).toBe(2)
|
|
70
74
|
})
|
|
71
75
|
|
|
72
76
|
test('deleteByIds should clear', async () => {
|