11import { dynamicallyExecuteFunction } from './functions/helpers' ;
22import { ref , shallowRef , readonly } from 'vue' ;
3+ import type { Ref , ShallowRef } from 'vue' ;
34
45/**
56 * It takes a value and returns an object with a value property that is a shallowRef/ref of the value
@@ -10,73 +11,44 @@ import { ref, shallowRef, readonly } from 'vue';
1011 * @returns A function that returns an object with a shallow/deep reactive value, a subscriber and a
1112 * few extra methods.
1213 */
13- export function useSubscription < T > ( value : T , deep = false ) {
14+ export function useSubscription < T , D extends boolean = false > ( value : T , deep : D = false as D ) {
1415 if ( value === undefined ) {
1516 throw new Error ( 'No value provided, Initial value is required' ) ;
1617 }
1718
18- const _subRef = deep === false ? shallowRef ( value ) : ref ( value ) ;
19- type SubType = typeof _subRef . value ;
19+ type SubType = D extends false ? ShallowRef < T > : Ref < T > ;
20+ const _subRef = ( deep === false ? shallowRef ( value ) : ref ( value ) ) as SubType ;
21+ type SubValue = SubType [ 'value' ] ;
2022
2123 type Subscriber = ( val : SubType ) => Promise < void > | void ;
2224 const _subscriptions : Set < Subscriber > = new Set ( ) ;
23- /**
24- * Takes a function as an argument and adds it to the subscriber list.
25- * @param subscriber - Subscriber
26- */
27- function addSubscriber ( subscriber : Subscriber ) {
28- if ( typeof subscriber !== 'function' ) {
29- throw new Error ( 'Subscriber must be a function' ) ;
30- }
31- _subscriptions . add ( subscriber ) ;
32- }
33- /**
34- * It deletes an event/subscriber from the subscriptions list.
35- * @param subscriber - Subscriber
36- */
37- function deleteSubscriber ( subscriber : Subscriber ) {
38- _subscriptions . delete ( subscriber ) ;
39- }
4025 /**
4126 * It loops through the Set of subscribers and executes each function with the value passed in as
4227 * an argument
4328 * @param {SubType } val - The value that is being passed to the subscribers.
4429 */
45- function triggerSubscribers ( val : SubType ) {
30+ function triggerSubscribers ( val : SubValue ) {
4631 _subscriptions . forEach ( dep => dynamicallyExecuteFunction ( dep , val ) ) ;
4732 }
48- type ValueMutator = ( val : SubType ) => SubType ;
49- /**
50- * It mutates the $value - for complex types that are typeof object.
51- * @param mutator - (val: T) => T
52- */
53- async function mutateSubscriber ( mutator : ValueMutator ) {
54- if ( typeof mutator !== 'function' ) {
55- throw new Error ( 'Mutation must be a function' ) ;
56- }
57- _subRef . value = await dynamicallyExecuteFunction ( mutator , _subRef . value ) ;
58- triggerSubscribers ( _subRef . value ) ;
59- }
6033
61- function setValue ( val : SubType ) {
34+ function setValue ( val : T ) {
6235 _subRef . value = val ;
6336 triggerSubscribers ( val ) ;
6437 }
65-
6638 return {
67- get $value ( ) : SubType {
39+ get $value ( ) : SubValue {
6840 return _subRef . value ;
6941 } ,
70- set $value ( val ) {
42+ set $value ( val : T ) {
7143 setValue ( val ) ;
7244 } ,
7345
74- $get ( ) : SubType {
46+ $get ( ) : SubValue {
7547 return _subRef . value ;
7648 } ,
77- $set ( val : SubType | ValueMutator ) {
49+ $set < V extends SubValue | ( ( val : SubValue ) => SubValue ) > ( val : V ) {
7850 if ( typeof val === 'function' ) setValue ( val ( _subRef . value ) ) ;
79- else setValue ( val ) ;
51+ else setValue ( val as SubValue ) ;
8052 } ,
8153
8254 /** ReadOnly version of value. Wraps the ref in readonly */
@@ -87,31 +59,47 @@ export function useSubscription<T>(value: T, deep = false) {
8759 * @param subscriber - type Subscriber = (val: T) => Promise<void> | void;
8860 */
8961 $addSub ( subscriber : Subscriber ) {
90- addSubscriber ( subscriber ) ;
62+ if ( typeof subscriber !== 'function' ) {
63+ throw new Error ( 'Subscriber must be a function' ) ;
64+ }
65+ _subscriptions . add ( subscriber ) ;
9166 } ,
9267 /**
9368 * A method that allows you to delete a subscriber from the Set of subscribers.
9469 * @param subscriber - Subscriber
9570 */
9671 $deleteSub ( subscriber : Subscriber ) {
97- deleteSubscriber ( subscriber ) ;
72+ _subscriptions . delete ( subscriber ) ;
9873 } ,
9974 /**
10075 * Manually trigger subscribers. Shouldn't be used unless explicity needed (rarely).
10176 */
10277 $triggerSubs ( ) {
10378 triggerSubscribers ( _subRef . value ) ;
10479 } ,
80+ /**
81+ * Clears all subscribers. Easy for cleanup in beforeUnmount.
82+ */
83+ $clearSubs ( ) {
84+ _subscriptions . clear ( ) ;
85+ } ,
10586
10687 /**
10788 * It mutates the value of the object.
10889 * @param mutator - (val: T) => T
90+ * @param mutator - (val: T) => Promise<T>
10991 */
110- $mutate ( mutator : ValueMutator ) {
92+ async $mutate ( mutator : ( val : SubValue ) => SubValue | Promise < SubValue > ) {
11193 if ( typeof _subRef . value !== 'object' ) {
11294 throw new Error ( 'Value passed is not an typeof object! $mutate only accepts `typeof object`' ) ;
11395 }
114- mutateSubscriber ( mutator ) ;
96+ if ( typeof mutator !== 'function' ) {
97+ throw new Error ( 'Mutator must be a function' ) ;
98+ }
99+ _subRef . value = await dynamicallyExecuteFunction ( mutator , _subRef . value ) ;
100+ triggerSubscribers ( _subRef . value ) ;
101+
102+ return _subRef . value ;
115103 }
116104 } ;
117105}
0 commit comments