@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.
- package/cjs/lazy/extensions.js +48 -0
- package/cjs/lazy/extensions.js.map +1 -0
- package/cjs/lazy/lazy.js +35 -12
- package/cjs/lazy/lazy.js.map +1 -1
- package/cjs/lazy/light.js +11 -1
- package/cjs/lazy/light.js.map +1 -1
- package/cjs/lazy/promise.js +165 -25
- package/cjs/lazy/promise.js.map +1 -1
- package/cjs/lazy/types.js +0 -2
- package/cjs/lazy/types.js.map +1 -1
- package/cjs/structures/extendObject.js +8 -0
- package/cjs/structures/extendObject.js.map +1 -0
- package/esm/lazy/extensions.js +45 -0
- package/esm/lazy/extensions.js.map +1 -0
- package/esm/lazy/lazy.js +35 -12
- package/esm/lazy/lazy.js.map +1 -1
- package/esm/lazy/light.js +11 -1
- package/esm/lazy/light.js.map +1 -1
- package/esm/lazy/promise.js +165 -25
- package/esm/lazy/promise.js.map +1 -1
- package/esm/lazy/types.js +0 -2
- package/esm/lazy/types.js.map +1 -1
- package/esm/structures/extendObject.js +5 -0
- package/esm/structures/extendObject.js.map +1 -0
- package/package.json +1 -1
- package/tsconfig.cjs.tsbuildinfo +1 -1
- package/tsconfig.esm.tsbuildinfo +1 -1
- package/tsconfig.types.tsbuildinfo +1 -1
- package/types/lazy/extensions.d.ts +10 -0
- package/types/lazy/lazy.d.ts +13 -2
- package/types/lazy/promise.d.ts +71 -11
- package/types/lazy/types.d.ts +111 -8
- package/types/structures/extendObject.d.ts +13 -0
package/types/lazy/types.d.ts
CHANGED
|
@@ -1,16 +1,119 @@
|
|
|
1
|
-
|
|
1
|
+
import type { IResettableModel } from '../models/types.js';
|
|
2
|
+
/** Represents a lazily loaded value that initializes on first access. */
|
|
2
3
|
export interface ILazy<T> {
|
|
3
|
-
/** Returns current value
|
|
4
|
+
/** Returns current value, triggering loading if not yet loaded. */
|
|
4
5
|
readonly value: T;
|
|
5
|
-
/** Returns
|
|
6
|
+
/** Returns true if value has been loaded. Does not trigger loading. */
|
|
6
7
|
readonly hasValue: boolean;
|
|
7
|
-
/** Returns current value or undefined if not
|
|
8
|
+
/** Returns current value or undefined if not loaded. Does not trigger loading. */
|
|
8
9
|
readonly currentValue: T | undefined;
|
|
10
|
+
/** Returns error message if loading failed, null otherwise. Does not trigger loading. */
|
|
11
|
+
readonly error: string | null;
|
|
9
12
|
}
|
|
10
|
-
/** Represents a lazily asynchronously loaded value. */
|
|
11
|
-
export interface ILazyPromise<T> extends ILazy<T> {
|
|
12
|
-
/**
|
|
13
|
+
/** Represents a lazily asynchronously loaded value with promise-based access. */
|
|
14
|
+
export interface ILazyPromise<T, TInitial extends T | undefined = undefined> extends ILazy<T | TInitial> {
|
|
15
|
+
/**
|
|
16
|
+
* Returns loading state: true (loading), false (loaded), null (not started).
|
|
17
|
+
* Does not trigger loading.
|
|
18
|
+
*/
|
|
13
19
|
readonly isLoading: boolean | null;
|
|
14
|
-
/** Returns the promise for the
|
|
20
|
+
/** Returns the promise for the value, triggering loading if not started. */
|
|
15
21
|
readonly promise: Promise<T>;
|
|
22
|
+
/**
|
|
23
|
+
* Re-executes the factory to get fresh data. If concurrent refreshes occur, the latest wins.
|
|
24
|
+
* All awaiting promises will resolve to the final refreshed value.
|
|
25
|
+
*
|
|
26
|
+
* **⚠️ Use sparingly:** Only refresh when explicitly needed for fresh data.
|
|
27
|
+
* Over-use defeats lazy loading and caching benefits.
|
|
28
|
+
*
|
|
29
|
+
* **Valid use cases:**
|
|
30
|
+
* - User-initiated refresh (pull-to-refresh, refresh button)
|
|
31
|
+
* - Cache invalidation after mutation
|
|
32
|
+
* - Time-based refresh with throttling
|
|
33
|
+
* - Error recovery
|
|
34
|
+
*
|
|
35
|
+
* **Avoid:**
|
|
36
|
+
* - Refreshing on every render/mount
|
|
37
|
+
* - Using instead of cache expiration (use `withExpire`)
|
|
38
|
+
* - Calling in loops or high-frequency events without debouncing
|
|
39
|
+
*
|
|
40
|
+
* @returns Promise resolving to the refreshed value
|
|
41
|
+
*/
|
|
42
|
+
refresh(): Promise<T>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Controllable lazy promise with manual state management.
|
|
46
|
+
* Extends ILazyPromise with methods to manually set values and reset state.
|
|
47
|
+
*/
|
|
48
|
+
export interface IControllableLazyPromise<T, TInitial extends T | undefined = undefined> extends ILazyPromise<T, TInitial>, IResettableModel {
|
|
49
|
+
/**
|
|
50
|
+
* Manually sets the value and marks loading as complete.
|
|
51
|
+
* Useful for cache synchronization and manual state updates.
|
|
52
|
+
*
|
|
53
|
+
* @param value - The value to set
|
|
54
|
+
* @returns The value that was set
|
|
55
|
+
*/
|
|
56
|
+
setInstance(value: T): T;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Factory function that retrieves the value for LazyPromise.
|
|
60
|
+
*
|
|
61
|
+
* @param refreshing - True when called via refresh(), false on initial load
|
|
62
|
+
*/
|
|
63
|
+
export type LazyFactory<T> = (refreshing?: boolean) => Promise<T>;
|
|
64
|
+
/**
|
|
65
|
+
* Extension for LazyPromise instances, enabling factory wrapping and instance augmentation.
|
|
66
|
+
*
|
|
67
|
+
* @template T - Value type the extension is compatible with (use `any` for universal extensions)
|
|
68
|
+
* @template TExtShape - Additional properties/methods added to the instance
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* // Universal logging extension
|
|
73
|
+
* const loggingExtension: ILazyPromiseExtension<any> = {
|
|
74
|
+
* overrideFactory: (original) => async (refreshing) => {
|
|
75
|
+
* console.log('Loading...');
|
|
76
|
+
* return await original(refreshing);
|
|
77
|
+
* }
|
|
78
|
+
* };
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export interface ILazyPromiseExtension<T = any, TExtShape extends object = object> {
|
|
82
|
+
/**
|
|
83
|
+
* Augment the instance with additional properties/methods.
|
|
84
|
+
* Receives IControllableLazyPromise with setInstance() and reset() for manual control.
|
|
85
|
+
*
|
|
86
|
+
* @param previous - The controllable LazyPromise instance
|
|
87
|
+
* @returns The instance with additional shape
|
|
88
|
+
*/
|
|
89
|
+
extendShape?: <TInitial extends T | undefined = undefined>(previous: IControllableLazyPromise<T, TInitial>) => IControllableLazyPromise<T, TInitial> & TExtShape;
|
|
90
|
+
/**
|
|
91
|
+
* Wrap or replace the factory function.
|
|
92
|
+
*
|
|
93
|
+
* @param original - The original factory function
|
|
94
|
+
* @param target - The LazyPromise instance being extended
|
|
95
|
+
* @returns A new factory function
|
|
96
|
+
*/
|
|
97
|
+
overrideFactory?: <TInitial extends T | undefined = undefined>(original: LazyFactory<T>, target: ILazyPromise<T, TInitial> & TExtShape) => LazyFactory<T>;
|
|
98
|
+
/**
|
|
99
|
+
* Cleanup function called when the LazyPromise is disposed.
|
|
100
|
+
* Use for cleaning up resources (timers, subscriptions, listeners).
|
|
101
|
+
* Executes in reverse order: newest extension first, oldest last.
|
|
102
|
+
*
|
|
103
|
+
* @param instance - The extended LazyPromise instance being disposed
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```typescript
|
|
107
|
+
* const intervalExtension: ILazyPromiseExtension<any, { stopTimer: () => void }> = {
|
|
108
|
+
* extendShape: (instance) => {
|
|
109
|
+
* let intervalId: NodeJS.Timeout | null = null;
|
|
110
|
+
* return Object.assign(instance, {
|
|
111
|
+
* stopTimer: () => { if (intervalId) clearInterval(intervalId); }
|
|
112
|
+
* });
|
|
113
|
+
* },
|
|
114
|
+
* dispose: (instance) => instance.stopTimer()
|
|
115
|
+
* };
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
dispose?: (instance: ILazyPromise<T, any> & TExtShape) => void;
|
|
16
119
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type BasePropertyDescriptor = Pick<PropertyDescriptor, 'configurable' | 'enumerable' | 'writable'>;
|
|
2
|
+
type PropertyDescriptorTyped<T> = BasePropertyDescriptor & ({
|
|
3
|
+
value: T;
|
|
4
|
+
} | {
|
|
5
|
+
get: () => T;
|
|
6
|
+
set?: (value: T) => void;
|
|
7
|
+
});
|
|
8
|
+
type ExtensionMap<T extends object> = {
|
|
9
|
+
[K in keyof T]: PropertyDescriptorTyped<T[K]>;
|
|
10
|
+
};
|
|
11
|
+
/** Type-safe version of `Object.defineProperties` */
|
|
12
|
+
export declare function extendObject<T extends object, TExtension extends object>(base: T, extensionDescriptorsMap: ExtensionMap<TExtension>): T & TExtension;
|
|
13
|
+
export {};
|