@xyo-network/archivist-indexeddb 2.87.0-rc.2 → 2.87.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/Archivist.d.cts +6 -8
- package/dist/browser/Archivist.d.cts.map +1 -1
- package/dist/browser/Archivist.d.mts +6 -8
- package/dist/browser/Archivist.d.mts.map +1 -1
- package/dist/browser/Archivist.d.ts +6 -8
- package/dist/browser/Archivist.d.ts.map +1 -1
- package/dist/browser/index.cjs +15 -25
- package/dist/browser/index.cjs.map +1 -1
- package/dist/browser/index.js +15 -25
- package/dist/browser/index.js.map +1 -1
- package/dist/node/Archivist.d.cts +6 -8
- package/dist/node/Archivist.d.cts.map +1 -1
- package/dist/node/Archivist.d.mts +6 -8
- package/dist/node/Archivist.d.mts.map +1 -1
- package/dist/node/Archivist.d.ts +6 -8
- package/dist/node/Archivist.d.ts.map +1 -1
- package/dist/node/index.cjs +16 -26
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.js +16 -26
- package/dist/node/index.js.map +1 -1
- package/package.json +9 -9
- package/src/Archivist.ts +18 -23
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AbstractArchivist } from '@xyo-network/archivist-abstract';
|
|
2
|
-
import { ArchivistModuleEventData
|
|
2
|
+
import { ArchivistModuleEventData } from '@xyo-network/archivist-model';
|
|
3
3
|
import { Payload } from '@xyo-network/payload-model';
|
|
4
4
|
import { IndexedDbArchivistParams } from './Params';
|
|
5
5
|
export interface PayloadStore {
|
|
@@ -10,9 +10,10 @@ export declare class IndexedDbArchivist<TParams extends IndexedDbArchivistParams
|
|
|
10
10
|
static readonly defaultDbName = "archivist";
|
|
11
11
|
static readonly defaultDbVersion = 1;
|
|
12
12
|
static readonly defaultStoreName = "payloads";
|
|
13
|
-
static readonly hashIndex
|
|
14
|
-
static readonly
|
|
15
|
-
static readonly
|
|
13
|
+
private static readonly hashIndex;
|
|
14
|
+
private static readonly schemaIndex;
|
|
15
|
+
static readonly hashIndexName: string;
|
|
16
|
+
static readonly schemaIndexName: string;
|
|
16
17
|
private _db;
|
|
17
18
|
/**
|
|
18
19
|
* The database name. If not supplied via config, it defaults
|
|
@@ -26,10 +27,6 @@ export declare class IndexedDbArchivist<TParams extends IndexedDbArchivistParams
|
|
|
26
27
|
* The database version. If not supplied via config, it defaults to 1.
|
|
27
28
|
*/
|
|
28
29
|
get dbVersion(): number;
|
|
29
|
-
/**
|
|
30
|
-
* The database indexes.
|
|
31
|
-
*/
|
|
32
|
-
get indexes(): IndexDescription[];
|
|
33
30
|
get queries(): string[];
|
|
34
31
|
/**
|
|
35
32
|
* The name of the object store. If not supplied via config, it defaults
|
|
@@ -37,6 +34,7 @@ export declare class IndexedDbArchivist<TParams extends IndexedDbArchivistParams
|
|
|
37
34
|
*/
|
|
38
35
|
get storeName(): string;
|
|
39
36
|
private get db();
|
|
37
|
+
private get indexes();
|
|
40
38
|
protected allHandler(): Promise<Payload[]>;
|
|
41
39
|
protected clearHandler(): Promise<void>;
|
|
42
40
|
protected deleteHandler(hashes: string[]): Promise<string[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Archivist.d.ts","sourceRoot":"","sources":["../../src/Archivist.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAKL,wBAAwB,
|
|
1
|
+
{"version":3,"file":"Archivist.d.ts","sourceRoot":"","sources":["../../src/Archivist.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAKL,wBAAwB,EAGzB,MAAM,8BAA8B,CAAA;AAGrC,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAIpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAA;AAEnD,MAAM,WAAW,YAAY;IAC3B,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB;AAED,qBACa,kBAAkB,CAC7B,OAAO,SAAS,wBAAwB,GAAG,wBAAwB,EACnE,UAAU,SAAS,wBAAwB,GAAG,wBAAwB,CACtE,SAAQ,iBAAiB,CAAC,OAAO,EAAE,UAAU,CAAC;IAC9C,OAAgB,aAAa,6CAAmC;IAChE,MAAM,CAAC,QAAQ,CAAC,aAAa,eAAc;IAC3C,MAAM,CAAC,QAAQ,CAAC,gBAAgB,KAAI;IACpC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,cAAa;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAA2E;IAC5G,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAA6E;IAEhH,MAAM,CAAC,QAAQ,CAAC,aAAa,SAAuD;IAEpF,MAAM,CAAC,QAAQ,CAAC,eAAe,SAAyD;IAExF,OAAO,CAAC,GAAG,CAAwC;IAEnD;;;;;;OAMG;IACH,IAAI,MAAM,WAET;IAED;;OAEG;IACH,IAAI,SAAS,WAEZ;IAED,IAAa,OAAO,aAEnB;IAED;;;OAGG;IACH,IAAI,SAAS,WAEZ;IAED,OAAO,KAAK,EAAE,GAEb;IAED,OAAO,KAAK,OAAO,GAElB;cAEwB,UAAU,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;cAOhC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;cAI7B,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;cAgBlD,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;cAKhD,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;cAiBtD,YAAY;CA2BtC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AbstractArchivist } from '@xyo-network/archivist-abstract';
|
|
2
|
-
import { ArchivistModuleEventData
|
|
2
|
+
import { ArchivistModuleEventData } from '@xyo-network/archivist-model';
|
|
3
3
|
import { Payload } from '@xyo-network/payload-model';
|
|
4
4
|
import { IndexedDbArchivistParams } from './Params';
|
|
5
5
|
export interface PayloadStore {
|
|
@@ -10,9 +10,10 @@ export declare class IndexedDbArchivist<TParams extends IndexedDbArchivistParams
|
|
|
10
10
|
static readonly defaultDbName = "archivist";
|
|
11
11
|
static readonly defaultDbVersion = 1;
|
|
12
12
|
static readonly defaultStoreName = "payloads";
|
|
13
|
-
static readonly hashIndex
|
|
14
|
-
static readonly
|
|
15
|
-
static readonly
|
|
13
|
+
private static readonly hashIndex;
|
|
14
|
+
private static readonly schemaIndex;
|
|
15
|
+
static readonly hashIndexName: string;
|
|
16
|
+
static readonly schemaIndexName: string;
|
|
16
17
|
private _db;
|
|
17
18
|
/**
|
|
18
19
|
* The database name. If not supplied via config, it defaults
|
|
@@ -26,10 +27,6 @@ export declare class IndexedDbArchivist<TParams extends IndexedDbArchivistParams
|
|
|
26
27
|
* The database version. If not supplied via config, it defaults to 1.
|
|
27
28
|
*/
|
|
28
29
|
get dbVersion(): number;
|
|
29
|
-
/**
|
|
30
|
-
* The database indexes.
|
|
31
|
-
*/
|
|
32
|
-
get indexes(): IndexDescription[];
|
|
33
30
|
get queries(): string[];
|
|
34
31
|
/**
|
|
35
32
|
* The name of the object store. If not supplied via config, it defaults
|
|
@@ -37,6 +34,7 @@ export declare class IndexedDbArchivist<TParams extends IndexedDbArchivistParams
|
|
|
37
34
|
*/
|
|
38
35
|
get storeName(): string;
|
|
39
36
|
private get db();
|
|
37
|
+
private get indexes();
|
|
40
38
|
protected allHandler(): Promise<Payload[]>;
|
|
41
39
|
protected clearHandler(): Promise<void>;
|
|
42
40
|
protected deleteHandler(hashes: string[]): Promise<string[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Archivist.d.ts","sourceRoot":"","sources":["../../src/Archivist.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAKL,wBAAwB,
|
|
1
|
+
{"version":3,"file":"Archivist.d.ts","sourceRoot":"","sources":["../../src/Archivist.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAKL,wBAAwB,EAGzB,MAAM,8BAA8B,CAAA;AAGrC,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAIpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAA;AAEnD,MAAM,WAAW,YAAY;IAC3B,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB;AAED,qBACa,kBAAkB,CAC7B,OAAO,SAAS,wBAAwB,GAAG,wBAAwB,EACnE,UAAU,SAAS,wBAAwB,GAAG,wBAAwB,CACtE,SAAQ,iBAAiB,CAAC,OAAO,EAAE,UAAU,CAAC;IAC9C,OAAgB,aAAa,6CAAmC;IAChE,MAAM,CAAC,QAAQ,CAAC,aAAa,eAAc;IAC3C,MAAM,CAAC,QAAQ,CAAC,gBAAgB,KAAI;IACpC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,cAAa;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAA2E;IAC5G,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAA6E;IAEhH,MAAM,CAAC,QAAQ,CAAC,aAAa,SAAuD;IAEpF,MAAM,CAAC,QAAQ,CAAC,eAAe,SAAyD;IAExF,OAAO,CAAC,GAAG,CAAwC;IAEnD;;;;;;OAMG;IACH,IAAI,MAAM,WAET;IAED;;OAEG;IACH,IAAI,SAAS,WAEZ;IAED,IAAa,OAAO,aAEnB;IAED;;;OAGG;IACH,IAAI,SAAS,WAEZ;IAED,OAAO,KAAK,EAAE,GAEb;IAED,OAAO,KAAK,OAAO,GAElB;cAEwB,UAAU,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;cAOhC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;cAI7B,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;cAgBlD,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;cAKhD,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;cAiBtD,YAAY;CA2BtC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AbstractArchivist } from '@xyo-network/archivist-abstract';
|
|
2
|
-
import { ArchivistModuleEventData
|
|
2
|
+
import { ArchivistModuleEventData } from '@xyo-network/archivist-model';
|
|
3
3
|
import { Payload } from '@xyo-network/payload-model';
|
|
4
4
|
import { IndexedDbArchivistParams } from './Params';
|
|
5
5
|
export interface PayloadStore {
|
|
@@ -10,9 +10,10 @@ export declare class IndexedDbArchivist<TParams extends IndexedDbArchivistParams
|
|
|
10
10
|
static readonly defaultDbName = "archivist";
|
|
11
11
|
static readonly defaultDbVersion = 1;
|
|
12
12
|
static readonly defaultStoreName = "payloads";
|
|
13
|
-
static readonly hashIndex
|
|
14
|
-
static readonly
|
|
15
|
-
static readonly
|
|
13
|
+
private static readonly hashIndex;
|
|
14
|
+
private static readonly schemaIndex;
|
|
15
|
+
static readonly hashIndexName: string;
|
|
16
|
+
static readonly schemaIndexName: string;
|
|
16
17
|
private _db;
|
|
17
18
|
/**
|
|
18
19
|
* The database name. If not supplied via config, it defaults
|
|
@@ -26,10 +27,6 @@ export declare class IndexedDbArchivist<TParams extends IndexedDbArchivistParams
|
|
|
26
27
|
* The database version. If not supplied via config, it defaults to 1.
|
|
27
28
|
*/
|
|
28
29
|
get dbVersion(): number;
|
|
29
|
-
/**
|
|
30
|
-
* The database indexes.
|
|
31
|
-
*/
|
|
32
|
-
get indexes(): IndexDescription[];
|
|
33
30
|
get queries(): string[];
|
|
34
31
|
/**
|
|
35
32
|
* The name of the object store. If not supplied via config, it defaults
|
|
@@ -37,6 +34,7 @@ export declare class IndexedDbArchivist<TParams extends IndexedDbArchivistParams
|
|
|
37
34
|
*/
|
|
38
35
|
get storeName(): string;
|
|
39
36
|
private get db();
|
|
37
|
+
private get indexes();
|
|
40
38
|
protected allHandler(): Promise<Payload[]>;
|
|
41
39
|
protected clearHandler(): Promise<void>;
|
|
42
40
|
protected deleteHandler(hashes: string[]): Promise<string[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Archivist.d.ts","sourceRoot":"","sources":["../../src/Archivist.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAKL,wBAAwB,
|
|
1
|
+
{"version":3,"file":"Archivist.d.ts","sourceRoot":"","sources":["../../src/Archivist.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAKL,wBAAwB,EAGzB,MAAM,8BAA8B,CAAA;AAGrC,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAIpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAA;AAEnD,MAAM,WAAW,YAAY;IAC3B,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB;AAED,qBACa,kBAAkB,CAC7B,OAAO,SAAS,wBAAwB,GAAG,wBAAwB,EACnE,UAAU,SAAS,wBAAwB,GAAG,wBAAwB,CACtE,SAAQ,iBAAiB,CAAC,OAAO,EAAE,UAAU,CAAC;IAC9C,OAAgB,aAAa,6CAAmC;IAChE,MAAM,CAAC,QAAQ,CAAC,aAAa,eAAc;IAC3C,MAAM,CAAC,QAAQ,CAAC,gBAAgB,KAAI;IACpC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,cAAa;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAA2E;IAC5G,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAA6E;IAEhH,MAAM,CAAC,QAAQ,CAAC,aAAa,SAAuD;IAEpF,MAAM,CAAC,QAAQ,CAAC,eAAe,SAAyD;IAExF,OAAO,CAAC,GAAG,CAAwC;IAEnD;;;;;;OAMG;IACH,IAAI,MAAM,WAET;IAED;;OAEG;IACH,IAAI,SAAS,WAEZ;IAED,IAAa,OAAO,aAEnB;IAED;;;OAGG;IACH,IAAI,SAAS,WAEZ;IAED,OAAO,KAAK,EAAE,GAEb;IAED,OAAO,KAAK,OAAO,GAElB;cAEwB,UAAU,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;cAOhC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;cAI7B,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;cAgBlD,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;cAKhD,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;cAiBtD,YAAY;CA2BtC"}
|
package/dist/browser/index.cjs
CHANGED
|
@@ -69,25 +69,19 @@ var IndexedDbArchivist = class _IndexedDbArchivist extends import_archivist_abst
|
|
|
69
69
|
_hash: 1
|
|
70
70
|
},
|
|
71
71
|
multiEntry: false,
|
|
72
|
-
name: "IX-_hash",
|
|
73
72
|
unique: true
|
|
74
73
|
};
|
|
75
|
-
static payloadSchemasIndex = {
|
|
76
|
-
key: {
|
|
77
|
-
payload_schemas: 1
|
|
78
|
-
},
|
|
79
|
-
multiEntry: false,
|
|
80
|
-
name: "IX-payload_schemas",
|
|
81
|
-
unique: false
|
|
82
|
-
};
|
|
83
74
|
static schemaIndex = {
|
|
84
75
|
key: {
|
|
85
76
|
schema: 1
|
|
86
77
|
},
|
|
87
78
|
multiEntry: false,
|
|
88
|
-
name: "IX-schema",
|
|
89
79
|
unique: false
|
|
90
80
|
};
|
|
81
|
+
// eslint-disable-next-line @typescript-eslint/member-ordering
|
|
82
|
+
static hashIndexName = (0, import_archivist_model.buildStandardIndexName)(_IndexedDbArchivist.hashIndex);
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/member-ordering
|
|
84
|
+
static schemaIndexName = (0, import_archivist_model.buildStandardIndexName)(_IndexedDbArchivist.schemaIndex);
|
|
91
85
|
_db;
|
|
92
86
|
/**
|
|
93
87
|
* The database name. If not supplied via config, it defaults
|
|
@@ -105,12 +99,6 @@ var IndexedDbArchivist = class _IndexedDbArchivist extends import_archivist_abst
|
|
|
105
99
|
get dbVersion() {
|
|
106
100
|
return this.config?.dbVersion ?? _IndexedDbArchivist.defaultDbVersion;
|
|
107
101
|
}
|
|
108
|
-
/**
|
|
109
|
-
* The database indexes.
|
|
110
|
-
*/
|
|
111
|
-
get indexes() {
|
|
112
|
-
return this.config?.storage?.indexes ?? [];
|
|
113
|
-
}
|
|
114
102
|
get queries() {
|
|
115
103
|
return [
|
|
116
104
|
import_archivist_model.ArchivistAllQuerySchema,
|
|
@@ -130,6 +118,9 @@ var IndexedDbArchivist = class _IndexedDbArchivist extends import_archivist_abst
|
|
|
130
118
|
get db() {
|
|
131
119
|
return (0, import_assert.assertEx)(this._db, "DB not initialized");
|
|
132
120
|
}
|
|
121
|
+
get indexes() {
|
|
122
|
+
return this.config?.storage?.indexes ?? [];
|
|
123
|
+
}
|
|
133
124
|
async allHandler() {
|
|
134
125
|
const payloads = await this.db.getAll(this.storeName);
|
|
135
126
|
return payloads.map((payload) => import_hash.PayloadHasher.jsonPayload(payload));
|
|
@@ -144,7 +135,7 @@ var IndexedDbArchivist = class _IndexedDbArchivist extends import_archivist_abst
|
|
|
144
135
|
const found = await Promise.all(distinctHashes.map(async (hash) => {
|
|
145
136
|
let existing;
|
|
146
137
|
do {
|
|
147
|
-
existing = await this.db.getKeyFromIndex(this.storeName, _IndexedDbArchivist.
|
|
138
|
+
existing = await this.db.getKeyFromIndex(this.storeName, _IndexedDbArchivist.hashIndexName, hash);
|
|
148
139
|
if (existing)
|
|
149
140
|
await this.db.delete(this.storeName, existing);
|
|
150
141
|
} while (!existing);
|
|
@@ -153,7 +144,7 @@ var IndexedDbArchivist = class _IndexedDbArchivist extends import_archivist_abst
|
|
|
153
144
|
return found.filter(import_exists.exists);
|
|
154
145
|
}
|
|
155
146
|
async getHandler(hashes) {
|
|
156
|
-
const payloads = await Promise.all(hashes.map((hash) => this.db.getFromIndex(this.storeName, _IndexedDbArchivist.
|
|
147
|
+
const payloads = await Promise.all(hashes.map((hash) => this.db.getFromIndex(this.storeName, _IndexedDbArchivist.hashIndexName, hash)));
|
|
157
148
|
return payloads.filter(import_exists.exists);
|
|
158
149
|
}
|
|
159
150
|
async insertHandler(payloads) {
|
|
@@ -161,7 +152,7 @@ var IndexedDbArchivist = class _IndexedDbArchivist extends import_archivist_abst
|
|
|
161
152
|
const inserted = await Promise.all(pairs.map(async ([payload, _hash]) => {
|
|
162
153
|
const tx = this.db.transaction(this.storeName, "readwrite");
|
|
163
154
|
const store = tx.objectStore(this.storeName);
|
|
164
|
-
const existing = await store.index(_IndexedDbArchivist.
|
|
155
|
+
const existing = await store.index(_IndexedDbArchivist.hashIndexName).get(_hash);
|
|
165
156
|
if (!existing) {
|
|
166
157
|
await this.db.put(this.storeName, {
|
|
167
158
|
...payload,
|
|
@@ -174,7 +165,7 @@ var IndexedDbArchivist = class _IndexedDbArchivist extends import_archivist_abst
|
|
|
174
165
|
}
|
|
175
166
|
async startHandler() {
|
|
176
167
|
await super.startHandler();
|
|
177
|
-
const {
|
|
168
|
+
const { dbName, dbVersion, indexes, storeName } = this;
|
|
178
169
|
this._db = await (0, import_idb.openDB)(dbName, dbVersion, {
|
|
179
170
|
async upgrade(database) {
|
|
180
171
|
await Promise.resolve();
|
|
@@ -184,15 +175,14 @@ var IndexedDbArchivist = class _IndexedDbArchivist extends import_archivist_abst
|
|
|
184
175
|
});
|
|
185
176
|
store.name = storeName;
|
|
186
177
|
const indexesToCreate = [
|
|
187
|
-
...indexes,
|
|
188
178
|
_IndexedDbArchivist.hashIndex,
|
|
189
|
-
_IndexedDbArchivist.
|
|
190
|
-
|
|
179
|
+
_IndexedDbArchivist.schemaIndex,
|
|
180
|
+
...indexes
|
|
191
181
|
];
|
|
192
|
-
for (const { key, multiEntry,
|
|
182
|
+
for (const { key, multiEntry, unique } of indexesToCreate) {
|
|
193
183
|
const indexKeys = Object.keys(key);
|
|
194
184
|
const keys = indexKeys.length === 1 ? indexKeys[0] : indexKeys;
|
|
195
|
-
const indexName =
|
|
185
|
+
const indexName = (0, import_archivist_model.buildStandardIndexName)({
|
|
196
186
|
key,
|
|
197
187
|
unique
|
|
198
188
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts","../../src/Archivist.ts","../../src/Schema.ts","../../src/Config.ts"],"sourcesContent":["export * from './Archivist'\nexport * from './Config'\nexport * from './Params'\nexport * from './Schema'\n","import { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport { AbstractArchivist } from '@xyo-network/archivist-abstract'\nimport {\n ArchivistAllQuerySchema,\n ArchivistClearQuerySchema,\n ArchivistDeleteQuerySchema,\n ArchivistInsertQuerySchema,\n ArchivistModuleEventData,\n buildStandardIndexName,\n IndexDescription,\n} from '@xyo-network/archivist-model'\nimport { PayloadHasher } from '@xyo-network/hash'\nimport { creatableModule } from '@xyo-network/module-model'\nimport { Payload } from '@xyo-network/payload-model'\nimport { IDBPDatabase, openDB } from 'idb'\n\nimport { IndexedDbArchivistConfigSchema } from './Config'\nimport { IndexedDbArchivistParams } from './Params'\n\nexport interface PayloadStore {\n [s: string]: Payload\n}\n\n@creatableModule()\nexport class IndexedDbArchivist<\n TParams extends IndexedDbArchivistParams = IndexedDbArchivistParams,\n TEventData extends ArchivistModuleEventData = ArchivistModuleEventData,\n> extends AbstractArchivist<TParams, TEventData> {\n static override configSchemas = [IndexedDbArchivistConfigSchema]\n static readonly defaultDbName = 'archivist'\n static readonly defaultDbVersion = 1\n static readonly defaultStoreName = 'payloads'\n static readonly hashIndex: Required<IndexDescription> = { key: { _hash: 1 }, multiEntry: false, name: 'IX-_hash', unique: true }\n static readonly payloadSchemasIndex: Required<IndexDescription> = {\n key: { payload_schemas: 1 },\n multiEntry: false,\n name: 'IX-payload_schemas',\n unique: false,\n }\n static readonly schemaIndex: Required<IndexDescription> = { key: { schema: 1 }, multiEntry: false, name: 'IX-schema', unique: false }\n\n private _db: IDBPDatabase<PayloadStore> | undefined\n\n /**\n * The database name. If not supplied via config, it defaults\n * to the module name (not guaranteed to be unique) and if module\n * name is not supplied, 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?.name ?? IndexedDbArchivist.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 ?? IndexedDbArchivist.defaultDbVersion\n }\n\n /**\n * The database indexes.\n */\n get indexes() {\n return this.config?.storage?.indexes ?? []\n }\n\n override get queries() {\n return [ArchivistAllQuerySchema, ArchivistClearQuerySchema, ArchivistDeleteQuerySchema, ArchivistInsertQuerySchema, ...super.queries]\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 allHandler(): Promise<Payload[]> {\n // Get all payloads from the store\n const payloads = await this.db.getAll(this.storeName)\n // Remove any metadata before returning to the client\n return payloads.map((payload) => PayloadHasher.jsonPayload(payload))\n }\n\n protected override async clearHandler(): Promise<void> {\n await this.db.clear(this.storeName)\n }\n\n protected override async deleteHandler(hashes: string[]): Promise<string[]> {\n const distinctHashes = [...new Set(hashes)]\n const found = await Promise.all(\n distinctHashes.map(async (hash) => {\n let existing: IDBValidKey | undefined\n do {\n existing = await this.db.getKeyFromIndex(this.storeName, IndexedDbArchivist.hashIndex.name, hash)\n if (existing) await this.db.delete(this.storeName, existing)\n } while (!existing)\n return hash\n }),\n )\n // Return hashes removed\n return found.filter(exists)\n }\n\n protected override async getHandler(hashes: string[]): Promise<Payload[]> {\n const payloads = await Promise.all(hashes.map((hash) => this.db.getFromIndex(this.storeName, IndexedDbArchivist.hashIndex.name, hash)))\n return payloads.filter(exists)\n }\n\n protected override async insertHandler(payloads: Payload[]): Promise<Payload[]> {\n const pairs = await PayloadHasher.hashPairs(payloads)\n // Only return the payloads that were successfully inserted\n const inserted = await Promise.all(\n pairs.map(async ([payload, _hash]) => {\n const tx = this.db.transaction(this.storeName, 'readwrite')\n const store = tx.objectStore(this.storeName)\n const existing = await store.index(IndexedDbArchivist.hashIndex.name).get(_hash)\n if (!existing) {\n await this.db.put(this.storeName, { ...payload, _hash })\n return payload\n }\n }),\n )\n return inserted.filter(exists)\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 const { indexes, storeName, dbName, dbVersion } = this\n this._db = await openDB<PayloadStore>(dbName, dbVersion, {\n async upgrade(database) {\n await Promise.resolve() // Async to match spec\n // Create the store\n const store = database.createObjectStore(storeName, {\n // If it isn't explicitly set, create a value by auto incrementing.\n autoIncrement: true,\n })\n // Name the store\n store.name = storeName\n // Create an index on the hash\n const indexesToCreate = [...indexes, IndexedDbArchivist.hashIndex, IndexedDbArchivist.payloadSchemasIndex, IndexedDbArchivist.schemaIndex]\n for (const { key, multiEntry, name, unique } of indexesToCreate) {\n const indexKeys = Object.keys(key)\n const keys = indexKeys.length === 1 ? indexKeys[0] : indexKeys\n const indexName = name ?? buildStandardIndexName({ key, unique })\n store.createIndex(indexName, keys, { multiEntry, unique })\n }\n },\n })\n\n return true\n }\n}\n","export type IndexedDbArchivistSchema = 'network.xyo.archivist.indexeddb'\nexport const IndexedDbArchivistSchema: IndexedDbArchivistSchema = 'network.xyo.archivist.indexeddb'\n","import { ArchivistConfig, IndexDescription } from '@xyo-network/archivist-model'\n\nimport { IndexedDbArchivistSchema } from './Schema'\n\nexport type IndexedDbArchivistConfigSchema = `${IndexedDbArchivistSchema}.config`\nexport const IndexedDbArchivistConfigSchema: IndexedDbArchivistConfigSchema = `${IndexedDbArchivistSchema}.config`\n\nexport type IndexedDbArchivistConfig = ArchivistConfig<{\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: IndexedDbArchivistConfigSchema\n /**\n * The storage configuration\n * // TODO: Hoist to main archivist 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"],"mappings":"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","names":["IndexedDbArchivistSchema","IndexedDbArchivistConfigSchema","IndexedDbArchivistSchema","IndexedDbArchivist","AbstractArchivist","configSchemas","IndexedDbArchivistConfigSchema","defaultDbName","defaultDbVersion","defaultStoreName","hashIndex","key","_hash","multiEntry","name","unique","payloadSchemasIndex","payload_schemas","schemaIndex","schema","_db","dbName","config","dbVersion","indexes","storage","queries","ArchivistAllQuerySchema","ArchivistClearQuerySchema","ArchivistDeleteQuerySchema","ArchivistInsertQuerySchema","storeName","db","assertEx","allHandler","payloads","getAll","map","payload","PayloadHasher","jsonPayload","clearHandler","clear","deleteHandler","hashes","distinctHashes","Set","found","Promise","all","hash","existing","getKeyFromIndex","delete","filter","exists","getHandler","getFromIndex","insertHandler","pairs","hashPairs","inserted","tx","transaction","store","objectStore","index","get","put","startHandler","openDB","upgrade","database","resolve","createObjectStore","autoIncrement","indexesToCreate","indexKeys","Object","keys","length","indexName","buildStandardIndexName","createIndex","creatableModule"]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts","../../src/Archivist.ts","../../src/Schema.ts","../../src/Config.ts"],"sourcesContent":["export * from './Archivist'\nexport * from './Config'\nexport * from './Params'\nexport * from './Schema'\n","import { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport { AbstractArchivist } from '@xyo-network/archivist-abstract'\nimport {\n ArchivistAllQuerySchema,\n ArchivistClearQuerySchema,\n ArchivistDeleteQuerySchema,\n ArchivistInsertQuerySchema,\n ArchivistModuleEventData,\n buildStandardIndexName,\n IndexDescription,\n} from '@xyo-network/archivist-model'\nimport { PayloadHasher } from '@xyo-network/hash'\nimport { creatableModule } from '@xyo-network/module-model'\nimport { Payload } from '@xyo-network/payload-model'\nimport { IDBPDatabase, openDB } from 'idb'\n\nimport { IndexedDbArchivistConfigSchema } from './Config'\nimport { IndexedDbArchivistParams } from './Params'\n\nexport interface PayloadStore {\n [s: string]: Payload\n}\n\n@creatableModule()\nexport class IndexedDbArchivist<\n TParams extends IndexedDbArchivistParams = IndexedDbArchivistParams,\n TEventData extends ArchivistModuleEventData = ArchivistModuleEventData,\n> extends AbstractArchivist<TParams, TEventData> {\n static override configSchemas = [IndexedDbArchivistConfigSchema]\n static readonly defaultDbName = 'archivist'\n static readonly defaultDbVersion = 1\n static readonly defaultStoreName = 'payloads'\n private static readonly hashIndex: IndexDescription = { key: { _hash: 1 }, multiEntry: false, unique: true }\n private static readonly schemaIndex: IndexDescription = { key: { schema: 1 }, multiEntry: false, unique: false }\n // eslint-disable-next-line @typescript-eslint/member-ordering\n static readonly hashIndexName = buildStandardIndexName(IndexedDbArchivist.hashIndex)\n // eslint-disable-next-line @typescript-eslint/member-ordering\n static readonly schemaIndexName = buildStandardIndexName(IndexedDbArchivist.schemaIndex)\n\n private _db: IDBPDatabase<PayloadStore> | undefined\n\n /**\n * The database name. If not supplied via config, it defaults\n * to the module name (not guaranteed to be unique) and if module\n * name is not supplied, 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?.name ?? IndexedDbArchivist.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 ?? IndexedDbArchivist.defaultDbVersion\n }\n\n override get queries() {\n return [ArchivistAllQuerySchema, ArchivistClearQuerySchema, ArchivistDeleteQuerySchema, ArchivistInsertQuerySchema, ...super.queries]\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 private get indexes() {\n return this.config?.storage?.indexes ?? []\n }\n\n protected override async allHandler(): Promise<Payload[]> {\n // Get all payloads from the store\n const payloads = await this.db.getAll(this.storeName)\n // Remove any metadata before returning to the client\n return payloads.map((payload) => PayloadHasher.jsonPayload(payload))\n }\n\n protected override async clearHandler(): Promise<void> {\n await this.db.clear(this.storeName)\n }\n\n protected override async deleteHandler(hashes: string[]): Promise<string[]> {\n const distinctHashes = [...new Set(hashes)]\n const found = await Promise.all(\n distinctHashes.map(async (hash) => {\n let existing: IDBValidKey | undefined\n do {\n existing = await this.db.getKeyFromIndex(this.storeName, IndexedDbArchivist.hashIndexName, hash)\n if (existing) await this.db.delete(this.storeName, existing)\n } while (!existing)\n return hash\n }),\n )\n // Return hashes removed\n return found.filter(exists)\n }\n\n protected override async getHandler(hashes: string[]): Promise<Payload[]> {\n const payloads = await Promise.all(hashes.map((hash) => this.db.getFromIndex(this.storeName, IndexedDbArchivist.hashIndexName, hash)))\n return payloads.filter(exists)\n }\n\n protected override async insertHandler(payloads: Payload[]): Promise<Payload[]> {\n const pairs = await PayloadHasher.hashPairs(payloads)\n // Only return the payloads that were successfully inserted\n const inserted = await Promise.all(\n pairs.map(async ([payload, _hash]) => {\n const tx = this.db.transaction(this.storeName, 'readwrite')\n const store = tx.objectStore(this.storeName)\n const existing = await store.index(IndexedDbArchivist.hashIndexName).get(_hash)\n if (!existing) {\n await this.db.put(this.storeName, { ...payload, _hash })\n return payload\n }\n }),\n )\n return inserted.filter(exists)\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 const { dbName, dbVersion, indexes, storeName } = this\n this._db = await openDB<PayloadStore>(dbName, dbVersion, {\n async upgrade(database) {\n await Promise.resolve() // Async to match spec\n // Create the store\n const store = database.createObjectStore(storeName, {\n // If it isn't explicitly set, create a value by auto incrementing.\n autoIncrement: true,\n })\n // Name the store\n store.name = storeName\n // Create an index on the hash\n const indexesToCreate = [IndexedDbArchivist.hashIndex, IndexedDbArchivist.schemaIndex, ...indexes]\n for (const { key, multiEntry, unique } of indexesToCreate) {\n const indexKeys = Object.keys(key)\n const keys = indexKeys.length === 1 ? indexKeys[0] : indexKeys\n const indexName = buildStandardIndexName({ key, unique })\n store.createIndex(indexName, keys, { multiEntry, unique })\n }\n },\n })\n return true\n }\n}\n","export type IndexedDbArchivistSchema = 'network.xyo.archivist.indexeddb'\nexport const IndexedDbArchivistSchema: IndexedDbArchivistSchema = 'network.xyo.archivist.indexeddb'\n","import { ArchivistConfig, IndexDescription } from '@xyo-network/archivist-model'\n\nimport { IndexedDbArchivistSchema } from './Schema'\n\nexport type IndexedDbArchivistConfigSchema = `${IndexedDbArchivistSchema}.config`\nexport const IndexedDbArchivistConfigSchema: IndexedDbArchivistConfigSchema = `${IndexedDbArchivistSchema}.config`\n\nexport type IndexedDbArchivistConfig = ArchivistConfig<{\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: IndexedDbArchivistConfigSchema\n /**\n * The storage configuration\n * // TODO: Hoist to main archivist 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"],"mappings":"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","names":["IndexedDbArchivistSchema","IndexedDbArchivistConfigSchema","IndexedDbArchivistSchema","IndexedDbArchivist","AbstractArchivist","configSchemas","IndexedDbArchivistConfigSchema","defaultDbName","defaultDbVersion","defaultStoreName","hashIndex","key","_hash","multiEntry","unique","schemaIndex","schema","hashIndexName","buildStandardIndexName","schemaIndexName","_db","dbName","config","name","dbVersion","queries","ArchivistAllQuerySchema","ArchivistClearQuerySchema","ArchivistDeleteQuerySchema","ArchivistInsertQuerySchema","storeName","db","assertEx","indexes","storage","allHandler","payloads","getAll","map","payload","PayloadHasher","jsonPayload","clearHandler","clear","deleteHandler","hashes","distinctHashes","Set","found","Promise","all","hash","existing","getKeyFromIndex","delete","filter","exists","getHandler","getFromIndex","insertHandler","pairs","hashPairs","inserted","tx","transaction","store","objectStore","index","get","put","startHandler","openDB","upgrade","database","resolve","createObjectStore","autoIncrement","indexesToCreate","indexKeys","Object","keys","length","indexName","createIndex","creatableModule"]}
|
package/dist/browser/index.js
CHANGED
|
@@ -43,25 +43,19 @@ var IndexedDbArchivist = class _IndexedDbArchivist extends AbstractArchivist {
|
|
|
43
43
|
_hash: 1
|
|
44
44
|
},
|
|
45
45
|
multiEntry: false,
|
|
46
|
-
name: "IX-_hash",
|
|
47
46
|
unique: true
|
|
48
47
|
};
|
|
49
|
-
static payloadSchemasIndex = {
|
|
50
|
-
key: {
|
|
51
|
-
payload_schemas: 1
|
|
52
|
-
},
|
|
53
|
-
multiEntry: false,
|
|
54
|
-
name: "IX-payload_schemas",
|
|
55
|
-
unique: false
|
|
56
|
-
};
|
|
57
48
|
static schemaIndex = {
|
|
58
49
|
key: {
|
|
59
50
|
schema: 1
|
|
60
51
|
},
|
|
61
52
|
multiEntry: false,
|
|
62
|
-
name: "IX-schema",
|
|
63
53
|
unique: false
|
|
64
54
|
};
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/member-ordering
|
|
56
|
+
static hashIndexName = buildStandardIndexName(_IndexedDbArchivist.hashIndex);
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/member-ordering
|
|
58
|
+
static schemaIndexName = buildStandardIndexName(_IndexedDbArchivist.schemaIndex);
|
|
65
59
|
_db;
|
|
66
60
|
/**
|
|
67
61
|
* The database name. If not supplied via config, it defaults
|
|
@@ -79,12 +73,6 @@ var IndexedDbArchivist = class _IndexedDbArchivist extends AbstractArchivist {
|
|
|
79
73
|
get dbVersion() {
|
|
80
74
|
return this.config?.dbVersion ?? _IndexedDbArchivist.defaultDbVersion;
|
|
81
75
|
}
|
|
82
|
-
/**
|
|
83
|
-
* The database indexes.
|
|
84
|
-
*/
|
|
85
|
-
get indexes() {
|
|
86
|
-
return this.config?.storage?.indexes ?? [];
|
|
87
|
-
}
|
|
88
76
|
get queries() {
|
|
89
77
|
return [
|
|
90
78
|
ArchivistAllQuerySchema,
|
|
@@ -104,6 +92,9 @@ var IndexedDbArchivist = class _IndexedDbArchivist extends AbstractArchivist {
|
|
|
104
92
|
get db() {
|
|
105
93
|
return assertEx(this._db, "DB not initialized");
|
|
106
94
|
}
|
|
95
|
+
get indexes() {
|
|
96
|
+
return this.config?.storage?.indexes ?? [];
|
|
97
|
+
}
|
|
107
98
|
async allHandler() {
|
|
108
99
|
const payloads = await this.db.getAll(this.storeName);
|
|
109
100
|
return payloads.map((payload) => PayloadHasher.jsonPayload(payload));
|
|
@@ -118,7 +109,7 @@ var IndexedDbArchivist = class _IndexedDbArchivist extends AbstractArchivist {
|
|
|
118
109
|
const found = await Promise.all(distinctHashes.map(async (hash) => {
|
|
119
110
|
let existing;
|
|
120
111
|
do {
|
|
121
|
-
existing = await this.db.getKeyFromIndex(this.storeName, _IndexedDbArchivist.
|
|
112
|
+
existing = await this.db.getKeyFromIndex(this.storeName, _IndexedDbArchivist.hashIndexName, hash);
|
|
122
113
|
if (existing)
|
|
123
114
|
await this.db.delete(this.storeName, existing);
|
|
124
115
|
} while (!existing);
|
|
@@ -127,7 +118,7 @@ var IndexedDbArchivist = class _IndexedDbArchivist extends AbstractArchivist {
|
|
|
127
118
|
return found.filter(exists);
|
|
128
119
|
}
|
|
129
120
|
async getHandler(hashes) {
|
|
130
|
-
const payloads = await Promise.all(hashes.map((hash) => this.db.getFromIndex(this.storeName, _IndexedDbArchivist.
|
|
121
|
+
const payloads = await Promise.all(hashes.map((hash) => this.db.getFromIndex(this.storeName, _IndexedDbArchivist.hashIndexName, hash)));
|
|
131
122
|
return payloads.filter(exists);
|
|
132
123
|
}
|
|
133
124
|
async insertHandler(payloads) {
|
|
@@ -135,7 +126,7 @@ var IndexedDbArchivist = class _IndexedDbArchivist extends AbstractArchivist {
|
|
|
135
126
|
const inserted = await Promise.all(pairs.map(async ([payload, _hash]) => {
|
|
136
127
|
const tx = this.db.transaction(this.storeName, "readwrite");
|
|
137
128
|
const store = tx.objectStore(this.storeName);
|
|
138
|
-
const existing = await store.index(_IndexedDbArchivist.
|
|
129
|
+
const existing = await store.index(_IndexedDbArchivist.hashIndexName).get(_hash);
|
|
139
130
|
if (!existing) {
|
|
140
131
|
await this.db.put(this.storeName, {
|
|
141
132
|
...payload,
|
|
@@ -148,7 +139,7 @@ var IndexedDbArchivist = class _IndexedDbArchivist extends AbstractArchivist {
|
|
|
148
139
|
}
|
|
149
140
|
async startHandler() {
|
|
150
141
|
await super.startHandler();
|
|
151
|
-
const {
|
|
142
|
+
const { dbName, dbVersion, indexes, storeName } = this;
|
|
152
143
|
this._db = await openDB(dbName, dbVersion, {
|
|
153
144
|
async upgrade(database) {
|
|
154
145
|
await Promise.resolve();
|
|
@@ -158,15 +149,14 @@ var IndexedDbArchivist = class _IndexedDbArchivist extends AbstractArchivist {
|
|
|
158
149
|
});
|
|
159
150
|
store.name = storeName;
|
|
160
151
|
const indexesToCreate = [
|
|
161
|
-
...indexes,
|
|
162
152
|
_IndexedDbArchivist.hashIndex,
|
|
163
|
-
_IndexedDbArchivist.
|
|
164
|
-
|
|
153
|
+
_IndexedDbArchivist.schemaIndex,
|
|
154
|
+
...indexes
|
|
165
155
|
];
|
|
166
|
-
for (const { key, multiEntry,
|
|
156
|
+
for (const { key, multiEntry, unique } of indexesToCreate) {
|
|
167
157
|
const indexKeys = Object.keys(key);
|
|
168
158
|
const keys = indexKeys.length === 1 ? indexKeys[0] : indexKeys;
|
|
169
|
-
const indexName =
|
|
159
|
+
const indexName = buildStandardIndexName({
|
|
170
160
|
key,
|
|
171
161
|
unique
|
|
172
162
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/Archivist.ts","../../src/Schema.ts","../../src/Config.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport { AbstractArchivist } from '@xyo-network/archivist-abstract'\nimport {\n ArchivistAllQuerySchema,\n ArchivistClearQuerySchema,\n ArchivistDeleteQuerySchema,\n ArchivistInsertQuerySchema,\n ArchivistModuleEventData,\n buildStandardIndexName,\n IndexDescription,\n} from '@xyo-network/archivist-model'\nimport { PayloadHasher } from '@xyo-network/hash'\nimport { creatableModule } from '@xyo-network/module-model'\nimport { Payload } from '@xyo-network/payload-model'\nimport { IDBPDatabase, openDB } from 'idb'\n\nimport { IndexedDbArchivistConfigSchema } from './Config'\nimport { IndexedDbArchivistParams } from './Params'\n\nexport interface PayloadStore {\n [s: string]: Payload\n}\n\n@creatableModule()\nexport class IndexedDbArchivist<\n TParams extends IndexedDbArchivistParams = IndexedDbArchivistParams,\n TEventData extends ArchivistModuleEventData = ArchivistModuleEventData,\n> extends AbstractArchivist<TParams, TEventData> {\n static override configSchemas = [IndexedDbArchivistConfigSchema]\n static readonly defaultDbName = 'archivist'\n static readonly defaultDbVersion = 1\n static readonly defaultStoreName = 'payloads'\n static readonly hashIndex: Required<IndexDescription> = { key: { _hash: 1 }, multiEntry: false, name: 'IX-_hash', unique: true }\n static readonly payloadSchemasIndex: Required<IndexDescription> = {\n key: { payload_schemas: 1 },\n multiEntry: false,\n name: 'IX-payload_schemas',\n unique: false,\n }\n static readonly schemaIndex: Required<IndexDescription> = { key: { schema: 1 }, multiEntry: false, name: 'IX-schema', unique: false }\n\n private _db: IDBPDatabase<PayloadStore> | undefined\n\n /**\n * The database name. If not supplied via config, it defaults\n * to the module name (not guaranteed to be unique) and if module\n * name is not supplied, 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?.name ?? IndexedDbArchivist.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 ?? IndexedDbArchivist.defaultDbVersion\n }\n\n /**\n * The database indexes.\n */\n get indexes() {\n return this.config?.storage?.indexes ?? []\n }\n\n override get queries() {\n return [ArchivistAllQuerySchema, ArchivistClearQuerySchema, ArchivistDeleteQuerySchema, ArchivistInsertQuerySchema, ...super.queries]\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 allHandler(): Promise<Payload[]> {\n // Get all payloads from the store\n const payloads = await this.db.getAll(this.storeName)\n // Remove any metadata before returning to the client\n return payloads.map((payload) => PayloadHasher.jsonPayload(payload))\n }\n\n protected override async clearHandler(): Promise<void> {\n await this.db.clear(this.storeName)\n }\n\n protected override async deleteHandler(hashes: string[]): Promise<string[]> {\n const distinctHashes = [...new Set(hashes)]\n const found = await Promise.all(\n distinctHashes.map(async (hash) => {\n let existing: IDBValidKey | undefined\n do {\n existing = await this.db.getKeyFromIndex(this.storeName, IndexedDbArchivist.hashIndex.name, hash)\n if (existing) await this.db.delete(this.storeName, existing)\n } while (!existing)\n return hash\n }),\n )\n // Return hashes removed\n return found.filter(exists)\n }\n\n protected override async getHandler(hashes: string[]): Promise<Payload[]> {\n const payloads = await Promise.all(hashes.map((hash) => this.db.getFromIndex(this.storeName, IndexedDbArchivist.hashIndex.name, hash)))\n return payloads.filter(exists)\n }\n\n protected override async insertHandler(payloads: Payload[]): Promise<Payload[]> {\n const pairs = await PayloadHasher.hashPairs(payloads)\n // Only return the payloads that were successfully inserted\n const inserted = await Promise.all(\n pairs.map(async ([payload, _hash]) => {\n const tx = this.db.transaction(this.storeName, 'readwrite')\n const store = tx.objectStore(this.storeName)\n const existing = await store.index(IndexedDbArchivist.hashIndex.name).get(_hash)\n if (!existing) {\n await this.db.put(this.storeName, { ...payload, _hash })\n return payload\n }\n }),\n )\n return inserted.filter(exists)\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 const { indexes, storeName, dbName, dbVersion } = this\n this._db = await openDB<PayloadStore>(dbName, dbVersion, {\n async upgrade(database) {\n await Promise.resolve() // Async to match spec\n // Create the store\n const store = database.createObjectStore(storeName, {\n // If it isn't explicitly set, create a value by auto incrementing.\n autoIncrement: true,\n })\n // Name the store\n store.name = storeName\n // Create an index on the hash\n const indexesToCreate = [...indexes, IndexedDbArchivist.hashIndex, IndexedDbArchivist.payloadSchemasIndex, IndexedDbArchivist.schemaIndex]\n for (const { key, multiEntry, name, unique } of indexesToCreate) {\n const indexKeys = Object.keys(key)\n const keys = indexKeys.length === 1 ? indexKeys[0] : indexKeys\n const indexName = name ?? buildStandardIndexName({ key, unique })\n store.createIndex(indexName, keys, { multiEntry, unique })\n }\n },\n })\n\n return true\n }\n}\n","export type IndexedDbArchivistSchema = 'network.xyo.archivist.indexeddb'\nexport const IndexedDbArchivistSchema: IndexedDbArchivistSchema = 'network.xyo.archivist.indexeddb'\n","import { ArchivistConfig, IndexDescription } from '@xyo-network/archivist-model'\n\nimport { IndexedDbArchivistSchema } from './Schema'\n\nexport type IndexedDbArchivistConfigSchema = `${IndexedDbArchivistSchema}.config`\nexport const IndexedDbArchivistConfigSchema: IndexedDbArchivistConfigSchema = `${IndexedDbArchivistSchema}.config`\n\nexport type IndexedDbArchivistConfig = ArchivistConfig<{\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: IndexedDbArchivistConfigSchema\n /**\n * The storage configuration\n * // TODO: Hoist to main archivist 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"],"mappings":"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","names":["assertEx","exists","AbstractArchivist","ArchivistAllQuerySchema","ArchivistClearQuerySchema","ArchivistDeleteQuerySchema","ArchivistInsertQuerySchema","buildStandardIndexName","PayloadHasher","creatableModule","openDB","IndexedDbArchivistSchema","IndexedDbArchivistConfigSchema","IndexedDbArchivistSchema","IndexedDbArchivist","AbstractArchivist","configSchemas","IndexedDbArchivistConfigSchema","defaultDbName","defaultDbVersion","defaultStoreName","hashIndex","key","_hash","multiEntry","name","unique","payloadSchemasIndex","payload_schemas","schemaIndex","schema","_db","dbName","config","dbVersion","indexes","storage","queries","ArchivistAllQuerySchema","ArchivistClearQuerySchema","ArchivistDeleteQuerySchema","ArchivistInsertQuerySchema","storeName","db","assertEx","allHandler","payloads","getAll","map","payload","PayloadHasher","jsonPayload","clearHandler","clear","deleteHandler","hashes","distinctHashes","Set","found","Promise","all","hash","existing","getKeyFromIndex","delete","filter","exists","getHandler","getFromIndex","insertHandler","pairs","hashPairs","inserted","tx","transaction","store","objectStore","index","get","put","startHandler","openDB","upgrade","database","resolve","createObjectStore","autoIncrement","indexesToCreate","indexKeys","Object","keys","length","indexName","buildStandardIndexName","createIndex","creatableModule"]}
|
|
1
|
+
{"version":3,"sources":["../../src/Archivist.ts","../../src/Schema.ts","../../src/Config.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport { AbstractArchivist } from '@xyo-network/archivist-abstract'\nimport {\n ArchivistAllQuerySchema,\n ArchivistClearQuerySchema,\n ArchivistDeleteQuerySchema,\n ArchivistInsertQuerySchema,\n ArchivistModuleEventData,\n buildStandardIndexName,\n IndexDescription,\n} from '@xyo-network/archivist-model'\nimport { PayloadHasher } from '@xyo-network/hash'\nimport { creatableModule } from '@xyo-network/module-model'\nimport { Payload } from '@xyo-network/payload-model'\nimport { IDBPDatabase, openDB } from 'idb'\n\nimport { IndexedDbArchivistConfigSchema } from './Config'\nimport { IndexedDbArchivistParams } from './Params'\n\nexport interface PayloadStore {\n [s: string]: Payload\n}\n\n@creatableModule()\nexport class IndexedDbArchivist<\n TParams extends IndexedDbArchivistParams = IndexedDbArchivistParams,\n TEventData extends ArchivistModuleEventData = ArchivistModuleEventData,\n> extends AbstractArchivist<TParams, TEventData> {\n static override configSchemas = [IndexedDbArchivistConfigSchema]\n static readonly defaultDbName = 'archivist'\n static readonly defaultDbVersion = 1\n static readonly defaultStoreName = 'payloads'\n private static readonly hashIndex: IndexDescription = { key: { _hash: 1 }, multiEntry: false, unique: true }\n private static readonly schemaIndex: IndexDescription = { key: { schema: 1 }, multiEntry: false, unique: false }\n // eslint-disable-next-line @typescript-eslint/member-ordering\n static readonly hashIndexName = buildStandardIndexName(IndexedDbArchivist.hashIndex)\n // eslint-disable-next-line @typescript-eslint/member-ordering\n static readonly schemaIndexName = buildStandardIndexName(IndexedDbArchivist.schemaIndex)\n\n private _db: IDBPDatabase<PayloadStore> | undefined\n\n /**\n * The database name. If not supplied via config, it defaults\n * to the module name (not guaranteed to be unique) and if module\n * name is not supplied, 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?.name ?? IndexedDbArchivist.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 ?? IndexedDbArchivist.defaultDbVersion\n }\n\n override get queries() {\n return [ArchivistAllQuerySchema, ArchivistClearQuerySchema, ArchivistDeleteQuerySchema, ArchivistInsertQuerySchema, ...super.queries]\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 private get indexes() {\n return this.config?.storage?.indexes ?? []\n }\n\n protected override async allHandler(): Promise<Payload[]> {\n // Get all payloads from the store\n const payloads = await this.db.getAll(this.storeName)\n // Remove any metadata before returning to the client\n return payloads.map((payload) => PayloadHasher.jsonPayload(payload))\n }\n\n protected override async clearHandler(): Promise<void> {\n await this.db.clear(this.storeName)\n }\n\n protected override async deleteHandler(hashes: string[]): Promise<string[]> {\n const distinctHashes = [...new Set(hashes)]\n const found = await Promise.all(\n distinctHashes.map(async (hash) => {\n let existing: IDBValidKey | undefined\n do {\n existing = await this.db.getKeyFromIndex(this.storeName, IndexedDbArchivist.hashIndexName, hash)\n if (existing) await this.db.delete(this.storeName, existing)\n } while (!existing)\n return hash\n }),\n )\n // Return hashes removed\n return found.filter(exists)\n }\n\n protected override async getHandler(hashes: string[]): Promise<Payload[]> {\n const payloads = await Promise.all(hashes.map((hash) => this.db.getFromIndex(this.storeName, IndexedDbArchivist.hashIndexName, hash)))\n return payloads.filter(exists)\n }\n\n protected override async insertHandler(payloads: Payload[]): Promise<Payload[]> {\n const pairs = await PayloadHasher.hashPairs(payloads)\n // Only return the payloads that were successfully inserted\n const inserted = await Promise.all(\n pairs.map(async ([payload, _hash]) => {\n const tx = this.db.transaction(this.storeName, 'readwrite')\n const store = tx.objectStore(this.storeName)\n const existing = await store.index(IndexedDbArchivist.hashIndexName).get(_hash)\n if (!existing) {\n await this.db.put(this.storeName, { ...payload, _hash })\n return payload\n }\n }),\n )\n return inserted.filter(exists)\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 const { dbName, dbVersion, indexes, storeName } = this\n this._db = await openDB<PayloadStore>(dbName, dbVersion, {\n async upgrade(database) {\n await Promise.resolve() // Async to match spec\n // Create the store\n const store = database.createObjectStore(storeName, {\n // If it isn't explicitly set, create a value by auto incrementing.\n autoIncrement: true,\n })\n // Name the store\n store.name = storeName\n // Create an index on the hash\n const indexesToCreate = [IndexedDbArchivist.hashIndex, IndexedDbArchivist.schemaIndex, ...indexes]\n for (const { key, multiEntry, unique } of indexesToCreate) {\n const indexKeys = Object.keys(key)\n const keys = indexKeys.length === 1 ? indexKeys[0] : indexKeys\n const indexName = buildStandardIndexName({ key, unique })\n store.createIndex(indexName, keys, { multiEntry, unique })\n }\n },\n })\n return true\n }\n}\n","export type IndexedDbArchivistSchema = 'network.xyo.archivist.indexeddb'\nexport const IndexedDbArchivistSchema: IndexedDbArchivistSchema = 'network.xyo.archivist.indexeddb'\n","import { ArchivistConfig, IndexDescription } from '@xyo-network/archivist-model'\n\nimport { IndexedDbArchivistSchema } from './Schema'\n\nexport type IndexedDbArchivistConfigSchema = `${IndexedDbArchivistSchema}.config`\nexport const IndexedDbArchivistConfigSchema: IndexedDbArchivistConfigSchema = `${IndexedDbArchivistSchema}.config`\n\nexport type IndexedDbArchivistConfig = ArchivistConfig<{\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: IndexedDbArchivistConfigSchema\n /**\n * The storage configuration\n * // TODO: Hoist to main archivist 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"],"mappings":"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","names":["assertEx","exists","AbstractArchivist","ArchivistAllQuerySchema","ArchivistClearQuerySchema","ArchivistDeleteQuerySchema","ArchivistInsertQuerySchema","buildStandardIndexName","PayloadHasher","creatableModule","openDB","IndexedDbArchivistSchema","IndexedDbArchivistConfigSchema","IndexedDbArchivistSchema","IndexedDbArchivist","AbstractArchivist","configSchemas","IndexedDbArchivistConfigSchema","defaultDbName","defaultDbVersion","defaultStoreName","hashIndex","key","_hash","multiEntry","unique","schemaIndex","schema","hashIndexName","buildStandardIndexName","schemaIndexName","_db","dbName","config","name","dbVersion","queries","ArchivistAllQuerySchema","ArchivistClearQuerySchema","ArchivistDeleteQuerySchema","ArchivistInsertQuerySchema","storeName","db","assertEx","indexes","storage","allHandler","payloads","getAll","map","payload","PayloadHasher","jsonPayload","clearHandler","clear","deleteHandler","hashes","distinctHashes","Set","found","Promise","all","hash","existing","getKeyFromIndex","delete","filter","exists","getHandler","getFromIndex","insertHandler","pairs","hashPairs","inserted","tx","transaction","store","objectStore","index","get","put","startHandler","openDB","upgrade","database","resolve","createObjectStore","autoIncrement","indexesToCreate","indexKeys","Object","keys","length","indexName","createIndex","creatableModule"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AbstractArchivist } from '@xyo-network/archivist-abstract';
|
|
2
|
-
import { ArchivistModuleEventData
|
|
2
|
+
import { ArchivistModuleEventData } from '@xyo-network/archivist-model';
|
|
3
3
|
import { Payload } from '@xyo-network/payload-model';
|
|
4
4
|
import { IndexedDbArchivistParams } from './Params';
|
|
5
5
|
export interface PayloadStore {
|
|
@@ -10,9 +10,10 @@ export declare class IndexedDbArchivist<TParams extends IndexedDbArchivistParams
|
|
|
10
10
|
static readonly defaultDbName = "archivist";
|
|
11
11
|
static readonly defaultDbVersion = 1;
|
|
12
12
|
static readonly defaultStoreName = "payloads";
|
|
13
|
-
static readonly hashIndex
|
|
14
|
-
static readonly
|
|
15
|
-
static readonly
|
|
13
|
+
private static readonly hashIndex;
|
|
14
|
+
private static readonly schemaIndex;
|
|
15
|
+
static readonly hashIndexName: string;
|
|
16
|
+
static readonly schemaIndexName: string;
|
|
16
17
|
private _db;
|
|
17
18
|
/**
|
|
18
19
|
* The database name. If not supplied via config, it defaults
|
|
@@ -26,10 +27,6 @@ export declare class IndexedDbArchivist<TParams extends IndexedDbArchivistParams
|
|
|
26
27
|
* The database version. If not supplied via config, it defaults to 1.
|
|
27
28
|
*/
|
|
28
29
|
get dbVersion(): number;
|
|
29
|
-
/**
|
|
30
|
-
* The database indexes.
|
|
31
|
-
*/
|
|
32
|
-
get indexes(): IndexDescription[];
|
|
33
30
|
get queries(): string[];
|
|
34
31
|
/**
|
|
35
32
|
* The name of the object store. If not supplied via config, it defaults
|
|
@@ -37,6 +34,7 @@ export declare class IndexedDbArchivist<TParams extends IndexedDbArchivistParams
|
|
|
37
34
|
*/
|
|
38
35
|
get storeName(): string;
|
|
39
36
|
private get db();
|
|
37
|
+
private get indexes();
|
|
40
38
|
protected allHandler(): Promise<Payload[]>;
|
|
41
39
|
protected clearHandler(): Promise<void>;
|
|
42
40
|
protected deleteHandler(hashes: string[]): Promise<string[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Archivist.d.ts","sourceRoot":"","sources":["../../src/Archivist.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAKL,wBAAwB,
|
|
1
|
+
{"version":3,"file":"Archivist.d.ts","sourceRoot":"","sources":["../../src/Archivist.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAKL,wBAAwB,EAGzB,MAAM,8BAA8B,CAAA;AAGrC,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAIpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAA;AAEnD,MAAM,WAAW,YAAY;IAC3B,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB;AAED,qBACa,kBAAkB,CAC7B,OAAO,SAAS,wBAAwB,GAAG,wBAAwB,EACnE,UAAU,SAAS,wBAAwB,GAAG,wBAAwB,CACtE,SAAQ,iBAAiB,CAAC,OAAO,EAAE,UAAU,CAAC;IAC9C,OAAgB,aAAa,6CAAmC;IAChE,MAAM,CAAC,QAAQ,CAAC,aAAa,eAAc;IAC3C,MAAM,CAAC,QAAQ,CAAC,gBAAgB,KAAI;IACpC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,cAAa;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAA2E;IAC5G,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAA6E;IAEhH,MAAM,CAAC,QAAQ,CAAC,aAAa,SAAuD;IAEpF,MAAM,CAAC,QAAQ,CAAC,eAAe,SAAyD;IAExF,OAAO,CAAC,GAAG,CAAwC;IAEnD;;;;;;OAMG;IACH,IAAI,MAAM,WAET;IAED;;OAEG;IACH,IAAI,SAAS,WAEZ;IAED,IAAa,OAAO,aAEnB;IAED;;;OAGG;IACH,IAAI,SAAS,WAEZ;IAED,OAAO,KAAK,EAAE,GAEb;IAED,OAAO,KAAK,OAAO,GAElB;cAEwB,UAAU,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;cAOhC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;cAI7B,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;cAgBlD,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;cAKhD,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;cAiBtD,YAAY;CA2BtC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AbstractArchivist } from '@xyo-network/archivist-abstract';
|
|
2
|
-
import { ArchivistModuleEventData
|
|
2
|
+
import { ArchivistModuleEventData } from '@xyo-network/archivist-model';
|
|
3
3
|
import { Payload } from '@xyo-network/payload-model';
|
|
4
4
|
import { IndexedDbArchivistParams } from './Params';
|
|
5
5
|
export interface PayloadStore {
|
|
@@ -10,9 +10,10 @@ export declare class IndexedDbArchivist<TParams extends IndexedDbArchivistParams
|
|
|
10
10
|
static readonly defaultDbName = "archivist";
|
|
11
11
|
static readonly defaultDbVersion = 1;
|
|
12
12
|
static readonly defaultStoreName = "payloads";
|
|
13
|
-
static readonly hashIndex
|
|
14
|
-
static readonly
|
|
15
|
-
static readonly
|
|
13
|
+
private static readonly hashIndex;
|
|
14
|
+
private static readonly schemaIndex;
|
|
15
|
+
static readonly hashIndexName: string;
|
|
16
|
+
static readonly schemaIndexName: string;
|
|
16
17
|
private _db;
|
|
17
18
|
/**
|
|
18
19
|
* The database name. If not supplied via config, it defaults
|
|
@@ -26,10 +27,6 @@ export declare class IndexedDbArchivist<TParams extends IndexedDbArchivistParams
|
|
|
26
27
|
* The database version. If not supplied via config, it defaults to 1.
|
|
27
28
|
*/
|
|
28
29
|
get dbVersion(): number;
|
|
29
|
-
/**
|
|
30
|
-
* The database indexes.
|
|
31
|
-
*/
|
|
32
|
-
get indexes(): IndexDescription[];
|
|
33
30
|
get queries(): string[];
|
|
34
31
|
/**
|
|
35
32
|
* The name of the object store. If not supplied via config, it defaults
|
|
@@ -37,6 +34,7 @@ export declare class IndexedDbArchivist<TParams extends IndexedDbArchivistParams
|
|
|
37
34
|
*/
|
|
38
35
|
get storeName(): string;
|
|
39
36
|
private get db();
|
|
37
|
+
private get indexes();
|
|
40
38
|
protected allHandler(): Promise<Payload[]>;
|
|
41
39
|
protected clearHandler(): Promise<void>;
|
|
42
40
|
protected deleteHandler(hashes: string[]): Promise<string[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Archivist.d.ts","sourceRoot":"","sources":["../../src/Archivist.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAKL,wBAAwB,
|
|
1
|
+
{"version":3,"file":"Archivist.d.ts","sourceRoot":"","sources":["../../src/Archivist.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAKL,wBAAwB,EAGzB,MAAM,8BAA8B,CAAA;AAGrC,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAIpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAA;AAEnD,MAAM,WAAW,YAAY;IAC3B,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB;AAED,qBACa,kBAAkB,CAC7B,OAAO,SAAS,wBAAwB,GAAG,wBAAwB,EACnE,UAAU,SAAS,wBAAwB,GAAG,wBAAwB,CACtE,SAAQ,iBAAiB,CAAC,OAAO,EAAE,UAAU,CAAC;IAC9C,OAAgB,aAAa,6CAAmC;IAChE,MAAM,CAAC,QAAQ,CAAC,aAAa,eAAc;IAC3C,MAAM,CAAC,QAAQ,CAAC,gBAAgB,KAAI;IACpC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,cAAa;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAA2E;IAC5G,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAA6E;IAEhH,MAAM,CAAC,QAAQ,CAAC,aAAa,SAAuD;IAEpF,MAAM,CAAC,QAAQ,CAAC,eAAe,SAAyD;IAExF,OAAO,CAAC,GAAG,CAAwC;IAEnD;;;;;;OAMG;IACH,IAAI,MAAM,WAET;IAED;;OAEG;IACH,IAAI,SAAS,WAEZ;IAED,IAAa,OAAO,aAEnB;IAED;;;OAGG;IACH,IAAI,SAAS,WAEZ;IAED,OAAO,KAAK,EAAE,GAEb;IAED,OAAO,KAAK,OAAO,GAElB;cAEwB,UAAU,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;cAOhC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;cAI7B,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;cAgBlD,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;cAKhD,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;cAiBtD,YAAY;CA2BtC"}
|
package/dist/node/Archivist.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AbstractArchivist } from '@xyo-network/archivist-abstract';
|
|
2
|
-
import { ArchivistModuleEventData
|
|
2
|
+
import { ArchivistModuleEventData } from '@xyo-network/archivist-model';
|
|
3
3
|
import { Payload } from '@xyo-network/payload-model';
|
|
4
4
|
import { IndexedDbArchivistParams } from './Params';
|
|
5
5
|
export interface PayloadStore {
|
|
@@ -10,9 +10,10 @@ export declare class IndexedDbArchivist<TParams extends IndexedDbArchivistParams
|
|
|
10
10
|
static readonly defaultDbName = "archivist";
|
|
11
11
|
static readonly defaultDbVersion = 1;
|
|
12
12
|
static readonly defaultStoreName = "payloads";
|
|
13
|
-
static readonly hashIndex
|
|
14
|
-
static readonly
|
|
15
|
-
static readonly
|
|
13
|
+
private static readonly hashIndex;
|
|
14
|
+
private static readonly schemaIndex;
|
|
15
|
+
static readonly hashIndexName: string;
|
|
16
|
+
static readonly schemaIndexName: string;
|
|
16
17
|
private _db;
|
|
17
18
|
/**
|
|
18
19
|
* The database name. If not supplied via config, it defaults
|
|
@@ -26,10 +27,6 @@ export declare class IndexedDbArchivist<TParams extends IndexedDbArchivistParams
|
|
|
26
27
|
* The database version. If not supplied via config, it defaults to 1.
|
|
27
28
|
*/
|
|
28
29
|
get dbVersion(): number;
|
|
29
|
-
/**
|
|
30
|
-
* The database indexes.
|
|
31
|
-
*/
|
|
32
|
-
get indexes(): IndexDescription[];
|
|
33
30
|
get queries(): string[];
|
|
34
31
|
/**
|
|
35
32
|
* The name of the object store. If not supplied via config, it defaults
|
|
@@ -37,6 +34,7 @@ export declare class IndexedDbArchivist<TParams extends IndexedDbArchivistParams
|
|
|
37
34
|
*/
|
|
38
35
|
get storeName(): string;
|
|
39
36
|
private get db();
|
|
37
|
+
private get indexes();
|
|
40
38
|
protected allHandler(): Promise<Payload[]>;
|
|
41
39
|
protected clearHandler(): Promise<void>;
|
|
42
40
|
protected deleteHandler(hashes: string[]): Promise<string[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Archivist.d.ts","sourceRoot":"","sources":["../../src/Archivist.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAKL,wBAAwB,
|
|
1
|
+
{"version":3,"file":"Archivist.d.ts","sourceRoot":"","sources":["../../src/Archivist.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAKL,wBAAwB,EAGzB,MAAM,8BAA8B,CAAA;AAGrC,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAIpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAA;AAEnD,MAAM,WAAW,YAAY;IAC3B,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB;AAED,qBACa,kBAAkB,CAC7B,OAAO,SAAS,wBAAwB,GAAG,wBAAwB,EACnE,UAAU,SAAS,wBAAwB,GAAG,wBAAwB,CACtE,SAAQ,iBAAiB,CAAC,OAAO,EAAE,UAAU,CAAC;IAC9C,OAAgB,aAAa,6CAAmC;IAChE,MAAM,CAAC,QAAQ,CAAC,aAAa,eAAc;IAC3C,MAAM,CAAC,QAAQ,CAAC,gBAAgB,KAAI;IACpC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,cAAa;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAA2E;IAC5G,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAA6E;IAEhH,MAAM,CAAC,QAAQ,CAAC,aAAa,SAAuD;IAEpF,MAAM,CAAC,QAAQ,CAAC,eAAe,SAAyD;IAExF,OAAO,CAAC,GAAG,CAAwC;IAEnD;;;;;;OAMG;IACH,IAAI,MAAM,WAET;IAED;;OAEG;IACH,IAAI,SAAS,WAEZ;IAED,IAAa,OAAO,aAEnB;IAED;;;OAGG;IACH,IAAI,SAAS,WAEZ;IAED,OAAO,KAAK,EAAE,GAEb;IAED,OAAO,KAAK,OAAO,GAElB;cAEwB,UAAU,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;cAOhC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;cAI7B,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;cAgBlD,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;cAKhD,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;cAiBtD,YAAY;CA2BtC"}
|
package/dist/node/index.cjs
CHANGED
|
@@ -79,13 +79,6 @@ var _IndexedDbArchivist = class _IndexedDbArchivist extends import_archivist_abs
|
|
|
79
79
|
var _a;
|
|
80
80
|
return ((_a = this.config) == null ? void 0 : _a.dbVersion) ?? _IndexedDbArchivist.defaultDbVersion;
|
|
81
81
|
}
|
|
82
|
-
/**
|
|
83
|
-
* The database indexes.
|
|
84
|
-
*/
|
|
85
|
-
get indexes() {
|
|
86
|
-
var _a, _b;
|
|
87
|
-
return ((_b = (_a = this.config) == null ? void 0 : _a.storage) == null ? void 0 : _b.indexes) ?? [];
|
|
88
|
-
}
|
|
89
82
|
get queries() {
|
|
90
83
|
return [
|
|
91
84
|
import_archivist_model.ArchivistAllQuerySchema,
|
|
@@ -106,6 +99,10 @@ var _IndexedDbArchivist = class _IndexedDbArchivist extends import_archivist_abs
|
|
|
106
99
|
get db() {
|
|
107
100
|
return (0, import_assert.assertEx)(this._db, "DB not initialized");
|
|
108
101
|
}
|
|
102
|
+
get indexes() {
|
|
103
|
+
var _a, _b;
|
|
104
|
+
return ((_b = (_a = this.config) == null ? void 0 : _a.storage) == null ? void 0 : _b.indexes) ?? [];
|
|
105
|
+
}
|
|
109
106
|
async allHandler() {
|
|
110
107
|
const payloads = await this.db.getAll(this.storeName);
|
|
111
108
|
return payloads.map((payload) => import_hash.PayloadHasher.jsonPayload(payload));
|
|
@@ -120,7 +117,7 @@ var _IndexedDbArchivist = class _IndexedDbArchivist extends import_archivist_abs
|
|
|
120
117
|
const found = await Promise.all(distinctHashes.map(async (hash) => {
|
|
121
118
|
let existing;
|
|
122
119
|
do {
|
|
123
|
-
existing = await this.db.getKeyFromIndex(this.storeName, _IndexedDbArchivist.
|
|
120
|
+
existing = await this.db.getKeyFromIndex(this.storeName, _IndexedDbArchivist.hashIndexName, hash);
|
|
124
121
|
if (existing)
|
|
125
122
|
await this.db.delete(this.storeName, existing);
|
|
126
123
|
} while (!existing);
|
|
@@ -129,7 +126,7 @@ var _IndexedDbArchivist = class _IndexedDbArchivist extends import_archivist_abs
|
|
|
129
126
|
return found.filter(import_exists.exists);
|
|
130
127
|
}
|
|
131
128
|
async getHandler(hashes) {
|
|
132
|
-
const payloads = await Promise.all(hashes.map((hash) => this.db.getFromIndex(this.storeName, _IndexedDbArchivist.
|
|
129
|
+
const payloads = await Promise.all(hashes.map((hash) => this.db.getFromIndex(this.storeName, _IndexedDbArchivist.hashIndexName, hash)));
|
|
133
130
|
return payloads.filter(import_exists.exists);
|
|
134
131
|
}
|
|
135
132
|
async insertHandler(payloads) {
|
|
@@ -137,7 +134,7 @@ var _IndexedDbArchivist = class _IndexedDbArchivist extends import_archivist_abs
|
|
|
137
134
|
const inserted = await Promise.all(pairs.map(async ([payload, _hash]) => {
|
|
138
135
|
const tx = this.db.transaction(this.storeName, "readwrite");
|
|
139
136
|
const store = tx.objectStore(this.storeName);
|
|
140
|
-
const existing = await store.index(_IndexedDbArchivist.
|
|
137
|
+
const existing = await store.index(_IndexedDbArchivist.hashIndexName).get(_hash);
|
|
141
138
|
if (!existing) {
|
|
142
139
|
await this.db.put(this.storeName, {
|
|
143
140
|
...payload,
|
|
@@ -150,7 +147,7 @@ var _IndexedDbArchivist = class _IndexedDbArchivist extends import_archivist_abs
|
|
|
150
147
|
}
|
|
151
148
|
async startHandler() {
|
|
152
149
|
await super.startHandler();
|
|
153
|
-
const {
|
|
150
|
+
const { dbName, dbVersion, indexes, storeName } = this;
|
|
154
151
|
this._db = await (0, import_idb.openDB)(dbName, dbVersion, {
|
|
155
152
|
async upgrade(database) {
|
|
156
153
|
await Promise.resolve();
|
|
@@ -160,15 +157,14 @@ var _IndexedDbArchivist = class _IndexedDbArchivist extends import_archivist_abs
|
|
|
160
157
|
});
|
|
161
158
|
store.name = storeName;
|
|
162
159
|
const indexesToCreate = [
|
|
163
|
-
...indexes,
|
|
164
160
|
_IndexedDbArchivist.hashIndex,
|
|
165
|
-
_IndexedDbArchivist.
|
|
166
|
-
|
|
161
|
+
_IndexedDbArchivist.schemaIndex,
|
|
162
|
+
...indexes
|
|
167
163
|
];
|
|
168
|
-
for (const { key, multiEntry,
|
|
164
|
+
for (const { key, multiEntry, unique } of indexesToCreate) {
|
|
169
165
|
const indexKeys = Object.keys(key);
|
|
170
166
|
const keys = indexKeys.length === 1 ? indexKeys[0] : indexKeys;
|
|
171
|
-
const indexName =
|
|
167
|
+
const indexName = (0, import_archivist_model.buildStandardIndexName)({
|
|
172
168
|
key,
|
|
173
169
|
unique
|
|
174
170
|
});
|
|
@@ -194,25 +190,19 @@ __publicField(_IndexedDbArchivist, "hashIndex", {
|
|
|
194
190
|
_hash: 1
|
|
195
191
|
},
|
|
196
192
|
multiEntry: false,
|
|
197
|
-
name: "IX-_hash",
|
|
198
193
|
unique: true
|
|
199
194
|
});
|
|
200
|
-
__publicField(_IndexedDbArchivist, "payloadSchemasIndex", {
|
|
201
|
-
key: {
|
|
202
|
-
payload_schemas: 1
|
|
203
|
-
},
|
|
204
|
-
multiEntry: false,
|
|
205
|
-
name: "IX-payload_schemas",
|
|
206
|
-
unique: false
|
|
207
|
-
});
|
|
208
195
|
__publicField(_IndexedDbArchivist, "schemaIndex", {
|
|
209
196
|
key: {
|
|
210
197
|
schema: 1
|
|
211
198
|
},
|
|
212
199
|
multiEntry: false,
|
|
213
|
-
name: "IX-schema",
|
|
214
200
|
unique: false
|
|
215
201
|
});
|
|
202
|
+
// eslint-disable-next-line @typescript-eslint/member-ordering
|
|
203
|
+
__publicField(_IndexedDbArchivist, "hashIndexName", (0, import_archivist_model.buildStandardIndexName)(_IndexedDbArchivist.hashIndex));
|
|
204
|
+
// eslint-disable-next-line @typescript-eslint/member-ordering
|
|
205
|
+
__publicField(_IndexedDbArchivist, "schemaIndexName", (0, import_archivist_model.buildStandardIndexName)(_IndexedDbArchivist.schemaIndex));
|
|
216
206
|
var IndexedDbArchivist = _IndexedDbArchivist;
|
|
217
207
|
IndexedDbArchivist = _ts_decorate([
|
|
218
208
|
(0, import_module_model.creatableModule)()
|
package/dist/node/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts","../../src/Archivist.ts","../../src/Schema.ts","../../src/Config.ts"],"sourcesContent":["export * from './Archivist'\nexport * from './Config'\nexport * from './Params'\nexport * from './Schema'\n","import { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport { AbstractArchivist } from '@xyo-network/archivist-abstract'\nimport {\n ArchivistAllQuerySchema,\n ArchivistClearQuerySchema,\n ArchivistDeleteQuerySchema,\n ArchivistInsertQuerySchema,\n ArchivistModuleEventData,\n buildStandardIndexName,\n IndexDescription,\n} from '@xyo-network/archivist-model'\nimport { PayloadHasher } from '@xyo-network/hash'\nimport { creatableModule } from '@xyo-network/module-model'\nimport { Payload } from '@xyo-network/payload-model'\nimport { IDBPDatabase, openDB } from 'idb'\n\nimport { IndexedDbArchivistConfigSchema } from './Config'\nimport { IndexedDbArchivistParams } from './Params'\n\nexport interface PayloadStore {\n [s: string]: Payload\n}\n\n@creatableModule()\nexport class IndexedDbArchivist<\n TParams extends IndexedDbArchivistParams = IndexedDbArchivistParams,\n TEventData extends ArchivistModuleEventData = ArchivistModuleEventData,\n> extends AbstractArchivist<TParams, TEventData> {\n static override configSchemas = [IndexedDbArchivistConfigSchema]\n static readonly defaultDbName = 'archivist'\n static readonly defaultDbVersion = 1\n static readonly defaultStoreName = 'payloads'\n static readonly hashIndex: Required<IndexDescription> = { key: { _hash: 1 }, multiEntry: false, name: 'IX-_hash', unique: true }\n static readonly payloadSchemasIndex: Required<IndexDescription> = {\n key: { payload_schemas: 1 },\n multiEntry: false,\n name: 'IX-payload_schemas',\n unique: false,\n }\n static readonly schemaIndex: Required<IndexDescription> = { key: { schema: 1 }, multiEntry: false, name: 'IX-schema', unique: false }\n\n private _db: IDBPDatabase<PayloadStore> | undefined\n\n /**\n * The database name. If not supplied via config, it defaults\n * to the module name (not guaranteed to be unique) and if module\n * name is not supplied, 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?.name ?? IndexedDbArchivist.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 ?? IndexedDbArchivist.defaultDbVersion\n }\n\n /**\n * The database indexes.\n */\n get indexes() {\n return this.config?.storage?.indexes ?? []\n }\n\n override get queries() {\n return [ArchivistAllQuerySchema, ArchivistClearQuerySchema, ArchivistDeleteQuerySchema, ArchivistInsertQuerySchema, ...super.queries]\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 allHandler(): Promise<Payload[]> {\n // Get all payloads from the store\n const payloads = await this.db.getAll(this.storeName)\n // Remove any metadata before returning to the client\n return payloads.map((payload) => PayloadHasher.jsonPayload(payload))\n }\n\n protected override async clearHandler(): Promise<void> {\n await this.db.clear(this.storeName)\n }\n\n protected override async deleteHandler(hashes: string[]): Promise<string[]> {\n const distinctHashes = [...new Set(hashes)]\n const found = await Promise.all(\n distinctHashes.map(async (hash) => {\n let existing: IDBValidKey | undefined\n do {\n existing = await this.db.getKeyFromIndex(this.storeName, IndexedDbArchivist.hashIndex.name, hash)\n if (existing) await this.db.delete(this.storeName, existing)\n } while (!existing)\n return hash\n }),\n )\n // Return hashes removed\n return found.filter(exists)\n }\n\n protected override async getHandler(hashes: string[]): Promise<Payload[]> {\n const payloads = await Promise.all(hashes.map((hash) => this.db.getFromIndex(this.storeName, IndexedDbArchivist.hashIndex.name, hash)))\n return payloads.filter(exists)\n }\n\n protected override async insertHandler(payloads: Payload[]): Promise<Payload[]> {\n const pairs = await PayloadHasher.hashPairs(payloads)\n // Only return the payloads that were successfully inserted\n const inserted = await Promise.all(\n pairs.map(async ([payload, _hash]) => {\n const tx = this.db.transaction(this.storeName, 'readwrite')\n const store = tx.objectStore(this.storeName)\n const existing = await store.index(IndexedDbArchivist.hashIndex.name).get(_hash)\n if (!existing) {\n await this.db.put(this.storeName, { ...payload, _hash })\n return payload\n }\n }),\n )\n return inserted.filter(exists)\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 const { indexes, storeName, dbName, dbVersion } = this\n this._db = await openDB<PayloadStore>(dbName, dbVersion, {\n async upgrade(database) {\n await Promise.resolve() // Async to match spec\n // Create the store\n const store = database.createObjectStore(storeName, {\n // If it isn't explicitly set, create a value by auto incrementing.\n autoIncrement: true,\n })\n // Name the store\n store.name = storeName\n // Create an index on the hash\n const indexesToCreate = [...indexes, IndexedDbArchivist.hashIndex, IndexedDbArchivist.payloadSchemasIndex, IndexedDbArchivist.schemaIndex]\n for (const { key, multiEntry, name, unique } of indexesToCreate) {\n const indexKeys = Object.keys(key)\n const keys = indexKeys.length === 1 ? indexKeys[0] : indexKeys\n const indexName = name ?? buildStandardIndexName({ key, unique })\n store.createIndex(indexName, keys, { multiEntry, unique })\n }\n },\n })\n\n return true\n }\n}\n","export type IndexedDbArchivistSchema = 'network.xyo.archivist.indexeddb'\nexport const IndexedDbArchivistSchema: IndexedDbArchivistSchema = 'network.xyo.archivist.indexeddb'\n","import { ArchivistConfig, IndexDescription } from '@xyo-network/archivist-model'\n\nimport { IndexedDbArchivistSchema } from './Schema'\n\nexport type IndexedDbArchivistConfigSchema = `${IndexedDbArchivistSchema}.config`\nexport const IndexedDbArchivistConfigSchema: IndexedDbArchivistConfigSchema = `${IndexedDbArchivistSchema}.config`\n\nexport type IndexedDbArchivistConfig = ArchivistConfig<{\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: IndexedDbArchivistConfigSchema\n /**\n * The storage configuration\n * // TODO: Hoist to main archivist 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"],"mappings":"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","names":["IndexedDbArchivistSchema","IndexedDbArchivistConfigSchema","IndexedDbArchivistSchema","IndexedDbArchivist","AbstractArchivist","_db","dbName","config","name","defaultDbName","dbVersion","defaultDbVersion","indexes","storage","queries","ArchivistAllQuerySchema","ArchivistClearQuerySchema","ArchivistDeleteQuerySchema","ArchivistInsertQuerySchema","storeName","defaultStoreName","db","assertEx","allHandler","payloads","getAll","map","payload","PayloadHasher","jsonPayload","clearHandler","clear","deleteHandler","hashes","distinctHashes","Set","found","Promise","all","hash","existing","getKeyFromIndex","hashIndex","delete","filter","exists","getHandler","getFromIndex","insertHandler","pairs","hashPairs","inserted","_hash","tx","transaction","store","objectStore","index","get","put","startHandler","openDB","upgrade","database","resolve","createObjectStore","autoIncrement","indexesToCreate","payloadSchemasIndex","schemaIndex","key","multiEntry","unique","indexKeys","Object","keys","length","indexName","buildStandardIndexName","createIndex","configSchemas","IndexedDbArchivistConfigSchema","payload_schemas","schema","creatableModule"]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts","../../src/Archivist.ts","../../src/Schema.ts","../../src/Config.ts"],"sourcesContent":["export * from './Archivist'\nexport * from './Config'\nexport * from './Params'\nexport * from './Schema'\n","import { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport { AbstractArchivist } from '@xyo-network/archivist-abstract'\nimport {\n ArchivistAllQuerySchema,\n ArchivistClearQuerySchema,\n ArchivistDeleteQuerySchema,\n ArchivistInsertQuerySchema,\n ArchivistModuleEventData,\n buildStandardIndexName,\n IndexDescription,\n} from '@xyo-network/archivist-model'\nimport { PayloadHasher } from '@xyo-network/hash'\nimport { creatableModule } from '@xyo-network/module-model'\nimport { Payload } from '@xyo-network/payload-model'\nimport { IDBPDatabase, openDB } from 'idb'\n\nimport { IndexedDbArchivistConfigSchema } from './Config'\nimport { IndexedDbArchivistParams } from './Params'\n\nexport interface PayloadStore {\n [s: string]: Payload\n}\n\n@creatableModule()\nexport class IndexedDbArchivist<\n TParams extends IndexedDbArchivistParams = IndexedDbArchivistParams,\n TEventData extends ArchivistModuleEventData = ArchivistModuleEventData,\n> extends AbstractArchivist<TParams, TEventData> {\n static override configSchemas = [IndexedDbArchivistConfigSchema]\n static readonly defaultDbName = 'archivist'\n static readonly defaultDbVersion = 1\n static readonly defaultStoreName = 'payloads'\n private static readonly hashIndex: IndexDescription = { key: { _hash: 1 }, multiEntry: false, unique: true }\n private static readonly schemaIndex: IndexDescription = { key: { schema: 1 }, multiEntry: false, unique: false }\n // eslint-disable-next-line @typescript-eslint/member-ordering\n static readonly hashIndexName = buildStandardIndexName(IndexedDbArchivist.hashIndex)\n // eslint-disable-next-line @typescript-eslint/member-ordering\n static readonly schemaIndexName = buildStandardIndexName(IndexedDbArchivist.schemaIndex)\n\n private _db: IDBPDatabase<PayloadStore> | undefined\n\n /**\n * The database name. If not supplied via config, it defaults\n * to the module name (not guaranteed to be unique) and if module\n * name is not supplied, 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?.name ?? IndexedDbArchivist.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 ?? IndexedDbArchivist.defaultDbVersion\n }\n\n override get queries() {\n return [ArchivistAllQuerySchema, ArchivistClearQuerySchema, ArchivistDeleteQuerySchema, ArchivistInsertQuerySchema, ...super.queries]\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 private get indexes() {\n return this.config?.storage?.indexes ?? []\n }\n\n protected override async allHandler(): Promise<Payload[]> {\n // Get all payloads from the store\n const payloads = await this.db.getAll(this.storeName)\n // Remove any metadata before returning to the client\n return payloads.map((payload) => PayloadHasher.jsonPayload(payload))\n }\n\n protected override async clearHandler(): Promise<void> {\n await this.db.clear(this.storeName)\n }\n\n protected override async deleteHandler(hashes: string[]): Promise<string[]> {\n const distinctHashes = [...new Set(hashes)]\n const found = await Promise.all(\n distinctHashes.map(async (hash) => {\n let existing: IDBValidKey | undefined\n do {\n existing = await this.db.getKeyFromIndex(this.storeName, IndexedDbArchivist.hashIndexName, hash)\n if (existing) await this.db.delete(this.storeName, existing)\n } while (!existing)\n return hash\n }),\n )\n // Return hashes removed\n return found.filter(exists)\n }\n\n protected override async getHandler(hashes: string[]): Promise<Payload[]> {\n const payloads = await Promise.all(hashes.map((hash) => this.db.getFromIndex(this.storeName, IndexedDbArchivist.hashIndexName, hash)))\n return payloads.filter(exists)\n }\n\n protected override async insertHandler(payloads: Payload[]): Promise<Payload[]> {\n const pairs = await PayloadHasher.hashPairs(payloads)\n // Only return the payloads that were successfully inserted\n const inserted = await Promise.all(\n pairs.map(async ([payload, _hash]) => {\n const tx = this.db.transaction(this.storeName, 'readwrite')\n const store = tx.objectStore(this.storeName)\n const existing = await store.index(IndexedDbArchivist.hashIndexName).get(_hash)\n if (!existing) {\n await this.db.put(this.storeName, { ...payload, _hash })\n return payload\n }\n }),\n )\n return inserted.filter(exists)\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 const { dbName, dbVersion, indexes, storeName } = this\n this._db = await openDB<PayloadStore>(dbName, dbVersion, {\n async upgrade(database) {\n await Promise.resolve() // Async to match spec\n // Create the store\n const store = database.createObjectStore(storeName, {\n // If it isn't explicitly set, create a value by auto incrementing.\n autoIncrement: true,\n })\n // Name the store\n store.name = storeName\n // Create an index on the hash\n const indexesToCreate = [IndexedDbArchivist.hashIndex, IndexedDbArchivist.schemaIndex, ...indexes]\n for (const { key, multiEntry, unique } of indexesToCreate) {\n const indexKeys = Object.keys(key)\n const keys = indexKeys.length === 1 ? indexKeys[0] : indexKeys\n const indexName = buildStandardIndexName({ key, unique })\n store.createIndex(indexName, keys, { multiEntry, unique })\n }\n },\n })\n return true\n }\n}\n","export type IndexedDbArchivistSchema = 'network.xyo.archivist.indexeddb'\nexport const IndexedDbArchivistSchema: IndexedDbArchivistSchema = 'network.xyo.archivist.indexeddb'\n","import { ArchivistConfig, IndexDescription } from '@xyo-network/archivist-model'\n\nimport { IndexedDbArchivistSchema } from './Schema'\n\nexport type IndexedDbArchivistConfigSchema = `${IndexedDbArchivistSchema}.config`\nexport const IndexedDbArchivistConfigSchema: IndexedDbArchivistConfigSchema = `${IndexedDbArchivistSchema}.config`\n\nexport type IndexedDbArchivistConfig = ArchivistConfig<{\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: IndexedDbArchivistConfigSchema\n /**\n * The storage configuration\n * // TODO: Hoist to main archivist 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"],"mappings":"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","names":["IndexedDbArchivistSchema","IndexedDbArchivistConfigSchema","IndexedDbArchivistSchema","IndexedDbArchivist","AbstractArchivist","_db","dbName","config","name","defaultDbName","dbVersion","defaultDbVersion","queries","ArchivistAllQuerySchema","ArchivistClearQuerySchema","ArchivistDeleteQuerySchema","ArchivistInsertQuerySchema","storeName","defaultStoreName","db","assertEx","indexes","storage","allHandler","payloads","getAll","map","payload","PayloadHasher","jsonPayload","clearHandler","clear","deleteHandler","hashes","distinctHashes","Set","found","Promise","all","hash","existing","getKeyFromIndex","hashIndexName","delete","filter","exists","getHandler","getFromIndex","insertHandler","pairs","hashPairs","inserted","_hash","tx","transaction","store","objectStore","index","get","put","startHandler","openDB","upgrade","database","resolve","createObjectStore","autoIncrement","indexesToCreate","hashIndex","schemaIndex","key","multiEntry","unique","indexKeys","Object","keys","length","indexName","buildStandardIndexName","createIndex","configSchemas","IndexedDbArchivistConfigSchema","schema","schemaIndexName","creatableModule"]}
|
package/dist/node/index.js
CHANGED
|
@@ -53,13 +53,6 @@ var _IndexedDbArchivist = class _IndexedDbArchivist extends AbstractArchivist {
|
|
|
53
53
|
var _a;
|
|
54
54
|
return ((_a = this.config) == null ? void 0 : _a.dbVersion) ?? _IndexedDbArchivist.defaultDbVersion;
|
|
55
55
|
}
|
|
56
|
-
/**
|
|
57
|
-
* The database indexes.
|
|
58
|
-
*/
|
|
59
|
-
get indexes() {
|
|
60
|
-
var _a, _b;
|
|
61
|
-
return ((_b = (_a = this.config) == null ? void 0 : _a.storage) == null ? void 0 : _b.indexes) ?? [];
|
|
62
|
-
}
|
|
63
56
|
get queries() {
|
|
64
57
|
return [
|
|
65
58
|
ArchivistAllQuerySchema,
|
|
@@ -80,6 +73,10 @@ var _IndexedDbArchivist = class _IndexedDbArchivist extends AbstractArchivist {
|
|
|
80
73
|
get db() {
|
|
81
74
|
return assertEx(this._db, "DB not initialized");
|
|
82
75
|
}
|
|
76
|
+
get indexes() {
|
|
77
|
+
var _a, _b;
|
|
78
|
+
return ((_b = (_a = this.config) == null ? void 0 : _a.storage) == null ? void 0 : _b.indexes) ?? [];
|
|
79
|
+
}
|
|
83
80
|
async allHandler() {
|
|
84
81
|
const payloads = await this.db.getAll(this.storeName);
|
|
85
82
|
return payloads.map((payload) => PayloadHasher.jsonPayload(payload));
|
|
@@ -94,7 +91,7 @@ var _IndexedDbArchivist = class _IndexedDbArchivist extends AbstractArchivist {
|
|
|
94
91
|
const found = await Promise.all(distinctHashes.map(async (hash) => {
|
|
95
92
|
let existing;
|
|
96
93
|
do {
|
|
97
|
-
existing = await this.db.getKeyFromIndex(this.storeName, _IndexedDbArchivist.
|
|
94
|
+
existing = await this.db.getKeyFromIndex(this.storeName, _IndexedDbArchivist.hashIndexName, hash);
|
|
98
95
|
if (existing)
|
|
99
96
|
await this.db.delete(this.storeName, existing);
|
|
100
97
|
} while (!existing);
|
|
@@ -103,7 +100,7 @@ var _IndexedDbArchivist = class _IndexedDbArchivist extends AbstractArchivist {
|
|
|
103
100
|
return found.filter(exists);
|
|
104
101
|
}
|
|
105
102
|
async getHandler(hashes) {
|
|
106
|
-
const payloads = await Promise.all(hashes.map((hash) => this.db.getFromIndex(this.storeName, _IndexedDbArchivist.
|
|
103
|
+
const payloads = await Promise.all(hashes.map((hash) => this.db.getFromIndex(this.storeName, _IndexedDbArchivist.hashIndexName, hash)));
|
|
107
104
|
return payloads.filter(exists);
|
|
108
105
|
}
|
|
109
106
|
async insertHandler(payloads) {
|
|
@@ -111,7 +108,7 @@ var _IndexedDbArchivist = class _IndexedDbArchivist extends AbstractArchivist {
|
|
|
111
108
|
const inserted = await Promise.all(pairs.map(async ([payload, _hash]) => {
|
|
112
109
|
const tx = this.db.transaction(this.storeName, "readwrite");
|
|
113
110
|
const store = tx.objectStore(this.storeName);
|
|
114
|
-
const existing = await store.index(_IndexedDbArchivist.
|
|
111
|
+
const existing = await store.index(_IndexedDbArchivist.hashIndexName).get(_hash);
|
|
115
112
|
if (!existing) {
|
|
116
113
|
await this.db.put(this.storeName, {
|
|
117
114
|
...payload,
|
|
@@ -124,7 +121,7 @@ var _IndexedDbArchivist = class _IndexedDbArchivist extends AbstractArchivist {
|
|
|
124
121
|
}
|
|
125
122
|
async startHandler() {
|
|
126
123
|
await super.startHandler();
|
|
127
|
-
const {
|
|
124
|
+
const { dbName, dbVersion, indexes, storeName } = this;
|
|
128
125
|
this._db = await openDB(dbName, dbVersion, {
|
|
129
126
|
async upgrade(database) {
|
|
130
127
|
await Promise.resolve();
|
|
@@ -134,15 +131,14 @@ var _IndexedDbArchivist = class _IndexedDbArchivist extends AbstractArchivist {
|
|
|
134
131
|
});
|
|
135
132
|
store.name = storeName;
|
|
136
133
|
const indexesToCreate = [
|
|
137
|
-
...indexes,
|
|
138
134
|
_IndexedDbArchivist.hashIndex,
|
|
139
|
-
_IndexedDbArchivist.
|
|
140
|
-
|
|
135
|
+
_IndexedDbArchivist.schemaIndex,
|
|
136
|
+
...indexes
|
|
141
137
|
];
|
|
142
|
-
for (const { key, multiEntry,
|
|
138
|
+
for (const { key, multiEntry, unique } of indexesToCreate) {
|
|
143
139
|
const indexKeys = Object.keys(key);
|
|
144
140
|
const keys = indexKeys.length === 1 ? indexKeys[0] : indexKeys;
|
|
145
|
-
const indexName =
|
|
141
|
+
const indexName = buildStandardIndexName({
|
|
146
142
|
key,
|
|
147
143
|
unique
|
|
148
144
|
});
|
|
@@ -168,25 +164,19 @@ __publicField(_IndexedDbArchivist, "hashIndex", {
|
|
|
168
164
|
_hash: 1
|
|
169
165
|
},
|
|
170
166
|
multiEntry: false,
|
|
171
|
-
name: "IX-_hash",
|
|
172
167
|
unique: true
|
|
173
168
|
});
|
|
174
|
-
__publicField(_IndexedDbArchivist, "payloadSchemasIndex", {
|
|
175
|
-
key: {
|
|
176
|
-
payload_schemas: 1
|
|
177
|
-
},
|
|
178
|
-
multiEntry: false,
|
|
179
|
-
name: "IX-payload_schemas",
|
|
180
|
-
unique: false
|
|
181
|
-
});
|
|
182
169
|
__publicField(_IndexedDbArchivist, "schemaIndex", {
|
|
183
170
|
key: {
|
|
184
171
|
schema: 1
|
|
185
172
|
},
|
|
186
173
|
multiEntry: false,
|
|
187
|
-
name: "IX-schema",
|
|
188
174
|
unique: false
|
|
189
175
|
});
|
|
176
|
+
// eslint-disable-next-line @typescript-eslint/member-ordering
|
|
177
|
+
__publicField(_IndexedDbArchivist, "hashIndexName", buildStandardIndexName(_IndexedDbArchivist.hashIndex));
|
|
178
|
+
// eslint-disable-next-line @typescript-eslint/member-ordering
|
|
179
|
+
__publicField(_IndexedDbArchivist, "schemaIndexName", buildStandardIndexName(_IndexedDbArchivist.schemaIndex));
|
|
190
180
|
var IndexedDbArchivist = _IndexedDbArchivist;
|
|
191
181
|
IndexedDbArchivist = _ts_decorate([
|
|
192
182
|
creatableModule()
|
package/dist/node/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/Archivist.ts","../../src/Schema.ts","../../src/Config.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport { AbstractArchivist } from '@xyo-network/archivist-abstract'\nimport {\n ArchivistAllQuerySchema,\n ArchivistClearQuerySchema,\n ArchivistDeleteQuerySchema,\n ArchivistInsertQuerySchema,\n ArchivistModuleEventData,\n buildStandardIndexName,\n IndexDescription,\n} from '@xyo-network/archivist-model'\nimport { PayloadHasher } from '@xyo-network/hash'\nimport { creatableModule } from '@xyo-network/module-model'\nimport { Payload } from '@xyo-network/payload-model'\nimport { IDBPDatabase, openDB } from 'idb'\n\nimport { IndexedDbArchivistConfigSchema } from './Config'\nimport { IndexedDbArchivistParams } from './Params'\n\nexport interface PayloadStore {\n [s: string]: Payload\n}\n\n@creatableModule()\nexport class IndexedDbArchivist<\n TParams extends IndexedDbArchivistParams = IndexedDbArchivistParams,\n TEventData extends ArchivistModuleEventData = ArchivistModuleEventData,\n> extends AbstractArchivist<TParams, TEventData> {\n static override configSchemas = [IndexedDbArchivistConfigSchema]\n static readonly defaultDbName = 'archivist'\n static readonly defaultDbVersion = 1\n static readonly defaultStoreName = 'payloads'\n static readonly hashIndex: Required<IndexDescription> = { key: { _hash: 1 }, multiEntry: false, name: 'IX-_hash', unique: true }\n static readonly payloadSchemasIndex: Required<IndexDescription> = {\n key: { payload_schemas: 1 },\n multiEntry: false,\n name: 'IX-payload_schemas',\n unique: false,\n }\n static readonly schemaIndex: Required<IndexDescription> = { key: { schema: 1 }, multiEntry: false, name: 'IX-schema', unique: false }\n\n private _db: IDBPDatabase<PayloadStore> | undefined\n\n /**\n * The database name. If not supplied via config, it defaults\n * to the module name (not guaranteed to be unique) and if module\n * name is not supplied, 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?.name ?? IndexedDbArchivist.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 ?? IndexedDbArchivist.defaultDbVersion\n }\n\n /**\n * The database indexes.\n */\n get indexes() {\n return this.config?.storage?.indexes ?? []\n }\n\n override get queries() {\n return [ArchivistAllQuerySchema, ArchivistClearQuerySchema, ArchivistDeleteQuerySchema, ArchivistInsertQuerySchema, ...super.queries]\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 allHandler(): Promise<Payload[]> {\n // Get all payloads from the store\n const payloads = await this.db.getAll(this.storeName)\n // Remove any metadata before returning to the client\n return payloads.map((payload) => PayloadHasher.jsonPayload(payload))\n }\n\n protected override async clearHandler(): Promise<void> {\n await this.db.clear(this.storeName)\n }\n\n protected override async deleteHandler(hashes: string[]): Promise<string[]> {\n const distinctHashes = [...new Set(hashes)]\n const found = await Promise.all(\n distinctHashes.map(async (hash) => {\n let existing: IDBValidKey | undefined\n do {\n existing = await this.db.getKeyFromIndex(this.storeName, IndexedDbArchivist.hashIndex.name, hash)\n if (existing) await this.db.delete(this.storeName, existing)\n } while (!existing)\n return hash\n }),\n )\n // Return hashes removed\n return found.filter(exists)\n }\n\n protected override async getHandler(hashes: string[]): Promise<Payload[]> {\n const payloads = await Promise.all(hashes.map((hash) => this.db.getFromIndex(this.storeName, IndexedDbArchivist.hashIndex.name, hash)))\n return payloads.filter(exists)\n }\n\n protected override async insertHandler(payloads: Payload[]): Promise<Payload[]> {\n const pairs = await PayloadHasher.hashPairs(payloads)\n // Only return the payloads that were successfully inserted\n const inserted = await Promise.all(\n pairs.map(async ([payload, _hash]) => {\n const tx = this.db.transaction(this.storeName, 'readwrite')\n const store = tx.objectStore(this.storeName)\n const existing = await store.index(IndexedDbArchivist.hashIndex.name).get(_hash)\n if (!existing) {\n await this.db.put(this.storeName, { ...payload, _hash })\n return payload\n }\n }),\n )\n return inserted.filter(exists)\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 const { indexes, storeName, dbName, dbVersion } = this\n this._db = await openDB<PayloadStore>(dbName, dbVersion, {\n async upgrade(database) {\n await Promise.resolve() // Async to match spec\n // Create the store\n const store = database.createObjectStore(storeName, {\n // If it isn't explicitly set, create a value by auto incrementing.\n autoIncrement: true,\n })\n // Name the store\n store.name = storeName\n // Create an index on the hash\n const indexesToCreate = [...indexes, IndexedDbArchivist.hashIndex, IndexedDbArchivist.payloadSchemasIndex, IndexedDbArchivist.schemaIndex]\n for (const { key, multiEntry, name, unique } of indexesToCreate) {\n const indexKeys = Object.keys(key)\n const keys = indexKeys.length === 1 ? indexKeys[0] : indexKeys\n const indexName = name ?? buildStandardIndexName({ key, unique })\n store.createIndex(indexName, keys, { multiEntry, unique })\n }\n },\n })\n\n return true\n }\n}\n","export type IndexedDbArchivistSchema = 'network.xyo.archivist.indexeddb'\nexport const IndexedDbArchivistSchema: IndexedDbArchivistSchema = 'network.xyo.archivist.indexeddb'\n","import { ArchivistConfig, IndexDescription } from '@xyo-network/archivist-model'\n\nimport { IndexedDbArchivistSchema } from './Schema'\n\nexport type IndexedDbArchivistConfigSchema = `${IndexedDbArchivistSchema}.config`\nexport const IndexedDbArchivistConfigSchema: IndexedDbArchivistConfigSchema = `${IndexedDbArchivistSchema}.config`\n\nexport type IndexedDbArchivistConfig = ArchivistConfig<{\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: IndexedDbArchivistConfigSchema\n /**\n * The storage configuration\n * // TODO: Hoist to main archivist 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"],"mappings":"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","names":["assertEx","exists","AbstractArchivist","ArchivistAllQuerySchema","ArchivistClearQuerySchema","ArchivistDeleteQuerySchema","ArchivistInsertQuerySchema","buildStandardIndexName","PayloadHasher","creatableModule","openDB","IndexedDbArchivistSchema","IndexedDbArchivistConfigSchema","IndexedDbArchivistSchema","IndexedDbArchivist","AbstractArchivist","_db","dbName","config","name","defaultDbName","dbVersion","defaultDbVersion","indexes","storage","queries","ArchivistAllQuerySchema","ArchivistClearQuerySchema","ArchivistDeleteQuerySchema","ArchivistInsertQuerySchema","storeName","defaultStoreName","db","assertEx","allHandler","payloads","getAll","map","payload","PayloadHasher","jsonPayload","clearHandler","clear","deleteHandler","hashes","distinctHashes","Set","found","Promise","all","hash","existing","getKeyFromIndex","hashIndex","delete","filter","exists","getHandler","getFromIndex","insertHandler","pairs","hashPairs","inserted","_hash","tx","transaction","store","objectStore","index","get","put","startHandler","openDB","upgrade","database","resolve","createObjectStore","autoIncrement","indexesToCreate","payloadSchemasIndex","schemaIndex","key","multiEntry","unique","indexKeys","Object","keys","length","indexName","buildStandardIndexName","createIndex","configSchemas","IndexedDbArchivistConfigSchema","payload_schemas","schema","creatableModule"]}
|
|
1
|
+
{"version":3,"sources":["../../src/Archivist.ts","../../src/Schema.ts","../../src/Config.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport { AbstractArchivist } from '@xyo-network/archivist-abstract'\nimport {\n ArchivistAllQuerySchema,\n ArchivistClearQuerySchema,\n ArchivistDeleteQuerySchema,\n ArchivistInsertQuerySchema,\n ArchivistModuleEventData,\n buildStandardIndexName,\n IndexDescription,\n} from '@xyo-network/archivist-model'\nimport { PayloadHasher } from '@xyo-network/hash'\nimport { creatableModule } from '@xyo-network/module-model'\nimport { Payload } from '@xyo-network/payload-model'\nimport { IDBPDatabase, openDB } from 'idb'\n\nimport { IndexedDbArchivistConfigSchema } from './Config'\nimport { IndexedDbArchivistParams } from './Params'\n\nexport interface PayloadStore {\n [s: string]: Payload\n}\n\n@creatableModule()\nexport class IndexedDbArchivist<\n TParams extends IndexedDbArchivistParams = IndexedDbArchivistParams,\n TEventData extends ArchivistModuleEventData = ArchivistModuleEventData,\n> extends AbstractArchivist<TParams, TEventData> {\n static override configSchemas = [IndexedDbArchivistConfigSchema]\n static readonly defaultDbName = 'archivist'\n static readonly defaultDbVersion = 1\n static readonly defaultStoreName = 'payloads'\n private static readonly hashIndex: IndexDescription = { key: { _hash: 1 }, multiEntry: false, unique: true }\n private static readonly schemaIndex: IndexDescription = { key: { schema: 1 }, multiEntry: false, unique: false }\n // eslint-disable-next-line @typescript-eslint/member-ordering\n static readonly hashIndexName = buildStandardIndexName(IndexedDbArchivist.hashIndex)\n // eslint-disable-next-line @typescript-eslint/member-ordering\n static readonly schemaIndexName = buildStandardIndexName(IndexedDbArchivist.schemaIndex)\n\n private _db: IDBPDatabase<PayloadStore> | undefined\n\n /**\n * The database name. If not supplied via config, it defaults\n * to the module name (not guaranteed to be unique) and if module\n * name is not supplied, 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?.name ?? IndexedDbArchivist.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 ?? IndexedDbArchivist.defaultDbVersion\n }\n\n override get queries() {\n return [ArchivistAllQuerySchema, ArchivistClearQuerySchema, ArchivistDeleteQuerySchema, ArchivistInsertQuerySchema, ...super.queries]\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 private get indexes() {\n return this.config?.storage?.indexes ?? []\n }\n\n protected override async allHandler(): Promise<Payload[]> {\n // Get all payloads from the store\n const payloads = await this.db.getAll(this.storeName)\n // Remove any metadata before returning to the client\n return payloads.map((payload) => PayloadHasher.jsonPayload(payload))\n }\n\n protected override async clearHandler(): Promise<void> {\n await this.db.clear(this.storeName)\n }\n\n protected override async deleteHandler(hashes: string[]): Promise<string[]> {\n const distinctHashes = [...new Set(hashes)]\n const found = await Promise.all(\n distinctHashes.map(async (hash) => {\n let existing: IDBValidKey | undefined\n do {\n existing = await this.db.getKeyFromIndex(this.storeName, IndexedDbArchivist.hashIndexName, hash)\n if (existing) await this.db.delete(this.storeName, existing)\n } while (!existing)\n return hash\n }),\n )\n // Return hashes removed\n return found.filter(exists)\n }\n\n protected override async getHandler(hashes: string[]): Promise<Payload[]> {\n const payloads = await Promise.all(hashes.map((hash) => this.db.getFromIndex(this.storeName, IndexedDbArchivist.hashIndexName, hash)))\n return payloads.filter(exists)\n }\n\n protected override async insertHandler(payloads: Payload[]): Promise<Payload[]> {\n const pairs = await PayloadHasher.hashPairs(payloads)\n // Only return the payloads that were successfully inserted\n const inserted = await Promise.all(\n pairs.map(async ([payload, _hash]) => {\n const tx = this.db.transaction(this.storeName, 'readwrite')\n const store = tx.objectStore(this.storeName)\n const existing = await store.index(IndexedDbArchivist.hashIndexName).get(_hash)\n if (!existing) {\n await this.db.put(this.storeName, { ...payload, _hash })\n return payload\n }\n }),\n )\n return inserted.filter(exists)\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 const { dbName, dbVersion, indexes, storeName } = this\n this._db = await openDB<PayloadStore>(dbName, dbVersion, {\n async upgrade(database) {\n await Promise.resolve() // Async to match spec\n // Create the store\n const store = database.createObjectStore(storeName, {\n // If it isn't explicitly set, create a value by auto incrementing.\n autoIncrement: true,\n })\n // Name the store\n store.name = storeName\n // Create an index on the hash\n const indexesToCreate = [IndexedDbArchivist.hashIndex, IndexedDbArchivist.schemaIndex, ...indexes]\n for (const { key, multiEntry, unique } of indexesToCreate) {\n const indexKeys = Object.keys(key)\n const keys = indexKeys.length === 1 ? indexKeys[0] : indexKeys\n const indexName = buildStandardIndexName({ key, unique })\n store.createIndex(indexName, keys, { multiEntry, unique })\n }\n },\n })\n return true\n }\n}\n","export type IndexedDbArchivistSchema = 'network.xyo.archivist.indexeddb'\nexport const IndexedDbArchivistSchema: IndexedDbArchivistSchema = 'network.xyo.archivist.indexeddb'\n","import { ArchivistConfig, IndexDescription } from '@xyo-network/archivist-model'\n\nimport { IndexedDbArchivistSchema } from './Schema'\n\nexport type IndexedDbArchivistConfigSchema = `${IndexedDbArchivistSchema}.config`\nexport const IndexedDbArchivistConfigSchema: IndexedDbArchivistConfigSchema = `${IndexedDbArchivistSchema}.config`\n\nexport type IndexedDbArchivistConfig = ArchivistConfig<{\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: IndexedDbArchivistConfigSchema\n /**\n * The storage configuration\n * // TODO: Hoist to main archivist 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"],"mappings":";;;;;;;;;AAAA,SAASA,gBAAgB;AACzB,SAASC,cAAc;AACvB,SAASC,yBAAyB;AAClC,SACEC,yBACAC,2BACAC,4BACAC,4BAEAC,8BAEK;AACP,SAASC,qBAAqB;AAC9B,SAASC,uBAAuB;AAEhC,SAAuBC,cAAc;;;ACd9B,IAAMC,2BAAqD;;;ACI3D,IAAMC,iCAAiE,GAAGC,wBAAAA;;;;;;;;;;;;;;AFoB1E,IAAMC,sBAAN,MAAMA,4BAGHC,kBAAAA;EAYAC;;;;;;;;EASR,IAAIC,SAAS;;AACX,aAAO,UAAKC,WAAL,mBAAaD,aAAU,UAAKC,WAAL,mBAAaC,SAAQL,oBAAmBM;EACxE;;;;EAKA,IAAIC,YAAY;;AACd,aAAO,UAAKH,WAAL,mBAAaG,cAAaP,oBAAmBQ;EACtD;EAEA,IAAaC,UAAU;AACrB,WAAO;MAACC;MAAyBC;MAA2BC;MAA4BC;SAA+B,MAAMJ;;EAC/H;;;;;EAMA,IAAIK,YAAY;;AACd,aAAO,UAAKV,WAAL,mBAAaU,cAAad,oBAAmBe;EACtD;EAEA,IAAYC,KAAiC;AAC3C,WAAOC,SAAS,KAAKf,KAAK,oBAAA;EAC5B;EAEA,IAAYgB,UAAU;;AACpB,aAAO,gBAAKd,WAAL,mBAAae,YAAb,mBAAsBD,YAAW,CAAA;EAC1C;EAEA,MAAyBE,aAAiC;AAExD,UAAMC,WAAW,MAAM,KAAKL,GAAGM,OAAO,KAAKR,SAAS;AAEpD,WAAOO,SAASE,IAAI,CAACC,YAAYC,cAAcC,YAAYF,OAAAA,CAAAA;EAC7D;EAEA,MAAyBG,eAA8B;AACrD,UAAM,KAAKX,GAAGY,MAAM,KAAKd,SAAS;EACpC;EAEA,MAAyBe,cAAcC,QAAqC;AAC1E,UAAMC,iBAAiB;SAAI,IAAIC,IAAIF,MAAAA;;AACnC,UAAMG,QAAQ,MAAMC,QAAQC,IAC1BJ,eAAeR,IAAI,OAAOa,SAAAA;AACxB,UAAIC;AACJ,SAAG;AACDA,mBAAW,MAAM,KAAKrB,GAAGsB,gBAAgB,KAAKxB,WAAWd,oBAAmBuC,eAAeH,IAAAA;AAC3F,YAAIC;AAAU,gBAAM,KAAKrB,GAAGwB,OAAO,KAAK1B,WAAWuB,QAAAA;MACrD,SAAS,CAACA;AACV,aAAOD;IACT,CAAA,CAAA;AAGF,WAAOH,MAAMQ,OAAOC,MAAAA;EACtB;EAEA,MAAyBC,WAAWb,QAAsC;AACxE,UAAMT,WAAW,MAAMa,QAAQC,IAAIL,OAAOP,IAAI,CAACa,SAAS,KAAKpB,GAAG4B,aAAa,KAAK9B,WAAWd,oBAAmBuC,eAAeH,IAAAA,CAAAA,CAAAA;AAC/H,WAAOf,SAASoB,OAAOC,MAAAA;EACzB;EAEA,MAAyBG,cAAcxB,UAAyC;AAC9E,UAAMyB,QAAQ,MAAMrB,cAAcsB,UAAU1B,QAAAA;AAE5C,UAAM2B,WAAW,MAAMd,QAAQC,IAC7BW,MAAMvB,IAAI,OAAO,CAACC,SAASyB,KAAAA,MAAM;AAC/B,YAAMC,KAAK,KAAKlC,GAAGmC,YAAY,KAAKrC,WAAW,WAAA;AAC/C,YAAMsC,QAAQF,GAAGG,YAAY,KAAKvC,SAAS;AAC3C,YAAMuB,WAAW,MAAMe,MAAME,MAAMtD,oBAAmBuC,aAAa,EAAEgB,IAAIN,KAAAA;AACzE,UAAI,CAACZ,UAAU;AACb,cAAM,KAAKrB,GAAGwC,IAAI,KAAK1C,WAAW;UAAE,GAAGU;UAASyB;QAAM,CAAA;AACtD,eAAOzB;MACT;IACF,CAAA,CAAA;AAEF,WAAOwB,SAASP,OAAOC,MAAAA;EACzB;EAEA,MAAyBe,eAAe;AACtC,UAAM,MAAMA,aAAAA;AAGZ,UAAM,EAAEtD,QAAQI,WAAWW,SAASJ,UAAS,IAAK;AAClD,SAAKZ,MAAM,MAAMwD,OAAqBvD,QAAQI,WAAW;MACvD,MAAMoD,QAAQC,UAAQ;AACpB,cAAM1B,QAAQ2B,QAAO;AAErB,cAAMT,QAAQQ,SAASE,kBAAkBhD,WAAW;;UAElDiD,eAAe;QACjB,CAAA;AAEAX,cAAM/C,OAAOS;AAEb,cAAMkD,kBAAkB;UAAChE,oBAAmBiE;UAAWjE,oBAAmBkE;aAAgBhD;;AAC1F,mBAAW,EAAEiD,KAAKC,YAAYC,OAAM,KAAML,iBAAiB;AACzD,gBAAMM,YAAYC,OAAOC,KAAKL,GAAAA;AAC9B,gBAAMK,OAAOF,UAAUG,WAAW,IAAIH,UAAU,CAAA,IAAKA;AACrD,gBAAMI,YAAYC,uBAAuB;YAAER;YAAKE;UAAO,CAAA;AACvDjB,gBAAMwB,YAAYF,WAAWF,MAAM;YAAEJ;YAAYC;UAAO,CAAA;QAC1D;MACF;IACF,CAAA;AACA,WAAO;EACT;AACF;AAhIUpE;AACR,cAJWD,qBAIK6E,iBAAgB;EAACC;;AACjC,cALW9E,qBAKKM,iBAAgB;AAChC,cANWN,qBAMKQ,oBAAmB;AACnC,cAPWR,qBAOKe,oBAAmB;AACnC,cARWf,qBAQaiE,aAA8B;EAAEE,KAAK;IAAElB,OAAO;EAAE;EAAGmB,YAAY;EAAOC,QAAQ;AAAK;AAC3G,cATWrE,qBASakE,eAAgC;EAAEC,KAAK;IAAEY,QAAQ;EAAE;EAAGX,YAAY;EAAOC,QAAQ;AAAM;;AAE/G,cAXWrE,qBAWKuC,iBAAgBoC,uBAAuB3E,oBAAmBiE,SAAS;;AAEnF,cAbWjE,qBAaKgF,mBAAkBL,uBAAuB3E,oBAAmBkE,WAAW;AAblF,IAAMlE,qBAAN;AAAMA,qBAAAA,aAAAA;EADZiF,gBAAAA;GACYjF,kBAAAA;","names":["assertEx","exists","AbstractArchivist","ArchivistAllQuerySchema","ArchivistClearQuerySchema","ArchivistDeleteQuerySchema","ArchivistInsertQuerySchema","buildStandardIndexName","PayloadHasher","creatableModule","openDB","IndexedDbArchivistSchema","IndexedDbArchivistConfigSchema","IndexedDbArchivistSchema","IndexedDbArchivist","AbstractArchivist","_db","dbName","config","name","defaultDbName","dbVersion","defaultDbVersion","queries","ArchivistAllQuerySchema","ArchivistClearQuerySchema","ArchivistDeleteQuerySchema","ArchivistInsertQuerySchema","storeName","defaultStoreName","db","assertEx","indexes","storage","allHandler","payloads","getAll","map","payload","PayloadHasher","jsonPayload","clearHandler","clear","deleteHandler","hashes","distinctHashes","Set","found","Promise","all","hash","existing","getKeyFromIndex","hashIndexName","delete","filter","exists","getHandler","getFromIndex","insertHandler","pairs","hashPairs","inserted","_hash","tx","transaction","store","objectStore","index","get","put","startHandler","openDB","upgrade","database","resolve","createObjectStore","autoIncrement","indexesToCreate","hashIndex","schemaIndex","key","multiEntry","unique","indexKeys","Object","keys","length","indexName","buildStandardIndexName","createIndex","configSchemas","IndexedDbArchivistConfigSchema","schema","schemaIndexName","creatableModule"]}
|
package/package.json
CHANGED
|
@@ -12,19 +12,19 @@
|
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@xylabs/assert": "^2.13.23",
|
|
14
14
|
"@xylabs/exists": "^2.13.23",
|
|
15
|
-
"@xyo-network/archivist-abstract": "~2.87.0-rc.
|
|
16
|
-
"@xyo-network/archivist-model": "~2.87.0-rc.
|
|
17
|
-
"@xyo-network/hash": "~2.87.0-rc.
|
|
18
|
-
"@xyo-network/module-model": "~2.87.0-rc.
|
|
19
|
-
"@xyo-network/payload-model": "~2.87.0-rc.
|
|
15
|
+
"@xyo-network/archivist-abstract": "~2.87.0-rc.3",
|
|
16
|
+
"@xyo-network/archivist-model": "~2.87.0-rc.3",
|
|
17
|
+
"@xyo-network/hash": "~2.87.0-rc.3",
|
|
18
|
+
"@xyo-network/module-model": "~2.87.0-rc.3",
|
|
19
|
+
"@xyo-network/payload-model": "~2.87.0-rc.3",
|
|
20
20
|
"idb": "^8.0.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@xylabs/ts-scripts-yarn3": "^3.2.33",
|
|
24
24
|
"@xylabs/tsconfig": "^3.2.33",
|
|
25
|
-
"@xyo-network/account": "~2.87.0-rc.
|
|
26
|
-
"@xyo-network/id-payload-plugin": "~2.87.0-rc.
|
|
27
|
-
"@xyo-network/payload-wrapper": "~2.87.0-rc.
|
|
25
|
+
"@xyo-network/account": "~2.87.0-rc.3",
|
|
26
|
+
"@xyo-network/id-payload-plugin": "~2.87.0-rc.3",
|
|
27
|
+
"@xyo-network/payload-wrapper": "~2.87.0-rc.3",
|
|
28
28
|
"fake-indexeddb": "^5.0.2",
|
|
29
29
|
"typescript": "^5.3.3"
|
|
30
30
|
},
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js.git"
|
|
68
68
|
},
|
|
69
69
|
"sideEffects": false,
|
|
70
|
-
"version": "2.87.0-rc.
|
|
70
|
+
"version": "2.87.0-rc.3",
|
|
71
71
|
"type": "module",
|
|
72
72
|
"stableVersion": "2.86.1"
|
|
73
73
|
}
|
package/src/Archivist.ts
CHANGED
|
@@ -31,14 +31,12 @@ export class IndexedDbArchivist<
|
|
|
31
31
|
static readonly defaultDbName = 'archivist'
|
|
32
32
|
static readonly defaultDbVersion = 1
|
|
33
33
|
static readonly defaultStoreName = 'payloads'
|
|
34
|
-
static readonly hashIndex:
|
|
35
|
-
static readonly
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
static readonly schemaIndex: Required<IndexDescription> = { key: { schema: 1 }, multiEntry: false, name: 'IX-schema', unique: false }
|
|
34
|
+
private static readonly hashIndex: IndexDescription = { key: { _hash: 1 }, multiEntry: false, unique: true }
|
|
35
|
+
private static readonly schemaIndex: IndexDescription = { key: { schema: 1 }, multiEntry: false, unique: false }
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/member-ordering
|
|
37
|
+
static readonly hashIndexName = buildStandardIndexName(IndexedDbArchivist.hashIndex)
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/member-ordering
|
|
39
|
+
static readonly schemaIndexName = buildStandardIndexName(IndexedDbArchivist.schemaIndex)
|
|
42
40
|
|
|
43
41
|
private _db: IDBPDatabase<PayloadStore> | undefined
|
|
44
42
|
|
|
@@ -60,16 +58,10 @@ export class IndexedDbArchivist<
|
|
|
60
58
|
return this.config?.dbVersion ?? IndexedDbArchivist.defaultDbVersion
|
|
61
59
|
}
|
|
62
60
|
|
|
63
|
-
/**
|
|
64
|
-
* The database indexes.
|
|
65
|
-
*/
|
|
66
|
-
get indexes() {
|
|
67
|
-
return this.config?.storage?.indexes ?? []
|
|
68
|
-
}
|
|
69
|
-
|
|
70
61
|
override get queries() {
|
|
71
62
|
return [ArchivistAllQuerySchema, ArchivistClearQuerySchema, ArchivistDeleteQuerySchema, ArchivistInsertQuerySchema, ...super.queries]
|
|
72
63
|
}
|
|
64
|
+
|
|
73
65
|
/**
|
|
74
66
|
* The name of the object store. If not supplied via config, it defaults
|
|
75
67
|
* to `payloads`.
|
|
@@ -82,6 +74,10 @@ export class IndexedDbArchivist<
|
|
|
82
74
|
return assertEx(this._db, 'DB not initialized')
|
|
83
75
|
}
|
|
84
76
|
|
|
77
|
+
private get indexes() {
|
|
78
|
+
return this.config?.storage?.indexes ?? []
|
|
79
|
+
}
|
|
80
|
+
|
|
85
81
|
protected override async allHandler(): Promise<Payload[]> {
|
|
86
82
|
// Get all payloads from the store
|
|
87
83
|
const payloads = await this.db.getAll(this.storeName)
|
|
@@ -99,7 +95,7 @@ export class IndexedDbArchivist<
|
|
|
99
95
|
distinctHashes.map(async (hash) => {
|
|
100
96
|
let existing: IDBValidKey | undefined
|
|
101
97
|
do {
|
|
102
|
-
existing = await this.db.getKeyFromIndex(this.storeName, IndexedDbArchivist.
|
|
98
|
+
existing = await this.db.getKeyFromIndex(this.storeName, IndexedDbArchivist.hashIndexName, hash)
|
|
103
99
|
if (existing) await this.db.delete(this.storeName, existing)
|
|
104
100
|
} while (!existing)
|
|
105
101
|
return hash
|
|
@@ -110,7 +106,7 @@ export class IndexedDbArchivist<
|
|
|
110
106
|
}
|
|
111
107
|
|
|
112
108
|
protected override async getHandler(hashes: string[]): Promise<Payload[]> {
|
|
113
|
-
const payloads = await Promise.all(hashes.map((hash) => this.db.getFromIndex(this.storeName, IndexedDbArchivist.
|
|
109
|
+
const payloads = await Promise.all(hashes.map((hash) => this.db.getFromIndex(this.storeName, IndexedDbArchivist.hashIndexName, hash)))
|
|
114
110
|
return payloads.filter(exists)
|
|
115
111
|
}
|
|
116
112
|
|
|
@@ -121,7 +117,7 @@ export class IndexedDbArchivist<
|
|
|
121
117
|
pairs.map(async ([payload, _hash]) => {
|
|
122
118
|
const tx = this.db.transaction(this.storeName, 'readwrite')
|
|
123
119
|
const store = tx.objectStore(this.storeName)
|
|
124
|
-
const existing = await store.index(IndexedDbArchivist.
|
|
120
|
+
const existing = await store.index(IndexedDbArchivist.hashIndexName).get(_hash)
|
|
125
121
|
if (!existing) {
|
|
126
122
|
await this.db.put(this.storeName, { ...payload, _hash })
|
|
127
123
|
return payload
|
|
@@ -135,7 +131,7 @@ export class IndexedDbArchivist<
|
|
|
135
131
|
await super.startHandler()
|
|
136
132
|
// NOTE: We could defer this creation to first access but we
|
|
137
133
|
// want to fail fast here in case something is wrong
|
|
138
|
-
const {
|
|
134
|
+
const { dbName, dbVersion, indexes, storeName } = this
|
|
139
135
|
this._db = await openDB<PayloadStore>(dbName, dbVersion, {
|
|
140
136
|
async upgrade(database) {
|
|
141
137
|
await Promise.resolve() // Async to match spec
|
|
@@ -147,16 +143,15 @@ export class IndexedDbArchivist<
|
|
|
147
143
|
// Name the store
|
|
148
144
|
store.name = storeName
|
|
149
145
|
// Create an index on the hash
|
|
150
|
-
const indexesToCreate = [
|
|
151
|
-
for (const { key, multiEntry,
|
|
146
|
+
const indexesToCreate = [IndexedDbArchivist.hashIndex, IndexedDbArchivist.schemaIndex, ...indexes]
|
|
147
|
+
for (const { key, multiEntry, unique } of indexesToCreate) {
|
|
152
148
|
const indexKeys = Object.keys(key)
|
|
153
149
|
const keys = indexKeys.length === 1 ? indexKeys[0] : indexKeys
|
|
154
|
-
const indexName =
|
|
150
|
+
const indexName = buildStandardIndexName({ key, unique })
|
|
155
151
|
store.createIndex(indexName, keys, { multiEntry, unique })
|
|
156
152
|
}
|
|
157
153
|
},
|
|
158
154
|
})
|
|
159
|
-
|
|
160
155
|
return true
|
|
161
156
|
}
|
|
162
157
|
}
|