@zajno/common 2.8.0 → 2.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createCacheExtension = createCacheExtension;
4
+ const extendObject_js_1 = require("../structures/extendObject.js");
5
+ function createCacheExtension(storage) {
6
+ return {
7
+ overrideFactory: (original) => {
8
+ return async (refreshing) => {
9
+ if (!refreshing) {
10
+ // read cached value first
11
+ const cached = await storage.getValue();
12
+ if (cached != null) {
13
+ return cached;
14
+ }
15
+ }
16
+ const value = await original(refreshing);
17
+ // cache the fresh result
18
+ storage.setValue(value);
19
+ return value;
20
+ };
21
+ },
22
+ extendShape: (previous) => {
23
+ return (0, extendObject_js_1.extendObject)(previous, {
24
+ cache: {
25
+ get: () => storage,
26
+ },
27
+ resetWithCache: {
28
+ value: () => {
29
+ storage.removeValue();
30
+ previous.reset();
31
+ },
32
+ },
33
+ setCachedInstance: {
34
+ value: (value) => {
35
+ if (value == null) {
36
+ storage.removeValue();
37
+ }
38
+ else {
39
+ storage.setValue(value);
40
+ }
41
+ return previous.setInstance(value);
42
+ },
43
+ },
44
+ });
45
+ },
46
+ };
47
+ }
48
+ //# sourceMappingURL=extensions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extensions.js","sourceRoot":"","sources":["../../../src/lazy/extensions.ts"],"names":[],"mappings":";;AAcA,oDAoDC;AAjED,mEAA6D;AAa7D,SAAgB,oBAAoB,CAA8D,OAAiB;IAC/G,OAAO;QACH,eAAe,EAAE,CACb,QAA8C,EACR,EAAE;YACxC,OAAO,KAAK,EAAE,UAAoB,EAAc,EAAE;gBAC9C,IAAI,CAAC,UAAU,EAAE,CAAC;oBACd,0BAA0B;oBAC1B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC;oBACxC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;wBACjB,OAAO,MAAM,CAAC;oBAClB,CAAC;gBACL,CAAC;gBAED,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,CAAC;gBAEzC,yBAAyB;gBACzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAExB,OAAO,KAAK,CAAC;YACjB,CAAC,CAAC;QACN,CAAC;QACD,WAAW,EAAE,CACT,QAA+C,EACjD,EAAE;YACA,OAAO,IAAA,8BAAY,EACf,QAAQ,EACR;gBACI,KAAK,EAAE;oBACH,GAAG,EAAE,GAAG,EAAE,CAAC,OAAO;iBACrB;gBACD,cAAc,EAAE;oBACZ,KAAK,EAAE,GAAG,EAAE;wBACR,OAAO,CAAC,WAAW,EAAE,CAAC;wBACtB,QAAQ,CAAC,KAAK,EAAE,CAAC;oBACrB,CAAC;iBACJ;gBACD,iBAAiB,EAAE;oBACf,KAAK,EAAE,CAAC,KAAQ,EAAE,EAAE;wBAChB,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;4BAChB,OAAO,CAAC,WAAW,EAAE,CAAC;wBAC1B,CAAC;6BAAM,CAAC;4BACJ,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;wBAC5B,CAAC;wBAED,OAAO,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;oBACvC,CAAC;iBACJ;aACJ,CACJ,CAAC;QACN,CAAC;KACJ,CAAC;AACN,CAAC"}
package/cjs/lazy/lazy.js CHANGED
@@ -2,11 +2,16 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Lazy = void 0;
4
4
  const disposer_js_1 = require("../functions/disposer.js");
5
+ /**
6
+ * Synchronous lazy-loading container that initializes a value on first access.
7
+ * The value is cached until reset or expired. Supports custom disposal and cache expiration.
8
+ */
5
9
  class Lazy {
6
10
  _factory;
7
11
  _instance = undefined;
8
12
  _expireTracker;
9
13
  _disposer;
14
+ _error = null;
10
15
  constructor(_factory) {
11
16
  this._factory = _factory;
12
17
  }
@@ -15,9 +20,8 @@ class Lazy {
15
20
  this.ensureInstance();
16
21
  return this._instance;
17
22
  }
18
- get currentValue() {
19
- return this._instance;
20
- }
23
+ get currentValue() { return this._instance; }
24
+ get error() { return this._error; }
21
25
  /** Override me: additional way to make sure instance is valid */
22
26
  get isValid() {
23
27
  if (!this.hasValue) {
@@ -31,27 +35,22 @@ class Lazy {
31
35
  }
32
36
  return true;
33
37
  }
38
+ /** Provides custom cleanup logic when the instance is reset or disposed. */
34
39
  withDisposer(disposer) {
35
40
  this._disposer = disposer;
36
41
  return this;
37
42
  }
43
+ /** Configures automatic cache expiration using an expire tracker. */
38
44
  withExpire(tracker) {
39
45
  this._expireTracker = tracker;
40
46
  return this;
41
47
  }
42
- ensureInstance() {
43
- if (this.isValid) {
44
- return;
45
- }
46
- // additional reset to make sure previous instance has been disposed
47
- this.reset();
48
- const res = this._factory();
49
- this.setInstance(res);
50
- }
48
+ /** Eagerly loads the value without accessing it. Useful for preloading. */
51
49
  prewarm() {
52
50
  this.ensureInstance();
53
51
  return this;
54
52
  }
53
+ /** Manually sets the cached value. */
55
54
  setInstance(instance) {
56
55
  this._instance = instance;
57
56
  if (this._instance !== undefined && this._expireTracker) {
@@ -68,8 +67,32 @@ class Lazy {
68
67
  }
69
68
  }
70
69
  this.setInstance(undefined);
70
+ this._error = null;
71
71
  }
72
72
  dispose() { this.reset(); }
73
+ ensureInstance() {
74
+ if (this.isValid) {
75
+ return;
76
+ }
77
+ // additional reset to make sure previous instance has been disposed
78
+ this.reset();
79
+ try {
80
+ const res = this._factory();
81
+ this.setInstance(res);
82
+ }
83
+ catch (e) {
84
+ this._error = this.parseError(e);
85
+ }
86
+ }
87
+ parseError(err) {
88
+ if (typeof err === 'string') {
89
+ return err;
90
+ }
91
+ if (err instanceof Error) {
92
+ return err.message;
93
+ }
94
+ return String(err) || 'Unknown error';
95
+ }
73
96
  }
74
97
  exports.Lazy = Lazy;
75
98
  //# sourceMappingURL=lazy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lazy.js","sourceRoot":"","sources":["../../../src/lazy/lazy.ts"],"names":[],"mappings":";;;AAAA,0DAAwE;AAKxE,MAAa,IAAI;IAMkB;IAJrB,SAAS,GAAkB,SAAS,CAAC;IACvC,cAAc,CAA6B;IAC3C,SAAS,CAAqB;IAEtC,YAA+B,QAAmB;QAAnB,aAAQ,GAAR,QAAQ,CAAW;IAAI,CAAC;IAEvD,IAAI,QAAQ,KAAK,OAAO,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC;IAEvD,IAAI,KAAK;QACL,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC,SAAU,CAAC;IAC3B,CAAC;IAED,IAAI,YAAY;QACZ,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IAED,iEAAiE;IACjE,IAAc,OAAO;QACjB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjB,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,IAAI,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;gBAChC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACb,OAAO,KAAK,CAAC;YACjB,CAAC;QACL,CAAC;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;IAEM,YAAY,CAAC,QAA2B;QAC3C,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;QAC1B,OAAO,IAAI,CAAC;IAChB,CAAC;IAEM,UAAU,CAAC,OAAmC;QACjD,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC;QAC9B,OAAO,IAAI,CAAC;IAChB,CAAC;IAEO,cAAc;QAClB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,OAAO;QACX,CAAC;QAED,oEAAoE;QACpE,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO;QACH,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,WAAW,CAAC,QAAuB;QAC/B,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;QAE1B,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACtD,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;QAClC,CAAC;IACL,CAAC;IAED,KAAK;QACD,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAClC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;gBACjB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACnC,CAAC;iBAAM,CAAC;gBACJ,IAAA,wBAAU,EAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC/B,CAAC;QACL,CAAC;QACD,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAChC,CAAC;IAED,OAAO,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;CAC9B;AAjFD,oBAiFC"}
1
+ {"version":3,"file":"lazy.js","sourceRoot":"","sources":["../../../src/lazy/lazy.ts"],"names":[],"mappings":"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"}
package/cjs/lazy/light.js CHANGED
@@ -4,17 +4,27 @@ exports.createLazy = createLazy;
4
4
  function createLazy(factory) {
5
5
  const _factory = factory;
6
6
  let _instance = undefined;
7
+ let _error = null;
7
8
  const res = {
8
9
  get value() {
9
10
  if (_instance === undefined) {
10
- _instance = _factory();
11
+ _error = null;
12
+ try {
13
+ _instance = _factory();
14
+ }
15
+ catch (e) {
16
+ _error = e instanceof Error ? e.message : String(e);
17
+ throw e;
18
+ }
11
19
  }
12
20
  return _instance;
13
21
  },
14
22
  get currentValue() { return _instance; },
15
23
  get hasValue() { return _instance !== undefined; },
24
+ get error() { return _error; },
16
25
  reset: () => {
17
26
  _instance = undefined;
27
+ _error = null;
18
28
  },
19
29
  dispose: () => res.reset(),
20
30
  };
@@ -1 +1 @@
1
- {"version":3,"file":"light.js","sourceRoot":"","sources":["../../../src/lazy/light.ts"],"names":[],"mappings":";;AAIA,gCAoBC;AApBD,SAAgB,UAAU,CAAI,OAAgB;IAC1C,MAAM,QAAQ,GAAG,OAAO,CAAC;IACzB,IAAI,SAAS,GAAkB,SAAS,CAAC;IAEzC,MAAM,GAAG,GAA8C;QACnD,IAAI,KAAK;YACL,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC1B,SAAS,GAAG,QAAQ,EAAE,CAAC;YAC3B,CAAC;YACD,OAAO,SAAS,CAAC;QACrB,CAAC;QACD,IAAI,YAAY,KAAK,OAAO,SAAS,CAAC,CAAC,CAAC;QACxC,IAAI,QAAQ,KAAK,OAAO,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC;QAClD,KAAK,EAAE,GAAG,EAAE;YACR,SAAS,GAAG,SAAS,CAAC;QAC1B,CAAC;QACD,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE;KAC7B,CAAC;IAEF,OAAO,GAAG,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"light.js","sourceRoot":"","sources":["../../../src/lazy/light.ts"],"names":[],"mappings":";;AAIA,gCA6BC;AA7BD,SAAgB,UAAU,CAAI,OAAgB;IAC1C,MAAM,QAAQ,GAAG,OAAO,CAAC;IACzB,IAAI,SAAS,GAAkB,SAAS,CAAC;IACzC,IAAI,MAAM,GAAkB,IAAI,CAAC;IAEjC,MAAM,GAAG,GAA8C;QACnD,IAAI,KAAK;YACL,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC1B,MAAM,GAAG,IAAI,CAAC;gBACd,IAAI,CAAC;oBACD,SAAS,GAAG,QAAQ,EAAE,CAAC;gBAC3B,CAAC;gBAAC,OAAO,CAAU,EAAE,CAAC;oBAClB,MAAM,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;oBACpD,MAAM,CAAC,CAAC;gBACZ,CAAC;YACL,CAAC;YACD,OAAO,SAAS,CAAC;QACrB,CAAC;QACD,IAAI,YAAY,KAAK,OAAO,SAAS,CAAC,CAAC,CAAC;QACxC,IAAI,QAAQ,KAAK,OAAO,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC;QAClD,IAAI,KAAK,KAAK,OAAO,MAAM,CAAC,CAAC,CAAC;QAC9B,KAAK,EAAE,GAAG,EAAE;YACR,SAAS,GAAG,SAAS,CAAC;YACtB,MAAM,GAAG,IAAI,CAAC;QAClB,CAAC;QACD,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE;KAC7B,CAAC;IAEF,OAAO,GAAG,CAAC;AACf,CAAC"}
@@ -2,20 +2,30 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LazyPromise = void 0;
4
4
  const disposer_js_1 = require("../functions/disposer.js");
5
+ /**
6
+ * Asynchronous lazy-loading container that initializes via a promise-based factory.
7
+ * Handles concurrent operations with "latest wins" semantics: multiple refreshes are automatically
8
+ * coordinated so all awaiting promises receive the final value. Supports extensions for custom behavior.
9
+ */
5
10
  class LazyPromise {
6
11
  _factory;
7
- initial;
8
- _instance = undefined;
12
+ _initial;
13
+ _instance;
9
14
  _isLoading = null;
10
15
  _promise;
11
16
  _expireTracker;
12
- constructor(_factory, initial = undefined) {
13
- this._factory = _factory;
14
- this.initial = initial;
15
- this._instance = initial;
17
+ // Track the active factory promise to determine "latest wins"
18
+ _activeFactoryPromise = null;
19
+ _error = null;
20
+ _ownDisposer;
21
+ constructor(factory, initial) {
22
+ this._factory = factory;
23
+ this._initial = initial;
24
+ this._instance = initial; // as ILazyValue<T, TInitial>;
16
25
  }
17
26
  get isLoading() { return this._isLoading; }
18
27
  get hasValue() { return this._isLoading === false; }
28
+ get error() { return this._error; }
19
29
  get promise() {
20
30
  this.ensureInstanceLoading();
21
31
  return this._promise;
@@ -24,50 +34,106 @@ class LazyPromise {
24
34
  this.ensureInstanceLoading();
25
35
  return this._instance;
26
36
  }
27
- /** does not calls factory */
37
+ /** Returns current value without triggering loading. */
28
38
  get currentValue() {
29
39
  return this._instance;
30
40
  }
41
+ /** Configures automatic cache expiration using an expire tracker. */
31
42
  withExpire(tracker) {
32
43
  this._expireTracker = tracker;
33
44
  return this;
34
45
  }
35
- ensureInstanceLoading() {
36
- if (this.isLoading === false && this._instance !== undefined && this._expireTracker?.isExpired) {
37
- // do not reset the instance, just make sure it will be reloaded
38
- this._isLoading = null;
46
+ /**
47
+ * Extends this instance with additional functionality via in-place mutation.
48
+ *
49
+ * **Capabilities:**
50
+ * - `overrideFactory`: Wrap the factory (logging, retry, caching, etc.)
51
+ * - `extendShape`: Add custom properties/methods
52
+ * - `dispose`: Cleanup resources when disposed
53
+ *
54
+ * **Type Safety:**
55
+ * - Use `ILazyPromiseExtension<any>` for universal extensions
56
+ * - Use `ILazyPromiseExtension<ConcreteType>` for type-specific extensions
57
+ *
58
+ * **Note:** Extensions mutate the instance and can be chained.
59
+ *
60
+ * @param extension - Extension configuration
61
+ * @returns The same instance with applied extensions
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * const logged = lazy.extend({
66
+ * overrideFactory: (factory) => async (refreshing) => {
67
+ * console.log('Loading...');
68
+ * return await factory(refreshing);
69
+ * }
70
+ * });
71
+ * ```
72
+ */
73
+ extend(
74
+ // Partial allows extensions with extra properties beyond the interface
75
+ // 'any' type parameter doesn't affect return type since we return 'this'
76
+ extension) {
77
+ let extended = this;
78
+ // Apply shape extension if provided
79
+ if (extension.extendShape) {
80
+ extended = extension.extendShape(this);
39
81
  }
40
- if (this._isLoading === null) {
41
- this._isLoading = true;
42
- this._promise = this._factory().then(this.onResolved.bind(this));
82
+ // Override the factory if provided
83
+ if (extension.overrideFactory) {
84
+ this._factory = extension.overrideFactory(this._factory, extended);
43
85
  }
44
- }
45
- onResolved(res) {
46
- // case: during the promise `setInstance` was called
47
- if (!this._isLoading && this._instance !== undefined) {
48
- return this._instance;
86
+ if (extension.dispose) {
87
+ const previousDisposer = this._ownDisposer;
88
+ const nextDisposer = extension.dispose;
89
+ this._ownDisposer = () => {
90
+ nextDisposer(extended);
91
+ previousDisposer?.();
92
+ };
49
93
  }
50
- this.setInstance(res);
51
- return res;
94
+ return extended;
52
95
  }
96
+ /**
97
+ * Manually sets the value and marks loading as complete.
98
+ * Clears any errors and restarts the expiration tracker if configured.
99
+ *
100
+ * @param res - The value to set
101
+ * @returns The value that was set
102
+ */
53
103
  setInstance(res) {
54
104
  this._isLoading = false;
105
+ this.clearError(); // clear error on successful set
55
106
  // refresh promise so it won't keep old callbacks
56
107
  // + make sure it's resolved with the freshest value
57
108
  // also do this before setting the instance... just in case :)
58
109
  this._promise = Promise.resolve(res);
110
+ this._activeFactoryPromise = null;
59
111
  this._instance = res;
60
- if (this._expireTracker) {
61
- this._expireTracker.restart();
62
- }
112
+ this._expireTracker?.restart();
63
113
  return res;
64
114
  }
115
+ /**
116
+ * Re-executes the factory to get fresh data.
117
+ *
118
+ * **Concurrency handling:**
119
+ * - Supersedes any in-progress load or refresh
120
+ * - Multiple concurrent refreshes: latest wins
121
+ * - All awaiting promises receive the final refreshed value
122
+ *
123
+ * @returns Promise resolving to the refreshed value
124
+ */
125
+ async refresh() {
126
+ this.startLoading(true);
127
+ return this._promise;
128
+ }
65
129
  reset() {
66
130
  this._isLoading = null;
131
+ this.clearError();
67
132
  const wasDisposed = (0, disposer_js_1.tryDispose)(this._instance);
68
- this._instance = this.initial;
133
+ this._instance = this._initial;
69
134
  const p = this._promise;
70
135
  this._promise = undefined;
136
+ this._activeFactoryPromise = null; // Clear active promise reference
71
137
  // check if loading is still in progress
72
138
  // need to dispose abandoned value
73
139
  if (p && !wasDisposed) {
@@ -77,8 +143,82 @@ class LazyPromise {
77
143
  }
78
144
  }
79
145
  dispose() {
146
+ this._ownDisposer?.();
80
147
  this.reset();
81
148
  }
149
+ ensureInstanceLoading() {
150
+ if (this.isLoading === false && this._instance !== undefined && this._expireTracker?.isExpired) {
151
+ // do not reset the instance, just make sure it will be reloaded
152
+ this._isLoading = null;
153
+ }
154
+ if (this._isLoading === null) {
155
+ this._isLoading = true;
156
+ this.startLoading(false);
157
+ }
158
+ }
159
+ startLoading(refreshing) {
160
+ if (!refreshing && this._activeFactoryPromise) {
161
+ // Case when refreshing already is happening - we have an active promise
162
+ return;
163
+ }
164
+ const factoryPromise = this._factory(refreshing)
165
+ .then(res => {
166
+ if (!this._activeFactoryPromise) {
167
+ // this promise was abandoned: was superseded or reset called
168
+ return this._instance ?? this._initial;
169
+ }
170
+ if (this._activeFactoryPromise === factoryPromise) {
171
+ // case: during the promise `setInstance` was called manually
172
+ if (!refreshing && !this._isLoading && this._instance !== undefined) {
173
+ return this._instance;
174
+ }
175
+ this.setInstance(res);
176
+ return res;
177
+ }
178
+ // Stale promise - return the latest active promise instead
179
+ // This ensures anyone awaiting this old promise gets the fresh value
180
+ return this._activeFactoryPromise;
181
+ })
182
+ .catch(err => {
183
+ if (!this._activeFactoryPromise || this._activeFactoryPromise === factoryPromise) {
184
+ return this.onRejected(err);
185
+ }
186
+ throw err;
187
+ });
188
+ const hadActive = !!this._activeFactoryPromise;
189
+ // This is now the active promise - any previous one is superseded
190
+ this._activeFactoryPromise = factoryPromise;
191
+ // don't overwrite an existing promise (e.g., from refresh)
192
+ // it should pick up the new active promise automatically
193
+ if (!this._promise || !hadActive) {
194
+ this._promise = factoryPromise;
195
+ }
196
+ }
197
+ onRejected(e) {
198
+ this._isLoading = false;
199
+ // Keep the current instance on error (don't reset to initial)
200
+ // This allows retaining the last successful value
201
+ const currentInstance = this._instance !== undefined ? this._instance : this._initial;
202
+ this._promise = Promise.resolve(currentInstance);
203
+ this._activeFactoryPromise = null;
204
+ this.setError(e);
205
+ return currentInstance;
206
+ }
207
+ setError(err) {
208
+ this._error = this.parseError(err);
209
+ }
210
+ clearError() {
211
+ this._error = null;
212
+ }
213
+ parseError(err) {
214
+ if (typeof err === 'string') {
215
+ return err;
216
+ }
217
+ if (err instanceof Error) {
218
+ return err.message;
219
+ }
220
+ return String(err) || 'Unknown error';
221
+ }
82
222
  }
83
223
  exports.LazyPromise = LazyPromise;
84
224
  //# sourceMappingURL=promise.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"promise.js","sourceRoot":"","sources":["../../../src/lazy/promise.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"promise.js","sourceRoot":"","sources":["../../../src/lazy/promise.ts"],"names":[],"mappings":"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"}
package/cjs/lazy/types.js CHANGED
@@ -1,5 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- ;
4
- ;
5
3
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lazy/types.ts"],"names":[],"mappings":";;AAWC,CAAC;AASD,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lazy/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extendObject = extendObject;
4
+ /** Type-safe version of `Object.defineProperties` */
5
+ function extendObject(base, extensionDescriptorsMap) {
6
+ return Object.defineProperties(base, extensionDescriptorsMap);
7
+ }
8
+ //# sourceMappingURL=extendObject.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extendObject.js","sourceRoot":"","sources":["../../../src/structures/extendObject.ts"],"names":[],"mappings":";;AAeA,oCAKC;AAND,qDAAqD;AACrD,SAAgB,YAAY,CAC1B,IAAO,EACP,uBAAiD;IAEjD,OAAO,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,uBAAuB,CAAmB,CAAC;AAClF,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { extendObject } from '../structures/extendObject.js';
2
+ export function createCacheExtension(storage) {
3
+ return {
4
+ overrideFactory: (original) => {
5
+ return async (refreshing) => {
6
+ if (!refreshing) {
7
+ // read cached value first
8
+ const cached = await storage.getValue();
9
+ if (cached != null) {
10
+ return cached;
11
+ }
12
+ }
13
+ const value = await original(refreshing);
14
+ // cache the fresh result
15
+ storage.setValue(value);
16
+ return value;
17
+ };
18
+ },
19
+ extendShape: (previous) => {
20
+ return extendObject(previous, {
21
+ cache: {
22
+ get: () => storage,
23
+ },
24
+ resetWithCache: {
25
+ value: () => {
26
+ storage.removeValue();
27
+ previous.reset();
28
+ },
29
+ },
30
+ setCachedInstance: {
31
+ value: (value) => {
32
+ if (value == null) {
33
+ storage.removeValue();
34
+ }
35
+ else {
36
+ storage.setValue(value);
37
+ }
38
+ return previous.setInstance(value);
39
+ },
40
+ },
41
+ });
42
+ },
43
+ };
44
+ }
45
+ //# sourceMappingURL=extensions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extensions.js","sourceRoot":"","sources":["../../../src/lazy/extensions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAa7D,MAAM,UAAU,oBAAoB,CAA8D,OAAiB;IAC/G,OAAO;QACH,eAAe,EAAE,CACb,QAA8C,EACR,EAAE;YACxC,OAAO,KAAK,EAAE,UAAoB,EAAc,EAAE;gBAC9C,IAAI,CAAC,UAAU,EAAE,CAAC;oBACd,0BAA0B;oBAC1B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC;oBACxC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;wBACjB,OAAO,MAAM,CAAC;oBAClB,CAAC;gBACL,CAAC;gBAED,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,CAAC;gBAEzC,yBAAyB;gBACzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAExB,OAAO,KAAK,CAAC;YACjB,CAAC,CAAC;QACN,CAAC;QACD,WAAW,EAAE,CACT,QAA+C,EACjD,EAAE;YACA,OAAO,YAAY,CACf,QAAQ,EACR;gBACI,KAAK,EAAE;oBACH,GAAG,EAAE,GAAG,EAAE,CAAC,OAAO;iBACrB;gBACD,cAAc,EAAE;oBACZ,KAAK,EAAE,GAAG,EAAE;wBACR,OAAO,CAAC,WAAW,EAAE,CAAC;wBACtB,QAAQ,CAAC,KAAK,EAAE,CAAC;oBACrB,CAAC;iBACJ;gBACD,iBAAiB,EAAE;oBACf,KAAK,EAAE,CAAC,KAAQ,EAAE,EAAE;wBAChB,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;4BAChB,OAAO,CAAC,WAAW,EAAE,CAAC;wBAC1B,CAAC;6BAAM,CAAC;4BACJ,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;wBAC5B,CAAC;wBAED,OAAO,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;oBACvC,CAAC;iBACJ;aACJ,CACJ,CAAC;QACN,CAAC;KACJ,CAAC;AACN,CAAC"}
package/esm/lazy/lazy.js CHANGED
@@ -1,9 +1,14 @@
1
1
  import { tryDispose } from '../functions/disposer.js';
2
+ /**
3
+ * Synchronous lazy-loading container that initializes a value on first access.
4
+ * The value is cached until reset or expired. Supports custom disposal and cache expiration.
5
+ */
2
6
  export class Lazy {
3
7
  _factory;
4
8
  _instance = undefined;
5
9
  _expireTracker;
6
10
  _disposer;
11
+ _error = null;
7
12
  constructor(_factory) {
8
13
  this._factory = _factory;
9
14
  }
@@ -12,9 +17,8 @@ export class Lazy {
12
17
  this.ensureInstance();
13
18
  return this._instance;
14
19
  }
15
- get currentValue() {
16
- return this._instance;
17
- }
20
+ get currentValue() { return this._instance; }
21
+ get error() { return this._error; }
18
22
  /** Override me: additional way to make sure instance is valid */
19
23
  get isValid() {
20
24
  if (!this.hasValue) {
@@ -28,27 +32,22 @@ export class Lazy {
28
32
  }
29
33
  return true;
30
34
  }
35
+ /** Provides custom cleanup logic when the instance is reset or disposed. */
31
36
  withDisposer(disposer) {
32
37
  this._disposer = disposer;
33
38
  return this;
34
39
  }
40
+ /** Configures automatic cache expiration using an expire tracker. */
35
41
  withExpire(tracker) {
36
42
  this._expireTracker = tracker;
37
43
  return this;
38
44
  }
39
- ensureInstance() {
40
- if (this.isValid) {
41
- return;
42
- }
43
- // additional reset to make sure previous instance has been disposed
44
- this.reset();
45
- const res = this._factory();
46
- this.setInstance(res);
47
- }
45
+ /** Eagerly loads the value without accessing it. Useful for preloading. */
48
46
  prewarm() {
49
47
  this.ensureInstance();
50
48
  return this;
51
49
  }
50
+ /** Manually sets the cached value. */
52
51
  setInstance(instance) {
53
52
  this._instance = instance;
54
53
  if (this._instance !== undefined && this._expireTracker) {
@@ -65,7 +64,31 @@ export class Lazy {
65
64
  }
66
65
  }
67
66
  this.setInstance(undefined);
67
+ this._error = null;
68
68
  }
69
69
  dispose() { this.reset(); }
70
+ ensureInstance() {
71
+ if (this.isValid) {
72
+ return;
73
+ }
74
+ // additional reset to make sure previous instance has been disposed
75
+ this.reset();
76
+ try {
77
+ const res = this._factory();
78
+ this.setInstance(res);
79
+ }
80
+ catch (e) {
81
+ this._error = this.parseError(e);
82
+ }
83
+ }
84
+ parseError(err) {
85
+ if (typeof err === 'string') {
86
+ return err;
87
+ }
88
+ if (err instanceof Error) {
89
+ return err.message;
90
+ }
91
+ return String(err) || 'Unknown error';
92
+ }
70
93
  }
71
94
  //# sourceMappingURL=lazy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lazy.js","sourceRoot":"","sources":["../../../src/lazy/lazy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAoB,MAAM,0BAA0B,CAAC;AAKxE,MAAM,OAAO,IAAI;IAMkB;IAJrB,SAAS,GAAkB,SAAS,CAAC;IACvC,cAAc,CAA6B;IAC3C,SAAS,CAAqB;IAEtC,YAA+B,QAAmB;QAAnB,aAAQ,GAAR,QAAQ,CAAW;IAAI,CAAC;IAEvD,IAAI,QAAQ,KAAK,OAAO,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC;IAEvD,IAAI,KAAK;QACL,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC,SAAU,CAAC;IAC3B,CAAC;IAED,IAAI,YAAY;QACZ,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IAED,iEAAiE;IACjE,IAAc,OAAO;QACjB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjB,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,IAAI,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;gBAChC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACb,OAAO,KAAK,CAAC;YACjB,CAAC;QACL,CAAC;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;IAEM,YAAY,CAAC,QAA2B;QAC3C,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;QAC1B,OAAO,IAAI,CAAC;IAChB,CAAC;IAEM,UAAU,CAAC,OAAmC;QACjD,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC;QAC9B,OAAO,IAAI,CAAC;IAChB,CAAC;IAEO,cAAc;QAClB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,OAAO;QACX,CAAC;QAED,oEAAoE;QACpE,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO;QACH,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,WAAW,CAAC,QAAuB;QAC/B,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;QAE1B,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACtD,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;QAClC,CAAC;IACL,CAAC;IAED,KAAK;QACD,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAClC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;gBACjB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACnC,CAAC;iBAAM,CAAC;gBACJ,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC/B,CAAC;QACL,CAAC;QACD,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAChC,CAAC;IAED,OAAO,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;CAC9B"}
1
+ {"version":3,"file":"lazy.js","sourceRoot":"","sources":["../../../src/lazy/lazy.ts"],"names":[],"mappings":"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"}