Skip to content

Commit 422ceca

Browse files
authored
Merge pull request #14 from srav001/1.0.2
1.0.2
2 parents 754fb62 + cc6ff51 commit 422ceca

File tree

7 files changed

+40
-52
lines changed

7 files changed

+40
-52
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Find it on `npm` - https://www.npmjs.com/package/vue-subscription.
1515

1616
## Introduction
1717

18-
Only 1.26 kB or gzip: 0.63 kB in size, the [useSubscription](#tldr) composable takes an initial value and returns an object with a reactive value that is by default shallow and only deep when explicitly enabled. The value property, `$value is not automatically unwrapped in template`. Additionally, it also provides `explicit getter and setter` if you like more control over the state.
18+
Only 1.3 kB or gzip: 0.7 kB in size, the [useSubscription](#tldr) composable takes an initial value and returns an object with a reactive value that is by default shallow and only deep when explicitly enabled. The value property, `$value is not automatically unwrapped in template`. Additionally, it also provides `explicit getter and setter` if you like more control over the state.
1919

2020
The package also provides a simple way to create reactive subscriptions that can be used to observe changes to a value and execute a list of subscribers when the value changes. It also includes methods to mutate the value for complex objects and trigger subscribers manually if and when needed rarely. Check out the [usage](#usage) examples.
2121

demo/ChildComp.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { useNotifier } from './composables/notifier';
44
const notifier = useNotifier();
55
function incrementer() {
66
notifier.$emit(val => val + 1);
7-
// or notifier.$emit(notifier.$state.value + 1);
87
}
98
</script>
109

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vue-subscription",
3-
"version": "1.0.1",
3+
"version": "1.0.2",
44
"description": "A type-safe 🔥 & tiny ⭐️ super-charged ref ⚡️ / eventBus replacement in Vue 💚.",
55
"keywords": [
66
"web",

scripts/release/releaseData.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"onGoing": false,
3-
"version": "1.0.1"
3+
"version": "1.0.2"
44
}

src/functions/helpers.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
* @returns A promise that resolves to the result of the function.
77
*/
88
// eslint-disable-next-line @typescript-eslint/ban-types
9-
export async function dynamicallyExecuteFunction<T>(func: Function, arg: T) {
9+
export async function dynamicallyExecuteFunction<T = unknown>(func: Function, arg: unknown) {
1010
try {
1111
const result = func(arg);
1212
if (result instanceof Promise) {
13-
return await result;
13+
return (await result) as T;
1414
} else {
15-
return result;
15+
return result as T;
1616
}
1717
} catch (err) {
1818
throw new Error('Function failed to run', { cause: err });

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export { useSubscription } from './subscription';
2+
export { dynamicallyExecuteFunction } from './functions/helpers';

src/subscription.ts

Lines changed: 33 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { dynamicallyExecuteFunction } from './functions/helpers';
22
import { 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

21-
type Subscriber = (val: SubType) => Promise<void> | void;
23+
type Subscriber = (val: SubValue) => 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

Comments
 (0)