@actdim/utico 0.9.5 → 0.9.7

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.
@@ -0,0 +1,10 @@
1
+ import { Executor } from './typeCore';
2
+ declare class AsyncMutex {
3
+ private mutex;
4
+ private locked;
5
+ lock(timeoutMs?: number): Promise<() => void>;
6
+ tryLock(): () => void | null;
7
+ dispatch<T>(fn: Executor<T>, timeoutMs?: number): Promise<T>;
8
+ }
9
+ export { AsyncMutex };
10
+ //# sourceMappingURL=asyncMutex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asyncMutex.d.ts","sourceRoot":"","sources":["../src/asyncMutex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAQtC,cAAM,UAAU;IACZ,OAAO,CAAC,KAAK,CAAqB;IAElC,OAAO,CAAC,MAAM,CAAS;IAEjB,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC;IAgCnD,OAAO,IAAI,MAAM,IAAI,GAAG,IAAI;IAiBtB,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;CAQrE;AAGD,OAAO,EACH,UAAU,EACb,CAAC"}
@@ -0,0 +1,47 @@
1
+ class n {
2
+ // or Mutex
3
+ mutex = Promise.resolve();
4
+ locked = !1;
5
+ async lock(e) {
6
+ let t = () => {
7
+ }, o;
8
+ const i = this.mutex;
9
+ this.mutex = this.mutex.then(() => new Promise(t)), this.locked = !0;
10
+ const r = new Promise((s, l) => {
11
+ t = s, e && (o = setTimeout(() => {
12
+ l(new Error("Mutex lock timeout"));
13
+ }, e));
14
+ });
15
+ try {
16
+ const s = await r;
17
+ return clearTimeout(o), () => {
18
+ this.locked = !1, s();
19
+ };
20
+ } catch (s) {
21
+ throw this.mutex = i, this.locked = !1, s;
22
+ }
23
+ }
24
+ tryLock() {
25
+ if (this.locked) return null;
26
+ let e;
27
+ return this.locked = !0, this.mutex = this.mutex.then(
28
+ () => new Promise((t) => {
29
+ e = () => {
30
+ this.locked = !1, t();
31
+ };
32
+ })
33
+ ), e;
34
+ }
35
+ async dispatch(e, t) {
36
+ const o = await this.lock(t);
37
+ try {
38
+ return await e();
39
+ } finally {
40
+ o();
41
+ }
42
+ }
43
+ }
44
+ export {
45
+ n as AsyncMutex
46
+ };
47
+ //# sourceMappingURL=asyncMutex.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asyncMutex.es.js","sources":["../src/asyncMutex.ts"],"sourcesContent":["import { Executor } from './typeCore';\r\n/**\r\n * Example:\r\n * const mutex = new Mutex();\r\n * await mutex.dispatch(async () => {...});\r\n */\r\n// type Executor<T> = () => Promise<T> | T;\r\n\r\nclass AsyncMutex { // or Mutex\r\n private mutex = Promise.resolve();\r\n\r\n private locked = false;\r\n \r\n async lock(timeoutMs?: number): Promise<() => void> {\r\n let begin: (unlock: () => void) => void = () => { };\r\n let timer: NodeJS.Timeout | undefined;\r\n\r\n const previous = this.mutex;\r\n this.mutex = this.mutex.then(() => new Promise(begin));\r\n this.locked = true;\r\n \r\n const lockPromise = new Promise<() => void>((resolve, reject) => {\r\n begin = resolve;\r\n\r\n if (timeoutMs) {\r\n timer = setTimeout(() => {\r\n reject(new Error(\"Mutex lock timeout\"));\r\n }, timeoutMs);\r\n }\r\n });\r\n\r\n try {\r\n const unlock = await lockPromise;\r\n clearTimeout(timer);\r\n return () => {\r\n this.locked = false;\r\n unlock();\r\n };\r\n } catch (err) {\r\n this.mutex = previous;\r\n this.locked = false;\r\n throw err;\r\n }\r\n }\r\n\r\n tryLock(): () => void | null {\r\n if (this.locked) return null;\r\n\r\n let unlock!: () => void;\r\n this.locked = true;\r\n this.mutex = this.mutex.then(\r\n () =>\r\n new Promise<void>(res => {\r\n unlock = () => {\r\n this.locked = false;\r\n res();\r\n };\r\n })\r\n );\r\n return unlock;\r\n }\r\n\r\n async dispatch<T>(fn: Executor<T>, timeoutMs?: number): Promise<T> {\r\n const unlock = await this.lock(timeoutMs);\r\n try {\r\n return await fn();\r\n } finally {\r\n unlock();\r\n }\r\n }\r\n}\r\n\r\n\r\nexport {\r\n AsyncMutex\r\n};"],"names":["AsyncMutex","timeoutMs","begin","timer","previous","lockPromise","resolve","reject","unlock","err","res","fn"],"mappings":"AAQA,MAAMA,EAAW;AAAA;AAAA,EACL,QAAQ,QAAQ,QAAA;AAAA,EAEhB,SAAS;AAAA,EAEjB,MAAM,KAAKC,GAAyC;AAChD,QAAIC,IAAsC,MAAM;AAAA,IAAE,GAC9CC;AAEJ,UAAMC,IAAW,KAAK;AACtB,SAAK,QAAQ,KAAK,MAAM,KAAK,MAAM,IAAI,QAAQF,CAAK,CAAC,GACrD,KAAK,SAAS;AAEd,UAAMG,IAAc,IAAI,QAAoB,CAACC,GAASC,MAAW;AAC7D,MAAAL,IAAQI,GAEJL,MACAE,IAAQ,WAAW,MAAM;AACrB,QAAAI,EAAO,IAAI,MAAM,oBAAoB,CAAC;AAAA,MAC1C,GAAGN,CAAS;AAAA,IAEpB,CAAC;AAED,QAAI;AACA,YAAMO,IAAS,MAAMH;AACrB,0BAAaF,CAAK,GACX,MAAM;AACT,aAAK,SAAS,IACdK,EAAA;AAAA,MACJ;AAAA,IACJ,SAASC,GAAK;AACV,iBAAK,QAAQL,GACb,KAAK,SAAS,IACRK;AAAA,IACV;AAAA,EACJ;AAAA,EAEA,UAA6B;AACzB,QAAI,KAAK,OAAQ,QAAO;AAExB,QAAID;AACJ,gBAAK,SAAS,IACd,KAAK,QAAQ,KAAK,MAAM;AAAA,MACpB,MACI,IAAI,QAAc,CAAAE,MAAO;AACrB,QAAAF,IAAS,MAAM;AACX,eAAK,SAAS,IACdE,EAAA;AAAA,QACJ;AAAA,MACJ,CAAC;AAAA,IAAA,GAEFF;AAAA,EACX;AAAA,EAEA,MAAM,SAAYG,GAAiBV,GAAgC;AAC/D,UAAMO,IAAS,MAAM,KAAK,KAAKP,CAAS;AACxC,QAAI;AACA,aAAO,MAAMU,EAAA;AAAA,IACjB,UAAA;AACI,MAAAH,EAAA;AAAA,IACJ;AAAA,EACJ;AACJ;"}
@@ -1,5 +1,5 @@
1
- import { IDataEntry, IDataItem } from '../store/dataStore';
2
- import { StructEventTarget } from '../structEvent';
1
+ import { IDataEntry, IDataItem, CacheDataEntry } from '../store/storeDb';
2
+ import { DataStore } from '../store/dataStore';
3
3
  type Duration = number | {
4
4
  seconds?: number;
5
5
  minutes?: number;
@@ -20,27 +20,22 @@ export type CacheEvictionEvent = {
20
20
  type PersistentCacheEventStruct = {
21
21
  evict: CacheEvictionEvent;
22
22
  };
23
- export declare class PersistentCache extends StructEventTarget<PersistentCacheEventStruct> {
24
- private _db;
25
- private _isDisposed;
23
+ export declare class PersistentCache extends DataStore<"cache", PersistentCacheEventStruct> {
26
24
  private _jobTimerId;
27
25
  private readonly _options;
26
+ static deleteAsync(name: string): Promise<void>;
27
+ static existsAsync(name: string): Promise<boolean>;
28
+ static openAsync(name: string, options: PersistentCacheOptions): Promise<PersistentCache>;
28
29
  constructor(name: string, options: PersistentCacheOptions);
29
30
  scheduleServiceJob(): void;
30
31
  deleteExpiredAsync(date?: Date): Promise<string[]>;
31
32
  dispose(): void;
32
- private execAsync;
33
- getKeysAsync(): Promise<string[]>;
34
- getAsync(key: string): Promise<Readonly<IDataEntry & IDataItem>>;
33
+ getAsync(key: string): Promise<Readonly<CacheDataEntry & IDataItem>>;
35
34
  bulkGetAsync(ids: string[]): Promise<{
36
- [key: string]: Readonly<IDataEntry & IDataItem>;
35
+ [key: string]: Readonly<CacheDataEntry & IDataItem>;
37
36
  }>;
38
- containsAsync(key: string): Promise<boolean>;
39
- deleteAsync(id: string): Promise<void>;
40
- bulkDeleteAsync(ids: string[]): Promise<void>;
41
- setAsync(id: string, value: any, options: CacheOptions): Promise<void>;
42
- getOrSetAsync(key: string, factory: () => any, options: CacheOptions): Promise<void>;
43
- clearAsync(): Promise<void>;
37
+ setAsync(key: string, value: any, options: CacheOptions): Promise<void>;
38
+ getOrSetAsync(key: string, factory: (key: string) => any, options: CacheOptions): Promise<Readonly<CacheDataEntry & IDataItem>>;
44
39
  }
45
40
  export {};
46
41
  //# sourceMappingURL=persistentCache.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"persistentCache.d.ts","sourceRoot":"","sources":["../../src/cache/persistentCache.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,UAAU,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAe,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAG/D,KAAK,QAAQ,GAAG,MAAM,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhF,MAAM,MAAM,sBAAsB,GAAG;IACjC,cAAc,EAAE,MAAM,CAAC;CAC1B,CAAC;AAMF,MAAM,MAAM,YAAY,GAAG;IACvB,kBAAkB,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IACnC,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,iBAAiB,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;CACrC,CAAC;AAGF,MAAM,MAAM,kBAAkB,GAAG;IAC7B,KAAK,EAAE,UAAU,CAAC;IAElB,gBAAgB,CAAC,EAAE,YAAY,CAAC;CACnC,CAAC;AAEF,KAAK,0BAA0B,GAAG;IAC9B,KAAK,EAAE,kBAAkB,CAAC;CAC7B,CAAC;AAKF,qBAAa,eAAgB,SAAQ,iBAAiB,CAAC,0BAA0B,CAAC;IAU9E,OAAO,CAAC,GAAG,CAAY;IAEvB,OAAO,CAAC,WAAW,CAAU;IAE7B,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyB;gBAGtC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB;IAazD,kBAAkB;IAiBZ,kBAAkB,CAAC,IAAI,CAAC,EAAE,IAAI;IA8BpC,OAAO;YAuBO,SAAS;IAejB,YAAY;IAIZ,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IAchE,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAC,UAAU,GAAG,SAAS,CAAC,CAAA;KAAE,CAAC;IA2CzF,aAAa,CAAC,GAAG,EAAE,MAAM;IAQzB,WAAW,CAAC,EAAE,EAAE,MAAM;IAOtB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE;IAO7B,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,YAAY;IA6BtD,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,EAAE,OAAO,EAAE,YAAY;IAUpE,UAAU;CAQnB"}
1
+ {"version":3,"file":"persistentCache.d.ts","sourceRoot":"","sources":["../../src/cache/persistentCache.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,UAAU,EAAE,SAAS,EAAc,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGtG,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,KAAK,QAAQ,GAAG,MAAM,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhF,MAAM,MAAM,sBAAsB,GAAG;IACjC,cAAc,EAAE,MAAM,CAAC;CAC1B,CAAC;AAMF,MAAM,MAAM,YAAY,GAAG;IACvB,kBAAkB,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IACnC,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,iBAAiB,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;CACrC,CAAC;AAGF,MAAM,MAAM,kBAAkB,GAAG;IAC7B,KAAK,EAAE,UAAU,CAAC;IAElB,gBAAgB,CAAC,EAAE,YAAY,CAAC;CACnC,CAAC;AAEF,KAAK,0BAA0B,GAAG;IAC9B,KAAK,EAAE,kBAAkB,CAAC;CAC7B,CAAC;AAIF,qBAAa,eAAgB,SAAQ,SAAS,CAAC,OAAO,EAAE,0BAA0B,CAAC;IAE/E,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyB;IAElD,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM;IAI/B,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM;IAI/B,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB;gBAKlD,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB;IAQzD,kBAAkB;IAiBZ,kBAAkB,CAAC,IAAI,CAAC,EAAE,IAAI;IA2BpC,OAAO;IAUD,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,cAAc,GAAG,SAAS,CAAC,CAAC;IAgBpE,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAC,cAAc,GAAG,SAAS,CAAC,CAAA;KAAE,CAAC;IA8B7F,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,YAAY;IA6BvD,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,GAAG,EAAE,OAAO,EAAE,YAAY;CAUxF"}
@@ -1,28 +1,25 @@
1
- import { keyOf as c } from "../typeUtils.es.js";
2
- import { DataStore as o } from "../store/dataStore.es.js";
3
- import { StructEventTarget as y, StructEvent as d } from "../structEvent.es.js";
4
- import { v4 as h } from "uuid";
5
- const u = {
1
+ import { keyOf as d } from "../typeUtils.es.js";
2
+ import { StructEvent as u } from "../structEvent.es.js";
3
+ import { v4 as l } from "uuid";
4
+ import { DataStore as c } from "../store/dataStore.es.js";
5
+ const y = {
6
6
  cleanupTimeout: 1e3
7
7
  };
8
- class f extends y {
9
- // https://demo.agektmr.com/storage/
10
- // https://www.html5rocks.com/en/tutorials/offline/quota-research/
11
- // https://www.raymondcamden.com/2015/04/17/indexeddb-and-limits
12
- // https://github.com/jonnysmith1981/getIndexedDbSize/blob/master/getIndexedDbSize.js
13
- // https://developer.chrome.com/apps/offline_storage#query
14
- // https://golb.hplar.ch/2018/01/IndexedDB-programming-with-Dexie-js.html
15
- // http://www.forerunnerdb.com/licensing.html
16
- // https://github.com/ignasbernotas/dexie-relationships
17
- _db;
18
- _isDisposed;
8
+ class o extends c {
19
9
  _jobTimerId;
20
10
  _options;
11
+ static deleteAsync(t) {
12
+ return c.$deleteAsync(t);
13
+ }
14
+ static existsAsync(t) {
15
+ return c.$existsAsync(t);
16
+ }
17
+ static openAsync(t, e) {
18
+ return c.$openAsync(t, () => new o(t, e));
19
+ }
21
20
  // cleanupTimeout - serviceJobTimeout
22
21
  constructor(t, e) {
23
- if (super(), !t)
24
- throw new Error("Name cannot be empty");
25
- this._isDisposed = !1, this._jobTimerId = null, this._db = new o(t), this._options = { ...e, ...u }, this.scheduleServiceJob();
22
+ super(t, "cache"), this._jobTimerId = null, this._options = { ...e, ...y }, this.scheduleServiceJob();
26
23
  }
27
24
  scheduleServiceJob() {
28
25
  if (this._options.cleanupTimeout) {
@@ -41,84 +38,65 @@ class f extends y {
41
38
  // evictExpiredAsync/clearExpiredAsync
42
39
  async deleteExpiredAsync(t) {
43
40
  const e = [];
44
- return t || (t = /* @__PURE__ */ new Date()), await this.execAsync(async () => {
45
- const s = await this._db.registry.where(c("expiresAt")).below(t.getTime()).toArray();
46
- for (const a of s) {
47
- const n = new d("evict", {
41
+ return t || (t = /* @__PURE__ */ new Date()), await this.$execAsync(async () => {
42
+ const i = await this._db.registry.where(d("expiresAt")).below(t.getTime()).toArray();
43
+ for (const n of i) {
44
+ const r = new u("evict", {
48
45
  detail: {
49
- entry: a
46
+ entry: n
50
47
  // keepAliveOptions: {}
51
48
  },
52
49
  target: this,
53
50
  cancelable: !0
54
51
  });
55
- this.dispatchEvent(n), await this._db.registry.delete(a.id), e.push(a.id);
52
+ this.dispatchEvent(r), this.deleteAsync(n.id), e.push(n.id);
56
53
  }
57
54
  }), e;
58
55
  }
59
56
  dispose() {
60
- this._isDisposed || (this._isDisposed = !0, this._jobTimerId && (window.clearTimeout(this._jobTimerId), this._jobTimerId = null), this._db && (this._db.isOpen() && this._db.close(), this._db = null));
61
- }
62
- async execAsync(t) {
63
- this._db.isOpen() || await this._db.open();
64
- try {
65
- return await t();
66
- } catch (e) {
67
- throw this._db.isOpen(), e;
68
- }
69
- }
70
- async getKeysAsync() {
71
- return await this._db.registry.filter((t) => !0).primaryKeys();
57
+ this._isDisposed || this._jobTimerId && (window.clearTimeout(this._jobTimerId), this._jobTimerId = null), super.dispose();
72
58
  }
73
59
  async getAsync(t) {
74
- return await this.execAsync(async () => {
60
+ return await this.$execAsync(async () => {
75
61
  const e = await this._db.registry.get(t);
76
62
  if (e) {
77
- const s = await this._db.data.get(t);
78
- return { ...e, ...s };
63
+ const i = await this._db.data.get(t);
64
+ return { ...e, ...i };
79
65
  }
80
66
  return null;
81
- });
67
+ }, "rw");
82
68
  }
83
69
  // getMany
84
70
  async bulkGetAsync(t) {
85
71
  const e = {};
86
- return await this.execAsync(async () => {
87
- const a = (await this._db.registry.bulkGet(t)).reduce((i, r, b) => (i[r.id] = r, i), {}), n = await this._db.data.bulkGet(t);
88
- for (const i of n)
89
- e[i.id] = { ...a[i.id], ...i }, delete a[i.id];
90
- for (const i of Object.keys(a))
91
- e[i] = { ...a[i], value: void 0 };
72
+ return await this.$execAsync(async () => {
73
+ const n = (await this._db.registry.bulkGet(t)).reduce((s, a, h) => (s[a.id] = a, s), {}), r = await this._db.data.bulkGet(t);
74
+ for (const s of r)
75
+ e[s.id] = { ...n[s.id], ...s }, delete n[s.id];
76
+ for (const s of Object.keys(n)) {
77
+ let a = {
78
+ id: s,
79
+ value: void 0
80
+ };
81
+ e[s] = { ...n[s], ...a };
82
+ }
92
83
  return e;
93
- });
94
- }
95
- async containsAsync(t) {
96
- return await this.execAsync(async () => await this._db.registry.get(t) != null);
97
- }
98
- async deleteAsync(t) {
99
- await this.execAsync(async () => {
100
- await this._db.registry.delete(t);
101
- });
102
- }
103
- // deleteManyAsync
104
- async bulkDeleteAsync(t) {
105
- await this.execAsync(async () => {
106
- await this._db.registry.bulkDelete(t);
107
- });
84
+ }, "rw");
108
85
  }
109
86
  // upsertAsync
110
- async setAsync(t, e, s) {
111
- return await this.execAsync(async () => {
112
- const a = await this._db.registry.get(t), n = (/* @__PURE__ */ new Date()).getTime();
113
- t || (t = h());
114
- const i = typeof s.absoluteExpiration == "number" ? s.absoluteExpiration : s.absoluteExpiration?.getTime(), r = typeof s.slidingExpiration == "number" ? s.slidingExpiration : s.slidingExpiration?.getTime();
87
+ async setAsync(t, e, i) {
88
+ return await this.$execAsync(async () => {
89
+ let n;
90
+ const r = (/* @__PURE__ */ new Date()).getTime();
91
+ t ? n = await this._db.registry.get(t) : t = l();
92
+ const s = typeof i.absoluteExpiration == "number" ? i.absoluteExpiration : i.absoluteExpiration?.getTime(), a = typeof i.slidingExpiration == "number" ? i.slidingExpiration : i.slidingExpiration?.getTime();
115
93
  await this._db.registry.put({
116
94
  id: t,
117
- createdAt: a ? a.createdAt : n,
118
- accessedAt: n,
119
- updatedAt: n,
120
- expiresAt: i,
121
- slidingExpiration: r
95
+ createdAt: n ? n.createdAt : r,
96
+ accessedAt: r,
97
+ updatedAt: r,
98
+ expiresAt: s,
99
+ slidingExpiration: a
122
100
  }), await this._db.data.put({
123
101
  id: t,
124
102
  value: e
@@ -126,18 +104,12 @@ class f extends y {
126
104
  });
127
105
  }
128
106
  // getOrAddAsync
129
- async getOrSetAsync(t, e, s) {
130
- await this.execAsync(async () => (await this.containsAsync(t) || await this.setAsync(t, e(), s), await this.getAsync(t)));
131
- }
132
- // clearAllAsync/evictAllAsync
133
- async clearAsync() {
134
- await this.execAsync(async () => {
135
- await this._db.registry.clear(), await this._db.data.clear();
136
- });
107
+ async getOrSetAsync(t, e, i) {
108
+ return await this.$execAsync(async () => (await this.containsAsync(t) || await this.setAsync(t, e(t), i), await this.getAsync(t)));
137
109
  }
138
110
  // TODO: support bulkSetAsync
139
111
  }
140
112
  export {
141
- f as PersistentCache
113
+ o as PersistentCache
142
114
  };
143
115
  //# sourceMappingURL=persistentCache.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"persistentCache.es.js","sources":["../../src/cache/persistentCache.ts"],"sourcesContent":["import { keyOf } from \"@/typeUtils\";\r\nimport { DataStore, IDataEntry, IDataItem } from \"../store/dataStore\";\r\nimport { StructEvent, StructEventTarget } from \"@/structEvent\";\r\nimport { v4 as uuid } from \"uuid\";\r\n\r\ntype Duration = number | { seconds?: number; minutes?: number; hours?: number };\r\n\r\nexport type PersistentCacheOptions = {\r\n cleanupTimeout: number;\r\n};\r\n\r\nconst defaultPersistentCacheOptions = {\r\n cleanupTimeout: 1000\r\n} satisfies PersistentCacheOptions;\r\n\r\nexport type CacheOptions = {\r\n absoluteExpiration?: Date | number;\r\n ttl?: Duration;\r\n slidingExpiration?: Date | number; // \"autoRenewOnUse\" pattern\r\n};\r\n\r\n// CacheEntryEvictionEvent\r\nexport type CacheEvictionEvent = {\r\n entry: IDataEntry;\r\n // or optionsOverride?\r\n keepAliveOptions?: CacheOptions; // TODO: delayed eviction (pending eviction) after gracePeriod\r\n};\r\n\r\ntype PersistentCacheEventStruct = {\r\n evict: CacheEvictionEvent;\r\n};\r\n\r\n// TODO: remove class, create factory method\r\n// implements Struct<StructEventTarget<PersistentCacheEventStruct>>\r\n// PersistentCacheManager\r\nexport class PersistentCache extends StructEventTarget<PersistentCacheEventStruct> {\r\n // https://demo.agektmr.com/storage/\r\n // https://www.html5rocks.com/en/tutorials/offline/quota-research/\r\n // https://www.raymondcamden.com/2015/04/17/indexeddb-and-limits\r\n // https://github.com/jonnysmith1981/getIndexedDbSize/blob/master/getIndexedDbSize.js\r\n // https://developer.chrome.com/apps/offline_storage#query\r\n // https://golb.hplar.ch/2018/01/IndexedDB-programming-with-Dexie-js.html\r\n // http://www.forerunnerdb.com/licensing.html\r\n // https://github.com/ignasbernotas/dexie-relationships\r\n\r\n private _db: DataStore;\r\n\r\n private _isDisposed: boolean;\r\n\r\n private _jobTimerId: number;\r\n\r\n private readonly _options: PersistentCacheOptions;\r\n\r\n // cleanupTimeout - serviceJobTimeout\r\n constructor(name: string, options: PersistentCacheOptions) {\r\n super();\r\n if (!name) {\r\n throw new Error(\"Name cannot be empty\");\r\n }\r\n this._isDisposed = false;\r\n this._jobTimerId = null;\r\n this._db = new DataStore(name);\r\n // https://docs.nestjs.com/techniques/task-scheduling\r\n this._options = { ...options, ...defaultPersistentCacheOptions };\r\n this.scheduleServiceJob();\r\n }\r\n\r\n scheduleServiceJob() {\r\n if (this._options.cleanupTimeout) {\r\n const doWork = async () => {\r\n try {\r\n // purge expired entries\r\n await this.deleteExpiredAsync();\r\n } catch (err) {\r\n console.error(\"Cache cleanup failed:\", err);\r\n } finally {\r\n setTimeout(doWork, this._options.cleanupTimeout);\r\n }\r\n };\r\n setTimeout(doWork, this._options.cleanupTimeout);\r\n }\r\n }\r\n\r\n // evictExpiredAsync/clearExpiredAsync\r\n async deleteExpiredAsync(date?: Date) {\r\n const result: string[] = []; // output ids\r\n if (!date) {\r\n date = new Date();\r\n }\r\n\r\n await this.execAsync(async () => {\r\n const entries = await this._db.registry.where(keyOf<IDataEntry>(\"expiresAt\")).below(date.getTime()).toArray();\r\n for (const entry of entries) {\r\n const evt = new StructEvent<PersistentCacheEventStruct, this>(\"evict\", {\r\n detail: {\r\n entry: entry\r\n // keepAliveOptions: {}\r\n },\r\n target: this,\r\n cancelable: true\r\n });\r\n this.dispatchEvent(evt);\r\n // evt.defaultPrevented?\r\n // TODO: support evt.detail.keepAliveOptions\r\n await this._db.registry.delete(entry.id);\r\n // await this._db.data.delete(entry.id);\r\n result.push(entry.id);\r\n // TODO: use bulkDelete\r\n // TODO: use transaction\r\n }\r\n });\r\n return result;\r\n }\r\n\r\n dispose() {\r\n if (!this._isDisposed) {\r\n this._isDisposed = true;\r\n\r\n if (this._jobTimerId) {\r\n window.clearTimeout(this._jobTimerId);\r\n this._jobTimerId = null;\r\n }\r\n\r\n if (this._db) {\r\n // this.exec(async () => {\r\n // \t// ...\r\n // }).then(() => {\r\n // \tthis._db = null;\r\n // });\r\n if (this._db.isOpen()) {\r\n this._db.close();\r\n }\r\n this._db = null;\r\n }\r\n }\r\n }\r\n\r\n private async execAsync<T>(action: () => Promise<T>) {\r\n if (!this._db.isOpen()) {\r\n await this._db.open();\r\n }\r\n try {\r\n const result = await action();\r\n return result;\r\n } catch (err) {\r\n if (this._db.isOpen()) {\r\n // this._db.close(); // generally speaking: we don't (never) need to close a connection\r\n }\r\n throw err;\r\n }\r\n }\r\n\r\n async getKeysAsync() {\r\n return await this._db.registry.filter((_) => true).primaryKeys();\r\n }\r\n\r\n async getAsync(key: string): Promise<Readonly<IDataEntry & IDataItem>> {\r\n return await this.execAsync(async () => {\r\n const entry = await this._db.registry.get(key);\r\n // const entry = await this._db.registry.where(keyOf<IDataEntry>(\"id\")).equals(key).first();\r\n if (entry) {\r\n const data = await this._db.data.get(key);\r\n // const data = await this._db.data.where(keyOf<IDataEntry>(\"id\")).equals(key).first();\r\n return { ...entry, ...data };\r\n }\r\n return null;\r\n });\r\n }\r\n\r\n // getMany\r\n async bulkGetAsync(ids: string[]): Promise<{ [key: string]: Readonly<IDataEntry & IDataItem> }> {\r\n const result: { [key: string]: Readonly<IDataEntry & IDataItem> } = {};\r\n return await this.execAsync(async () => {\r\n // const entries = await this._db.registry.where(keyOf<IDataEntry>(\"id\")).anyOf(ids).toArray();\r\n const entries = await this._db.registry.bulkGet(ids);\r\n const entryMap: { [key: string]: IDataEntry } = entries.reduce((map, entry, i) => {\r\n map[entry.id] = entry;\r\n return map;\r\n }, {});\r\n\r\n // const dataItems = this._db.data.where(keyOf<IDataEntry>(\"id\")).anyOf(ids);\r\n // await dataItems.each((dataItem) => {\r\n // result[dataItem.id] = { ...entryMap[dataItem.id], ...dataItem };\r\n // delete entryMap[dataItem.id];\r\n // });\r\n\r\n const dataItems = await this._db.data.bulkGet(ids);\r\n for (const dataItem of dataItems) {\r\n result[dataItem.id] = { ...entryMap[dataItem.id], ...dataItem };\r\n delete entryMap[dataItem.id];\r\n }\r\n\r\n // TODO: update data entry \r\n // accessedAt,\r\n // updatedAt,\r\n // expiresAt // for sliding expiration\r\n\r\n for (const key of Object.keys(entryMap)) {\r\n // abandoned/orphaned entries:\r\n result[key] = { ...entryMap[key], value: undefined };\r\n\r\n // Object.defineProperty(result[key], keyOf<IDataItem>(\"value\"), {\r\n // writable: false,\r\n // get: function () {\r\n // throw new Error(\"Not found\");\r\n // }\r\n // });\r\n }\r\n\r\n return result;\r\n });\r\n }\r\n\r\n async containsAsync(key: string) {\r\n return await this.execAsync(async () => {\r\n const entry = await this._db.registry.get(key);\r\n // const entry = await this._db.registry.where(keyOf<IDataEntry>(\"id\")).equals(key).first();\r\n return entry != undefined;\r\n });\r\n }\r\n\r\n async deleteAsync(id: string) {\r\n await this.execAsync(async () => {\r\n await this._db.registry.delete(id);\r\n });\r\n }\r\n\r\n // deleteManyAsync\r\n async bulkDeleteAsync(ids: string[]) {\r\n await this.execAsync(async () => {\r\n await this._db.registry.bulkDelete(ids);\r\n });\r\n }\r\n\r\n // upsertAsync\r\n async setAsync(id: string, value: any, options: CacheOptions) {\r\n return await this.execAsync(async () => {\r\n const entry = await this._db.registry.get(id);\r\n // const entry = await this._db.registry.where(keyOf<IDataEntry>(\"id\")).equals(key).first();\r\n const now = new Date().getTime();\r\n if (!id) {\r\n id = uuid();\r\n }\r\n const expiresAt =\r\n typeof options.absoluteExpiration === \"number\" ? options.absoluteExpiration : options.absoluteExpiration?.getTime();\r\n const slidingExpiration =\r\n typeof options.slidingExpiration === \"number\" ? options.slidingExpiration : options.slidingExpiration?.getTime();\r\n\r\n await this._db.registry.put({\r\n id: id,\r\n createdAt: entry ? entry.createdAt : now,\r\n accessedAt: now,\r\n updatedAt: now,\r\n expiresAt: expiresAt,\r\n slidingExpiration: slidingExpiration\r\n });\r\n await this._db.data.put({\r\n id: id,\r\n value: value\r\n });\r\n });\r\n }\r\n\r\n // getOrAddAsync\r\n async getOrSetAsync(key: string, factory: () => any, options: CacheOptions) {\r\n await this.execAsync(async () => {\r\n if (!(await this.containsAsync(key))) {\r\n await this.setAsync(key, factory(), options);\r\n }\r\n return await this.getAsync(key);\r\n });\r\n }\r\n\r\n // clearAllAsync/evictAllAsync\r\n async clearAsync() {\r\n await this.execAsync(async () => {\r\n await this._db.registry.clear();\r\n await this._db.data.clear();\r\n });\r\n }\r\n\r\n // TODO: support bulkSetAsync\r\n}\r\n\r\n// https://medium.com/square-corner-blog/useful-tools-headless-chrome-puppeteer-for-browser-automation-testing-1ac7707bad40\r\n// https://developers.google.com/web/updates/2017/06/headless-karma-mocha-chai?hl=ru\r\n// https://github.com/puppeteer/puppeteer\r\n// https://medium.com/web-standards/puppeteer-crawl-to-markdown-7752dff36b68\r\n"],"names":["defaultPersistentCacheOptions","PersistentCache","StructEventTarget","name","options","DataStore","doWork","err","date","result","entries","keyOf","entry","evt","StructEvent","action","_","key","data","ids","entryMap","map","i","dataItems","dataItem","id","value","now","uuid","expiresAt","slidingExpiration","factory"],"mappings":"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"}
1
+ {"version":3,"file":"persistentCache.es.js","sources":["../../src/cache/persistentCache.ts"],"sourcesContent":["import { keyOf } from \"@/typeUtils\";\r\nimport { ICacheDataEntry, IDataEntry, IDataItem, EntryTypes, CacheDataEntry } from \"../store/storeDb\";\r\nimport { StructEvent } from \"@/structEvent\";\r\nimport { v4 as uuid } from \"uuid\";\r\nimport { DataStore } from \"@/store/dataStore\";\r\n\r\ntype Duration = number | { seconds?: number; minutes?: number; hours?: number };\r\n\r\nexport type PersistentCacheOptions = {\r\n cleanupTimeout: number;\r\n};\r\n\r\nconst defaultPersistentCacheOptions = {\r\n cleanupTimeout: 1000\r\n} satisfies PersistentCacheOptions;\r\n\r\nexport type CacheOptions = {\r\n absoluteExpiration?: Date | number;\r\n ttl?: Duration;\r\n slidingExpiration?: Date | number; // \"autoRenewOnUse\" pattern\r\n};\r\n\r\n// CacheEntryEvictionEvent\r\nexport type CacheEvictionEvent = {\r\n entry: IDataEntry;\r\n // or optionsOverride?\r\n keepAliveOptions?: CacheOptions; // TODO: delayed eviction (pending eviction) after gracePeriod\r\n};\r\n\r\ntype PersistentCacheEventStruct = {\r\n evict: CacheEvictionEvent;\r\n};\r\n\r\n// implements Struct<StructEventTarget<PersistentCacheEventStruct>>\r\n// PersistentCacheManager\r\nexport class PersistentCache extends DataStore<\"cache\", PersistentCacheEventStruct> {\r\n\r\n private _jobTimerId: number;\r\n\r\n private readonly _options: PersistentCacheOptions;\r\n\r\n static deleteAsync(name: string) {\r\n return DataStore.$deleteAsync(name);\r\n }\r\n\r\n static existsAsync(name: string) {\r\n return DataStore.$existsAsync(name);\r\n }\r\n\r\n static openAsync(name: string, options: PersistentCacheOptions) {\r\n return DataStore.$openAsync(name, () => new PersistentCache(name, options));\r\n }\r\n\r\n // cleanupTimeout - serviceJobTimeout\r\n constructor(name: string, options: PersistentCacheOptions) {\r\n super(name, \"cache\");\r\n this._jobTimerId = null;\r\n this._options = { ...options, ...defaultPersistentCacheOptions };\r\n // https://docs.nestjs.com/techniques/task-scheduling\r\n this.scheduleServiceJob();\r\n }\r\n\r\n scheduleServiceJob() {\r\n if (this._options.cleanupTimeout) {\r\n const doWork = async () => {\r\n try {\r\n // purge expired entries\r\n await this.deleteExpiredAsync();\r\n } catch (err) {\r\n console.error(\"Cache cleanup failed:\", err);\r\n } finally {\r\n setTimeout(doWork, this._options.cleanupTimeout);\r\n }\r\n };\r\n setTimeout(doWork, this._options.cleanupTimeout);\r\n }\r\n }\r\n\r\n // evictExpiredAsync/clearExpiredAsync\r\n async deleteExpiredAsync(date?: Date) {\r\n const result: string[] = []; // output ids\r\n if (!date) {\r\n date = new Date();\r\n }\r\n await this.$execAsync(async () => {\r\n const entries = await this._db.registry.where(keyOf<ICacheDataEntry>(\"expiresAt\")).below(date.getTime()).toArray();\r\n for (const entry of entries) {\r\n const evt = new StructEvent<PersistentCacheEventStruct, this>(\"evict\", {\r\n detail: {\r\n entry: entry\r\n // keepAliveOptions: {}\r\n },\r\n target: this,\r\n cancelable: true\r\n });\r\n this.dispatchEvent(evt);\r\n // evt.defaultPrevented?\r\n // TODO: support evt.detail.keepAliveOptions\r\n this.deleteAsync(entry.id);\r\n result.push(entry.id);\r\n // TODO: use bulkDelete\r\n }\r\n });\r\n return result;\r\n }\r\n\r\n dispose() {\r\n if (!this._isDisposed) {\r\n if (this._jobTimerId) {\r\n window.clearTimeout(this._jobTimerId);\r\n this._jobTimerId = null;\r\n }\r\n }\r\n super.dispose();\r\n }\r\n\r\n async getAsync(key: string): Promise<Readonly<CacheDataEntry & IDataItem>> {\r\n return await this.$execAsync(async () => {\r\n const entry = await this._db.registry.get(key);\r\n if (entry) {\r\n const data = await this._db.data.get(key);\r\n // TODO: update data entry\r\n // accessedAt,\r\n // updatedAt,\r\n // expiresAt // for sliding expiration\r\n return { ...entry, ...data };\r\n }\r\n return null;\r\n }, \"rw\");\r\n }\r\n\r\n // getMany\r\n async bulkGetAsync(ids: string[]): Promise<{ [key: string]: Readonly<CacheDataEntry & IDataItem> }> {\r\n const result: { [key: string]: Readonly<EntryTypes[\"cache\"] & IDataItem> } = {};\r\n return await this.$execAsync(async () => {\r\n const entries = await this._db.registry.bulkGet(ids);\r\n const entryMap: { [key: string]: CacheDataEntry } = entries.reduce((map, entry, i) => {\r\n map[entry.id] = entry;\r\n return map;\r\n }, {});\r\n const dataItems = await this._db.data.bulkGet(ids);\r\n // TODO: update data entries\r\n // accessedAt,\r\n // updatedAt,\r\n // expiresAt // for sliding expiration\r\n for (const dataItem of dataItems) {\r\n result[dataItem.id] = { ...entryMap[dataItem.id], ...dataItem };\r\n delete entryMap[dataItem.id];\r\n }\r\n for (const key of Object.keys(entryMap)) {\r\n // abandoned/orphaned entries:\r\n let dataItem: IDataItem = {\r\n id: key,\r\n value: undefined\r\n }\r\n result[key] = { ...entryMap[key], ...dataItem };\r\n }\r\n return result;\r\n }, \"rw\");\r\n }\r\n\r\n // upsertAsync\r\n async setAsync(key: string, value: any, options: CacheOptions) {\r\n return await this.$execAsync(async () => {\r\n let entry;\r\n const now = new Date().getTime();\r\n if (key) {\r\n entry = await this._db.registry.get(key);\r\n } else {\r\n key = uuid();\r\n }\r\n const expiresAt =\r\n typeof options.absoluteExpiration === \"number\" ? options.absoluteExpiration : options.absoluteExpiration?.getTime();\r\n const slidingExpiration =\r\n typeof options.slidingExpiration === \"number\" ? options.slidingExpiration : options.slidingExpiration?.getTime();\r\n await this._db.registry.put({\r\n id: key,\r\n createdAt: entry ? entry.createdAt : now,\r\n accessedAt: now,\r\n updatedAt: now,\r\n expiresAt: expiresAt,\r\n slidingExpiration: slidingExpiration\r\n });\r\n await this._db.data.put({\r\n id: key,\r\n value: value\r\n });\r\n });\r\n }\r\n\r\n // getOrAddAsync\r\n async getOrSetAsync(key: string, factory: (key: string) => any, options: CacheOptions) {\r\n return await this.$execAsync(async () => {\r\n if (!(await this.containsAsync(key))) {\r\n await this.setAsync(key, factory(key), options);\r\n }\r\n return await this.getAsync(key);\r\n });\r\n }\r\n\r\n // TODO: support bulkSetAsync\r\n}\r\n\r\n// extra links:\r\n// https://demo.agektmr.com/storage/\r\n// https://www.html5rocks.com/en/tutorials/offline/quota-research/\r\n// https://www.raymondcamden.com/2015/04/17/indexeddb-and-limits\r\n// https://github.com/jonnysmith1981/getIndexedDbSize/blob/master/getIndexedDbSize.js\r\n// https://developer.chrome.com/apps/offline_storage#query\r\n// https://golb.hplar.ch/2018/01/IndexedDB-programming-with-Dexie-js.html\r\n// http://www.forerunnerdb.com/licensing.html\r\n// https://github.com/ignasbernotas/dexie-relationships\r\n// https://medium.com/square-corner-blog/useful-tools-headless-chrome-puppeteer-for-browser-automation-testing-1ac7707bad40\r\n// https://developers.google.com/web/updates/2017/06/headless-karma-mocha-chai?hl=ru\r\n// https://github.com/puppeteer/puppeteer\r\n// https://medium.com/web-standards/puppeteer-crawl-to-markdown-7752dff36b68\r\n"],"names":["defaultPersistentCacheOptions","PersistentCache","DataStore","name","options","doWork","err","date","result","entries","keyOf","entry","evt","StructEvent","key","data","ids","entryMap","map","i","dataItems","dataItem","value","now","uuid","expiresAt","slidingExpiration","factory"],"mappings":"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"}
@@ -1,33 +1,29 @@
1
- import { default as Dexie } from 'dexie';
2
- export interface IDataEntry {
3
- id: string;
4
- createdAt: number;
5
- updatedAt: number;
6
- accessedAt: number;
7
- slidingExpiration?: number;
8
- expiresAt: number;
9
- }
10
- export interface IDataItem {
11
- readonly id: string;
12
- readonly value: any;
13
- }
14
- export declare class DataEntry implements IDataEntry {
15
- id: string;
16
- createdAt: number;
17
- updatedAt: number;
18
- accessedAt: number;
19
- expiresAt: number;
20
- constructor(src: Partial<DataEntry>);
21
- }
22
- export declare class DataItem implements IDataItem {
23
- id: string;
24
- value: any;
25
- constructor(src: Partial<DataItem>);
26
- }
27
- export declare class DataStore extends Dexie {
28
- registry: Dexie.Table<IDataEntry, string>;
29
- data: Dexie.Table<IDataItem, string>;
30
- constructor(name: string);
31
- static delete(name: string): Promise<void>;
1
+ import { EntryTypes, IDataItem, StoreDb } from './storeDb';
2
+ import { StructEventTarget } from '../structEvent';
3
+ import { TransactionMode } from 'dexie';
4
+ export type IDataStoreBase = {
5
+ openAsync(): PromiseLike<void>;
6
+ };
7
+ export declare class DataStore<TEntryTemplate extends keyof EntryTypes, TEventStruct extends Record<string, any> = unknown> extends StructEventTarget<TEventStruct> implements IDataStoreBase {
8
+ protected _db: StoreDb<TEntryTemplate>;
9
+ protected _isDisposed: boolean;
10
+ protected static $deleteAsync(name: string): Promise<void>;
11
+ protected static $existsAsync(name: string): Promise<boolean>;
12
+ protected static $openAsync<T extends IDataStoreBase>(name: string, factory: (name: string) => T): Promise<T>;
13
+ constructor(name: string, entryTemplate: TEntryTemplate);
14
+ openAsync(): Promise<void>;
15
+ dispose(): void;
16
+ protected $execAsync<T>(action: () => Promise<T>, transactionMode?: TransactionMode): Promise<T>;
17
+ getKeysAsync(): Promise<string[]>;
18
+ getAsync(key: string): Promise<Readonly<EntryTypes[TEntryTemplate] & IDataItem>>;
19
+ bulkGetAsync(ids: string[]): Promise<{
20
+ [key: string]: Readonly<EntryTypes[TEntryTemplate] & IDataItem>;
21
+ }>;
22
+ containsAsync(key: string): Promise<boolean>;
23
+ deleteAsync(key: string): Promise<void>;
24
+ bulkDeleteAsync(keys: string[]): Promise<void>;
25
+ protected $setAsync(key: string, value: any): Promise<void>;
26
+ protected $getOrSetAsync(key: string, factory: (key: string) => any): Promise<Readonly<EntryTypes[TEntryTemplate] & IDataItem>>;
27
+ clearAsync(): Promise<void>;
32
28
  }
33
29
  //# sourceMappingURL=dataStore.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dataStore.d.ts","sourceRoot":"","sources":["../../src/store/dataStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAA0B,MAAM,OAAO,CAAC;AAK/C,MAAM,WAAW,UAAU;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,SAAS,EAAE,MAAM,CAAC;CACrB;AAKD,MAAM,WAAW,SAAS;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC;CACvB;AAOD,qBAAa,SAAU,YAAW,UAAU;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;gBAEN,GAAG,EAAE,OAAO,CAAC,SAAS,CAAC;CAStC;AAGD,qBAAa,QAAS,YAAW,SAAS;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,GAAG,CAAC;gBAEC,GAAG,EAAE,OAAO,CAAC,QAAQ,CAAC;CAQrC;AAED,qBAAa,SAAU,SAAQ,KAAK;IAEhC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC1C,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;gBAEzB,IAAI,EAAE,MAAM;IA0CxB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM;CAG7B"}
1
+ {"version":3,"file":"dataStore.d.ts","sourceRoot":"","sources":["../../src/store/dataStore.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAc,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAU/C,MAAM,MAAM,cAAc,GAAG;IACzB,SAAS,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC;CAClC,CAAA;AAED,qBAAa,SAAS,CAAC,cAAc,SAAS,MAAM,UAAU,EAAE,YAAY,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAE,SAAQ,iBAAiB,CAAC,YAAY,CAAE,YAAW,cAAc;IAEjL,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAEvC,SAAS,CAAC,WAAW,EAAE,OAAO,CAAC;qBAER,YAAY,CAAC,IAAI,EAAE,MAAM;IAgBhD,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM;qBAInB,UAAU,CAAC,CAAC,SAAS,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,CAAC;gBAQ1F,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,cAAc;IASjD,SAAS;IAef,OAAO;cAiBS,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,eAAe,GAAE,eAAsB;IAezF,YAAY;IAIZ,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC,CAAC;IAchF,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC,CAAA;KAAE,CAAC;IA8CzG,aAAa,CAAC,GAAG,EAAE,MAAM;IAQzB,WAAW,CAAC,GAAG,EAAE,MAAM;IAQvB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE;cAQpB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG;cAuBjC,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,GAAG;IAUnE,UAAU;CAQnB"}
@@ -1,49 +1,133 @@
1
- import r from "dexie";
2
- const i = "registry", a = "data", c = ["id", "createdAt", "accessedAt", "updatedAt", "expiresAt"], n = ["id", "value"];
3
- class y {
4
- id;
5
- createdAt;
6
- updatedAt;
7
- accessedAt;
8
- expiresAt;
9
- constructor(t) {
10
- Object.assign(this, t);
1
+ import { AsyncMutex as y } from "../asyncMutex.es.js";
2
+ import { StoreDb as c } from "./storeDb.es.js";
3
+ import { StructEventTarget as h } from "../structEvent.es.js";
4
+ import n from "dexie";
5
+ import { v4 as w } from "uuid";
6
+ import { strictSatisfies as l } from "../typeUtils.es.js";
7
+ const d = new y();
8
+ class m extends h {
9
+ _db;
10
+ _isDisposed;
11
+ static async $deleteAsync(t) {
12
+ try {
13
+ await d.dispatch(async () => {
14
+ await c.exists(t) && await c.delete(t);
15
+ });
16
+ } catch (s) {
17
+ if (s instanceof n.InvalidStateError || s instanceof n.VersionError)
18
+ console.warn(`[DataStore] delete(${t}) failed:`, s);
19
+ else
20
+ throw s;
21
+ }
11
22
  }
12
- }
13
- class p {
14
- id;
15
- value;
16
- constructor(t) {
17
- Object.assign(this, t);
18
- }
19
- // constructor(key: string, value: string) {
20
- // this.key = key;
21
- // this.value = value;
22
- // }
23
- }
24
- class u extends r {
25
- // catalog/entries
26
- registry;
27
- data;
28
- constructor(t) {
29
- if (!t)
30
- throw new Error("Invalid database name");
31
- super(t);
32
- const e = this;
33
- e.version(1).stores({
34
- [i]: c.join(", "),
35
- [a]: n.join(", ")
36
- }), this.registry = e.table(i), this.data = e.table(a), e.registry.hook("deleting", async (o, l, d) => {
37
- await d.table(a).delete(o);
23
+ static $existsAsync(t) {
24
+ return n.exists(t);
25
+ }
26
+ static async $openAsync(t, s) {
27
+ return await d.dispatch(async () => {
28
+ const e = s(t);
29
+ return await e.openAsync(), e;
38
30
  });
39
31
  }
40
- static delete(t) {
41
- return r.delete(t);
32
+ constructor(t, s) {
33
+ if (super(), !t)
34
+ throw new Error("Name cannot be empty");
35
+ this._isDisposed = !1, this._db = new c(t, s);
36
+ }
37
+ async openAsync() {
38
+ if (!this._db.isOpen())
39
+ try {
40
+ await this._db.open();
41
+ } catch (t) {
42
+ if (t instanceof n.OpenFailedError)
43
+ await this._db.open();
44
+ else
45
+ throw t;
46
+ }
47
+ }
48
+ dispose() {
49
+ this._isDisposed || (this._db && (this._db.isOpen() && this._db.close(), this._db = null), this._isDisposed = !0);
50
+ }
51
+ async $execAsync(t, s = "rw") {
52
+ await this.openAsync();
53
+ try {
54
+ return await this._db.transaction(s, this._db.registry, this._db.data, async () => await t());
55
+ } catch (e) {
56
+ throw this._db.isOpen(), e;
57
+ }
58
+ }
59
+ async getKeysAsync() {
60
+ return await this._db.registry.filter((t) => !0).primaryKeys();
61
+ }
62
+ async getAsync(t) {
63
+ return await this.$execAsync(async () => {
64
+ const s = await this._db.registry.get(t);
65
+ if (s) {
66
+ const e = await this._db.data.get(t);
67
+ return { ...s, ...e };
68
+ }
69
+ return null;
70
+ }, "readonly");
71
+ }
72
+ // getMany
73
+ async bulkGetAsync(t) {
74
+ const s = {};
75
+ return await this.$execAsync(async () => {
76
+ const i = (await this._db.registry.bulkGet(t)).reduce((a, r, b) => (a[r.id] = r, a), {}), o = await this._db.data.bulkGet(t);
77
+ for (const a of o)
78
+ s[a.id] = { ...i[a.id], ...a }, delete i[a.id];
79
+ for (const a of Object.keys(i)) {
80
+ let r = {
81
+ id: a,
82
+ value: void 0
83
+ };
84
+ s[a] = { ...i[a], ...r };
85
+ }
86
+ return s;
87
+ }, "readonly");
88
+ }
89
+ async containsAsync(t) {
90
+ return await this.$execAsync(async () => await this._db.registry.get(t) != null);
91
+ }
92
+ async deleteAsync(t) {
93
+ await this.$execAsync(async () => {
94
+ await this._db.registry.delete(t), await this._db.data.delete(t);
95
+ });
96
+ }
97
+ // deleteManyAsync
98
+ async bulkDeleteAsync(t) {
99
+ await this.$execAsync(async () => {
100
+ await this._db.registry.bulkDelete(t), await this._db.data.bulkDelete(t);
101
+ });
102
+ }
103
+ // upsertAsync
104
+ async $setAsync(t, s) {
105
+ return await this.$execAsync(async () => {
106
+ let e;
107
+ const i = (/* @__PURE__ */ new Date()).getTime();
108
+ t ? e = await this._db.registry.get(t) : t = w(), await this._db.registry.put(l()({
109
+ id: t,
110
+ createdAt: e ? e.createdAt : i,
111
+ updatedAt: i
112
+ })), await this._db.data.put({
113
+ id: t,
114
+ value: s
115
+ });
116
+ });
117
+ }
118
+ // getOrAddAsync
119
+ async $getOrSetAsync(t, s) {
120
+ return await this.$execAsync(async () => (await this.containsAsync(t) || await this.$setAsync(t, s(t)), await this.getAsync(t)));
121
+ }
122
+ // clearAllAsync/evictAllAsync
123
+ async clearAsync() {
124
+ await this.$execAsync(async () => {
125
+ await this._db.registry.clear(), await this._db.data.clear();
126
+ });
42
127
  }
128
+ // TODO: support bulkSetAsync
43
129
  }
44
130
  export {
45
- y as DataEntry,
46
- p as DataItem,
47
- u as DataStore
131
+ m as DataStore
48
132
  };
49
133
  //# sourceMappingURL=dataStore.es.js.map