@atproto-labs/simple-store 0.1.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @atproto-labs/simple-store
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#4108](https://github.com/bluesky-social/atproto/pull/4108) [`f9dc9aa4c`](https://github.com/bluesky-social/atproto/commit/f9dc9aa4c9eaf2f82d140fbf011a9015e7f1a00d) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Allow `Key` type to be anything (except nullable values)
8
+
9
+ - [#4108](https://github.com/bluesky-social/atproto/pull/4108) [`f9dc9aa4c`](https://github.com/bluesky-social/atproto/commit/f9dc9aa4c9eaf2f82d140fbf011a9015e7f1a00d) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Update `Getter` function's option argument to `GetterOptions`
10
+
11
+ ## 0.2.0
12
+
13
+ ### Minor Changes
14
+
15
+ - [#3776](https://github.com/bluesky-social/atproto/pull/3776) [`0d77d1b55`](https://github.com/bluesky-social/atproto/commit/0d77d1b550a58117aee8f7f1e2be24d255ade9e4) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Remove `bind` method from `CachedGetter`
16
+
17
+ ### Patch Changes
18
+
19
+ - [#3776](https://github.com/bluesky-social/atproto/pull/3776) [`0d77d1b55`](https://github.com/bluesky-social/atproto/commit/0d77d1b550a58117aee8f7f1e2be24d255ade9e4) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Add `context` getter option to `CachedGetter` class
20
+
3
21
  ## 0.1.2
4
22
 
5
23
  ### Patch Changes
package/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  Dual MIT/Apache-2.0 License
2
2
 
3
- Copyright (c) 2022-2024 Bluesky PBC, and Contributors
3
+ Copyright (c) 2022-2025 Bluesky Social PBC, and Contributors
4
4
 
5
5
  Except as otherwise noted in individual files, this software is licensed under the MIT license (<http://opensource.org/licenses/MIT>), or the Apache License, Version 2.0 (<http://www.apache.org/licenses/LICENSE-2.0>).
6
6
 
@@ -1,5 +1,7 @@
1
- import { Awaitable, Key, SimpleStore, Value } from './simple-store.js';
2
- export type GetCachedOptions = {
1
+ import { GetOptions, Key, SimpleStore, Value } from './simple-store.js';
2
+ import { Awaitable, ContextOptions } from './util.js';
3
+ export type { GetOptions };
4
+ export type GetCachedOptions<C = void> = ContextOptions<C> & {
3
5
  signal?: AbortSignal;
4
6
  /**
5
7
  * Do not use the cache to get the value. Always get a new value from the
@@ -19,8 +21,13 @@ export type GetCachedOptions = {
19
21
  */
20
22
  allowStale?: boolean;
21
23
  };
22
- export type Getter<K, V> = (key: K, options: undefined | GetCachedOptions, storedValue: undefined | V) => Awaitable<V>;
23
- export type CachedGetterOptions<K, V> = {
24
+ export type GetterOptions<C = void> = {
25
+ context: C extends void ? undefined : C;
26
+ noCache: boolean;
27
+ signal?: AbortSignal;
28
+ };
29
+ export type Getter<K extends Key, V extends Value, C = void> = (key: K, options: GetterOptions<C>, storedValue: undefined | V) => Awaitable<V>;
30
+ export type CachedGetterOptions<K extends Key, V extends Value> = {
24
31
  isStale?: (key: K, value: V) => boolean | PromiseLike<boolean>;
25
32
  onStoreError?: (err: unknown, key: K, value: V) => void | PromiseLike<void>;
26
33
  deleteOnError?: (err: unknown, key: K, value: V) => boolean | PromiseLike<boolean>;
@@ -29,15 +36,15 @@ export type CachedGetterOptions<K, V> = {
29
36
  * Wrapper utility that uses a store to speed up the retrieval of values from an
30
37
  * (expensive) getter function.
31
38
  */
32
- export declare class CachedGetter<K extends Key = string, V extends Value = Value> {
33
- readonly getter: Getter<K, V>;
39
+ export declare class CachedGetter<K extends Key = string, V extends Value = Value, C = void> {
40
+ readonly getter: Getter<K, V, C>;
34
41
  readonly store: SimpleStore<K, V>;
35
- readonly options?: Readonly<CachedGetterOptions<K, V>> | undefined;
36
- private pending;
37
- constructor(getter: Getter<K, V>, store: SimpleStore<K, V>, options?: Readonly<CachedGetterOptions<K, V>> | undefined);
38
- get(key: K, options?: GetCachedOptions): Promise<V>;
39
- bind(key: K): (options?: GetCachedOptions) => Promise<V>;
40
- getStored(key: K, options?: GetCachedOptions): Promise<V | undefined>;
42
+ readonly options: CachedGetterOptions<K, V>;
43
+ private readonly pending;
44
+ constructor(getter: Getter<K, V, C>, store: SimpleStore<K, V>, options?: CachedGetterOptions<K, V>);
45
+ get(key: C extends void ? K : never, options?: GetCachedOptions<C>): Promise<V>;
46
+ get(key: C extends void ? never : K, options: GetCachedOptions<C>): Promise<V>;
47
+ getStored(key: K, options?: GetOptions): Promise<V | undefined>;
41
48
  setStored(key: K, value: V): Promise<void>;
42
49
  delStored(key: K, _cause?: unknown): Promise<void>;
43
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cached-getter.d.ts","sourceRoot":"","sources":["../src/cached-getter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAEtE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,CAAC,EAAE,WAAW,CAAA;IAEpB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CACzB,GAAG,EAAE,CAAC,EACN,OAAO,EAAE,SAAS,GAAG,gBAAgB,EACrC,WAAW,EAAE,SAAS,GAAG,CAAC,KACvB,SAAS,CAAC,CAAC,CAAC,CAAA;AAEjB,MAAM,MAAM,mBAAmB,CAAC,CAAC,EAAE,CAAC,IAAI;IACtC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,CAAA;IAC9D,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAA;IAC3E,aAAa,CAAC,EAAE,CACd,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,CAAC,EACN,KAAK,EAAE,CAAC,KACL,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,CAAA;CACpC,CAAA;AAOD;;;GAGG;AACH,qBAAa,YAAY,CAAC,CAAC,SAAS,GAAG,GAAG,MAAM,EAAE,CAAC,SAAS,KAAK,GAAG,KAAK;IAIrE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IALxD,OAAO,CAAC,OAAO,CAA+B;gBAGnC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EACpB,KAAK,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,EACxB,OAAO,CAAC,EAAE,QAAQ,CAAC,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAA;IAGlD,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,CAAC;IAqFzD,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,CAAC,CAAC;IAIlD,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAQrE,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAS1C,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAGzD"}
1
+ {"version":3,"file":"cached-getter.d.ts","sourceRoot":"","sources":["../src/cached-getter.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,7 @@ const returnFalse = () => false;
8
8
  * (expensive) getter function.
9
9
  */
10
10
  class CachedGetter {
11
- constructor(getter, store, options) {
11
+ constructor(getter, store, options = {}) {
12
12
  Object.defineProperty(this, "getter", {
13
13
  enumerable: true,
14
14
  configurable: true,
@@ -34,26 +34,30 @@ class CachedGetter {
34
34
  value: new Map()
35
35
  });
36
36
  }
37
- async get(key, options) {
38
- options?.signal?.throwIfAborted();
39
- const isStale = this.options?.isStale;
40
- const allowStored = options?.noCache
37
+ async get(key, { signal, context, allowStale = false, noCache = false, } = {}) {
38
+ signal?.throwIfAborted();
39
+ const { isStale, deleteOnError } = this.options;
40
+ const allowStored = noCache
41
41
  ? returnFalse // Never allow stored values to be returned
42
- : options?.allowStale || isStale == null
42
+ : allowStale || isStale == null
43
43
  ? returnTrue // Always allow stored values to be returned
44
44
  : async (value) => !(await isStale(key, value));
45
45
  // As long as concurrent requests are made for the same key, only one
46
- // request will be made to the cache & getter function at a time. This works
47
- // because there is no async operation between the while() loop and the
48
- // pending.set() call. Because of the "single threaded" nature of
46
+ // request will be made to the getStored & getter functions at a time. This
47
+ // works because there is no async operation between the while() loop and
48
+ // the pending.set() call below. Because of the single threaded nature of
49
49
  // JavaScript, the pending item will be set before the next iteration of the
50
- // while loop.
50
+ // while loop of any concurrent request.
51
51
  let previousExecutionFlow;
52
52
  while ((previousExecutionFlow = this.pending.get(key))) {
53
53
  try {
54
+ // If a concurrent request is already in progress, wait for it to finish
54
55
  const { isFresh, value } = await previousExecutionFlow;
56
+ // Use the concurrent request's result if it is fresh
55
57
  if (isFresh)
56
58
  return value;
59
+ // Use the concurrent request's result if not fresh (loaded from the
60
+ // store), and matches the conditions for using a stored value.
57
61
  if (await allowStored(value))
58
62
  return value;
59
63
  }
@@ -61,11 +65,12 @@ class CachedGetter {
61
65
  // Ignore errors from previous execution flows (they will have been
62
66
  // propagated by that flow).
63
67
  }
64
- options?.signal?.throwIfAborted();
68
+ // Break the loop if the signal was aborted
69
+ signal?.throwIfAborted();
65
70
  }
66
71
  const currentExecutionFlow = Promise.resolve()
67
72
  .then(async () => {
68
- const storedValue = await this.getStored(key, options);
73
+ const storedValue = await this.getStored(key, { signal });
69
74
  if (storedValue !== undefined && (await allowStored(storedValue))) {
70
75
  // Use the stored value as return value for the current execution
71
76
  // flow. Notify other concurrent execution flows (that should be
@@ -74,11 +79,13 @@ class CachedGetter {
74
79
  return { isFresh: false, value: storedValue };
75
80
  }
76
81
  return Promise.resolve()
77
- .then(async () => (0, this.getter)(key, options, storedValue))
82
+ .then(async () => {
83
+ const options = { signal, noCache, context };
84
+ return this.getter.call(null, key, options, storedValue);
85
+ })
78
86
  .catch(async (err) => {
79
87
  if (storedValue !== undefined) {
80
88
  try {
81
- const deleteOnError = this.options?.deleteOnError;
82
89
  if (await deleteOnError?.(err, key, storedValue)) {
83
90
  await this.delStored(key, err);
84
91
  }
@@ -109,9 +116,6 @@ class CachedGetter {
109
116
  const { value } = await currentExecutionFlow;
110
117
  return value;
111
118
  }
112
- bind(key) {
113
- return async (options) => this.get(key, options);
114
- }
115
119
  async getStored(key, options) {
116
120
  try {
117
121
  return await this.store.get(key, options);
@@ -1 +1 @@
1
- {"version":3,"file":"cached-getter.js","sourceRoot":"","sources":["../src/cached-getter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cached-getter.js","sourceRoot":"","sources":["../src/cached-getter.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './cached-getter.js';
2
2
  export * from './simple-store.js';
3
+ export * from './util.js';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,WAAW,CAAA"}
package/dist/index.js CHANGED
@@ -16,4 +16,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./cached-getter.js"), exports);
18
18
  __exportStar(require("./simple-store.js"), exports);
19
+ __exportStar(require("./util.js"), exports);
19
20
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,qDAAkC;AAClC,oDAAiC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,qDAAkC;AAClC,oDAAiC;AACjC,4CAAyB"}
@@ -1,10 +1,10 @@
1
- export type Awaitable<V> = V | PromiseLike<V>;
2
- export type Key = string | number;
1
+ import { Awaitable } from './util.js';
2
+ export type Key = NonNullable<unknown>;
3
3
  export type Value = NonNullable<unknown> | null;
4
4
  export type GetOptions = {
5
5
  signal?: AbortSignal;
6
6
  };
7
- export interface SimpleStore<K extends Key = string, V extends Value = Value> {
7
+ export interface SimpleStore<K extends Key, V extends Value> {
8
8
  /**
9
9
  * @return undefined if the key is not in the store (which is why Value cannot contain "undefined").
10
10
  */
@@ -1 +1 @@
1
- {"version":3,"file":"simple-store.d.ts","sourceRoot":"","sources":["../src/simple-store.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAA;AAE7C,MAAM,MAAM,GAAG,GAAG,MAAM,GAAG,MAAM,CAAA;AACjC,MAAM,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG,IAAI,CAAA;AAE/C,MAAM,MAAM,UAAU,GAAG;IAAE,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,CAAA;AAEjD,MAAM,WAAW,WAAW,CAAC,CAAC,SAAS,GAAG,GAAG,MAAM,EAAE,CAAC,SAAS,KAAK,GAAG,KAAK;IAC1E;;OAEG;IACH,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,UAAU,KAAK,SAAS,CAAC,SAAS,GAAG,CAAC,CAAC,CAAA;IAC/D,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,SAAS,CAAC,IAAI,CAAC,CAAA;IAC1C,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,SAAS,CAAC,IAAI,CAAC,CAAA;IAChC,KAAK,CAAC,EAAE,MAAM,SAAS,CAAC,IAAI,CAAC,CAAA;CAC9B"}
1
+ {"version":3,"file":"simple-store.d.ts","sourceRoot":"","sources":["../src/simple-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAErC,MAAM,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,CAAC,CAAA;AACtC,MAAM,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG,IAAI,CAAA;AAE/C,MAAM,MAAM,UAAU,GAAG;IAAE,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,CAAA;AAEjD,MAAM,WAAW,WAAW,CAAC,CAAC,SAAS,GAAG,EAAE,CAAC,SAAS,KAAK;IACzD;;OAEG;IACH,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,UAAU,KAAK,SAAS,CAAC,SAAS,GAAG,CAAC,CAAC,CAAA;IAC/D,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,SAAS,CAAC,IAAI,CAAC,CAAA;IAC1C,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,SAAS,CAAC,IAAI,CAAC,CAAA;IAChC,KAAK,CAAC,EAAE,MAAM,SAAS,CAAC,IAAI,CAAC,CAAA;CAC9B"}
package/dist/util.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export type Awaitable<V> = V | PromiseLike<V>;
2
+ export type ContextOptions<C> = C extends void | undefined ? {
3
+ context?: undefined;
4
+ } : {
5
+ context: C;
6
+ };
7
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAA;AAE7C,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,CAAC,SAAS,IAAI,GAAG,SAAS,GACtD;IAAE,OAAO,CAAC,EAAE,SAAS,CAAA;CAAE,GACvB;IAAE,OAAO,EAAE,CAAC,CAAA;CAAE,CAAA"}
package/dist/util.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto-labs/simple-store",
3
- "version": "0.1.2",
3
+ "version": "0.3.0",
4
4
  "license": "MIT",
5
5
  "description": "Simple store interfaces & utilities",
6
6
  "keywords": [
@@ -1,6 +1,8 @@
1
- import { Awaitable, Key, SimpleStore, Value } from './simple-store.js'
1
+ import { GetOptions, Key, SimpleStore, Value } from './simple-store.js'
2
+ import { Awaitable, ContextOptions } from './util.js'
2
3
 
3
- export type GetCachedOptions = {
4
+ export type { GetOptions }
5
+ export type GetCachedOptions<C = void> = ContextOptions<C> & {
4
6
  signal?: AbortSignal
5
7
 
6
8
  /**
@@ -23,13 +25,19 @@ export type GetCachedOptions = {
23
25
  allowStale?: boolean
24
26
  }
25
27
 
26
- export type Getter<K, V> = (
28
+ export type GetterOptions<C = void> = {
29
+ context: C extends void ? undefined : C
30
+ noCache: boolean
31
+ signal?: AbortSignal
32
+ }
33
+
34
+ export type Getter<K extends Key, V extends Value, C = void> = (
27
35
  key: K,
28
- options: undefined | GetCachedOptions,
36
+ options: GetterOptions<C>,
29
37
  storedValue: undefined | V,
30
38
  ) => Awaitable<V>
31
39
 
32
- export type CachedGetterOptions<K, V> = {
40
+ export type CachedGetterOptions<K extends Key, V extends Value> = {
33
41
  isStale?: (key: K, value: V) => boolean | PromiseLike<boolean>
34
42
  onStoreError?: (err: unknown, key: K, value: V) => void | PromiseLike<void>
35
43
  deleteOnError?: (
@@ -48,50 +56,76 @@ const returnFalse = () => false
48
56
  * Wrapper utility that uses a store to speed up the retrieval of values from an
49
57
  * (expensive) getter function.
50
58
  */
51
- export class CachedGetter<K extends Key = string, V extends Value = Value> {
52
- private pending = new Map<K, PendingItem<V>>()
59
+ export class CachedGetter<
60
+ K extends Key = string,
61
+ V extends Value = Value,
62
+ C = void,
63
+ > {
64
+ private readonly pending = new Map<K, PendingItem<V>>()
53
65
 
54
66
  constructor(
55
- readonly getter: Getter<K, V>,
67
+ readonly getter: Getter<K, V, C>,
56
68
  readonly store: SimpleStore<K, V>,
57
- readonly options?: Readonly<CachedGetterOptions<K, V>>,
69
+ readonly options: CachedGetterOptions<K, V> = {},
58
70
  ) {}
59
71
 
60
- async get(key: K, options?: GetCachedOptions): Promise<V> {
61
- options?.signal?.throwIfAborted()
62
-
63
- const isStale = this.options?.isStale
64
-
65
- const allowStored: (value: V) => Awaitable<boolean> = options?.noCache
72
+ async get(
73
+ key: C extends void ? K : never,
74
+ options?: GetCachedOptions<C>,
75
+ ): Promise<V>
76
+ async get(
77
+ key: C extends void ? never : K,
78
+ options: GetCachedOptions<C>,
79
+ ): Promise<V>
80
+ async get(
81
+ key: K,
82
+ {
83
+ signal,
84
+ context,
85
+ allowStale = false,
86
+ noCache = false,
87
+ } = {} as GetCachedOptions<C>,
88
+ ): Promise<V> {
89
+ signal?.throwIfAborted()
90
+
91
+ const { isStale, deleteOnError } = this.options
92
+
93
+ const allowStored: (value: V) => Awaitable<boolean> = noCache
66
94
  ? returnFalse // Never allow stored values to be returned
67
- : options?.allowStale || isStale == null
95
+ : allowStale || isStale == null
68
96
  ? returnTrue // Always allow stored values to be returned
69
97
  : async (value: V) => !(await isStale(key, value))
70
98
 
71
99
  // As long as concurrent requests are made for the same key, only one
72
- // request will be made to the cache & getter function at a time. This works
73
- // because there is no async operation between the while() loop and the
74
- // pending.set() call. Because of the "single threaded" nature of
100
+ // request will be made to the getStored & getter functions at a time. This
101
+ // works because there is no async operation between the while() loop and
102
+ // the pending.set() call below. Because of the single threaded nature of
75
103
  // JavaScript, the pending item will be set before the next iteration of the
76
- // while loop.
104
+ // while loop of any concurrent request.
77
105
  let previousExecutionFlow: undefined | PendingItem<V>
78
106
  while ((previousExecutionFlow = this.pending.get(key))) {
79
107
  try {
108
+ // If a concurrent request is already in progress, wait for it to finish
80
109
  const { isFresh, value } = await previousExecutionFlow
81
110
 
111
+ // Use the concurrent request's result if it is fresh
82
112
  if (isFresh) return value
113
+ // Use the concurrent request's result if not fresh (loaded from the
114
+ // store), and matches the conditions for using a stored value.
83
115
  if (await allowStored(value)) return value
84
116
  } catch {
85
117
  // Ignore errors from previous execution flows (they will have been
86
118
  // propagated by that flow).
87
119
  }
88
120
 
89
- options?.signal?.throwIfAborted()
121
+ // Break the loop if the signal was aborted
122
+ signal?.throwIfAborted()
90
123
  }
91
124
 
92
125
  const currentExecutionFlow: PendingItem<V> = Promise.resolve()
93
126
  .then(async () => {
94
- const storedValue = await this.getStored(key, options)
127
+ const storedValue = await this.getStored(key, { signal })
128
+
95
129
  if (storedValue !== undefined && (await allowStored(storedValue))) {
96
130
  // Use the stored value as return value for the current execution
97
131
  // flow. Notify other concurrent execution flows (that should be
@@ -101,11 +135,13 @@ export class CachedGetter<K extends Key = string, V extends Value = Value> {
101
135
  }
102
136
 
103
137
  return Promise.resolve()
104
- .then(async () => (0, this.getter)(key, options, storedValue))
138
+ .then(async () => {
139
+ const options = { signal, noCache, context } as GetterOptions<C>
140
+ return this.getter.call(null, key, options, storedValue)
141
+ })
105
142
  .catch(async (err) => {
106
143
  if (storedValue !== undefined) {
107
144
  try {
108
- const deleteOnError = this.options?.deleteOnError
109
145
  if (await deleteOnError?.(err, key, storedValue)) {
110
146
  await this.delStored(key, err)
111
147
  }
@@ -142,11 +178,7 @@ export class CachedGetter<K extends Key = string, V extends Value = Value> {
142
178
  return value
143
179
  }
144
180
 
145
- bind(key: K): (options?: GetCachedOptions) => Promise<V> {
146
- return async (options) => this.get(key, options)
147
- }
148
-
149
- async getStored(key: K, options?: GetCachedOptions): Promise<V | undefined> {
181
+ async getStored(key: K, options?: GetOptions): Promise<V | undefined> {
150
182
  try {
151
183
  return await this.store.get(key, options)
152
184
  } catch (err) {
package/src/index.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './cached-getter.js'
2
2
  export * from './simple-store.js'
3
+ export * from './util.js'
@@ -1,11 +1,11 @@
1
- export type Awaitable<V> = V | PromiseLike<V>
1
+ import { Awaitable } from './util.js'
2
2
 
3
- export type Key = string | number
3
+ export type Key = NonNullable<unknown>
4
4
  export type Value = NonNullable<unknown> | null
5
5
 
6
6
  export type GetOptions = { signal?: AbortSignal }
7
7
 
8
- export interface SimpleStore<K extends Key = string, V extends Value = Value> {
8
+ export interface SimpleStore<K extends Key, V extends Value> {
9
9
  /**
10
10
  * @return undefined if the key is not in the store (which is why Value cannot contain "undefined").
11
11
  */
package/src/util.ts ADDED
@@ -0,0 +1,5 @@
1
+ export type Awaitable<V> = V | PromiseLike<V>
2
+
3
+ export type ContextOptions<C> = C extends void | undefined
4
+ ? { context?: undefined }
5
+ : { context: C }
@@ -1 +1 @@
1
- {"root":["./src/cached-getter.ts","./src/index.ts","./src/simple-store.ts"],"version":"5.6.3"}
1
+ {"root":["./src/cached-getter.ts","./src/index.ts","./src/simple-store.ts","./src/util.ts"],"version":"5.8.2"}