@microphi/json-db 2.3.0 → 2.6.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/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  > Small, fast and simple file based json-db super powered by [minisearch](https://github.com/lucaong/minisearch)
4
4
 
5
5
  ## Install
6
- With your preferend package manager install
6
+ With your preferred package manager install
7
7
  ```
8
8
  @microphi/json-db
9
9
  ```
@@ -51,3 +51,11 @@ const storage = new JsonStorage<User>('users', '.data', {
51
51
  The third object in the JsonStorage constructor is the `Options` object of minisearch which documentation can be found [here](https://lucaong.github.io/minisearch/classes/MiniSearch.MiniSearch.html#constructor)
52
52
 
53
53
  JsonStorage uses internally rxjs to queue the operations on the index and so to avoid too many read/write to occur simultaneously. By default `index.json` is written on disk after 3 second of inactivity. This can be changed using the fourth argument of the constructor specifying the time in milliseconds. Also a fifth argument can be passed to change the default rxjs scheduler (asapScheduler).
54
+
55
+ #### Minisearch
56
+ minisearch functionalities are available through the `search` field.
57
+ ```typescript
58
+ storage.search.search('batman', { fields: ['name'] });
59
+ ```
60
+ Remember documents are added/updated/removed to minisearch automatically.
61
+ For more info on minisearch please consult their [repo](https://github.com/lucaong/minisearch).
package/lib/index.d.ts CHANGED
@@ -1,3 +1,2 @@
1
- export * from './lib/list/list';
2
1
  export * from './lib/storage/json-storage';
3
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC"}
package/lib/index.js CHANGED
@@ -1,3 +1 @@
1
- export * from './lib/list/list';
2
1
  export * from './lib/storage/json-storage';
3
- //# sourceMappingURL=index.js.map
@@ -1,6 +1,6 @@
1
1
  import MiniSearch, { Options } from 'minisearch';
2
2
  import { Scheduler, Subject } from 'rxjs';
3
- import { List } from '../list/list';
3
+ import { List } from '@microphi/list';
4
4
  /**
5
5
  * Mark T as having auto trailing attributes
6
6
  *
@@ -1 +1 @@
1
- {"version":3,"file":"json-storage.d.ts","sourceRoot":"","sources":["../../../src/lib/storage/json-storage.ts"],"names":[],"mappings":"AACA,OAAO,UAAU,EAAE,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAGjD,OAAO,EAAE,SAAS,EAAE,OAAO,EAAgD,MAAM,MAAM,CAAC;AACxF,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEpC;;;;GAIG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAA;AAED,MAAM,MAAM,MAAM,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG;IACzC,EAAE,EAAE,MAAM,CAAC;CACZ,CAAA;AAED,qBAAa,WAAW,CAAC,CAAC,SAAS,MAAM;;IAwBrC,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,QAAQ;IAGhB,OAAO,CAAC,SAAS,CAAC;IAxBpB,YAAY,mBAA0B;IAEtC,KAAK;YAAgC,MAAM;cAAQ,MAAM;QAAgB;IAEzE,IAAI,MAAM,IAAI,UAAU,CAAC,CAAC,CAAC,CAM1B;IAED,IAAI,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAE9B;IAED,OAAO,CAAC,OAAO,CAAiB;gBAItB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EACxB,kBAAkB,CAAC,EAAE,OAAO,EAC5B,QAAQ,CAAC,EAAE,MAAM,EACT,SAAS,CAAC,uBAAW;IAgEzB,SAAS;IAMf,GAAG,CAAC,EAAE,EAAE,MAAM;IAIR,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;IA+B7B,MAAM,CAAC,GAAG,GAAG,EAAE,MAAM,EAAE;IAqC7B,QAAQ;IAIR,SAAS;IAqBT,MAAM;YAMQ,WAAW;IAuBzB,OAAO,CAAC,SAAS;IAIX,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAC,SAAS,CAAC;YAsB7B,QAAQ;YAKR,OAAO;CAKtB"}
1
+ {"version":3,"file":"json-storage.d.ts","sourceRoot":"","sources":["../../../src/lib/storage/json-storage.ts"],"names":[],"mappings":"AACA,OAAO,UAAU,EAAE,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAGjD,OAAO,EAAE,SAAS,EAAE,OAAO,EAAgD,MAAM,MAAM,CAAC;AACxF,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAEtC;;;;GAIG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAA;AAED,MAAM,MAAM,MAAM,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG;IACzC,EAAE,EAAE,MAAM,CAAC;CACZ,CAAA;AAED,qBAAa,WAAW,CAAC,CAAC,SAAS,MAAM;;IAwBrC,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,SAAS,CAAC;IA1BpB,YAAY,mBAA0B;IAEtC,KAAK;YAAgC,MAAM;cAAQ,MAAM;QAAgB;IAEzE,IAAI,MAAM,IAAI,UAAU,CAAC,CAAC,CAAC,CAM1B;IAED,IAAI,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAE9B;IAED,OAAO,CAAC,OAAO,CAAiB;gBAItB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAExB,kBAAkB,CAAC,EAAE,OAAO,EAE5B,QAAQ,CAAC,EAAE,MAAM,EACT,SAAS,CAAC,uBAAW;IAgEzB,SAAS;IAMf,GAAG,CAAC,EAAE,EAAE,MAAM;IAIR,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;IA+B7B,MAAM,CAAC,GAAG,GAAG,EAAE,MAAM,EAAE;IAqC7B,QAAQ;IAIR,SAAS;IAqBT,MAAM;YAMQ,WAAW;IAuBzB,OAAO,CAAC,SAAS;IAIX,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAC,SAAS,CAAC;YAsB7B,QAAQ;YAKR,OAAO;CAKtB"}
@@ -5,7 +5,7 @@ import MiniSearch from 'minisearch';
5
5
  import { close, exists, existsSync, mkdir, openSync, readFileSync, rmSync, unlink, writeFileSync } from 'node:fs';
6
6
  import { dirname, join } from 'node:path';
7
7
  import { Subject, asapScheduler, debounceTime, from, switchMap } from 'rxjs';
8
- import { List } from '../list/list';
8
+ import { List } from '@microphi/list';
9
9
  export class JsonStorage {
10
10
  get search() {
11
11
  if (!this._search) {
@@ -16,7 +16,11 @@ export class JsonStorage {
16
16
  set search(value) {
17
17
  this._search = value;
18
18
  }
19
- constructor(entity, basePath, searchIndexOptions, debounce, scheduler) {
19
+ constructor(entity, basePath,
20
+ // minisearch index options
21
+ searchIndexOptions,
22
+ // Debounce time in ms
23
+ debounce, scheduler) {
20
24
  this.entity = entity;
21
25
  this.basePath = basePath;
22
26
  this.scheduler = scheduler;
@@ -194,4 +198,3 @@ export class JsonStorage {
194
198
  }
195
199
  }
196
200
  _JsonStorage_l = new WeakMap();
197
- //# sourceMappingURL=json-storage.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microphi/json-db",
3
- "version": "2.3.0",
3
+ "version": "2.6.0",
4
4
  "description": "Small, fast and simple file based json-db",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
@@ -29,7 +29,7 @@
29
29
  "lint": "eslint ./src"
30
30
  },
31
31
  "dependencies": {
32
- "@microphi/debug": "^2.3.0"
32
+ "@microphi/debug": "^2.6.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@babel/plugin-transform-modules-commonjs": "^7.23.3",
@@ -39,8 +39,9 @@
39
39
  "utility-types": "^3.10.0"
40
40
  },
41
41
  "peerDependencies": {
42
+ "@microphi/list": "^2.3.0",
42
43
  "minisearch": "^6.3.0",
43
44
  "rxjs": "~7.8.0"
44
45
  },
45
- "gitHead": "6b2df1f7209ccda9b934bbdbcf71f59acc383380"
46
+ "gitHead": "6239637f38d555081da1647b962184616010146e"
46
47
  }
package/lib/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC","sourcesContent":["export * from './lib/list/list';\nexport * from './lib/storage/json-storage';\n"]}
@@ -1,28 +0,0 @@
1
- import { Subject } from 'rxjs';
2
- import { $Keys, FunctionKeys } from 'utility-types';
3
- export interface Operation {
4
- op: FunctionKeys<List<any>>;
5
- payload?: unknown;
6
- timestamp: Date;
7
- }
8
- export declare class List<EntityType extends object> implements Iterable<EntityType> {
9
- private IDField;
10
- operations$: Subject<Operation>;
11
- readonly entities: Map<string, EntityType>;
12
- /**
13
- * maps entities position from the original array to their ids
14
- */
15
- private readonly ids;
16
- get size(): number;
17
- has(id: string): boolean;
18
- get(id: string): EntityType | undefined;
19
- private getId;
20
- constructor(IDField: $Keys<EntityType>, entities?: EntityType[]);
21
- [Symbol.iterator](): IterableIterator<EntityType>;
22
- upsert(...entities: EntityType[]): void;
23
- prepend(...entities: EntityType[]): void;
24
- clear(): void;
25
- delete(...entities: EntityType[]): void;
26
- append(...entities: EntityType[]): void;
27
- }
28
- //# sourceMappingURL=list.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/lib/list/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGpD,MAAM,WAAW,SAAS;IAExB,EAAE,EAAE,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,qBAAa,IAAI,CAAC,UAAU,SAAS,MAAM,CAAE,YAAW,QAAQ,CAAC,UAAU,CAAC;IAgC9D,OAAO,CAAC,OAAO;IA9BpB,WAAW,qBAA4B;IAE9C,SAAgB,QAAQ,0BAAiC;IAEzD;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAgB;IAEpC,IAAW,IAAI,WAOd;IAEM,GAAG,CAAC,EAAE,EAAE,MAAM;IAId,GAAG,CAAC,EAAE,EAAE,MAAM;IAIrB,OAAO,CAAC,KAAK;gBAIO,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,EAAE,QAAQ,GAAE,UAAU,EAAO;IAW1E,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,UAAU,CAAC;IAa3C,MAAM,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE;IAehC,OAAO,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE;IAgBjC,KAAK;IAQL,MAAM,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE;IAehC,MAAM,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE;CAgBxC"}
@@ -1,94 +0,0 @@
1
- import { Subject } from 'rxjs';
2
- export class List {
3
- get size() {
4
- if (this.ids.length !== this.entities.size) {
5
- throw new Error(`Size Mismatch ${this.ids.length} !== ${this.entities.size}`);
6
- }
7
- return this.entities.size;
8
- }
9
- has(id) {
10
- return this.entities.has(id);
11
- }
12
- get(id) {
13
- return this.entities.get(id);
14
- }
15
- getId(entity) {
16
- return entity[this.IDField];
17
- }
18
- constructor(IDField, entities = []) {
19
- this.IDField = IDField;
20
- this.operations$ = new Subject();
21
- this.entities = new Map();
22
- /**
23
- * maps entities position from the original array to their ids
24
- */
25
- this.ids = [];
26
- this.ids = entities.map((e) => this.getId(e));
27
- entities
28
- .forEach((item) => {
29
- const id = this.getId(item);
30
- this.entities.set(id, item);
31
- });
32
- }
33
- *[Symbol.iterator]() {
34
- for (const idx in this.ids) {
35
- const id = this.ids[idx];
36
- const entity = this.entities.get(id);
37
- if (entity) {
38
- yield entity;
39
- }
40
- else {
41
- throw new Error(`Cannot get entity with id ${id}`);
42
- }
43
- }
44
- }
45
- upsert(...entities) {
46
- entities.forEach((e) => {
47
- const id = this.getId(e);
48
- if (!this.entities.has(id)) {
49
- this.ids.push(id);
50
- }
51
- this.entities.set(id, e);
52
- });
53
- this.operations$.next({ op: 'upsert', payload: entities, timestamp: new Date() });
54
- }
55
- prepend(...entities) {
56
- entities.reverse().forEach((e) => {
57
- const id = this.getId(e);
58
- if (this.entities.has(id)) {
59
- this.delete(e);
60
- }
61
- this.ids.unshift(id);
62
- this.entities.set(id, e);
63
- });
64
- this.operations$.next({ op: 'prepend', payload: entities, timestamp: new Date() });
65
- }
66
- clear() {
67
- this.ids.length = 0;
68
- this.entities.clear();
69
- this.operations$.next({ op: 'clear', timestamp: new Date() });
70
- }
71
- delete(...entities) {
72
- entities.forEach((e) => {
73
- const id = this.getId(e);
74
- const indexOfId = this.ids.findIndex((_id) => _id === id);
75
- if (indexOfId >= 0) {
76
- this.ids.splice(indexOfId, 1);
77
- this.entities.delete(id);
78
- }
79
- });
80
- this.operations$.next({ op: 'delete', payload: entities, timestamp: new Date() });
81
- }
82
- append(...entities) {
83
- entities.forEach((e) => {
84
- const id = this.getId(e);
85
- if (this.entities.has(id)) {
86
- this.delete(e);
87
- }
88
- this.ids.push(id);
89
- this.entities.set(id, e);
90
- });
91
- this.operations$.next({ op: 'append', payload: entities, timestamp: new Date() });
92
- }
93
- }
94
- //# sourceMappingURL=list.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/lib/list/list.ts"],"names":[],"mappings":"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","sourcesContent":["import { Subject } from 'rxjs';\nimport { $Keys, FunctionKeys } from 'utility-types';\n\n\nexport interface Operation {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n op: FunctionKeys<List<any>>;\n payload?: unknown;\n timestamp: Date;\n}\n\nexport class List<EntityType extends object> implements Iterable<EntityType> {\n\n public operations$ = new Subject<Operation>();\n\n public readonly entities = new Map<string, EntityType>();\n\n /**\n * maps entities position from the original array to their ids\n */\n private readonly ids: string[] = [];\n\n public get size() {\n if (this.ids.length !== this.entities.size) {\n\n throw new Error(`Size Mismatch ${this.ids.length} !== ${this.entities.size}`);\n }\n\n return this.entities.size;\n }\n\n public has(id: string) {\n return this.entities.has(id);\n }\n\n public get(id: string) {\n return this.entities.get(id);\n }\n\n private getId(entity: EntityType): string {\n return entity[this.IDField] as string;\n }\n\n constructor(private IDField: $Keys<EntityType>, entities: EntityType[] = []) {\n\n this.ids = entities.map((e) => this.getId(e));\n\n entities\n .forEach((item) => {\n const id = this.getId(item);\n this.entities.set(id, item);\n });\n }\n\n *[Symbol.iterator](): IterableIterator<EntityType> {\n for (const idx in this.ids) {\n const id = this.ids[idx];\n\n const entity = this.entities.get(id);\n if (entity) {\n yield entity;\n } else {\n throw new Error(`Cannot get entity with id ${id}`);\n }\n }\n }\n\n public upsert(...entities: EntityType[]) {\n entities.forEach((e) => {\n const id = this.getId(e);\n\n if (!this.entities.has(id)) {\n this.ids.push(id);\n }\n\n this.entities.set(id, e);\n\n });\n\n this.operations$.next({ op: 'upsert', payload: entities, timestamp: new Date() });\n }\n\n public prepend(...entities: EntityType[]) {\n entities.reverse().forEach((e) => {\n const id = this.getId(e);\n\n if (this.entities.has(id)) {\n this.delete(e);\n }\n\n this.ids.unshift(id);\n\n this.entities.set(id, e);\n\n });\n this.operations$.next({ op: 'prepend', payload: entities, timestamp: new Date() });\n }\n\n public clear() {\n\n this.ids.length = 0;\n this.entities.clear();\n this.operations$.next({ op: 'clear', timestamp: new Date() });\n\n }\n\n public delete(...entities: EntityType[]) {\n\n entities.forEach((e) => {\n const id = this.getId(e);\n const indexOfId = this.ids.findIndex((_id) => _id === id);\n\n if (indexOfId >= 0) {\n this.ids.splice(indexOfId, 1);\n this.entities.delete(id);\n }\n });\n\n this.operations$.next({ op: 'delete', payload: entities, timestamp: new Date() });\n }\n\n public append(...entities: EntityType[]) {\n entities.forEach((e) => {\n const id = this.getId(e);\n\n if (this.entities.has(id)) {\n this.delete(e);\n }\n\n this.ids.push(id);\n this.entities.set(id, e);\n });\n\n this.operations$.next({ op: 'append', payload: entities, timestamp: new Date() });\n }\n\n\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"json-storage.js","sourceRoot":"","sources":["../../../src/lib/storage/json-storage.ts"],"names":[],"mappings":"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","sourcesContent":["import { getDebugger } from '@microphi/debug';\nimport MiniSearch, { Options } from 'minisearch';\nimport { close, exists, existsSync, mkdir, openSync, readFileSync, rmSync, unlink, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { Scheduler, Subject, asapScheduler, debounceTime, from, switchMap } from 'rxjs';\nimport { List } from '../list/list';\n\n/**\n * Mark T as having auto trailing attributes\n *\n * `modified` and `created` iso string date;\n */\nexport type withAutoTrail<T> = T & {\n modified?: string;\n created?: string;\n}\n\nexport type withId<T extends object> = T & {\n id: string;\n}\n\nexport class JsonStorage<T extends object> {\n\n #l = getDebugger(`JsonStorage:${this.entity}`);\n\n syncPending$ = new Subject<boolean>();\n\n index = new List<withAutoTrail<{ id: string; path: string; }>>('id', []);\n\n get search(): MiniSearch<T> {\n if (!this._search) {\n throw Error(`Need to enable search by passing Minisearch Options to constructor. ${this.entity}`);\n }\n\n return this._search;\n }\n\n set search(value: MiniSearch<T>) {\n this._search = value;\n }\n\n private _search!: MiniSearch<T>;\n\n\n constructor(\n private entity: string,\n private basePath: string,\n searchIndexOptions?: Options,\n debounce?: number,\n private scheduler?: Scheduler,\n ) {\n\n this.index.operations$.pipe(\n debounceTime(debounce || 3_000, this.scheduler || asapScheduler),\n switchMap(() => {\n return from(this.saveIndex());\n })\n ).subscribe(() => {\n this.#l(`index has been quiet for ${debounce}ms. Updated`);\n });\n\n this.#l('creating service');\n\n if (searchIndexOptions) {\n this._search = new MiniSearch(searchIndexOptions);\n }\n\n this.getIndex().then((data) => {\n\n this.index.upsert(...data);\n\n this.#l(`loaded index for ${data.length} items`);\n this.#l('getting documents');\n\n const documents = [...this.index].map(({ id }) => {\n return this.get(id);\n });\n this.#l(`got ${documents.length} documents`);\n\n if (searchIndexOptions) {\n this.#l('reading files to generate search index');\n Promise.all(documents).then((actualDocs) => {\n\n this.#l('rebuilding search index with', actualDocs.length);\n\n actualDocs.forEach((doc) => {\n\n try {\n\n if (doc && doc['id']) {\n // this.l(`adding document with id ${doc['id']}`);\n\n this._search.add(doc);\n }\n\n } catch (err) {\n console.error('Error while loading entity into search index');\n this.#l(doc);\n // console.error(actualDocs);\n console.error(err);\n }\n\n });\n\n this.#l('search index rebuilt');\n this.#l(`handling ${this._search.documentCount} documents for free search`);\n\n });\n }\n });\n\n }\n\n async saveIndex() {\n const path = await this.storageFile('index');\n writeFileSync(path, JSON.stringify([...this.index]));\n return Promise.resolve('ok');\n }\n\n has(id: string) {\n return this.index.has(id);\n }\n\n async upsert(...docs: (withId<T>)[]) {\n\n for (const {id, ...doc} of docs) {\n const timestamp = new Date().toISOString();\n const updateTime = this.index.has(id) ? {\n modified: timestamp,\n } : {\n modified: timestamp,\n created: timestamp,\n };\n\n this.index.upsert({\n id: id,\n path: await this.storageFile(id),\n ...updateTime\n });\n\n await this.setItem(id, doc as T);\n\n if (this._search) {\n if (this._search.has(id)) {\n this._search.replace({id, ...doc} as T);\n } else {\n this._search.add({id, ...doc} as T);\n }\n }\n }\n\n return Promise.resolve();\n }\n\n async remove(...ids: string[]) {\n return new Promise((resolve, reject) => {\n\n for (const id of ids) {\n\n const entry = this.index.get(id);\n\n if (!entry) {\n resolve('ok');\n }\n\n this.get(id).then((doc) => {\n\n if (entry) {\n\n // remove index and search entry\n this.index.delete(entry);\n\n if (doc) {\n this._search?.remove(doc);\n }\n\n // finally remove json file\n unlink(entry.path, (err) => {\n if (err) reject(err);\n\n resolve('ok');\n });\n }\n\n\n });\n }\n\n });\n }\n\n getCount() {\n return this.index.size;\n }\n\n deleteAll() {\n this.index.clear();\n\n if (this._search) {\n this._search.removeAll();\n }\n\n return new Promise((resolve) => {\n exists(`${this.basePath}/${this.entity}`, (exists) => {\n if (exists) {\n\n rmSync(`${this.basePath}/${this.entity}`, { recursive: true });\n\n }\n\n resolve('ok');\n\n });\n });\n }\n\n getAll() {\n const items$ = [...this.index].map(({ id }) => this.get(id));\n\n return Promise.all(items$);\n }\n\n private async storageFile(key: string): Promise<string> {\n const path = this.buildPath(key);\n const folder = dirname(path);\n\n if (existsSync(path)) {\n return Promise.resolve(path);\n }\n\n return new Promise((resolve, reject) => {\n mkdir(folder, { recursive: true }, (err) => {\n if (err) reject(err);\n\n const fd = openSync(path, 'w');\n close(fd, (err) => {\n if (err) reject(err);\n\n resolve(path);\n });\n\n });\n });\n }\n\n private buildPath(id: string) {\n return join(this.basePath, this.entity, `${id}.json`);\n }\n\n async get(id: string): Promise<T|undefined> {\n const path = await this.storageFile(id);\n const data = readFileSync(path, {encoding: 'utf8'});\n let entity: T;\n\n try {\n\n entity = JSON.parse(data);\n\n return entity;\n } catch (e) {\n // console.log(e);\n this.#l(`error while trying to load data for item with id ${id}`);\n this.#l('item does not exists');\n this.#l('clearing index');\n this.index.delete({id, path});\n }\n\n return Promise.resolve(undefined);\n }\n\n\n private async getIndex(): Promise<{id: string; path: string;}[]> {\n const index = readFileSync(await this.storageFile('index'), {encoding: 'utf8'});\n return JSON.parse(index || '[]');\n }\n\n private async setItem(id: string, doc: T) {\n writeFileSync(join(this.basePath, this.entity, `${id}.json`), JSON.stringify({id, ...doc}));\n // this.l('wrote doc to disk', id, doc);\n return Promise.resolve('ok');\n }\n}\n"]}