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

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 (77) hide show
  1. package/LICENSE +165 -0
  2. package/README.md +13 -0
  3. package/dist/browser/Config.d.cts +30 -0
  4. package/dist/browser/Config.d.cts.map +1 -0
  5. package/dist/browser/Config.d.mts +30 -0
  6. package/dist/browser/Config.d.mts.map +1 -0
  7. package/dist/browser/Config.d.ts +30 -0
  8. package/dist/browser/Config.d.ts.map +1 -0
  9. package/dist/browser/Diviner.d.cts +38 -0
  10. package/dist/browser/Diviner.d.cts.map +1 -0
  11. package/dist/browser/Diviner.d.mts +38 -0
  12. package/dist/browser/Diviner.d.mts.map +1 -0
  13. package/dist/browser/Diviner.d.ts +38 -0
  14. package/dist/browser/Diviner.d.ts.map +1 -0
  15. package/dist/browser/Params.d.cts +5 -0
  16. package/dist/browser/Params.d.cts.map +1 -0
  17. package/dist/browser/Params.d.mts +5 -0
  18. package/dist/browser/Params.d.mts.map +1 -0
  19. package/dist/browser/Params.d.ts +5 -0
  20. package/dist/browser/Params.d.ts.map +1 -0
  21. package/dist/browser/Schema.d.cts +3 -0
  22. package/dist/browser/Schema.d.cts.map +1 -0
  23. package/dist/browser/Schema.d.mts +3 -0
  24. package/dist/browser/Schema.d.mts.map +1 -0
  25. package/dist/browser/Schema.d.ts +3 -0
  26. package/dist/browser/Schema.d.ts.map +1 -0
  27. package/dist/browser/index.cjs +156 -0
  28. package/dist/browser/index.cjs.map +1 -0
  29. package/dist/browser/index.d.cts +5 -0
  30. package/dist/browser/index.d.cts.map +1 -0
  31. package/dist/browser/index.d.mts +5 -0
  32. package/dist/browser/index.d.mts.map +1 -0
  33. package/dist/browser/index.d.ts +5 -0
  34. package/dist/browser/index.d.ts.map +1 -0
  35. package/dist/browser/index.js +135 -0
  36. package/dist/browser/index.js.map +1 -0
  37. package/dist/node/Config.d.cts +30 -0
  38. package/dist/node/Config.d.cts.map +1 -0
  39. package/dist/node/Config.d.mts +30 -0
  40. package/dist/node/Config.d.mts.map +1 -0
  41. package/dist/node/Config.d.ts +30 -0
  42. package/dist/node/Config.d.ts.map +1 -0
  43. package/dist/node/Diviner.d.cts +38 -0
  44. package/dist/node/Diviner.d.cts.map +1 -0
  45. package/dist/node/Diviner.d.mts +38 -0
  46. package/dist/node/Diviner.d.mts.map +1 -0
  47. package/dist/node/Diviner.d.ts +38 -0
  48. package/dist/node/Diviner.d.ts.map +1 -0
  49. package/dist/node/Params.d.cts +5 -0
  50. package/dist/node/Params.d.cts.map +1 -0
  51. package/dist/node/Params.d.mts +5 -0
  52. package/dist/node/Params.d.mts.map +1 -0
  53. package/dist/node/Params.d.ts +5 -0
  54. package/dist/node/Params.d.ts.map +1 -0
  55. package/dist/node/Schema.d.cts +3 -0
  56. package/dist/node/Schema.d.cts.map +1 -0
  57. package/dist/node/Schema.d.mts +3 -0
  58. package/dist/node/Schema.d.mts.map +1 -0
  59. package/dist/node/Schema.d.ts +3 -0
  60. package/dist/node/Schema.d.ts.map +1 -0
  61. package/dist/node/index.cjs +171 -0
  62. package/dist/node/index.cjs.map +1 -0
  63. package/dist/node/index.d.cts +5 -0
  64. package/dist/node/index.d.cts.map +1 -0
  65. package/dist/node/index.d.mts +5 -0
  66. package/dist/node/index.d.mts.map +1 -0
  67. package/dist/node/index.d.ts +5 -0
  68. package/dist/node/index.d.ts.map +1 -0
  69. package/dist/node/index.js +144 -0
  70. package/dist/node/index.js.map +1 -0
  71. package/package.json +76 -0
  72. package/src/Config.ts +33 -0
  73. package/src/Diviner.ts +156 -0
  74. package/src/Params.ts +6 -0
  75. package/src/Schema.ts +4 -0
  76. package/src/index.ts +4 -0
  77. package/typedoc.json +5 -0
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+ var __publicField = (obj, key, value) => {
22
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
23
+ return value;
24
+ };
25
+
26
+ // src/index.ts
27
+ var src_exports = {};
28
+ __export(src_exports, {
29
+ IndexedDbPayloadDiviner: () => IndexedDbPayloadDiviner,
30
+ IndexedDbPayloadDivinerConfigSchema: () => IndexedDbPayloadDivinerConfigSchema,
31
+ IndexedDbPayloadDivinerSchema: () => IndexedDbPayloadDivinerSchema
32
+ });
33
+ module.exports = __toCommonJS(src_exports);
34
+
35
+ // src/Schema.ts
36
+ var import_diviner_payload_model = require("@xyo-network/diviner-payload-model");
37
+ var IndexedDbPayloadDivinerSchema = `${import_diviner_payload_model.PayloadDivinerSchema}.indexeddb`;
38
+
39
+ // src/Config.ts
40
+ var IndexedDbPayloadDivinerConfigSchema = `${IndexedDbPayloadDivinerSchema}.config`;
41
+
42
+ // src/Diviner.ts
43
+ var import_assert = require("@xylabs/assert");
44
+ var import_archivist_model = require("@xyo-network/archivist-model");
45
+ var import_diviner_payload_abstract = require("@xyo-network/diviner-payload-abstract");
46
+ var import_diviner_payload_model2 = require("@xyo-network/diviner-payload-model");
47
+ var import_hash = require("@xyo-network/hash");
48
+ var import_idb = require("idb");
49
+ var _IndexedDbPayloadDiviner = class _IndexedDbPayloadDiviner extends import_diviner_payload_abstract.PayloadDiviner {
50
+ _db;
51
+ /**
52
+ * The database name. If not supplied via config it defaults to
53
+ * `archivist`. This behavior biases towards a single, isolated
54
+ * DB per archivist which seems to make the most sense for 99% of
55
+ * use cases.
56
+ */
57
+ get dbName() {
58
+ var _a;
59
+ return ((_a = this.config) == null ? void 0 : _a.dbName) ?? _IndexedDbPayloadDiviner.defaultDbName;
60
+ }
61
+ /**
62
+ * The database version. If not supplied via config, it defaults to 1.
63
+ */
64
+ get dbVersion() {
65
+ var _a;
66
+ return ((_a = this.config) == null ? void 0 : _a.dbVersion) ?? _IndexedDbPayloadDiviner.defaultDbVersion;
67
+ }
68
+ /**
69
+ * The database indexes.
70
+ */
71
+ get indexes() {
72
+ var _a, _b;
73
+ return ((_b = (_a = this.config) == null ? void 0 : _a.storage) == null ? void 0 : _b.indexes) ?? [];
74
+ }
75
+ /**
76
+ * The name of the object store. If not supplied via config, it defaults
77
+ * to `payloads`.
78
+ */
79
+ get storeName() {
80
+ var _a;
81
+ return ((_a = this.config) == null ? void 0 : _a.storeName) ?? _IndexedDbPayloadDiviner.defaultStoreName;
82
+ }
83
+ get db() {
84
+ return (0, import_assert.assertEx)(this._db, "DB not initialized");
85
+ }
86
+ async divineHandler(payloads) {
87
+ var _a;
88
+ const query = (0, import_assert.assertEx)((_a = payloads == null ? void 0 : payloads.filter(import_diviner_payload_model2.isPayloadDivinerQueryPayload)) == null ? void 0 : _a.pop(), "Missing query payload");
89
+ if (!query)
90
+ return [];
91
+ const { schemas, limit, offset, hash, order, schema: _schema, sources, ...props } = query;
92
+ const tx = this.db.transaction(this.storeName, "readonly");
93
+ const store = tx.objectStore(this.storeName);
94
+ const results = [];
95
+ let parsedOffset = offset ?? 0;
96
+ const parsedLimit = limit ?? 10;
97
+ (0, import_assert.assertEx)(((schemas == null ? void 0 : schemas.length) ?? 1) === 1, "IndexedDbPayloadDiviner: Only one filter schema supported");
98
+ const filterSchema = schemas == null ? void 0 : schemas[0];
99
+ const filter = filterSchema ? {
100
+ schema: filterSchema,
101
+ ...props
102
+ } : {
103
+ ...props
104
+ };
105
+ const direction = order === "desc" ? "prev" : "next";
106
+ const suggestedIndex = this.selectBestIndex(filter, store);
107
+ const filterValues = this.getKeyValuesFromQuery(suggestedIndex, filter);
108
+ let cursor = suggestedIndex ? await store.index(suggestedIndex).openCursor(IDBKeyRange.only(filterValues.length === 1 ? filterValues[0] : filterValues), direction) : await store.openCursor(suggestedIndex, direction);
109
+ while (cursor && parsedOffset > 0) {
110
+ cursor = await cursor.advance(parsedOffset);
111
+ parsedOffset = 0;
112
+ }
113
+ while (cursor && results.length < parsedLimit) {
114
+ results.push(cursor.value);
115
+ cursor = await cursor.continue();
116
+ }
117
+ await tx.done;
118
+ return results.map((payload) => import_hash.PayloadHasher.jsonPayload(payload));
119
+ }
120
+ async startHandler() {
121
+ await super.startHandler();
122
+ this._db = await (0, import_idb.openDB)(this.dbName, this.dbVersion);
123
+ return true;
124
+ }
125
+ getKeyValuesFromQuery(indexName, query) {
126
+ if (!indexName)
127
+ return [];
128
+ const extractFields = /* @__PURE__ */ __name((indexName2) => {
129
+ return indexName2.slice(3).split(import_archivist_model.IndexSeparator).map((field) => field.toLowerCase());
130
+ }, "extractFields");
131
+ const indexFields = extractFields(indexName);
132
+ return indexFields.map((field) => query[field]);
133
+ }
134
+ selectBestIndex(query, store) {
135
+ const { indexNames } = store;
136
+ const extractFields = /* @__PURE__ */ __name((indexName) => {
137
+ return indexName.slice(3).split(import_archivist_model.IndexSeparator).map((field) => field.toLowerCase());
138
+ }, "extractFields");
139
+ const queryKeys = new Set(Object.keys(query).map((key) => key.toLowerCase()));
140
+ let bestMatch = {
141
+ indexName: "",
142
+ matchCount: 0
143
+ };
144
+ for (const indexName of indexNames) {
145
+ const indexFields = extractFields(indexName);
146
+ const matchCount = indexFields.filter((field) => queryKeys.has(field)).length;
147
+ if (matchCount > bestMatch.matchCount) {
148
+ bestMatch = {
149
+ indexName,
150
+ matchCount
151
+ };
152
+ }
153
+ }
154
+ return bestMatch.matchCount > 0 ? bestMatch.indexName : null;
155
+ }
156
+ };
157
+ __name(_IndexedDbPayloadDiviner, "IndexedDbPayloadDiviner");
158
+ __publicField(_IndexedDbPayloadDiviner, "configSchemas", [
159
+ IndexedDbPayloadDivinerConfigSchema
160
+ ]);
161
+ __publicField(_IndexedDbPayloadDiviner, "defaultDbName", "archivist");
162
+ __publicField(_IndexedDbPayloadDiviner, "defaultDbVersion", 1);
163
+ __publicField(_IndexedDbPayloadDiviner, "defaultStoreName", "payloads");
164
+ var IndexedDbPayloadDiviner = _IndexedDbPayloadDiviner;
165
+ // Annotate the CommonJS export names for ESM import in node:
166
+ 0 && (module.exports = {
167
+ IndexedDbPayloadDiviner,
168
+ IndexedDbPayloadDivinerConfigSchema,
169
+ IndexedDbPayloadDivinerSchema
170
+ });
171
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +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","_db","dbName","config","defaultDbName","dbVersion","defaultDbVersion","indexes","storage","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","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","configSchemas","IndexedDbPayloadDivinerConfigSchema"]}
@@ -0,0 +1,5 @@
1
+ export * from './Config';
2
+ export * from './Diviner';
3
+ export * from './Params';
4
+ export * from './Schema';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA;AACxB,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA"}
@@ -0,0 +1,5 @@
1
+ export * from './Config';
2
+ export * from './Diviner';
3
+ export * from './Params';
4
+ export * from './Schema';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA;AACxB,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA"}
@@ -0,0 +1,5 @@
1
+ export * from './Config';
2
+ export * from './Diviner';
3
+ export * from './Params';
4
+ export * from './Schema';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA;AACxB,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA"}
@@ -0,0 +1,144 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
4
+ var __publicField = (obj, key, value) => {
5
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
6
+ return value;
7
+ };
8
+
9
+ // src/Schema.ts
10
+ import { PayloadDivinerSchema } from "@xyo-network/diviner-payload-model";
11
+ var IndexedDbPayloadDivinerSchema = `${PayloadDivinerSchema}.indexeddb`;
12
+
13
+ // src/Config.ts
14
+ var IndexedDbPayloadDivinerConfigSchema = `${IndexedDbPayloadDivinerSchema}.config`;
15
+
16
+ // src/Diviner.ts
17
+ import { assertEx } from "@xylabs/assert";
18
+ import { IndexSeparator } from "@xyo-network/archivist-model";
19
+ import { PayloadDiviner } from "@xyo-network/diviner-payload-abstract";
20
+ import { isPayloadDivinerQueryPayload } from "@xyo-network/diviner-payload-model";
21
+ import { PayloadHasher } from "@xyo-network/hash";
22
+ import { openDB } from "idb";
23
+ var _IndexedDbPayloadDiviner = class _IndexedDbPayloadDiviner extends PayloadDiviner {
24
+ _db;
25
+ /**
26
+ * The database name. If not supplied via config it defaults to
27
+ * `archivist`. This behavior biases towards a single, isolated
28
+ * DB per archivist which seems to make the most sense for 99% of
29
+ * use cases.
30
+ */
31
+ get dbName() {
32
+ var _a;
33
+ return ((_a = this.config) == null ? void 0 : _a.dbName) ?? _IndexedDbPayloadDiviner.defaultDbName;
34
+ }
35
+ /**
36
+ * The database version. If not supplied via config, it defaults to 1.
37
+ */
38
+ get dbVersion() {
39
+ var _a;
40
+ return ((_a = this.config) == null ? void 0 : _a.dbVersion) ?? _IndexedDbPayloadDiviner.defaultDbVersion;
41
+ }
42
+ /**
43
+ * The database indexes.
44
+ */
45
+ get indexes() {
46
+ var _a, _b;
47
+ return ((_b = (_a = this.config) == null ? void 0 : _a.storage) == null ? void 0 : _b.indexes) ?? [];
48
+ }
49
+ /**
50
+ * The name of the object store. If not supplied via config, it defaults
51
+ * to `payloads`.
52
+ */
53
+ get storeName() {
54
+ var _a;
55
+ return ((_a = this.config) == null ? void 0 : _a.storeName) ?? _IndexedDbPayloadDiviner.defaultStoreName;
56
+ }
57
+ get db() {
58
+ return assertEx(this._db, "DB not initialized");
59
+ }
60
+ async divineHandler(payloads) {
61
+ var _a;
62
+ const query = assertEx((_a = payloads == null ? void 0 : payloads.filter(isPayloadDivinerQueryPayload)) == null ? void 0 : _a.pop(), "Missing query payload");
63
+ if (!query)
64
+ return [];
65
+ const { schemas, limit, offset, hash, order, schema: _schema, sources, ...props } = query;
66
+ const tx = this.db.transaction(this.storeName, "readonly");
67
+ const store = tx.objectStore(this.storeName);
68
+ const results = [];
69
+ let parsedOffset = offset ?? 0;
70
+ const parsedLimit = limit ?? 10;
71
+ assertEx(((schemas == null ? void 0 : schemas.length) ?? 1) === 1, "IndexedDbPayloadDiviner: Only one filter schema supported");
72
+ const filterSchema = schemas == null ? void 0 : schemas[0];
73
+ const filter = filterSchema ? {
74
+ schema: filterSchema,
75
+ ...props
76
+ } : {
77
+ ...props
78
+ };
79
+ const direction = order === "desc" ? "prev" : "next";
80
+ const suggestedIndex = this.selectBestIndex(filter, store);
81
+ const filterValues = this.getKeyValuesFromQuery(suggestedIndex, filter);
82
+ let cursor = suggestedIndex ? await store.index(suggestedIndex).openCursor(IDBKeyRange.only(filterValues.length === 1 ? filterValues[0] : filterValues), direction) : await store.openCursor(suggestedIndex, direction);
83
+ while (cursor && parsedOffset > 0) {
84
+ cursor = await cursor.advance(parsedOffset);
85
+ parsedOffset = 0;
86
+ }
87
+ while (cursor && results.length < parsedLimit) {
88
+ results.push(cursor.value);
89
+ cursor = await cursor.continue();
90
+ }
91
+ await tx.done;
92
+ return results.map((payload) => PayloadHasher.jsonPayload(payload));
93
+ }
94
+ async startHandler() {
95
+ await super.startHandler();
96
+ this._db = await openDB(this.dbName, this.dbVersion);
97
+ return true;
98
+ }
99
+ getKeyValuesFromQuery(indexName, query) {
100
+ if (!indexName)
101
+ return [];
102
+ const extractFields = /* @__PURE__ */ __name((indexName2) => {
103
+ return indexName2.slice(3).split(IndexSeparator).map((field) => field.toLowerCase());
104
+ }, "extractFields");
105
+ const indexFields = extractFields(indexName);
106
+ return indexFields.map((field) => query[field]);
107
+ }
108
+ selectBestIndex(query, store) {
109
+ const { indexNames } = store;
110
+ const extractFields = /* @__PURE__ */ __name((indexName) => {
111
+ return indexName.slice(3).split(IndexSeparator).map((field) => field.toLowerCase());
112
+ }, "extractFields");
113
+ const queryKeys = new Set(Object.keys(query).map((key) => key.toLowerCase()));
114
+ let bestMatch = {
115
+ indexName: "",
116
+ matchCount: 0
117
+ };
118
+ for (const indexName of indexNames) {
119
+ const indexFields = extractFields(indexName);
120
+ const matchCount = indexFields.filter((field) => queryKeys.has(field)).length;
121
+ if (matchCount > bestMatch.matchCount) {
122
+ bestMatch = {
123
+ indexName,
124
+ matchCount
125
+ };
126
+ }
127
+ }
128
+ return bestMatch.matchCount > 0 ? bestMatch.indexName : null;
129
+ }
130
+ };
131
+ __name(_IndexedDbPayloadDiviner, "IndexedDbPayloadDiviner");
132
+ __publicField(_IndexedDbPayloadDiviner, "configSchemas", [
133
+ IndexedDbPayloadDivinerConfigSchema
134
+ ]);
135
+ __publicField(_IndexedDbPayloadDiviner, "defaultDbName", "archivist");
136
+ __publicField(_IndexedDbPayloadDiviner, "defaultDbVersion", 1);
137
+ __publicField(_IndexedDbPayloadDiviner, "defaultStoreName", "payloads");
138
+ var IndexedDbPayloadDiviner = _IndexedDbPayloadDiviner;
139
+ export {
140
+ IndexedDbPayloadDiviner,
141
+ IndexedDbPayloadDivinerConfigSchema,
142
+ IndexedDbPayloadDivinerSchema
143
+ };
144
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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","_db","dbName","config","defaultDbName","dbVersion","defaultDbVersion","indexes","storage","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","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","configSchemas","IndexedDbPayloadDivinerConfigSchema"]}
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@xyo-network/diviner-payload-indexeddb",
3
+ "author": {
4
+ "email": "support@xyo.network",
5
+ "name": "XYO Development Team",
6
+ "url": "https://xyo.network"
7
+ },
8
+ "bugs": {
9
+ "email": "support@xyo.network",
10
+ "url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/issues"
11
+ },
12
+ "dependencies": {
13
+ "@xylabs/assert": "^2.13.23",
14
+ "@xyo-network/diviner-model": "~2.87.0-rc.2",
15
+ "@xyo-network/diviner-payload-abstract": "~2.87.0-rc.2",
16
+ "@xyo-network/diviner-payload-model": "~2.87.0-rc.2",
17
+ "@xyo-network/hash": "~2.87.0-rc.2",
18
+ "@xyo-network/payload-model": "~2.87.0-rc.2",
19
+ "idb": "^8.0.0"
20
+ },
21
+ "devDependencies": {
22
+ "@xylabs/ts-scripts-yarn3": "^3.2.33",
23
+ "@xylabs/tsconfig": "^3.2.33",
24
+ "@xyo-network/account": "~2.87.0-rc.2",
25
+ "@xyo-network/archivist-indexeddb": "~2.87.0-rc.2",
26
+ "@xyo-network/archivist-model": "~2.87.0-rc.2",
27
+ "@xyo-network/module-model": "~2.87.0-rc.2",
28
+ "@xyo-network/node-memory": "~2.87.0-rc.2",
29
+ "@xyo-network/object": "~2.87.0-rc.2",
30
+ "@xyo-network/payload-builder": "~2.87.0-rc.2",
31
+ "fake-indexeddb": "^5.0.2",
32
+ "typescript": "^5.3.3"
33
+ },
34
+ "description": "Primary SDK for using XYO Protocol 2.0",
35
+ "types": "dist/node/index.d.ts",
36
+ "exports": {
37
+ ".": {
38
+ "browser": {
39
+ "require": {
40
+ "types": "./dist/browser/index.d.cts",
41
+ "default": "./dist/browser/index.cjs"
42
+ },
43
+ "import": {
44
+ "types": "./dist/browser/index.d.mts",
45
+ "default": "./dist/browser/index.js"
46
+ }
47
+ },
48
+ "node": {
49
+ "require": {
50
+ "types": "./dist/node/index.d.cts",
51
+ "default": "./dist/node/index.cjs"
52
+ },
53
+ "import": {
54
+ "types": "./dist/node/index.d.mts",
55
+ "default": "./dist/node/index.js"
56
+ }
57
+ }
58
+ },
59
+ "./package.json": "./package.json"
60
+ },
61
+ "main": "dist/node/index.cjs",
62
+ "module": "dist/node/index.js",
63
+ "homepage": "https://xyo.network",
64
+ "license": "LGPL-3.0-only",
65
+ "publishConfig": {
66
+ "access": "public"
67
+ },
68
+ "repository": {
69
+ "type": "git",
70
+ "url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js.git"
71
+ },
72
+ "sideEffects": false,
73
+ "version": "2.87.0-rc.2",
74
+ "type": "module",
75
+ "stableVersion": "2.86.1"
76
+ }
package/src/Config.ts ADDED
@@ -0,0 +1,33 @@
1
+ import { IndexDescription } from '@xyo-network/archivist-model'
2
+ import { DivinerConfig } from '@xyo-network/diviner-model'
3
+
4
+ import { IndexedDbPayloadDivinerSchema } from './Schema'
5
+
6
+ export const IndexedDbPayloadDivinerConfigSchema = `${IndexedDbPayloadDivinerSchema}.config`
7
+ export type IndexedDbPayloadDivinerConfigSchema = typeof IndexedDbPayloadDivinerConfigSchema
8
+
9
+ export type IndexedDbPayloadDivinerConfig = DivinerConfig<{
10
+ /**
11
+ * The database name
12
+ */
13
+ dbName?: string
14
+ /**
15
+ * The version of the DB, defaults to 1
16
+ */
17
+ dbVersion?: number
18
+ schema: IndexedDbPayloadDivinerConfigSchema
19
+ /**
20
+ * The storage configuration
21
+ * // TODO: Hoist to main diviner config
22
+ */
23
+ storage?: {
24
+ /**
25
+ * The indexes to create on the object store
26
+ */
27
+ indexes?: IndexDescription[]
28
+ }
29
+ /**
30
+ * The name of the object store
31
+ */
32
+ storeName?: string
33
+ }>