@xyo-network/diviner-payload-indexeddb 2.87.0-rc.2 → 2.87.0-rc.4

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.
@@ -5,25 +5,19 @@ import { Payload } from '@xyo-network/payload-model';
5
5
  import { IndexedDbPayloadDivinerParams } from './Params';
6
6
  export declare class IndexedDbPayloadDiviner<TParams extends IndexedDbPayloadDivinerParams = IndexedDbPayloadDivinerParams, TIn extends PayloadDivinerQueryPayload = PayloadDivinerQueryPayload, TOut extends Payload = Payload, TEventData extends DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut> = DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut>> extends PayloadDiviner<TParams, TIn, TOut, TEventData> {
7
7
  static configSchemas: string[];
8
- static defaultDbName: string;
9
- static defaultDbVersion: number;
10
- static defaultStoreName: string;
11
8
  private _db;
12
9
  /**
13
- * The database name. If not supplied via config it defaults to
14
- * `archivist`. This behavior biases towards a single, isolated
15
- * DB per archivist which seems to make the most sense for 99% of
16
- * use cases.
10
+ * The database name. If not supplied via config, it defaults
11
+ * to the archivist's name and if archivist's name is not supplied,
12
+ * it defaults to `archivist`. This behavior
13
+ * biases towards a single, isolated DB per archivist which seems to
14
+ * make the most sense for 99% of use cases.
17
15
  */
18
16
  get dbName(): string;
19
17
  /**
20
- * The database version. If not supplied via config, it defaults to 1.
18
+ * The database version. If not supplied via config, it defaults to the archivist default version.
21
19
  */
22
20
  get dbVersion(): number;
23
- /**
24
- * The database indexes.
25
- */
26
- get indexes(): import("@xyo-network/archivist-model").IndexDescription[];
27
21
  /**
28
22
  * The name of the object store. If not supplied via config, it defaults
29
23
  * to `payloads`.
@@ -32,7 +26,7 @@ export declare class IndexedDbPayloadDiviner<TParams extends IndexedDbPayloadDiv
32
26
  private get db();
33
27
  protected divineHandler(payloads?: TIn[]): Promise<TOut[]>;
34
28
  protected startHandler(): Promise<boolean>;
35
- private getKeyValuesFromQuery;
29
+ private getKeyRangeValue;
36
30
  private selectBestIndex;
37
31
  }
38
32
  //# sourceMappingURL=Diviner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Diviner.d.ts","sourceRoot":"","sources":["../../src/Diviner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AAClF,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAA;AACtE,OAAO,EAAgC,0BAA0B,EAAE,MAAM,oCAAoC,CAAA;AAG7G,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAIpD,OAAO,EAAE,6BAA6B,EAAE,MAAM,UAAU,CAAA;AAMxD,qBAAa,uBAAuB,CAClC,OAAO,SAAS,6BAA6B,GAAG,6BAA6B,EAC7E,GAAG,SAAS,0BAA0B,GAAG,0BAA0B,EACnE,IAAI,SAAS,OAAO,GAAG,OAAO,EAC9B,UAAU,SAAS,sBAAsB,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,sBAAsB,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CACxI,SAAQ,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,CAAC;IACtD,OAAgB,aAAa,WAAwC;IACrE,MAAM,CAAC,aAAa,SAAc;IAClC,MAAM,CAAC,gBAAgB,SAAI;IAC3B,MAAM,CAAC,gBAAgB,SAAa;IAEpC,OAAO,CAAC,GAAG,CAAwC;IAEnD;;;;;OAKG;IACH,IAAI,MAAM,WAET;IAED;;OAEG;IACH,IAAI,SAAS,WAEZ;IAED;;OAEG;IACH,IAAI,OAAO,8DAEV;IAED;;;OAGG;IACH,IAAI,SAAS,WAEZ;IAED,OAAO,KAAK,EAAE,GAEb;cAEwB,aAAa,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;cAqChD,YAAY;IAQrC,OAAO,CAAC,qBAAqB;IAiB7B,OAAO,CAAC,eAAe;CA2BxB"}
1
+ {"version":3,"file":"Diviner.d.ts","sourceRoot":"","sources":["../../src/Diviner.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AAClF,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAA;AACtE,OAAO,EAAgC,0BAA0B,EAAE,MAAM,oCAAoC,CAAA;AAG7G,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAIpD,OAAO,EAAE,6BAA6B,EAAE,MAAM,UAAU,CAAA;AAoBxD,qBAAa,uBAAuB,CAClC,OAAO,SAAS,6BAA6B,GAAG,6BAA6B,EAC7E,GAAG,SAAS,0BAA0B,GAAG,0BAA0B,EACnE,IAAI,SAAS,OAAO,GAAG,OAAO,EAC9B,UAAU,SAAS,sBAAsB,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,sBAAsB,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CACxI,SAAQ,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,CAAC;IACtD,OAAgB,aAAa,WAAwC;IAErE,OAAO,CAAC,GAAG,CAAwC;IAEnD;;;;;;OAMG;IACH,IAAI,MAAM,WAET;IAED;;OAEG;IACH,IAAI,SAAS,WAEZ;IAED;;;OAGG;IACH,IAAI,SAAS,WAEZ;IAED,OAAO,KAAK,EAAE,GAEb;cAEwB,aAAa,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;cAuDhD,YAAY;IAQrC,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,eAAe;CA2BxB"}
@@ -5,25 +5,19 @@ import { Payload } from '@xyo-network/payload-model';
5
5
  import { IndexedDbPayloadDivinerParams } from './Params';
6
6
  export declare class IndexedDbPayloadDiviner<TParams extends IndexedDbPayloadDivinerParams = IndexedDbPayloadDivinerParams, TIn extends PayloadDivinerQueryPayload = PayloadDivinerQueryPayload, TOut extends Payload = Payload, TEventData extends DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut> = DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut>> extends PayloadDiviner<TParams, TIn, TOut, TEventData> {
7
7
  static configSchemas: string[];
8
- static defaultDbName: string;
9
- static defaultDbVersion: number;
10
- static defaultStoreName: string;
11
8
  private _db;
12
9
  /**
13
- * The database name. If not supplied via config it defaults to
14
- * `archivist`. This behavior biases towards a single, isolated
15
- * DB per archivist which seems to make the most sense for 99% of
16
- * use cases.
10
+ * The database name. If not supplied via config, it defaults
11
+ * to the archivist's name and if archivist's name is not supplied,
12
+ * it defaults to `archivist`. This behavior
13
+ * biases towards a single, isolated DB per archivist which seems to
14
+ * make the most sense for 99% of use cases.
17
15
  */
18
16
  get dbName(): string;
19
17
  /**
20
- * The database version. If not supplied via config, it defaults to 1.
18
+ * The database version. If not supplied via config, it defaults to the archivist default version.
21
19
  */
22
20
  get dbVersion(): number;
23
- /**
24
- * The database indexes.
25
- */
26
- get indexes(): import("@xyo-network/archivist-model").IndexDescription[];
27
21
  /**
28
22
  * The name of the object store. If not supplied via config, it defaults
29
23
  * to `payloads`.
@@ -32,7 +26,7 @@ export declare class IndexedDbPayloadDiviner<TParams extends IndexedDbPayloadDiv
32
26
  private get db();
33
27
  protected divineHandler(payloads?: TIn[]): Promise<TOut[]>;
34
28
  protected startHandler(): Promise<boolean>;
35
- private getKeyValuesFromQuery;
29
+ private getKeyRangeValue;
36
30
  private selectBestIndex;
37
31
  }
38
32
  //# sourceMappingURL=Diviner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Diviner.d.ts","sourceRoot":"","sources":["../../src/Diviner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AAClF,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAA;AACtE,OAAO,EAAgC,0BAA0B,EAAE,MAAM,oCAAoC,CAAA;AAG7G,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAIpD,OAAO,EAAE,6BAA6B,EAAE,MAAM,UAAU,CAAA;AAMxD,qBAAa,uBAAuB,CAClC,OAAO,SAAS,6BAA6B,GAAG,6BAA6B,EAC7E,GAAG,SAAS,0BAA0B,GAAG,0BAA0B,EACnE,IAAI,SAAS,OAAO,GAAG,OAAO,EAC9B,UAAU,SAAS,sBAAsB,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,sBAAsB,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CACxI,SAAQ,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,CAAC;IACtD,OAAgB,aAAa,WAAwC;IACrE,MAAM,CAAC,aAAa,SAAc;IAClC,MAAM,CAAC,gBAAgB,SAAI;IAC3B,MAAM,CAAC,gBAAgB,SAAa;IAEpC,OAAO,CAAC,GAAG,CAAwC;IAEnD;;;;;OAKG;IACH,IAAI,MAAM,WAET;IAED;;OAEG;IACH,IAAI,SAAS,WAEZ;IAED;;OAEG;IACH,IAAI,OAAO,8DAEV;IAED;;;OAGG;IACH,IAAI,SAAS,WAEZ;IAED,OAAO,KAAK,EAAE,GAEb;cAEwB,aAAa,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;cAqChD,YAAY;IAQrC,OAAO,CAAC,qBAAqB;IAiB7B,OAAO,CAAC,eAAe;CA2BxB"}
1
+ {"version":3,"file":"Diviner.d.ts","sourceRoot":"","sources":["../../src/Diviner.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AAClF,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAA;AACtE,OAAO,EAAgC,0BAA0B,EAAE,MAAM,oCAAoC,CAAA;AAG7G,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAIpD,OAAO,EAAE,6BAA6B,EAAE,MAAM,UAAU,CAAA;AAoBxD,qBAAa,uBAAuB,CAClC,OAAO,SAAS,6BAA6B,GAAG,6BAA6B,EAC7E,GAAG,SAAS,0BAA0B,GAAG,0BAA0B,EACnE,IAAI,SAAS,OAAO,GAAG,OAAO,EAC9B,UAAU,SAAS,sBAAsB,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,sBAAsB,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CACxI,SAAQ,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,CAAC;IACtD,OAAgB,aAAa,WAAwC;IAErE,OAAO,CAAC,GAAG,CAAwC;IAEnD;;;;;;OAMG;IACH,IAAI,MAAM,WAET;IAED;;OAEG;IACH,IAAI,SAAS,WAEZ;IAED;;;OAGG;IACH,IAAI,SAAS,WAEZ;IAED,OAAO,KAAK,EAAE,GAEb;cAEwB,aAAa,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;cAuDhD,YAAY;IAQrC,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,eAAe;CA2BxB"}
@@ -5,25 +5,19 @@ import { Payload } from '@xyo-network/payload-model';
5
5
  import { IndexedDbPayloadDivinerParams } from './Params';
6
6
  export declare class IndexedDbPayloadDiviner<TParams extends IndexedDbPayloadDivinerParams = IndexedDbPayloadDivinerParams, TIn extends PayloadDivinerQueryPayload = PayloadDivinerQueryPayload, TOut extends Payload = Payload, TEventData extends DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut> = DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut>> extends PayloadDiviner<TParams, TIn, TOut, TEventData> {
7
7
  static configSchemas: string[];
8
- static defaultDbName: string;
9
- static defaultDbVersion: number;
10
- static defaultStoreName: string;
11
8
  private _db;
12
9
  /**
13
- * The database name. If not supplied via config it defaults to
14
- * `archivist`. This behavior biases towards a single, isolated
15
- * DB per archivist which seems to make the most sense for 99% of
16
- * use cases.
10
+ * The database name. If not supplied via config, it defaults
11
+ * to the archivist's name and if archivist's name is not supplied,
12
+ * it defaults to `archivist`. This behavior
13
+ * biases towards a single, isolated DB per archivist which seems to
14
+ * make the most sense for 99% of use cases.
17
15
  */
18
16
  get dbName(): string;
19
17
  /**
20
- * The database version. If not supplied via config, it defaults to 1.
18
+ * The database version. If not supplied via config, it defaults to the archivist default version.
21
19
  */
22
20
  get dbVersion(): number;
23
- /**
24
- * The database indexes.
25
- */
26
- get indexes(): import("@xyo-network/archivist-model").IndexDescription[];
27
21
  /**
28
22
  * The name of the object store. If not supplied via config, it defaults
29
23
  * to `payloads`.
@@ -32,7 +26,7 @@ export declare class IndexedDbPayloadDiviner<TParams extends IndexedDbPayloadDiv
32
26
  private get db();
33
27
  protected divineHandler(payloads?: TIn[]): Promise<TOut[]>;
34
28
  protected startHandler(): Promise<boolean>;
35
- private getKeyValuesFromQuery;
29
+ private getKeyRangeValue;
36
30
  private selectBestIndex;
37
31
  }
38
32
  //# sourceMappingURL=Diviner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Diviner.d.ts","sourceRoot":"","sources":["../../src/Diviner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AAClF,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAA;AACtE,OAAO,EAAgC,0BAA0B,EAAE,MAAM,oCAAoC,CAAA;AAG7G,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAIpD,OAAO,EAAE,6BAA6B,EAAE,MAAM,UAAU,CAAA;AAMxD,qBAAa,uBAAuB,CAClC,OAAO,SAAS,6BAA6B,GAAG,6BAA6B,EAC7E,GAAG,SAAS,0BAA0B,GAAG,0BAA0B,EACnE,IAAI,SAAS,OAAO,GAAG,OAAO,EAC9B,UAAU,SAAS,sBAAsB,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,sBAAsB,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CACxI,SAAQ,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,CAAC;IACtD,OAAgB,aAAa,WAAwC;IACrE,MAAM,CAAC,aAAa,SAAc;IAClC,MAAM,CAAC,gBAAgB,SAAI;IAC3B,MAAM,CAAC,gBAAgB,SAAa;IAEpC,OAAO,CAAC,GAAG,CAAwC;IAEnD;;;;;OAKG;IACH,IAAI,MAAM,WAET;IAED;;OAEG;IACH,IAAI,SAAS,WAEZ;IAED;;OAEG;IACH,IAAI,OAAO,8DAEV;IAED;;;OAGG;IACH,IAAI,SAAS,WAEZ;IAED,OAAO,KAAK,EAAE,GAEb;cAEwB,aAAa,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;cAqChD,YAAY;IAQrC,OAAO,CAAC,qBAAqB;IAiB7B,OAAO,CAAC,eAAe;CA2BxB"}
1
+ {"version":3,"file":"Diviner.d.ts","sourceRoot":"","sources":["../../src/Diviner.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AAClF,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAA;AACtE,OAAO,EAAgC,0BAA0B,EAAE,MAAM,oCAAoC,CAAA;AAG7G,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAIpD,OAAO,EAAE,6BAA6B,EAAE,MAAM,UAAU,CAAA;AAoBxD,qBAAa,uBAAuB,CAClC,OAAO,SAAS,6BAA6B,GAAG,6BAA6B,EAC7E,GAAG,SAAS,0BAA0B,GAAG,0BAA0B,EACnE,IAAI,SAAS,OAAO,GAAG,OAAO,EAC9B,UAAU,SAAS,sBAAsB,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,sBAAsB,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CACxI,SAAQ,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,CAAC;IACtD,OAAgB,aAAa,WAAwC;IAErE,OAAO,CAAC,GAAG,CAAwC;IAEnD;;;;;;OAMG;IACH,IAAI,MAAM,WAET;IAED;;OAEG;IACH,IAAI,SAAS,WAEZ;IAED;;;OAGG;IACH,IAAI,SAAS,WAEZ;IAED,OAAO,KAAK,EAAE,GAEb;cAEwB,aAAa,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;cAuDhD,YAAY;IAQrC,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,eAAe;CA2BxB"}
@@ -35,50 +35,57 @@ var IndexedDbPayloadDivinerSchema = `${import_diviner_payload_model.PayloadDivin
35
35
  var IndexedDbPayloadDivinerConfigSchema = `${IndexedDbPayloadDivinerSchema}.config`;
36
36
 
37
37
  // src/Diviner.ts
38
+ var import_array = require("@xylabs/array");
38
39
  var import_assert = require("@xylabs/assert");
40
+ var import_exists = require("@xylabs/exists");
41
+ var import_archivist_indexeddb = require("@xyo-network/archivist-indexeddb");
39
42
  var import_archivist_model = require("@xyo-network/archivist-model");
40
43
  var import_diviner_payload_abstract = require("@xyo-network/diviner-payload-abstract");
41
44
  var import_diviner_payload_model2 = require("@xyo-network/diviner-payload-model");
42
45
  var import_hash = require("@xyo-network/hash");
43
46
  var import_idb = require("idb");
44
- var IndexedDbPayloadDiviner = class _IndexedDbPayloadDiviner extends import_diviner_payload_abstract.PayloadDiviner {
47
+ var payloadValueFilter = /* @__PURE__ */ __name((key, value) => {
48
+ if (!value)
49
+ return void 0;
50
+ return (payload) => {
51
+ if (!payload)
52
+ return false;
53
+ const sourceValue = payload?.[key];
54
+ if (sourceValue === void 0)
55
+ return false;
56
+ return Array.isArray(sourceValue) && Array.isArray(value) ? (0, import_array.containsAll)(sourceValue, value) : sourceValue == value;
57
+ };
58
+ }, "payloadValueFilter");
59
+ var IndexedDbPayloadDiviner = class extends import_diviner_payload_abstract.PayloadDiviner {
45
60
  static {
46
61
  __name(this, "IndexedDbPayloadDiviner");
47
62
  }
48
63
  static configSchemas = [
49
64
  IndexedDbPayloadDivinerConfigSchema
50
65
  ];
51
- static defaultDbName = "archivist";
52
- static defaultDbVersion = 1;
53
- static defaultStoreName = "payloads";
54
66
  _db;
55
67
  /**
56
- * The database name. If not supplied via config it defaults to
57
- * `archivist`. This behavior biases towards a single, isolated
58
- * DB per archivist which seems to make the most sense for 99% of
59
- * use cases.
68
+ * The database name. If not supplied via config, it defaults
69
+ * to the archivist's name and if archivist's name is not supplied,
70
+ * it defaults to `archivist`. This behavior
71
+ * biases towards a single, isolated DB per archivist which seems to
72
+ * make the most sense for 99% of use cases.
60
73
  */
61
74
  get dbName() {
62
- return this.config?.dbName ?? _IndexedDbPayloadDiviner.defaultDbName;
75
+ return this.config?.dbName ?? this.config?.archivist ?? import_archivist_indexeddb.IndexedDbArchivist.defaultDbName;
63
76
  }
64
77
  /**
65
- * The database version. If not supplied via config, it defaults to 1.
78
+ * The database version. If not supplied via config, it defaults to the archivist default version.
66
79
  */
67
80
  get dbVersion() {
68
- return this.config?.dbVersion ?? _IndexedDbPayloadDiviner.defaultDbVersion;
69
- }
70
- /**
71
- * The database indexes.
72
- */
73
- get indexes() {
74
- return this.config?.storage?.indexes ?? [];
81
+ return this.config?.dbVersion ?? import_archivist_indexeddb.IndexedDbArchivist.defaultDbVersion;
75
82
  }
76
83
  /**
77
84
  * The name of the object store. If not supplied via config, it defaults
78
85
  * to `payloads`.
79
86
  */
80
87
  get storeName() {
81
- return this.config?.storeName ?? _IndexedDbPayloadDiviner.defaultStoreName;
88
+ return this.config?.storeName ?? import_archivist_indexeddb.IndexedDbArchivist.defaultStoreName;
82
89
  }
83
90
  get db() {
84
91
  return (0, import_assert.assertEx)(this._db, "DB not initialized");
@@ -103,14 +110,24 @@ var IndexedDbPayloadDiviner = class _IndexedDbPayloadDiviner extends import_divi
103
110
  };
104
111
  const direction = order === "desc" ? "prev" : "next";
105
112
  const suggestedIndex = this.selectBestIndex(filter, store);
106
- const filterValues = this.getKeyValuesFromQuery(suggestedIndex, filter);
107
- let cursor = suggestedIndex ? await store.index(suggestedIndex).openCursor(IDBKeyRange.only(filterValues.length === 1 ? filterValues[0] : filterValues), direction) : await store.openCursor(suggestedIndex, direction);
113
+ const keyRangeValue = this.getKeyRangeValue(suggestedIndex, filter);
114
+ const valueFilters = props ? Object.entries(props).map(([key, value]) => payloadValueFilter(key, value)).filter(import_exists.exists) : [];
115
+ let cursor = suggestedIndex ? await store.index(suggestedIndex).openCursor(IDBKeyRange.only(keyRangeValue), direction) : await store.openCursor(suggestedIndex, direction);
108
116
  while (cursor && parsedOffset > 0) {
109
117
  cursor = await cursor.advance(parsedOffset);
110
118
  parsedOffset = 0;
111
119
  }
112
120
  while (cursor && results.length < parsedLimit) {
113
- results.push(cursor.value);
121
+ const value = cursor.value;
122
+ if (value) {
123
+ if (valueFilters.length > 0) {
124
+ if (valueFilters.every((filter2) => filter2(value))) {
125
+ results.push(value);
126
+ }
127
+ } else {
128
+ results.push(value);
129
+ }
130
+ }
114
131
  cursor = await cursor.continue();
115
132
  }
116
133
  await tx.done;
@@ -121,14 +138,15 @@ var IndexedDbPayloadDiviner = class _IndexedDbPayloadDiviner extends import_divi
121
138
  this._db = await (0, import_idb.openDB)(this.dbName, this.dbVersion);
122
139
  return true;
123
140
  }
124
- getKeyValuesFromQuery(indexName, query) {
141
+ getKeyRangeValue(indexName, query) {
125
142
  if (!indexName)
126
143
  return [];
127
144
  const extractFields = /* @__PURE__ */ __name((indexName2) => {
128
145
  return indexName2.slice(3).split(import_archivist_model.IndexSeparator).map((field) => field.toLowerCase());
129
146
  }, "extractFields");
130
147
  const indexFields = extractFields(indexName);
131
- return indexFields.map((field) => query[field]);
148
+ const keyRangeValue = indexFields.map((field) => query[field]);
149
+ return keyRangeValue.length === 1 ? keyRangeValue[0] : keyRangeValue;
132
150
  }
133
151
  selectBestIndex(query, store) {
134
152
  const { indexNames } = store;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts","../../src/Schema.ts","../../src/Config.ts","../../src/Diviner.ts"],"sourcesContent":["export * from './Config'\nexport * from './Diviner'\nexport * from './Params'\nexport * from './Schema'\n","import { PayloadDivinerSchema } from '@xyo-network/diviner-payload-model'\n\nexport const IndexedDbPayloadDivinerSchema = `${PayloadDivinerSchema}.indexeddb`\nexport type IndexedDbPayloadDivinerSchema = typeof IndexedDbPayloadDivinerSchema\n","import { IndexDescription } from '@xyo-network/archivist-model'\nimport { DivinerConfig } from '@xyo-network/diviner-model'\n\nimport { IndexedDbPayloadDivinerSchema } from './Schema'\n\nexport const IndexedDbPayloadDivinerConfigSchema = `${IndexedDbPayloadDivinerSchema}.config`\nexport type IndexedDbPayloadDivinerConfigSchema = typeof IndexedDbPayloadDivinerConfigSchema\n\nexport type IndexedDbPayloadDivinerConfig = DivinerConfig<{\n /**\n * The database name\n */\n dbName?: string\n /**\n * The version of the DB, defaults to 1\n */\n dbVersion?: number\n schema: IndexedDbPayloadDivinerConfigSchema\n /**\n * The storage configuration\n * // TODO: Hoist to main diviner config\n */\n storage?: {\n /**\n * The indexes to create on the object store\n */\n indexes?: IndexDescription[]\n }\n /**\n * The name of the object store\n */\n storeName?: string\n}>\n","import { assertEx } from '@xylabs/assert'\nimport { IndexSeparator } from '@xyo-network/archivist-model'\nimport { DivinerModule, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { PayloadDiviner } from '@xyo-network/diviner-payload-abstract'\nimport { isPayloadDivinerQueryPayload, PayloadDivinerQueryPayload } from '@xyo-network/diviner-payload-model'\nimport { PayloadHasher } from '@xyo-network/hash'\nimport { AnyObject } from '@xyo-network/object'\nimport { Payload } from '@xyo-network/payload-model'\nimport { IDBPDatabase, IDBPObjectStore, openDB } from 'idb'\n\nimport { IndexedDbPayloadDivinerConfigSchema } from './Config'\nimport { IndexedDbPayloadDivinerParams } from './Params'\n\ninterface PayloadStore {\n [s: string]: Payload\n}\n\nexport class IndexedDbPayloadDiviner<\n TParams extends IndexedDbPayloadDivinerParams = IndexedDbPayloadDivinerParams,\n TIn extends PayloadDivinerQueryPayload = PayloadDivinerQueryPayload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut> = DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut>,\n> extends PayloadDiviner<TParams, TIn, TOut, TEventData> {\n static override configSchemas = [IndexedDbPayloadDivinerConfigSchema]\n static defaultDbName = 'archivist'\n static defaultDbVersion = 1\n static defaultStoreName = 'payloads'\n\n private _db: IDBPDatabase<PayloadStore> | undefined\n\n /**\n * The database name. If not supplied via config it defaults to\n * `archivist`. This behavior biases towards a single, isolated\n * DB per archivist which seems to make the most sense for 99% of\n * use cases.\n */\n get dbName() {\n return this.config?.dbName ?? IndexedDbPayloadDiviner.defaultDbName\n }\n\n /**\n * The database version. If not supplied via config, it defaults to 1.\n */\n get dbVersion() {\n return this.config?.dbVersion ?? IndexedDbPayloadDiviner.defaultDbVersion\n }\n\n /**\n * The database indexes.\n */\n get indexes() {\n return this.config?.storage?.indexes ?? []\n }\n\n /**\n * The name of the object store. If not supplied via config, it defaults\n * to `payloads`.\n */\n get storeName() {\n return this.config?.storeName ?? IndexedDbPayloadDiviner.defaultStoreName\n }\n\n private get db(): IDBPDatabase<PayloadStore> {\n return assertEx(this._db, 'DB not initialized')\n }\n\n protected override async divineHandler(payloads?: TIn[]): Promise<TOut[]> {\n const query = assertEx(payloads?.filter(isPayloadDivinerQueryPayload)?.pop(), 'Missing query payload')\n if (!query) return []\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { schemas, limit, offset, hash, order, schema: _schema, sources, ...props } = query as unknown as TIn & { sources?: string[] }\n const tx = this.db.transaction(this.storeName, 'readonly')\n const store = tx.objectStore(this.storeName)\n const results: TOut[] = []\n let parsedOffset = offset ?? 0\n const parsedLimit = limit ?? 10\n assertEx((schemas?.length ?? 1) === 1, 'IndexedDbPayloadDiviner: Only one filter schema supported')\n const filterSchema = schemas?.[0]\n const filter = filterSchema ? { schema: filterSchema, ...props } : { ...props }\n const direction: IDBCursorDirection = order === 'desc' ? 'prev' : 'next'\n const suggestedIndex = this.selectBestIndex(filter, store)\n const filterValues = this.getKeyValuesFromQuery(suggestedIndex, filter)\n let cursor = suggestedIndex\n ? // Conditionally filter on schemas\n await store.index(suggestedIndex).openCursor(IDBKeyRange.only(filterValues.length === 1 ? filterValues[0] : filterValues), direction)\n : // Just iterate all records\n await store.openCursor(suggestedIndex, direction)\n\n // Skip records until the offset is reached\n while (cursor && parsedOffset > 0) {\n cursor = await cursor.advance(parsedOffset)\n parsedOffset = 0 // Reset offset after skipping\n }\n // Collect results up to the limit\n while (cursor && results.length < parsedLimit) {\n results.push(cursor.value)\n cursor = await cursor.continue()\n }\n await tx.done\n // Remove any metadata before returning to the client\n return results.map((payload) => PayloadHasher.jsonPayload(payload))\n }\n\n protected override async startHandler() {\n await super.startHandler()\n // NOTE: We could defer this creation to first access but we\n // want to fail fast here in case something is wrong\n this._db = await openDB<PayloadStore>(this.dbName, this.dbVersion)\n return true\n }\n\n private getKeyValuesFromQuery(indexName: string | null, query: AnyObject): unknown[] {\n if (!indexName) return []\n // Function to extract fields from an index name\n const extractFields = (indexName: string): string[] => {\n return indexName\n .slice(3)\n .split(IndexSeparator)\n .map((field) => field.toLowerCase())\n }\n\n // Extracting the relevant fields from the index name\n const indexFields = extractFields(indexName)\n\n // Collecting the values for these fields from the query object\n return indexFields.map((field) => query[field as keyof AnyObject])\n }\n\n private selectBestIndex(query: AnyObject, store: IDBPObjectStore<PayloadStore>): string | null {\n // List of available indexes\n const { indexNames } = store\n\n // Function to extract fields from an index name\n const extractFields = (indexName: string): string[] => {\n return indexName\n .slice(3)\n .split(IndexSeparator)\n .map((field) => field.toLowerCase())\n }\n\n // Convert query object keys to a set for easier comparison\n const queryKeys = new Set(Object.keys(query).map((key) => key.toLowerCase()))\n\n // Find the best matching index\n let bestMatch: { indexName: string; matchCount: number } = { indexName: '', matchCount: 0 }\n\n for (const indexName of indexNames) {\n const indexFields = extractFields(indexName)\n const matchCount = indexFields.filter((field) => queryKeys.has(field)).length\n if (matchCount > bestMatch.matchCount) {\n bestMatch = { indexName, matchCount }\n }\n }\n return bestMatch.matchCount > 0 ? bestMatch.indexName : null\n }\n}\n"],"mappings":"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","names":["IndexedDbPayloadDivinerSchema","PayloadDivinerSchema","IndexedDbPayloadDivinerConfigSchema","IndexedDbPayloadDivinerSchema","import_diviner_payload_model","IndexedDbPayloadDiviner","PayloadDiviner","configSchemas","IndexedDbPayloadDivinerConfigSchema","defaultDbName","defaultDbVersion","defaultStoreName","_db","dbName","config","dbVersion","indexes","storage","storeName","db","assertEx","divineHandler","payloads","query","filter","isPayloadDivinerQueryPayload","pop","schemas","limit","offset","hash","order","schema","_schema","sources","props","tx","transaction","store","objectStore","results","parsedOffset","parsedLimit","length","filterSchema","direction","suggestedIndex","selectBestIndex","filterValues","getKeyValuesFromQuery","cursor","index","openCursor","IDBKeyRange","only","advance","push","value","continue","done","map","payload","PayloadHasher","jsonPayload","startHandler","openDB","indexName","extractFields","slice","split","IndexSeparator","field","toLowerCase","indexFields","indexNames","queryKeys","Set","Object","keys","key","bestMatch","matchCount","has"]}
1
+ {"version":3,"sources":["../../src/index.ts","../../src/Schema.ts","../../src/Config.ts","../../src/Diviner.ts"],"sourcesContent":["export * from './Config'\nexport * from './Diviner'\nexport * from './Params'\nexport * from './Schema'\n","import { PayloadDivinerSchema } from '@xyo-network/diviner-payload-model'\n\nexport const IndexedDbPayloadDivinerSchema = `${PayloadDivinerSchema}.indexeddb`\nexport type IndexedDbPayloadDivinerSchema = typeof IndexedDbPayloadDivinerSchema\n","import { IndexDescription } from '@xyo-network/archivist-model'\nimport { DivinerConfig } from '@xyo-network/diviner-model'\n\nimport { IndexedDbPayloadDivinerSchema } from './Schema'\n\nexport const IndexedDbPayloadDivinerConfigSchema = `${IndexedDbPayloadDivinerSchema}.config`\nexport type IndexedDbPayloadDivinerConfigSchema = typeof IndexedDbPayloadDivinerConfigSchema\n\nexport type IndexedDbPayloadDivinerConfig = DivinerConfig<{\n /**\n * The database name\n */\n dbName?: string\n /**\n * The version of the DB, defaults to 1\n */\n dbVersion?: number\n schema: IndexedDbPayloadDivinerConfigSchema\n /**\n * The storage configuration\n * // TODO: Hoist to main diviner config\n */\n storage?: {\n /**\n * The indexes to create on the object store\n */\n indexes?: IndexDescription[]\n }\n /**\n * The name of the object store\n */\n storeName?: string\n}>\n","import { containsAll } from '@xylabs/array'\nimport { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport { IndexedDbArchivist } from '@xyo-network/archivist-indexeddb'\nimport { IndexSeparator } from '@xyo-network/archivist-model'\nimport { DivinerModule, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { PayloadDiviner } from '@xyo-network/diviner-payload-abstract'\nimport { isPayloadDivinerQueryPayload, PayloadDivinerQueryPayload } from '@xyo-network/diviner-payload-model'\nimport { PayloadHasher } from '@xyo-network/hash'\nimport { AnyObject } from '@xyo-network/object'\nimport { Payload } from '@xyo-network/payload-model'\nimport { IDBPDatabase, IDBPObjectStore, openDB } from 'idb'\n\nimport { IndexedDbPayloadDivinerConfigSchema } from './Config'\nimport { IndexedDbPayloadDivinerParams } from './Params'\n\ninterface PayloadStore {\n [s: string]: Payload\n}\n\ntype AnyPayload = Payload<Record<string, unknown>>\n\ntype ValueFilter = (payload?: AnyPayload | null) => boolean\n\nconst payloadValueFilter = (key: keyof AnyPayload, value?: unknown | unknown[]): ValueFilter | undefined => {\n if (!value) return undefined\n return (payload) => {\n if (!payload) return false\n const sourceValue = payload?.[key]\n if (sourceValue === undefined) return false\n return Array.isArray(sourceValue) && Array.isArray(value) ? containsAll(sourceValue, value) : sourceValue == value\n }\n}\n\nexport class IndexedDbPayloadDiviner<\n TParams extends IndexedDbPayloadDivinerParams = IndexedDbPayloadDivinerParams,\n TIn extends PayloadDivinerQueryPayload = PayloadDivinerQueryPayload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut> = DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut>,\n> extends PayloadDiviner<TParams, TIn, TOut, TEventData> {\n static override configSchemas = [IndexedDbPayloadDivinerConfigSchema]\n\n private _db: IDBPDatabase<PayloadStore> | undefined\n\n /**\n * The database name. If not supplied via config, it defaults\n * to the archivist's name and if archivist's name is not supplied,\n * it defaults to `archivist`. This behavior\n * biases towards a single, isolated DB per archivist which seems to\n * make the most sense for 99% of use cases.\n */\n get dbName() {\n return this.config?.dbName ?? this.config?.archivist ?? IndexedDbArchivist.defaultDbName\n }\n\n /**\n * The database version. If not supplied via config, it defaults to the archivist default version.\n */\n get dbVersion() {\n return this.config?.dbVersion ?? IndexedDbArchivist.defaultDbVersion\n }\n\n /**\n * The name of the object store. If not supplied via config, it defaults\n * to `payloads`.\n */\n get storeName() {\n return this.config?.storeName ?? IndexedDbArchivist.defaultStoreName\n }\n\n private get db(): IDBPDatabase<PayloadStore> {\n return assertEx(this._db, 'DB not initialized')\n }\n\n protected override async divineHandler(payloads?: TIn[]): Promise<TOut[]> {\n const query = assertEx(payloads?.filter(isPayloadDivinerQueryPayload)?.pop(), 'Missing query payload')\n if (!query) return []\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { schemas, limit, offset, hash, order, schema: _schema, sources, ...props } = query as unknown as TIn & { sources?: string[] }\n const tx = this.db.transaction(this.storeName, 'readonly')\n const store = tx.objectStore(this.storeName)\n const results: TOut[] = []\n let parsedOffset = offset ?? 0\n const parsedLimit = limit ?? 10\n assertEx((schemas?.length ?? 1) === 1, 'IndexedDbPayloadDiviner: Only one filter schema supported')\n const filterSchema = schemas?.[0]\n const filter = filterSchema ? { schema: filterSchema, ...props } : { ...props }\n const direction: IDBCursorDirection = order === 'desc' ? 'prev' : 'next'\n const suggestedIndex = this.selectBestIndex(filter, store)\n const keyRangeValue = this.getKeyRangeValue(suggestedIndex, filter)\n const valueFilters: ValueFilter[] = props\n ? Object.entries(props)\n .map(([key, value]) => payloadValueFilter(key, value))\n .filter(exists)\n : []\n let cursor = suggestedIndex\n ? // Conditionally filter on schemas\n await store.index(suggestedIndex).openCursor(IDBKeyRange.only(keyRangeValue), direction)\n : // Just iterate all records\n await store.openCursor(suggestedIndex, direction)\n\n // Skip records until the offset is reached\n while (cursor && parsedOffset > 0) {\n cursor = await cursor.advance(parsedOffset)\n parsedOffset = 0 // Reset offset after skipping\n }\n // Collect results up to the limit\n while (cursor && results.length < parsedLimit) {\n const value = cursor.value\n if (value) {\n // If we're filtering on more than just the schema\n if (valueFilters.length > 0) {\n // Ensure all filters pass\n if (valueFilters.every((filter) => filter(value))) {\n // Then save the value\n results.push(value)\n }\n } else {\n // Otherwise just save the value\n results.push(value)\n }\n }\n cursor = await cursor.continue()\n }\n await tx.done\n // Remove any metadata before returning to the client\n return results.map((payload) => PayloadHasher.jsonPayload(payload))\n }\n\n protected override async startHandler() {\n await super.startHandler()\n // NOTE: We could defer this creation to first access but we\n // want to fail fast here in case something is wrong\n this._db = await openDB<PayloadStore>(this.dbName, this.dbVersion)\n return true\n }\n\n private getKeyRangeValue(indexName: string | null, query: AnyObject): unknown | unknown[] {\n if (!indexName) return []\n // Function to extract fields from an index name\n const extractFields = (indexName: string): string[] => {\n return indexName\n .slice(3)\n .split(IndexSeparator)\n .map((field) => field.toLowerCase())\n }\n\n // Extracting the relevant fields from the index name\n const indexFields = extractFields(indexName)\n\n // Collecting the values for these fields from the query object\n const keyRangeValue = indexFields.map((field) => query[field as keyof AnyObject])\n return keyRangeValue.length === 1 ? keyRangeValue[0] : keyRangeValue\n }\n\n private selectBestIndex(query: AnyObject, store: IDBPObjectStore<PayloadStore>): string | null {\n // List of available indexes\n const { indexNames } = store\n\n // Function to extract fields from an index name\n const extractFields = (indexName: string): string[] => {\n return indexName\n .slice(3)\n .split(IndexSeparator)\n .map((field) => field.toLowerCase())\n }\n\n // Convert query object keys to a set for easier comparison\n const queryKeys = new Set(Object.keys(query).map((key) => key.toLowerCase()))\n\n // Find the best matching index\n let bestMatch: { indexName: string; matchCount: number } = { indexName: '', matchCount: 0 }\n\n for (const indexName of indexNames) {\n const indexFields = extractFields(indexName)\n const matchCount = indexFields.filter((field) => queryKeys.has(field)).length\n if (matchCount > bestMatch.matchCount) {\n bestMatch = { indexName, matchCount }\n }\n }\n return bestMatch.matchCount > 0 ? bestMatch.indexName : null\n }\n}\n"],"mappings":"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","names":["IndexedDbPayloadDivinerSchema","PayloadDivinerSchema","IndexedDbPayloadDivinerConfigSchema","IndexedDbPayloadDivinerSchema","import_diviner_payload_model","payloadValueFilter","key","value","undefined","payload","sourceValue","Array","isArray","containsAll","IndexedDbPayloadDiviner","PayloadDiviner","configSchemas","IndexedDbPayloadDivinerConfigSchema","_db","dbName","config","archivist","IndexedDbArchivist","defaultDbName","dbVersion","defaultDbVersion","storeName","defaultStoreName","db","assertEx","divineHandler","payloads","query","filter","isPayloadDivinerQueryPayload","pop","schemas","limit","offset","hash","order","schema","_schema","sources","props","tx","transaction","store","objectStore","results","parsedOffset","parsedLimit","length","filterSchema","direction","suggestedIndex","selectBestIndex","keyRangeValue","getKeyRangeValue","valueFilters","Object","entries","map","exists","cursor","index","openCursor","IDBKeyRange","only","advance","every","push","continue","done","PayloadHasher","jsonPayload","startHandler","openDB","indexName","extractFields","slice","split","IndexSeparator","field","toLowerCase","indexFields","indexNames","queryKeys","Set","keys","bestMatch","matchCount","has"]}
@@ -9,50 +9,57 @@ var IndexedDbPayloadDivinerSchema = `${PayloadDivinerSchema}.indexeddb`;
9
9
  var IndexedDbPayloadDivinerConfigSchema = `${IndexedDbPayloadDivinerSchema}.config`;
10
10
 
11
11
  // src/Diviner.ts
12
+ import { containsAll } from "@xylabs/array";
12
13
  import { assertEx } from "@xylabs/assert";
14
+ import { exists } from "@xylabs/exists";
15
+ import { IndexedDbArchivist } from "@xyo-network/archivist-indexeddb";
13
16
  import { IndexSeparator } from "@xyo-network/archivist-model";
14
17
  import { PayloadDiviner } from "@xyo-network/diviner-payload-abstract";
15
18
  import { isPayloadDivinerQueryPayload } from "@xyo-network/diviner-payload-model";
16
19
  import { PayloadHasher } from "@xyo-network/hash";
17
20
  import { openDB } from "idb";
18
- var IndexedDbPayloadDiviner = class _IndexedDbPayloadDiviner extends PayloadDiviner {
21
+ var payloadValueFilter = /* @__PURE__ */ __name((key, value) => {
22
+ if (!value)
23
+ return void 0;
24
+ return (payload) => {
25
+ if (!payload)
26
+ return false;
27
+ const sourceValue = payload?.[key];
28
+ if (sourceValue === void 0)
29
+ return false;
30
+ return Array.isArray(sourceValue) && Array.isArray(value) ? containsAll(sourceValue, value) : sourceValue == value;
31
+ };
32
+ }, "payloadValueFilter");
33
+ var IndexedDbPayloadDiviner = class extends PayloadDiviner {
19
34
  static {
20
35
  __name(this, "IndexedDbPayloadDiviner");
21
36
  }
22
37
  static configSchemas = [
23
38
  IndexedDbPayloadDivinerConfigSchema
24
39
  ];
25
- static defaultDbName = "archivist";
26
- static defaultDbVersion = 1;
27
- static defaultStoreName = "payloads";
28
40
  _db;
29
41
  /**
30
- * The database name. If not supplied via config it defaults to
31
- * `archivist`. This behavior biases towards a single, isolated
32
- * DB per archivist which seems to make the most sense for 99% of
33
- * use cases.
42
+ * The database name. If not supplied via config, it defaults
43
+ * to the archivist's name and if archivist's name is not supplied,
44
+ * it defaults to `archivist`. This behavior
45
+ * biases towards a single, isolated DB per archivist which seems to
46
+ * make the most sense for 99% of use cases.
34
47
  */
35
48
  get dbName() {
36
- return this.config?.dbName ?? _IndexedDbPayloadDiviner.defaultDbName;
49
+ return this.config?.dbName ?? this.config?.archivist ?? IndexedDbArchivist.defaultDbName;
37
50
  }
38
51
  /**
39
- * The database version. If not supplied via config, it defaults to 1.
52
+ * The database version. If not supplied via config, it defaults to the archivist default version.
40
53
  */
41
54
  get dbVersion() {
42
- return this.config?.dbVersion ?? _IndexedDbPayloadDiviner.defaultDbVersion;
43
- }
44
- /**
45
- * The database indexes.
46
- */
47
- get indexes() {
48
- return this.config?.storage?.indexes ?? [];
55
+ return this.config?.dbVersion ?? IndexedDbArchivist.defaultDbVersion;
49
56
  }
50
57
  /**
51
58
  * The name of the object store. If not supplied via config, it defaults
52
59
  * to `payloads`.
53
60
  */
54
61
  get storeName() {
55
- return this.config?.storeName ?? _IndexedDbPayloadDiviner.defaultStoreName;
62
+ return this.config?.storeName ?? IndexedDbArchivist.defaultStoreName;
56
63
  }
57
64
  get db() {
58
65
  return assertEx(this._db, "DB not initialized");
@@ -77,14 +84,24 @@ var IndexedDbPayloadDiviner = class _IndexedDbPayloadDiviner extends PayloadDivi
77
84
  };
78
85
  const direction = order === "desc" ? "prev" : "next";
79
86
  const suggestedIndex = this.selectBestIndex(filter, store);
80
- const filterValues = this.getKeyValuesFromQuery(suggestedIndex, filter);
81
- let cursor = suggestedIndex ? await store.index(suggestedIndex).openCursor(IDBKeyRange.only(filterValues.length === 1 ? filterValues[0] : filterValues), direction) : await store.openCursor(suggestedIndex, direction);
87
+ const keyRangeValue = this.getKeyRangeValue(suggestedIndex, filter);
88
+ const valueFilters = props ? Object.entries(props).map(([key, value]) => payloadValueFilter(key, value)).filter(exists) : [];
89
+ let cursor = suggestedIndex ? await store.index(suggestedIndex).openCursor(IDBKeyRange.only(keyRangeValue), direction) : await store.openCursor(suggestedIndex, direction);
82
90
  while (cursor && parsedOffset > 0) {
83
91
  cursor = await cursor.advance(parsedOffset);
84
92
  parsedOffset = 0;
85
93
  }
86
94
  while (cursor && results.length < parsedLimit) {
87
- results.push(cursor.value);
95
+ const value = cursor.value;
96
+ if (value) {
97
+ if (valueFilters.length > 0) {
98
+ if (valueFilters.every((filter2) => filter2(value))) {
99
+ results.push(value);
100
+ }
101
+ } else {
102
+ results.push(value);
103
+ }
104
+ }
88
105
  cursor = await cursor.continue();
89
106
  }
90
107
  await tx.done;
@@ -95,14 +112,15 @@ var IndexedDbPayloadDiviner = class _IndexedDbPayloadDiviner extends PayloadDivi
95
112
  this._db = await openDB(this.dbName, this.dbVersion);
96
113
  return true;
97
114
  }
98
- getKeyValuesFromQuery(indexName, query) {
115
+ getKeyRangeValue(indexName, query) {
99
116
  if (!indexName)
100
117
  return [];
101
118
  const extractFields = /* @__PURE__ */ __name((indexName2) => {
102
119
  return indexName2.slice(3).split(IndexSeparator).map((field) => field.toLowerCase());
103
120
  }, "extractFields");
104
121
  const indexFields = extractFields(indexName);
105
- return indexFields.map((field) => query[field]);
122
+ const keyRangeValue = indexFields.map((field) => query[field]);
123
+ return keyRangeValue.length === 1 ? keyRangeValue[0] : keyRangeValue;
106
124
  }
107
125
  selectBestIndex(query, store) {
108
126
  const { indexNames } = store;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/Schema.ts","../../src/Config.ts","../../src/Diviner.ts"],"sourcesContent":["import { PayloadDivinerSchema } from '@xyo-network/diviner-payload-model'\n\nexport const IndexedDbPayloadDivinerSchema = `${PayloadDivinerSchema}.indexeddb`\nexport type IndexedDbPayloadDivinerSchema = typeof IndexedDbPayloadDivinerSchema\n","import { IndexDescription } from '@xyo-network/archivist-model'\nimport { DivinerConfig } from '@xyo-network/diviner-model'\n\nimport { IndexedDbPayloadDivinerSchema } from './Schema'\n\nexport const IndexedDbPayloadDivinerConfigSchema = `${IndexedDbPayloadDivinerSchema}.config`\nexport type IndexedDbPayloadDivinerConfigSchema = typeof IndexedDbPayloadDivinerConfigSchema\n\nexport type IndexedDbPayloadDivinerConfig = DivinerConfig<{\n /**\n * The database name\n */\n dbName?: string\n /**\n * The version of the DB, defaults to 1\n */\n dbVersion?: number\n schema: IndexedDbPayloadDivinerConfigSchema\n /**\n * The storage configuration\n * // TODO: Hoist to main diviner config\n */\n storage?: {\n /**\n * The indexes to create on the object store\n */\n indexes?: IndexDescription[]\n }\n /**\n * The name of the object store\n */\n storeName?: string\n}>\n","import { assertEx } from '@xylabs/assert'\nimport { IndexSeparator } from '@xyo-network/archivist-model'\nimport { DivinerModule, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { PayloadDiviner } from '@xyo-network/diviner-payload-abstract'\nimport { isPayloadDivinerQueryPayload, PayloadDivinerQueryPayload } from '@xyo-network/diviner-payload-model'\nimport { PayloadHasher } from '@xyo-network/hash'\nimport { AnyObject } from '@xyo-network/object'\nimport { Payload } from '@xyo-network/payload-model'\nimport { IDBPDatabase, IDBPObjectStore, openDB } from 'idb'\n\nimport { IndexedDbPayloadDivinerConfigSchema } from './Config'\nimport { IndexedDbPayloadDivinerParams } from './Params'\n\ninterface PayloadStore {\n [s: string]: Payload\n}\n\nexport class IndexedDbPayloadDiviner<\n TParams extends IndexedDbPayloadDivinerParams = IndexedDbPayloadDivinerParams,\n TIn extends PayloadDivinerQueryPayload = PayloadDivinerQueryPayload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut> = DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut>,\n> extends PayloadDiviner<TParams, TIn, TOut, TEventData> {\n static override configSchemas = [IndexedDbPayloadDivinerConfigSchema]\n static defaultDbName = 'archivist'\n static defaultDbVersion = 1\n static defaultStoreName = 'payloads'\n\n private _db: IDBPDatabase<PayloadStore> | undefined\n\n /**\n * The database name. If not supplied via config it defaults to\n * `archivist`. This behavior biases towards a single, isolated\n * DB per archivist which seems to make the most sense for 99% of\n * use cases.\n */\n get dbName() {\n return this.config?.dbName ?? IndexedDbPayloadDiviner.defaultDbName\n }\n\n /**\n * The database version. If not supplied via config, it defaults to 1.\n */\n get dbVersion() {\n return this.config?.dbVersion ?? IndexedDbPayloadDiviner.defaultDbVersion\n }\n\n /**\n * The database indexes.\n */\n get indexes() {\n return this.config?.storage?.indexes ?? []\n }\n\n /**\n * The name of the object store. If not supplied via config, it defaults\n * to `payloads`.\n */\n get storeName() {\n return this.config?.storeName ?? IndexedDbPayloadDiviner.defaultStoreName\n }\n\n private get db(): IDBPDatabase<PayloadStore> {\n return assertEx(this._db, 'DB not initialized')\n }\n\n protected override async divineHandler(payloads?: TIn[]): Promise<TOut[]> {\n const query = assertEx(payloads?.filter(isPayloadDivinerQueryPayload)?.pop(), 'Missing query payload')\n if (!query) return []\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { schemas, limit, offset, hash, order, schema: _schema, sources, ...props } = query as unknown as TIn & { sources?: string[] }\n const tx = this.db.transaction(this.storeName, 'readonly')\n const store = tx.objectStore(this.storeName)\n const results: TOut[] = []\n let parsedOffset = offset ?? 0\n const parsedLimit = limit ?? 10\n assertEx((schemas?.length ?? 1) === 1, 'IndexedDbPayloadDiviner: Only one filter schema supported')\n const filterSchema = schemas?.[0]\n const filter = filterSchema ? { schema: filterSchema, ...props } : { ...props }\n const direction: IDBCursorDirection = order === 'desc' ? 'prev' : 'next'\n const suggestedIndex = this.selectBestIndex(filter, store)\n const filterValues = this.getKeyValuesFromQuery(suggestedIndex, filter)\n let cursor = suggestedIndex\n ? // Conditionally filter on schemas\n await store.index(suggestedIndex).openCursor(IDBKeyRange.only(filterValues.length === 1 ? filterValues[0] : filterValues), direction)\n : // Just iterate all records\n await store.openCursor(suggestedIndex, direction)\n\n // Skip records until the offset is reached\n while (cursor && parsedOffset > 0) {\n cursor = await cursor.advance(parsedOffset)\n parsedOffset = 0 // Reset offset after skipping\n }\n // Collect results up to the limit\n while (cursor && results.length < parsedLimit) {\n results.push(cursor.value)\n cursor = await cursor.continue()\n }\n await tx.done\n // Remove any metadata before returning to the client\n return results.map((payload) => PayloadHasher.jsonPayload(payload))\n }\n\n protected override async startHandler() {\n await super.startHandler()\n // NOTE: We could defer this creation to first access but we\n // want to fail fast here in case something is wrong\n this._db = await openDB<PayloadStore>(this.dbName, this.dbVersion)\n return true\n }\n\n private getKeyValuesFromQuery(indexName: string | null, query: AnyObject): unknown[] {\n if (!indexName) return []\n // Function to extract fields from an index name\n const extractFields = (indexName: string): string[] => {\n return indexName\n .slice(3)\n .split(IndexSeparator)\n .map((field) => field.toLowerCase())\n }\n\n // Extracting the relevant fields from the index name\n const indexFields = extractFields(indexName)\n\n // Collecting the values for these fields from the query object\n return indexFields.map((field) => query[field as keyof AnyObject])\n }\n\n private selectBestIndex(query: AnyObject, store: IDBPObjectStore<PayloadStore>): string | null {\n // List of available indexes\n const { indexNames } = store\n\n // Function to extract fields from an index name\n const extractFields = (indexName: string): string[] => {\n return indexName\n .slice(3)\n .split(IndexSeparator)\n .map((field) => field.toLowerCase())\n }\n\n // Convert query object keys to a set for easier comparison\n const queryKeys = new Set(Object.keys(query).map((key) => key.toLowerCase()))\n\n // Find the best matching index\n let bestMatch: { indexName: string; matchCount: number } = { indexName: '', matchCount: 0 }\n\n for (const indexName of indexNames) {\n const indexFields = extractFields(indexName)\n const matchCount = indexFields.filter((field) => queryKeys.has(field)).length\n if (matchCount > bestMatch.matchCount) {\n bestMatch = { indexName, matchCount }\n }\n }\n return bestMatch.matchCount > 0 ? bestMatch.indexName : null\n }\n}\n"],"mappings":"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","names":["PayloadDivinerSchema","IndexedDbPayloadDivinerSchema","IndexedDbPayloadDivinerConfigSchema","IndexedDbPayloadDivinerSchema","assertEx","IndexSeparator","PayloadDiviner","isPayloadDivinerQueryPayload","PayloadHasher","openDB","IndexedDbPayloadDiviner","PayloadDiviner","configSchemas","IndexedDbPayloadDivinerConfigSchema","defaultDbName","defaultDbVersion","defaultStoreName","_db","dbName","config","dbVersion","indexes","storage","storeName","db","assertEx","divineHandler","payloads","query","filter","isPayloadDivinerQueryPayload","pop","schemas","limit","offset","hash","order","schema","_schema","sources","props","tx","transaction","store","objectStore","results","parsedOffset","parsedLimit","length","filterSchema","direction","suggestedIndex","selectBestIndex","filterValues","getKeyValuesFromQuery","cursor","index","openCursor","IDBKeyRange","only","advance","push","value","continue","done","map","payload","PayloadHasher","jsonPayload","startHandler","openDB","indexName","extractFields","slice","split","IndexSeparator","field","toLowerCase","indexFields","indexNames","queryKeys","Set","Object","keys","key","bestMatch","matchCount","has"]}
1
+ {"version":3,"sources":["../../src/Schema.ts","../../src/Config.ts","../../src/Diviner.ts"],"sourcesContent":["import { PayloadDivinerSchema } from '@xyo-network/diviner-payload-model'\n\nexport const IndexedDbPayloadDivinerSchema = `${PayloadDivinerSchema}.indexeddb`\nexport type IndexedDbPayloadDivinerSchema = typeof IndexedDbPayloadDivinerSchema\n","import { IndexDescription } from '@xyo-network/archivist-model'\nimport { DivinerConfig } from '@xyo-network/diviner-model'\n\nimport { IndexedDbPayloadDivinerSchema } from './Schema'\n\nexport const IndexedDbPayloadDivinerConfigSchema = `${IndexedDbPayloadDivinerSchema}.config`\nexport type IndexedDbPayloadDivinerConfigSchema = typeof IndexedDbPayloadDivinerConfigSchema\n\nexport type IndexedDbPayloadDivinerConfig = DivinerConfig<{\n /**\n * The database name\n */\n dbName?: string\n /**\n * The version of the DB, defaults to 1\n */\n dbVersion?: number\n schema: IndexedDbPayloadDivinerConfigSchema\n /**\n * The storage configuration\n * // TODO: Hoist to main diviner config\n */\n storage?: {\n /**\n * The indexes to create on the object store\n */\n indexes?: IndexDescription[]\n }\n /**\n * The name of the object store\n */\n storeName?: string\n}>\n","import { containsAll } from '@xylabs/array'\nimport { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport { IndexedDbArchivist } from '@xyo-network/archivist-indexeddb'\nimport { IndexSeparator } from '@xyo-network/archivist-model'\nimport { DivinerModule, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { PayloadDiviner } from '@xyo-network/diviner-payload-abstract'\nimport { isPayloadDivinerQueryPayload, PayloadDivinerQueryPayload } from '@xyo-network/diviner-payload-model'\nimport { PayloadHasher } from '@xyo-network/hash'\nimport { AnyObject } from '@xyo-network/object'\nimport { Payload } from '@xyo-network/payload-model'\nimport { IDBPDatabase, IDBPObjectStore, openDB } from 'idb'\n\nimport { IndexedDbPayloadDivinerConfigSchema } from './Config'\nimport { IndexedDbPayloadDivinerParams } from './Params'\n\ninterface PayloadStore {\n [s: string]: Payload\n}\n\ntype AnyPayload = Payload<Record<string, unknown>>\n\ntype ValueFilter = (payload?: AnyPayload | null) => boolean\n\nconst payloadValueFilter = (key: keyof AnyPayload, value?: unknown | unknown[]): ValueFilter | undefined => {\n if (!value) return undefined\n return (payload) => {\n if (!payload) return false\n const sourceValue = payload?.[key]\n if (sourceValue === undefined) return false\n return Array.isArray(sourceValue) && Array.isArray(value) ? containsAll(sourceValue, value) : sourceValue == value\n }\n}\n\nexport class IndexedDbPayloadDiviner<\n TParams extends IndexedDbPayloadDivinerParams = IndexedDbPayloadDivinerParams,\n TIn extends PayloadDivinerQueryPayload = PayloadDivinerQueryPayload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut> = DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut>,\n> extends PayloadDiviner<TParams, TIn, TOut, TEventData> {\n static override configSchemas = [IndexedDbPayloadDivinerConfigSchema]\n\n private _db: IDBPDatabase<PayloadStore> | undefined\n\n /**\n * The database name. If not supplied via config, it defaults\n * to the archivist's name and if archivist's name is not supplied,\n * it defaults to `archivist`. This behavior\n * biases towards a single, isolated DB per archivist which seems to\n * make the most sense for 99% of use cases.\n */\n get dbName() {\n return this.config?.dbName ?? this.config?.archivist ?? IndexedDbArchivist.defaultDbName\n }\n\n /**\n * The database version. If not supplied via config, it defaults to the archivist default version.\n */\n get dbVersion() {\n return this.config?.dbVersion ?? IndexedDbArchivist.defaultDbVersion\n }\n\n /**\n * The name of the object store. If not supplied via config, it defaults\n * to `payloads`.\n */\n get storeName() {\n return this.config?.storeName ?? IndexedDbArchivist.defaultStoreName\n }\n\n private get db(): IDBPDatabase<PayloadStore> {\n return assertEx(this._db, 'DB not initialized')\n }\n\n protected override async divineHandler(payloads?: TIn[]): Promise<TOut[]> {\n const query = assertEx(payloads?.filter(isPayloadDivinerQueryPayload)?.pop(), 'Missing query payload')\n if (!query) return []\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { schemas, limit, offset, hash, order, schema: _schema, sources, ...props } = query as unknown as TIn & { sources?: string[] }\n const tx = this.db.transaction(this.storeName, 'readonly')\n const store = tx.objectStore(this.storeName)\n const results: TOut[] = []\n let parsedOffset = offset ?? 0\n const parsedLimit = limit ?? 10\n assertEx((schemas?.length ?? 1) === 1, 'IndexedDbPayloadDiviner: Only one filter schema supported')\n const filterSchema = schemas?.[0]\n const filter = filterSchema ? { schema: filterSchema, ...props } : { ...props }\n const direction: IDBCursorDirection = order === 'desc' ? 'prev' : 'next'\n const suggestedIndex = this.selectBestIndex(filter, store)\n const keyRangeValue = this.getKeyRangeValue(suggestedIndex, filter)\n const valueFilters: ValueFilter[] = props\n ? Object.entries(props)\n .map(([key, value]) => payloadValueFilter(key, value))\n .filter(exists)\n : []\n let cursor = suggestedIndex\n ? // Conditionally filter on schemas\n await store.index(suggestedIndex).openCursor(IDBKeyRange.only(keyRangeValue), direction)\n : // Just iterate all records\n await store.openCursor(suggestedIndex, direction)\n\n // Skip records until the offset is reached\n while (cursor && parsedOffset > 0) {\n cursor = await cursor.advance(parsedOffset)\n parsedOffset = 0 // Reset offset after skipping\n }\n // Collect results up to the limit\n while (cursor && results.length < parsedLimit) {\n const value = cursor.value\n if (value) {\n // If we're filtering on more than just the schema\n if (valueFilters.length > 0) {\n // Ensure all filters pass\n if (valueFilters.every((filter) => filter(value))) {\n // Then save the value\n results.push(value)\n }\n } else {\n // Otherwise just save the value\n results.push(value)\n }\n }\n cursor = await cursor.continue()\n }\n await tx.done\n // Remove any metadata before returning to the client\n return results.map((payload) => PayloadHasher.jsonPayload(payload))\n }\n\n protected override async startHandler() {\n await super.startHandler()\n // NOTE: We could defer this creation to first access but we\n // want to fail fast here in case something is wrong\n this._db = await openDB<PayloadStore>(this.dbName, this.dbVersion)\n return true\n }\n\n private getKeyRangeValue(indexName: string | null, query: AnyObject): unknown | unknown[] {\n if (!indexName) return []\n // Function to extract fields from an index name\n const extractFields = (indexName: string): string[] => {\n return indexName\n .slice(3)\n .split(IndexSeparator)\n .map((field) => field.toLowerCase())\n }\n\n // Extracting the relevant fields from the index name\n const indexFields = extractFields(indexName)\n\n // Collecting the values for these fields from the query object\n const keyRangeValue = indexFields.map((field) => query[field as keyof AnyObject])\n return keyRangeValue.length === 1 ? keyRangeValue[0] : keyRangeValue\n }\n\n private selectBestIndex(query: AnyObject, store: IDBPObjectStore<PayloadStore>): string | null {\n // List of available indexes\n const { indexNames } = store\n\n // Function to extract fields from an index name\n const extractFields = (indexName: string): string[] => {\n return indexName\n .slice(3)\n .split(IndexSeparator)\n .map((field) => field.toLowerCase())\n }\n\n // Convert query object keys to a set for easier comparison\n const queryKeys = new Set(Object.keys(query).map((key) => key.toLowerCase()))\n\n // Find the best matching index\n let bestMatch: { indexName: string; matchCount: number } = { indexName: '', matchCount: 0 }\n\n for (const indexName of indexNames) {\n const indexFields = extractFields(indexName)\n const matchCount = indexFields.filter((field) => queryKeys.has(field)).length\n if (matchCount > bestMatch.matchCount) {\n bestMatch = { indexName, matchCount }\n }\n }\n return bestMatch.matchCount > 0 ? bestMatch.indexName : null\n }\n}\n"],"mappings":"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","names":["PayloadDivinerSchema","IndexedDbPayloadDivinerSchema","IndexedDbPayloadDivinerConfigSchema","IndexedDbPayloadDivinerSchema","containsAll","assertEx","exists","IndexedDbArchivist","IndexSeparator","PayloadDiviner","isPayloadDivinerQueryPayload","PayloadHasher","openDB","payloadValueFilter","key","value","undefined","payload","sourceValue","Array","isArray","containsAll","IndexedDbPayloadDiviner","PayloadDiviner","configSchemas","IndexedDbPayloadDivinerConfigSchema","_db","dbName","config","archivist","IndexedDbArchivist","defaultDbName","dbVersion","defaultDbVersion","storeName","defaultStoreName","db","assertEx","divineHandler","payloads","query","filter","isPayloadDivinerQueryPayload","pop","schemas","limit","offset","hash","order","schema","_schema","sources","props","tx","transaction","store","objectStore","results","parsedOffset","parsedLimit","length","filterSchema","direction","suggestedIndex","selectBestIndex","keyRangeValue","getKeyRangeValue","valueFilters","Object","entries","map","exists","cursor","index","openCursor","IDBKeyRange","only","advance","every","push","continue","done","PayloadHasher","jsonPayload","startHandler","openDB","indexName","extractFields","slice","split","IndexSeparator","field","toLowerCase","indexFields","indexNames","queryKeys","Set","keys","bestMatch","matchCount","has"]}
@@ -5,25 +5,19 @@ import { Payload } from '@xyo-network/payload-model';
5
5
  import { IndexedDbPayloadDivinerParams } from './Params';
6
6
  export declare class IndexedDbPayloadDiviner<TParams extends IndexedDbPayloadDivinerParams = IndexedDbPayloadDivinerParams, TIn extends PayloadDivinerQueryPayload = PayloadDivinerQueryPayload, TOut extends Payload = Payload, TEventData extends DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut> = DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut>> extends PayloadDiviner<TParams, TIn, TOut, TEventData> {
7
7
  static configSchemas: string[];
8
- static defaultDbName: string;
9
- static defaultDbVersion: number;
10
- static defaultStoreName: string;
11
8
  private _db;
12
9
  /**
13
- * The database name. If not supplied via config it defaults to
14
- * `archivist`. This behavior biases towards a single, isolated
15
- * DB per archivist which seems to make the most sense for 99% of
16
- * use cases.
10
+ * The database name. If not supplied via config, it defaults
11
+ * to the archivist's name and if archivist's name is not supplied,
12
+ * it defaults to `archivist`. This behavior
13
+ * biases towards a single, isolated DB per archivist which seems to
14
+ * make the most sense for 99% of use cases.
17
15
  */
18
16
  get dbName(): string;
19
17
  /**
20
- * The database version. If not supplied via config, it defaults to 1.
18
+ * The database version. If not supplied via config, it defaults to the archivist default version.
21
19
  */
22
20
  get dbVersion(): number;
23
- /**
24
- * The database indexes.
25
- */
26
- get indexes(): import("@xyo-network/archivist-model").IndexDescription[];
27
21
  /**
28
22
  * The name of the object store. If not supplied via config, it defaults
29
23
  * to `payloads`.
@@ -32,7 +26,7 @@ export declare class IndexedDbPayloadDiviner<TParams extends IndexedDbPayloadDiv
32
26
  private get db();
33
27
  protected divineHandler(payloads?: TIn[]): Promise<TOut[]>;
34
28
  protected startHandler(): Promise<boolean>;
35
- private getKeyValuesFromQuery;
29
+ private getKeyRangeValue;
36
30
  private selectBestIndex;
37
31
  }
38
32
  //# sourceMappingURL=Diviner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Diviner.d.ts","sourceRoot":"","sources":["../../src/Diviner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AAClF,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAA;AACtE,OAAO,EAAgC,0BAA0B,EAAE,MAAM,oCAAoC,CAAA;AAG7G,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAIpD,OAAO,EAAE,6BAA6B,EAAE,MAAM,UAAU,CAAA;AAMxD,qBAAa,uBAAuB,CAClC,OAAO,SAAS,6BAA6B,GAAG,6BAA6B,EAC7E,GAAG,SAAS,0BAA0B,GAAG,0BAA0B,EACnE,IAAI,SAAS,OAAO,GAAG,OAAO,EAC9B,UAAU,SAAS,sBAAsB,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,sBAAsB,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CACxI,SAAQ,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,CAAC;IACtD,OAAgB,aAAa,WAAwC;IACrE,MAAM,CAAC,aAAa,SAAc;IAClC,MAAM,CAAC,gBAAgB,SAAI;IAC3B,MAAM,CAAC,gBAAgB,SAAa;IAEpC,OAAO,CAAC,GAAG,CAAwC;IAEnD;;;;;OAKG;IACH,IAAI,MAAM,WAET;IAED;;OAEG;IACH,IAAI,SAAS,WAEZ;IAED;;OAEG;IACH,IAAI,OAAO,8DAEV;IAED;;;OAGG;IACH,IAAI,SAAS,WAEZ;IAED,OAAO,KAAK,EAAE,GAEb;cAEwB,aAAa,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;cAqChD,YAAY;IAQrC,OAAO,CAAC,qBAAqB;IAiB7B,OAAO,CAAC,eAAe;CA2BxB"}
1
+ {"version":3,"file":"Diviner.d.ts","sourceRoot":"","sources":["../../src/Diviner.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AAClF,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAA;AACtE,OAAO,EAAgC,0BAA0B,EAAE,MAAM,oCAAoC,CAAA;AAG7G,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAIpD,OAAO,EAAE,6BAA6B,EAAE,MAAM,UAAU,CAAA;AAoBxD,qBAAa,uBAAuB,CAClC,OAAO,SAAS,6BAA6B,GAAG,6BAA6B,EAC7E,GAAG,SAAS,0BAA0B,GAAG,0BAA0B,EACnE,IAAI,SAAS,OAAO,GAAG,OAAO,EAC9B,UAAU,SAAS,sBAAsB,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,sBAAsB,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CACxI,SAAQ,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,CAAC;IACtD,OAAgB,aAAa,WAAwC;IAErE,OAAO,CAAC,GAAG,CAAwC;IAEnD;;;;;;OAMG;IACH,IAAI,MAAM,WAET;IAED;;OAEG;IACH,IAAI,SAAS,WAEZ;IAED;;;OAGG;IACH,IAAI,SAAS,WAEZ;IAED,OAAO,KAAK,EAAE,GAEb;cAEwB,aAAa,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;cAuDhD,YAAY;IAQrC,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,eAAe;CA2BxB"}
@@ -5,25 +5,19 @@ import { Payload } from '@xyo-network/payload-model';
5
5
  import { IndexedDbPayloadDivinerParams } from './Params';
6
6
  export declare class IndexedDbPayloadDiviner<TParams extends IndexedDbPayloadDivinerParams = IndexedDbPayloadDivinerParams, TIn extends PayloadDivinerQueryPayload = PayloadDivinerQueryPayload, TOut extends Payload = Payload, TEventData extends DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut> = DivinerModuleEventData<DivinerModule<TParams>, TIn, TOut>> extends PayloadDiviner<TParams, TIn, TOut, TEventData> {
7
7
  static configSchemas: string[];
8
- static defaultDbName: string;
9
- static defaultDbVersion: number;
10
- static defaultStoreName: string;
11
8
  private _db;
12
9
  /**
13
- * The database name. If not supplied via config it defaults to
14
- * `archivist`. This behavior biases towards a single, isolated
15
- * DB per archivist which seems to make the most sense for 99% of
16
- * use cases.
10
+ * The database name. If not supplied via config, it defaults
11
+ * to the archivist's name and if archivist's name is not supplied,
12
+ * it defaults to `archivist`. This behavior
13
+ * biases towards a single, isolated DB per archivist which seems to
14
+ * make the most sense for 99% of use cases.
17
15
  */
18
16
  get dbName(): string;
19
17
  /**
20
- * The database version. If not supplied via config, it defaults to 1.
18
+ * The database version. If not supplied via config, it defaults to the archivist default version.
21
19
  */
22
20
  get dbVersion(): number;
23
- /**
24
- * The database indexes.
25
- */
26
- get indexes(): import("@xyo-network/archivist-model").IndexDescription[];
27
21
  /**
28
22
  * The name of the object store. If not supplied via config, it defaults
29
23
  * to `payloads`.
@@ -32,7 +26,7 @@ export declare class IndexedDbPayloadDiviner<TParams extends IndexedDbPayloadDiv
32
26
  private get db();
33
27
  protected divineHandler(payloads?: TIn[]): Promise<TOut[]>;
34
28
  protected startHandler(): Promise<boolean>;
35
- private getKeyValuesFromQuery;
29
+ private getKeyRangeValue;
36
30
  private selectBestIndex;
37
31
  }
38
32
  //# sourceMappingURL=Diviner.d.ts.map