@naturalcycles/db-lib 10.7.0 → 10.9.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.
Files changed (44) hide show
  1. package/dist/adapter/file/file.db.js +2 -2
  2. package/dist/adapter/file/inMemory.persistence.plugin.js +1 -1
  3. package/dist/adapter/file/localFile.persistence.plugin.js +1 -1
  4. package/dist/commondao/common.dao.js +16 -13
  5. package/dist/commondao/common.dao.model.d.ts +10 -6
  6. package/dist/inmemory/inMemory.db.d.ts +1 -27
  7. package/dist/inmemory/inMemory.db.js +3 -49
  8. package/dist/inmemory/queryInMemory.js +1 -1
  9. package/dist/kv/commonKeyValueDao.js +2 -2
  10. package/dist/kv/commonKeyValueDaoMemoCache.js +1 -1
  11. package/dist/model.util.js +1 -1
  12. package/dist/pipeline/dbPipelineBackup.js +2 -2
  13. package/dist/pipeline/dbPipelineCopy.d.ts +1 -1
  14. package/dist/pipeline/dbPipelineCopy.js +3 -3
  15. package/dist/pipeline/dbPipelineRestore.d.ts +1 -1
  16. package/dist/pipeline/dbPipelineRestore.js +3 -3
  17. package/dist/query/dbQuery.js +1 -1
  18. package/dist/testing/commonDBTest.js +3 -3
  19. package/dist/testing/commonDaoTest.js +2 -2
  20. package/dist/testing/keyValueDBTest.js +1 -1
  21. package/dist/testing/keyValueDaoTest.js +1 -1
  22. package/dist/testing/test.model.js +1 -1
  23. package/dist/testing/timeSeriesTest.util.js +2 -1
  24. package/package.json +4 -3
  25. package/src/adapter/file/file.db.ts +2 -2
  26. package/src/adapter/file/inMemory.persistence.plugin.ts +1 -1
  27. package/src/adapter/file/localFile.persistence.plugin.ts +1 -1
  28. package/src/commondao/common.dao.model.ts +11 -7
  29. package/src/commondao/common.dao.ts +15 -16
  30. package/src/inmemory/inMemory.db.ts +4 -96
  31. package/src/inmemory/queryInMemory.ts +1 -1
  32. package/src/kv/commonKeyValueDao.ts +2 -2
  33. package/src/kv/commonKeyValueDaoMemoCache.ts +1 -1
  34. package/src/model.util.ts +1 -1
  35. package/src/pipeline/dbPipelineBackup.ts +2 -2
  36. package/src/pipeline/dbPipelineCopy.ts +3 -3
  37. package/src/pipeline/dbPipelineRestore.ts +3 -3
  38. package/src/query/dbQuery.ts +1 -1
  39. package/src/testing/commonDBTest.ts +3 -3
  40. package/src/testing/commonDaoTest.ts +2 -2
  41. package/src/testing/keyValueDBTest.ts +1 -1
  42. package/src/testing/keyValueDaoTest.ts +1 -1
  43. package/src/testing/test.model.ts +1 -1
  44. package/src/testing/timeSeriesTest.util.ts +2 -1
@@ -1,6 +1,6 @@
1
- import { _by, _sortBy } from '@naturalcycles/js-lib';
1
+ import { _by, _sortBy } from '@naturalcycles/js-lib/array';
2
2
  import { _since, localTime } from '@naturalcycles/js-lib/datetime';
3
- import { _assert } from '@naturalcycles/js-lib/error';
3
+ import { _assert } from '@naturalcycles/js-lib/error/assert.js';
4
4
  import { generateJsonSchemaFromData } from '@naturalcycles/js-lib/json-schema';
5
5
  import { _deepEquals, _filterUndefinedValues, _sortObjectDeep } from '@naturalcycles/js-lib/object';
6
6
  import { _stringMapValues, } from '@naturalcycles/js-lib/types';
@@ -1,4 +1,4 @@
1
- import { _by } from '@naturalcycles/js-lib';
1
+ import { _by } from '@naturalcycles/js-lib/array/array.util.js';
2
2
  /**
3
3
  * Mostly useful for testing.
4
4
  */
@@ -1,5 +1,5 @@
1
1
  import { Readable } from 'node:stream';
2
- import { pMap } from '@naturalcycles/js-lib/promise';
2
+ import { pMap } from '@naturalcycles/js-lib/promise/pMap.js';
3
3
  import { fs2 } from '@naturalcycles/nodejs-lib/fs2';
4
4
  import { _pipeline, createReadStreamAsNDJSON, createWriteStreamAsNDJSON, } from '@naturalcycles/nodejs-lib/stream';
5
5
  /**
@@ -1,9 +1,12 @@
1
- import { _isTruthy, _uniqBy } from '@naturalcycles/js-lib';
2
- import { _since, localTime } from '@naturalcycles/js-lib/datetime';
1
+ import { _isTruthy } from '@naturalcycles/js-lib';
2
+ import { _uniqBy } from '@naturalcycles/js-lib/array/array.util.js';
3
+ import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js';
4
+ import { _since } from '@naturalcycles/js-lib/datetime/time.util.js';
3
5
  import { _assert, AppError, ErrorMode } from '@naturalcycles/js-lib/error';
4
- import { _deepCopy, _deepJsonEquals, _filterUndefinedValues, _objectAssignExact, } from '@naturalcycles/js-lib/object';
5
- import { pMap } from '@naturalcycles/js-lib/promise';
6
- import { _truncate } from '@naturalcycles/js-lib/string';
6
+ import { _deepJsonEquals } from '@naturalcycles/js-lib/object/deepEquals.js';
7
+ import { _deepCopy, _filterUndefinedValues, _objectAssignExact, } from '@naturalcycles/js-lib/object/object.util.js';
8
+ import { pMap } from '@naturalcycles/js-lib/promise/pMap.js';
9
+ import { _truncate } from '@naturalcycles/js-lib/string/string.util.js';
7
10
  import { _passthroughPredicate, _typeCast, SKIP } from '@naturalcycles/js-lib/types';
8
11
  import { ZodType, zSafeValidate } from '@naturalcycles/js-lib/zod';
9
12
  import { stringId } from '@naturalcycles/nodejs-lib';
@@ -962,7 +965,14 @@ export class CommonDao {
962
965
  const objectName = table;
963
966
  let error;
964
967
  let convertedValue;
965
- if (schema instanceof ZodType) {
968
+ if (this.cfg.validateBM) {
969
+ const [err, value] = this.cfg.validateBM(obj, {
970
+ itemName: table,
971
+ });
972
+ error = err;
973
+ convertedValue = value;
974
+ }
975
+ else if (schema instanceof ZodType) {
966
976
  // Zod schema
967
977
  const vr = zSafeValidate(obj, schema);
968
978
  error = vr.error;
@@ -977,14 +987,7 @@ export class CommonDao {
977
987
  }
978
988
  else {
979
989
  // Joi
980
- const start = localTime.nowUnixMillis();
981
990
  const vr = getValidationResult(obj, schema, objectName);
982
- const tookMillis = localTime.nowUnixMillis() - start;
983
- this.cfg.onValidationTime?.({
984
- tookMillis,
985
- table,
986
- obj,
987
- });
988
991
  error = vr.error;
989
992
  convertedValue = vr.value;
990
993
  }
@@ -1,3 +1,4 @@
1
+ import type { ValidationFunction } from '@naturalcycles/js-lib';
1
2
  import type { ErrorMode } from '@naturalcycles/js-lib/error';
2
3
  import type { CommonLogger } from '@naturalcycles/js-lib/log';
3
4
  import type { BaseDBEntity, NumberOfMilliseconds, Promisable, UnixTimestamp } from '@naturalcycles/js-lib/types';
@@ -105,6 +106,15 @@ export interface CommonDaoCfg<BM extends BaseDBEntity, DBM extends BaseDBEntity
105
106
  * Joi, AjvSchema or ZodSchema is supported.
106
107
  */
107
108
  bmSchema?: ObjectSchema<BM> | AjvSchema<BM> | ZodType<BM>;
109
+ /**
110
+ * Experimental alternative to bmSchema.
111
+ * "Bring your own validation function".
112
+ * It removes the knowledge from CommonDao about the validation library used
113
+ * and abstracts it away.
114
+ *
115
+ * @experimental
116
+ */
117
+ validateBM?: ValidationFunction<BM, any>;
108
118
  excludeFromIndexes?: (keyof DBM)[];
109
119
  /**
110
120
  * Defaults to true.
@@ -116,12 +126,6 @@ export interface CommonDaoCfg<BM extends BaseDBEntity, DBM extends BaseDBEntity
116
126
  * If set to false - save (write) operations will skip validation (and conversion).
117
127
  */
118
128
  validateOnSave?: boolean;
119
- /**
120
- * The hook allows to get a callback, to instrument "validation time".
121
- *
122
- * @experimental
123
- */
124
- onValidationTime?: (data: OnValidationTimeData) => void;
125
129
  /**
126
130
  * Defaults to false.
127
131
  * Setting it to true will set saveMethod to `insert` for save/saveBatch, which will
@@ -1,7 +1,7 @@
1
1
  import { type JsonSchemaObject, type JsonSchemaRootObject } from '@naturalcycles/js-lib/json-schema';
2
2
  import type { CommonLogger } from '@naturalcycles/js-lib/log';
3
3
  import { type AnyObjectWithId, type ObjectWithId, type StringMap } from '@naturalcycles/js-lib/types';
4
- import { type ReadableTyped } from '@naturalcycles/nodejs-lib/stream';
4
+ import type { ReadableTyped } from '@naturalcycles/nodejs-lib/stream/stream.model.js';
5
5
  import type { CommonDB, CommonDBSupport } from '../commondb/common.db.js';
6
6
  import { CommonDBType } from '../commondb/common.db.js';
7
7
  import type { CommonDBCreateOptions, CommonDBOptions, CommonDBSaveOptions, CommonDBTransactionOptions, DBOperation, DBTransaction, DBTransactionFn, RunQueryResult } from '../db.model.js';
@@ -25,24 +25,6 @@ export interface InMemoryDBCfg {
25
25
  * Defaults to true.
26
26
  */
27
27
  forbidTransactionReadAfterWrite?: boolean;
28
- /**
29
- * @default false
30
- *
31
- * Set to true to enable disk persistence (!).
32
- */
33
- persistenceEnabled: boolean;
34
- /**
35
- * @default ./tmp/inmemorydb.ndjson.gz
36
- *
37
- * Will store one ndjson file per table.
38
- * Will only flush on demand (see .flushToDisk() and .restoreFromDisk() methods).
39
- * Even if persistence is enabled - nothing is flushed or restored automatically.
40
- */
41
- persistentStoragePath: string;
42
- /**
43
- * @default true
44
- */
45
- persistZip: boolean;
46
28
  /**
47
29
  * Defaults to `console`.
48
30
  */
@@ -78,14 +60,6 @@ export declare class InMemoryDB implements CommonDB {
78
60
  runInTransaction(fn: DBTransactionFn, opt?: CommonDBTransactionOptions): Promise<void>;
79
61
  createTransaction(opt?: CommonDBTransactionOptions): Promise<DBTransaction>;
80
62
  incrementBatch(table: string, prop: string, incrementMap: StringMap<number>, _opt?: CommonDBOptions): Promise<StringMap<number>>;
81
- /**
82
- * Flushes all tables (all namespaces) at once.
83
- */
84
- flushToDisk(): Promise<void>;
85
- /**
86
- * Restores all tables (all namespaces) at once.
87
- */
88
- restoreFromDisk(): Promise<void>;
89
63
  }
90
64
  export declare class InMemoryDBTransaction implements DBTransaction {
91
65
  private db;
@@ -1,14 +1,10 @@
1
1
  import { Readable } from 'node:stream';
2
- import { _by, _isEmptyObject } from '@naturalcycles/js-lib';
3
- import { _since, localTime } from '@naturalcycles/js-lib/datetime';
4
- import { _assert } from '@naturalcycles/js-lib/error';
2
+ import { _isEmptyObject } from '@naturalcycles/js-lib';
3
+ import { _assert } from '@naturalcycles/js-lib/error/assert.js';
5
4
  import { generateJsonSchemaFromData, } from '@naturalcycles/js-lib/json-schema';
6
5
  import { _deepCopy, _sortObjectDeep } from '@naturalcycles/js-lib/object';
7
- import { pMap } from '@naturalcycles/js-lib/promise';
8
6
  import { _stringMapEntries, _stringMapValues, } from '@naturalcycles/js-lib/types';
9
- import { dimGrey, yellow } from '@naturalcycles/nodejs-lib/colors';
10
- import { fs2 } from '@naturalcycles/nodejs-lib/fs2';
11
- import { _pipeline, bufferReviver, createReadStreamAsNDJSON, createWriteStreamAsNDJSON, } from '@naturalcycles/nodejs-lib/stream';
7
+ import { bufferReviver } from '@naturalcycles/nodejs-lib/stream/ndjson/transformJsonParse.js';
12
8
  import { commonDBFullSupport, CommonDBType } from '../commondb/common.db.js';
13
9
  import { queryInMemory } from './queryInMemory.js';
14
10
  export class InMemoryDB {
@@ -22,9 +18,6 @@ export class InMemoryDB {
22
18
  // defaults
23
19
  tablesPrefix: '',
24
20
  forbidTransactionReadAfterWrite: true,
25
- persistenceEnabled: false,
26
- persistZip: true,
27
- persistentStoragePath: './tmp/inmemorydb',
28
21
  logger: console,
29
22
  ...cfg,
30
23
  };
@@ -173,45 +166,6 @@ export class InMemoryDB {
173
166
  }
174
167
  return result;
175
168
  }
176
- /**
177
- * Flushes all tables (all namespaces) at once.
178
- */
179
- async flushToDisk() {
180
- _assert(this.cfg.persistenceEnabled, 'flushToDisk() called but persistenceEnabled=false');
181
- const { persistentStoragePath, persistZip } = this.cfg;
182
- const started = localTime.nowUnixMillis();
183
- await fs2.emptyDirAsync(persistentStoragePath);
184
- let tables = 0;
185
- // infinite concurrency for now
186
- await pMap(Object.keys(this.data), async (table) => {
187
- const rows = Object.values(this.data[table]);
188
- if (rows.length === 0)
189
- return; // 0 rows
190
- tables++;
191
- const fname = `${persistentStoragePath}/${table}.ndjson${persistZip ? '.gz' : ''}`;
192
- await _pipeline([Readable.from(rows), ...createWriteStreamAsNDJSON(fname)]);
193
- });
194
- this.cfg.logger.log(`flushToDisk took ${dimGrey(_since(started))} to save ${yellow(tables)} tables`);
195
- }
196
- /**
197
- * Restores all tables (all namespaces) at once.
198
- */
199
- async restoreFromDisk() {
200
- _assert(this.cfg.persistenceEnabled, 'restoreFromDisk() called but persistenceEnabled=false');
201
- const { persistentStoragePath } = this.cfg;
202
- const started = localTime.nowUnixMillis();
203
- await fs2.ensureDirAsync(persistentStoragePath);
204
- this.data = {}; // empty it in the beginning!
205
- const files = (await fs2.readdirAsync(persistentStoragePath)).filter(f => f.includes('.ndjson'));
206
- // infinite concurrency for now
207
- await pMap(files, async (file) => {
208
- const fname = `${persistentStoragePath}/${file}`;
209
- const table = file.split('.ndjson')[0];
210
- const rows = await createReadStreamAsNDJSON(fname).toArray();
211
- this.data[table] = _by(rows, r => r.id);
212
- });
213
- this.cfg.logger.log(`restoreFromDisk took ${dimGrey(_since(started))} to read ${yellow(files.length)} tables`);
214
- }
215
169
  }
216
170
  export class InMemoryDBTransaction {
217
171
  db;
@@ -1,4 +1,4 @@
1
- import { _get, _pick } from '@naturalcycles/js-lib/object';
1
+ import { _get, _pick } from '@naturalcycles/js-lib/object/object.util.js';
2
2
  const FILTER_FNS = {
3
3
  '==': (v, val) => v === val,
4
4
  '!=': (v, val) => v !== val,
@@ -1,5 +1,5 @@
1
- import { AppError } from '@naturalcycles/js-lib/error';
2
- import { pMap } from '@naturalcycles/js-lib/promise';
1
+ import { AppError } from '@naturalcycles/js-lib/error/error.util.js';
2
+ import { pMap } from '@naturalcycles/js-lib/promise/pMap.js';
3
3
  import { deflateString, inflateToString } from '@naturalcycles/nodejs-lib/zip';
4
4
  export const commonKeyValueDaoDeflatedJsonTransformer = {
5
5
  valueToBuffer: async (v) => await deflateString(JSON.stringify(v)),
@@ -1,4 +1,4 @@
1
- import { localTime } from '@naturalcycles/js-lib/datetime';
1
+ import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js';
2
2
  import { MISS } from '@naturalcycles/js-lib/types';
3
3
  /**
4
4
  * AsyncMemoCache implementation, backed by CommonKeyValueDao.
@@ -1,4 +1,4 @@
1
- import { localTime } from '@naturalcycles/js-lib/datetime';
1
+ import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js';
2
2
  import { stringId } from '@naturalcycles/nodejs-lib';
3
3
  export function createdUpdatedFields(existingObject) {
4
4
  const now = localTime.nowUnix();
@@ -1,6 +1,6 @@
1
- import { localTime } from '@naturalcycles/js-lib/datetime';
1
+ import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js';
2
2
  import { AppError, ErrorMode } from '@naturalcycles/js-lib/error';
3
- import { pMap } from '@naturalcycles/js-lib/promise';
3
+ import { pMap } from '@naturalcycles/js-lib/promise/pMap.js';
4
4
  import { _passthroughMapper } from '@naturalcycles/js-lib/types';
5
5
  import { boldWhite, dimWhite, grey, yellow } from '@naturalcycles/nodejs-lib/colors';
6
6
  import { fs2 } from '@naturalcycles/nodejs-lib/fs2';
@@ -1,4 +1,4 @@
1
- import { ErrorMode } from '@naturalcycles/js-lib/error';
1
+ import { ErrorMode } from '@naturalcycles/js-lib/error/errorMode.js';
2
2
  import type { AsyncMapper, UnixTimestamp } from '@naturalcycles/js-lib/types';
3
3
  import type { TransformLogProgressOptions, TransformMapOptions } from '@naturalcycles/nodejs-lib/stream';
4
4
  import { NDJsonStats } from '@naturalcycles/nodejs-lib/stream';
@@ -1,6 +1,6 @@
1
- import { localTime } from '@naturalcycles/js-lib/datetime';
2
- import { ErrorMode } from '@naturalcycles/js-lib/error';
3
- import { pMap } from '@naturalcycles/js-lib/promise';
1
+ import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js';
2
+ import { ErrorMode } from '@naturalcycles/js-lib/error/errorMode.js';
3
+ import { pMap } from '@naturalcycles/js-lib/promise/pMap.js';
4
4
  import { _passthroughMapper } from '@naturalcycles/js-lib/types';
5
5
  import { boldWhite, dimWhite, grey, yellow } from '@naturalcycles/nodejs-lib/colors';
6
6
  import { _pipeline, NDJsonStats, transformChunk, transformLogProgress, transformMap, transformTap, writableForEach, } from '@naturalcycles/nodejs-lib/stream';
@@ -1,4 +1,4 @@
1
- import { ErrorMode } from '@naturalcycles/js-lib/error';
1
+ import { ErrorMode } from '@naturalcycles/js-lib/error/errorMode.js';
2
2
  import type { AsyncMapper, UnixTimestamp } from '@naturalcycles/js-lib/types';
3
3
  import { type TransformLogProgressOptions, type TransformMapOptions } from '@naturalcycles/nodejs-lib/stream';
4
4
  import { NDJsonStats } from '@naturalcycles/nodejs-lib/stream';
@@ -1,8 +1,8 @@
1
1
  import { _hb } from '@naturalcycles/js-lib';
2
- import { localTime } from '@naturalcycles/js-lib/datetime';
3
- import { ErrorMode } from '@naturalcycles/js-lib/error';
2
+ import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js';
3
+ import { ErrorMode } from '@naturalcycles/js-lib/error/errorMode.js';
4
4
  import { _mapValues } from '@naturalcycles/js-lib/object';
5
- import { pMap } from '@naturalcycles/js-lib/promise';
5
+ import { pMap } from '@naturalcycles/js-lib/promise/pMap.js';
6
6
  import { _passthroughMapper } from '@naturalcycles/js-lib/types';
7
7
  import { boldWhite, dimWhite, grey, yellow } from '@naturalcycles/nodejs-lib/colors';
8
8
  import { fs2 } from '@naturalcycles/nodejs-lib/fs2';
@@ -1,4 +1,4 @@
1
- import { _truncate } from '@naturalcycles/js-lib/string';
1
+ import { _truncate } from '@naturalcycles/js-lib/string/string.util.js';
2
2
  import { _objectAssign } from '@naturalcycles/js-lib/types';
3
3
  export const dbQueryFilterOperatorValues = [
4
4
  '<',
@@ -1,7 +1,7 @@
1
- import { _sortBy } from '@naturalcycles/js-lib';
2
- import { localTime } from '@naturalcycles/js-lib/datetime';
1
+ import { _sortBy } from '@naturalcycles/js-lib/array/array.util.js';
2
+ import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js';
3
3
  import { _deepFreeze, _filterObject, _pick } from '@naturalcycles/js-lib/object';
4
- import { pMap } from '@naturalcycles/js-lib/promise';
4
+ import { pMap } from '@naturalcycles/js-lib/promise/pMap.js';
5
5
  import { CommonDBType } from '../commondb/common.db.js';
6
6
  import { DBQuery } from '../query/dbQuery.js';
7
7
  import { createTestItemDBM, createTestItemsDBM, TEST_TABLE, testItemBMJsonSchema, } from './test.model.js';
@@ -1,6 +1,6 @@
1
1
  import { Readable } from 'node:stream';
2
- import { _sortBy } from '@naturalcycles/js-lib';
3
- import { localTime } from '@naturalcycles/js-lib/datetime';
2
+ import { _sortBy } from '@naturalcycles/js-lib/array/array.util.js';
3
+ import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js';
4
4
  import { _deepCopy, _filterObject, _omit, _pick } from '@naturalcycles/js-lib/object';
5
5
  import { _pipeline } from '@naturalcycles/nodejs-lib/stream';
6
6
  import { CommonDao } from '../commondao/common.dao.js';
@@ -1,4 +1,4 @@
1
- import { _range, _sortBy } from '@naturalcycles/js-lib';
1
+ import { _range, _sortBy } from '@naturalcycles/js-lib/array';
2
2
  import { TEST_TABLE } from './test.model.js';
3
3
  const testIds = _range(1, 4).map(n => `id${n}`);
4
4
  const testEntries = testIds.map(id => [
@@ -1,4 +1,4 @@
1
- import { _sortBy } from '@naturalcycles/js-lib';
1
+ import { _sortBy } from '@naturalcycles/js-lib/array/array.util.js';
2
2
  import { CommonKeyValueDao } from '../kv/commonKeyValueDao.js';
3
3
  import { createTestItemsBM, TEST_TABLE } from './test.model.js';
4
4
  const testItems = createTestItemsBM(4);
@@ -1,4 +1,4 @@
1
- import { _range } from '@naturalcycles/js-lib';
1
+ import { _range } from '@naturalcycles/js-lib/array/range.js';
2
2
  import { jsonSchema } from '@naturalcycles/js-lib/json-schema';
3
3
  import { baseDBEntitySchema, binarySchema, booleanSchema, numberSchema, objectSchema, stringSchema, } from '@naturalcycles/nodejs-lib/joi';
4
4
  const MOCK_TS_2018_06_21 = 1529539200;
@@ -1,4 +1,5 @@
1
- import { _randomInt, _range } from '@naturalcycles/js-lib';
1
+ import { _randomInt } from '@naturalcycles/js-lib';
2
+ import { _range } from '@naturalcycles/js-lib/array/range.js';
2
3
  export function createTestTimeSeries(count = 10) {
3
4
  const ts = Date.now();
4
5
  return _range(1, count + 1).map(i => [ts - i * 60_000, _randomInt(10, 20)]);
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@naturalcycles/db-lib",
3
3
  "type": "module",
4
- "version": "10.7.0",
4
+ "version": "10.9.0",
5
5
  "dependencies": {
6
6
  "@naturalcycles/js-lib": "^15",
7
7
  "@naturalcycles/nodejs-lib": "^15"
8
8
  },
9
9
  "devDependencies": {
10
- "@naturalcycles/dev-lib": "19.8.0"
10
+ "@naturalcycles/dev-lib": "19.11.0"
11
11
  },
12
12
  "files": [
13
13
  "dist",
@@ -28,7 +28,8 @@
28
28
  "./dao": "./dist/commondao/index.js",
29
29
  "./cachedb": "./dist/adapter/cachedb/index.js",
30
30
  "./file": "./dist/adapter/file/index.js",
31
- "./inmemory": "./dist/inmemory/index.js"
31
+ "./inmemory": "./dist/inmemory/index.js",
32
+ "./inmemory/*": "./dist/inmemory/*.js"
32
33
  },
33
34
  "publishConfig": {
34
35
  "access": "public"
@@ -1,6 +1,6 @@
1
- import { _by, _sortBy } from '@naturalcycles/js-lib'
1
+ import { _by, _sortBy } from '@naturalcycles/js-lib/array'
2
2
  import { _since, localTime } from '@naturalcycles/js-lib/datetime'
3
- import { _assert } from '@naturalcycles/js-lib/error'
3
+ import { _assert } from '@naturalcycles/js-lib/error/assert.js'
4
4
  import type { JsonSchemaRootObject } from '@naturalcycles/js-lib/json-schema'
5
5
  import { generateJsonSchemaFromData } from '@naturalcycles/js-lib/json-schema'
6
6
  import { _deepEquals, _filterUndefinedValues, _sortObjectDeep } from '@naturalcycles/js-lib/object'
@@ -1,4 +1,4 @@
1
- import { _by } from '@naturalcycles/js-lib'
1
+ import { _by } from '@naturalcycles/js-lib/array/array.util.js'
2
2
  import type { ObjectWithId, StringMap } from '@naturalcycles/js-lib/types'
3
3
  import type { DBSaveBatchOperation } from '../../db.model.js'
4
4
  import type { FileDBPersistencePlugin } from './file.db.model.js'
@@ -1,5 +1,5 @@
1
1
  import { Readable } from 'node:stream'
2
- import { pMap } from '@naturalcycles/js-lib/promise'
2
+ import { pMap } from '@naturalcycles/js-lib/promise/pMap.js'
3
3
  import type { ObjectWithId } from '@naturalcycles/js-lib/types'
4
4
  import { fs2 } from '@naturalcycles/nodejs-lib/fs2'
5
5
  import {
@@ -1,3 +1,4 @@
1
+ import type { ValidationFunction } from '@naturalcycles/js-lib'
1
2
  import type { ErrorMode } from '@naturalcycles/js-lib/error'
2
3
  import type { CommonLogger } from '@naturalcycles/js-lib/log'
3
4
  import type {
@@ -132,6 +133,16 @@ export interface CommonDaoCfg<
132
133
  */
133
134
  bmSchema?: ObjectSchema<BM> | AjvSchema<BM> | ZodType<BM>
134
135
 
136
+ /**
137
+ * Experimental alternative to bmSchema.
138
+ * "Bring your own validation function".
139
+ * It removes the knowledge from CommonDao about the validation library used
140
+ * and abstracts it away.
141
+ *
142
+ * @experimental
143
+ */
144
+ validateBM?: ValidationFunction<BM, any>
145
+
135
146
  excludeFromIndexes?: (keyof DBM)[]
136
147
 
137
148
  /**
@@ -146,13 +157,6 @@ export interface CommonDaoCfg<
146
157
  */
147
158
  validateOnSave?: boolean
148
159
 
149
- /**
150
- * The hook allows to get a callback, to instrument "validation time".
151
- *
152
- * @experimental
153
- */
154
- onValidationTime?: (data: OnValidationTimeData) => void
155
-
156
160
  /**
157
161
  * Defaults to false.
158
162
  * Setting it to true will set saveMethod to `insert` for save/saveBatch, which will
@@ -1,17 +1,19 @@
1
1
  import type { Transform } from 'node:stream'
2
- import { _isTruthy, _uniqBy } from '@naturalcycles/js-lib'
3
- import { _since, localTime } from '@naturalcycles/js-lib/datetime'
2
+ import { _isTruthy } from '@naturalcycles/js-lib'
3
+ import { _uniqBy } from '@naturalcycles/js-lib/array/array.util.js'
4
+ import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js'
5
+ import { _since } from '@naturalcycles/js-lib/datetime/time.util.js'
4
6
  import { _assert, AppError, ErrorMode } from '@naturalcycles/js-lib/error'
5
7
  import type { JsonSchemaObject, JsonSchemaRootObject } from '@naturalcycles/js-lib/json-schema'
6
8
  import type { CommonLogger } from '@naturalcycles/js-lib/log'
9
+ import { _deepJsonEquals } from '@naturalcycles/js-lib/object/deepEquals.js'
7
10
  import {
8
11
  _deepCopy,
9
- _deepJsonEquals,
10
12
  _filterUndefinedValues,
11
13
  _objectAssignExact,
12
- } from '@naturalcycles/js-lib/object'
13
- import { pMap } from '@naturalcycles/js-lib/promise'
14
- import { _truncate } from '@naturalcycles/js-lib/string'
14
+ } from '@naturalcycles/js-lib/object/object.util.js'
15
+ import { pMap } from '@naturalcycles/js-lib/promise/pMap.js'
16
+ import { _truncate } from '@naturalcycles/js-lib/string/string.util.js'
15
17
  import type {
16
18
  AsyncIndexedMapper,
17
19
  BaseDBEntity,
@@ -1240,7 +1242,13 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM, I
1240
1242
  let error: JoiValidationError | AjvValidationError | ZodValidationError | undefined
1241
1243
  let convertedValue: any
1242
1244
 
1243
- if (schema instanceof ZodType) {
1245
+ if (this.cfg.validateBM) {
1246
+ const [err, value] = this.cfg.validateBM(obj as any as BM, {
1247
+ itemName: table,
1248
+ })
1249
+ error = err
1250
+ convertedValue = value
1251
+ } else if (schema instanceof ZodType) {
1244
1252
  // Zod schema
1245
1253
  const vr = zSafeValidate(obj as T, schema)
1246
1254
  error = vr.error
@@ -1254,16 +1262,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM, I
1254
1262
  })
1255
1263
  } else {
1256
1264
  // Joi
1257
- const start = localTime.nowUnixMillis()
1258
1265
  const vr = getValidationResult(obj, schema, objectName)
1259
- const tookMillis = localTime.nowUnixMillis() - start
1260
-
1261
- this.cfg.onValidationTime?.({
1262
- tookMillis,
1263
- table,
1264
- obj,
1265
- })
1266
-
1267
1266
  error = vr.error
1268
1267
  convertedValue = vr.value
1269
1268
  }
@@ -1,7 +1,6 @@
1
1
  import { Readable } from 'node:stream'
2
- import { _by, _isEmptyObject } from '@naturalcycles/js-lib'
3
- import { _since, localTime } from '@naturalcycles/js-lib/datetime'
4
- import { _assert } from '@naturalcycles/js-lib/error'
2
+ import { _isEmptyObject } from '@naturalcycles/js-lib'
3
+ import { _assert } from '@naturalcycles/js-lib/error/assert.js'
5
4
  import {
6
5
  generateJsonSchemaFromData,
7
6
  type JsonSchemaObject,
@@ -9,7 +8,6 @@ import {
9
8
  } from '@naturalcycles/js-lib/json-schema'
10
9
  import type { CommonLogger } from '@naturalcycles/js-lib/log'
11
10
  import { _deepCopy, _sortObjectDeep } from '@naturalcycles/js-lib/object'
12
- import { pMap } from '@naturalcycles/js-lib/promise'
13
11
  import {
14
12
  _stringMapEntries,
15
13
  _stringMapValues,
@@ -17,15 +15,8 @@ import {
17
15
  type ObjectWithId,
18
16
  type StringMap,
19
17
  } from '@naturalcycles/js-lib/types'
20
- import { dimGrey, yellow } from '@naturalcycles/nodejs-lib/colors'
21
- import { fs2 } from '@naturalcycles/nodejs-lib/fs2'
22
- import {
23
- _pipeline,
24
- bufferReviver,
25
- createReadStreamAsNDJSON,
26
- createWriteStreamAsNDJSON,
27
- type ReadableTyped,
28
- } from '@naturalcycles/nodejs-lib/stream'
18
+ import { bufferReviver } from '@naturalcycles/nodejs-lib/stream/ndjson/transformJsonParse.js'
19
+ import type { ReadableTyped } from '@naturalcycles/nodejs-lib/stream/stream.model.js'
29
20
  import type { CommonDB, CommonDBSupport } from '../commondb/common.db.js'
30
21
  import { commonDBFullSupport, CommonDBType } from '../commondb/common.db.js'
31
22
  import type {
@@ -62,27 +53,6 @@ export interface InMemoryDBCfg {
62
53
  */
63
54
  forbidTransactionReadAfterWrite?: boolean
64
55
 
65
- /**
66
- * @default false
67
- *
68
- * Set to true to enable disk persistence (!).
69
- */
70
- persistenceEnabled: boolean
71
-
72
- /**
73
- * @default ./tmp/inmemorydb.ndjson.gz
74
- *
75
- * Will store one ndjson file per table.
76
- * Will only flush on demand (see .flushToDisk() and .restoreFromDisk() methods).
77
- * Even if persistence is enabled - nothing is flushed or restored automatically.
78
- */
79
- persistentStoragePath: string
80
-
81
- /**
82
- * @default true
83
- */
84
- persistZip: boolean
85
-
86
56
  /**
87
57
  * Defaults to `console`.
88
58
  */
@@ -102,9 +72,6 @@ export class InMemoryDB implements CommonDB {
102
72
  // defaults
103
73
  tablesPrefix: '',
104
74
  forbidTransactionReadAfterWrite: true,
105
- persistenceEnabled: false,
106
- persistZip: true,
107
- persistentStoragePath: './tmp/inmemorydb',
108
75
  logger: console,
109
76
  ...cfg,
110
77
  }
@@ -310,65 +277,6 @@ export class InMemoryDB implements CommonDB {
310
277
 
311
278
  return result
312
279
  }
313
-
314
- /**
315
- * Flushes all tables (all namespaces) at once.
316
- */
317
- async flushToDisk(): Promise<void> {
318
- _assert(this.cfg.persistenceEnabled, 'flushToDisk() called but persistenceEnabled=false')
319
- const { persistentStoragePath, persistZip } = this.cfg
320
-
321
- const started = localTime.nowUnixMillis()
322
-
323
- await fs2.emptyDirAsync(persistentStoragePath)
324
-
325
- let tables = 0
326
-
327
- // infinite concurrency for now
328
- await pMap(Object.keys(this.data), async table => {
329
- const rows = Object.values(this.data[table]!)
330
- if (rows.length === 0) return // 0 rows
331
-
332
- tables++
333
- const fname = `${persistentStoragePath}/${table}.ndjson${persistZip ? '.gz' : ''}`
334
-
335
- await _pipeline([Readable.from(rows), ...createWriteStreamAsNDJSON(fname)])
336
- })
337
-
338
- this.cfg.logger!.log(
339
- `flushToDisk took ${dimGrey(_since(started))} to save ${yellow(tables)} tables`,
340
- )
341
- }
342
-
343
- /**
344
- * Restores all tables (all namespaces) at once.
345
- */
346
- async restoreFromDisk(): Promise<void> {
347
- _assert(this.cfg.persistenceEnabled, 'restoreFromDisk() called but persistenceEnabled=false')
348
- const { persistentStoragePath } = this.cfg
349
-
350
- const started = localTime.nowUnixMillis()
351
-
352
- await fs2.ensureDirAsync(persistentStoragePath)
353
-
354
- this.data = {} // empty it in the beginning!
355
-
356
- const files = (await fs2.readdirAsync(persistentStoragePath)).filter(f => f.includes('.ndjson'))
357
-
358
- // infinite concurrency for now
359
- await pMap(files, async file => {
360
- const fname = `${persistentStoragePath}/${file}`
361
- const table = file.split('.ndjson')[0]!
362
-
363
- const rows = await createReadStreamAsNDJSON(fname).toArray()
364
-
365
- this.data[table] = _by(rows, r => r.id)
366
- })
367
-
368
- this.cfg.logger!.log(
369
- `restoreFromDisk took ${dimGrey(_since(started))} to read ${yellow(files.length)} tables`,
370
- )
371
- }
372
280
  }
373
281
 
374
282
  export class InMemoryDBTransaction implements DBTransaction {
@@ -1,4 +1,4 @@
1
- import { _get, _pick } from '@naturalcycles/js-lib/object'
1
+ import { _get, _pick } from '@naturalcycles/js-lib/object/object.util.js'
2
2
  import type { ObjectWithId } from '@naturalcycles/js-lib/types'
3
3
  import type { DBQuery, DBQueryFilterOperator } from '../query/dbQuery.js'
4
4
 
@@ -1,6 +1,6 @@
1
- import { AppError } from '@naturalcycles/js-lib/error'
1
+ import { AppError } from '@naturalcycles/js-lib/error/error.util.js'
2
2
  import type { CommonLogger } from '@naturalcycles/js-lib/log'
3
- import { pMap } from '@naturalcycles/js-lib/promise'
3
+ import { pMap } from '@naturalcycles/js-lib/promise/pMap.js'
4
4
  import type { KeyValueTuple } from '@naturalcycles/js-lib/types'
5
5
  import type { ReadableTyped } from '@naturalcycles/nodejs-lib/stream'
6
6
  import { deflateString, inflateToString } from '@naturalcycles/nodejs-lib/zip'
@@ -1,4 +1,4 @@
1
- import { localTime } from '@naturalcycles/js-lib/datetime'
1
+ import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js'
2
2
  import type { AsyncMemoCache } from '@naturalcycles/js-lib/decorators'
3
3
  import type { NumberOfSeconds, UnixTimestamp } from '@naturalcycles/js-lib/types'
4
4
  import { MISS } from '@naturalcycles/js-lib/types'
package/src/model.util.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { localTime } from '@naturalcycles/js-lib/datetime'
1
+ import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js'
2
2
  import type { CreatedUpdated, CreatedUpdatedId } from '@naturalcycles/js-lib/types'
3
3
  import { stringId } from '@naturalcycles/nodejs-lib'
4
4
 
@@ -1,6 +1,6 @@
1
- import { localTime } from '@naturalcycles/js-lib/datetime'
1
+ import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js'
2
2
  import { AppError, ErrorMode } from '@naturalcycles/js-lib/error'
3
- import { pMap } from '@naturalcycles/js-lib/promise'
3
+ import { pMap } from '@naturalcycles/js-lib/promise/pMap.js'
4
4
  import type { AsyncMapper, StringMap, UnixTimestamp } from '@naturalcycles/js-lib/types'
5
5
  import { _passthroughMapper } from '@naturalcycles/js-lib/types'
6
6
  import { boldWhite, dimWhite, grey, yellow } from '@naturalcycles/nodejs-lib/colors'
@@ -1,6 +1,6 @@
1
- import { localTime } from '@naturalcycles/js-lib/datetime'
2
- import { ErrorMode } from '@naturalcycles/js-lib/error'
3
- import { pMap } from '@naturalcycles/js-lib/promise'
1
+ import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js'
2
+ import { ErrorMode } from '@naturalcycles/js-lib/error/errorMode.js'
3
+ import { pMap } from '@naturalcycles/js-lib/promise/pMap.js'
4
4
  import type { AsyncMapper, BaseDBEntity, UnixTimestamp } from '@naturalcycles/js-lib/types'
5
5
  import { _passthroughMapper } from '@naturalcycles/js-lib/types'
6
6
  import { boldWhite, dimWhite, grey, yellow } from '@naturalcycles/nodejs-lib/colors'
@@ -1,9 +1,9 @@
1
1
  import { _hb } from '@naturalcycles/js-lib'
2
- import { localTime } from '@naturalcycles/js-lib/datetime'
3
- import { ErrorMode } from '@naturalcycles/js-lib/error'
2
+ import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js'
3
+ import { ErrorMode } from '@naturalcycles/js-lib/error/errorMode.js'
4
4
  import type { JsonSchemaObject } from '@naturalcycles/js-lib/json-schema'
5
5
  import { _mapValues } from '@naturalcycles/js-lib/object'
6
- import { pMap } from '@naturalcycles/js-lib/promise'
6
+ import { pMap } from '@naturalcycles/js-lib/promise/pMap.js'
7
7
  import type { AsyncMapper, BaseDBEntity, UnixTimestamp } from '@naturalcycles/js-lib/types'
8
8
  import { _passthroughMapper } from '@naturalcycles/js-lib/types'
9
9
  import { boldWhite, dimWhite, grey, yellow } from '@naturalcycles/nodejs-lib/colors'
@@ -1,4 +1,4 @@
1
- import { _truncate } from '@naturalcycles/js-lib/string'
1
+ import { _truncate } from '@naturalcycles/js-lib/string/string.util.js'
2
2
  import type { AsyncIndexedMapper, BaseDBEntity, ObjectWithId } from '@naturalcycles/js-lib/types'
3
3
  import { _objectAssign } from '@naturalcycles/js-lib/types'
4
4
  import type { ReadableTyped } from '@naturalcycles/nodejs-lib/stream'
@@ -1,7 +1,7 @@
1
- import { _sortBy } from '@naturalcycles/js-lib'
2
- import { localTime } from '@naturalcycles/js-lib/datetime'
1
+ import { _sortBy } from '@naturalcycles/js-lib/array/array.util.js'
2
+ import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js'
3
3
  import { _deepFreeze, _filterObject, _pick } from '@naturalcycles/js-lib/object'
4
- import { pMap } from '@naturalcycles/js-lib/promise'
4
+ import { pMap } from '@naturalcycles/js-lib/promise/pMap.js'
5
5
  import type { CommonDB } from '../commondb/common.db.js'
6
6
  import { CommonDBType } from '../commondb/common.db.js'
7
7
  import { DBQuery } from '../query/dbQuery.js'
@@ -1,6 +1,6 @@
1
1
  import { Readable } from 'node:stream'
2
- import { _sortBy } from '@naturalcycles/js-lib'
3
- import { localTime } from '@naturalcycles/js-lib/datetime'
2
+ import { _sortBy } from '@naturalcycles/js-lib/array/array.util.js'
3
+ import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js'
4
4
  import { _deepCopy, _filterObject, _omit, _pick } from '@naturalcycles/js-lib/object'
5
5
  import { _pipeline } from '@naturalcycles/nodejs-lib/stream'
6
6
  import { CommonDao } from '../commondao/common.dao.js'
@@ -1,4 +1,4 @@
1
- import { _range, _sortBy } from '@naturalcycles/js-lib'
1
+ import { _range, _sortBy } from '@naturalcycles/js-lib/array'
2
2
  import type { KeyValueTuple } from '@naturalcycles/js-lib/types'
3
3
  import type { CommonKeyValueDB } from '../kv/commonKeyValueDB.js'
4
4
  import { TEST_TABLE } from './test.model.js'
@@ -1,4 +1,4 @@
1
- import { _sortBy } from '@naturalcycles/js-lib'
1
+ import { _sortBy } from '@naturalcycles/js-lib/array/array.util.js'
2
2
  import { CommonKeyValueDao } from '../kv/commonKeyValueDao.js'
3
3
  import type { CommonKeyValueDB, KeyValueDBTuple } from '../kv/commonKeyValueDB.js'
4
4
  import { createTestItemsBM, TEST_TABLE } from './test.model.js'
@@ -1,4 +1,4 @@
1
- import { _range } from '@naturalcycles/js-lib'
1
+ import { _range } from '@naturalcycles/js-lib/array/range.js'
2
2
  import type { JsonSchemaObject } from '@naturalcycles/js-lib/json-schema'
3
3
  import { jsonSchema } from '@naturalcycles/js-lib/json-schema'
4
4
  import type { BaseDBEntity, UnixTimestamp } from '@naturalcycles/js-lib/types'
@@ -1,4 +1,5 @@
1
- import { _randomInt, _range } from '@naturalcycles/js-lib'
1
+ import { _randomInt } from '@naturalcycles/js-lib'
2
+ import { _range } from '@naturalcycles/js-lib/array/range.js'
2
3
  import type { TimeSeriesDataPoint } from '../timeseries/timeSeries.model.js'
3
4
 
4
5
  export function createTestTimeSeries(count = 10): TimeSeriesDataPoint[] {