@zeix/cause-effect 0.11.0 → 0.12.1

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,127 @@
1
+ /* === Types === */
2
+
3
+ export type EnqueueDedupe = [Element, string]
4
+
5
+ export type Watcher = () => void
6
+ export type Updater = <T>() => T
7
+
8
+ /* === Internal === */
9
+
10
+ // Currently active watcher
11
+ let active: Watcher | undefined
12
+
13
+ // Pending queue for batched change notifications
14
+ const pending = new Set<Watcher>()
15
+ let batchDepth = 0
16
+
17
+ // Map of DOM elements to update functions
18
+ const updateMap = new Map<Element, Map<string, () => void>>()
19
+ let requestId: number | undefined
20
+
21
+ const updateDOM = () => {
22
+ requestId = undefined
23
+ for (const elementMap of updateMap.values()) {
24
+ for (const fn of elementMap.values()) {
25
+ fn()
26
+ }
27
+ elementMap.clear()
28
+ }
29
+ }
30
+
31
+ const requestTick = () => {
32
+ if (requestId) cancelAnimationFrame(requestId)
33
+ requestId = requestAnimationFrame(updateDOM)
34
+ }
35
+
36
+ // Initial render when the call stack is empty
37
+ queueMicrotask(updateDOM)
38
+
39
+ /* === Exported Functions === */
40
+
41
+ /**
42
+ * Add active watcher to the array of watchers
43
+ *
44
+ * @param {Watcher[]} watchers - watchers of the signal
45
+ */
46
+ export const subscribe = (watchers: Watcher[]) => {
47
+ // if (!active) console.warn('Calling .get() outside of a reactive context')
48
+ if (active && !watchers.includes(active)) {
49
+ watchers.push(active)
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Add watchers to the pending set of change notifications
55
+ *
56
+ * @param {Watcher[]} watchers - watchers of the signal
57
+ */
58
+ export const notify = (watchers: Watcher[]) => {
59
+ for (const mark of watchers) {
60
+ batchDepth ? pending.add(mark) : mark()
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Flush all pending changes to notify watchers
66
+ */
67
+ export const flush = () => {
68
+ while (pending.size) {
69
+ const watchers = Array.from(pending)
70
+ pending.clear()
71
+ for (const mark of watchers) {
72
+ mark()
73
+ }
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Batch multiple changes in a single signal graph and DOM update cycle
79
+ *
80
+ * @param {() => void} fn - function with multiple signal writes to be batched
81
+ */
82
+ export const batch = (fn: () => void) => {
83
+ batchDepth++
84
+ fn()
85
+ flush()
86
+ batchDepth--
87
+ }
88
+
89
+ /**
90
+ * Run a function in a reactive context
91
+ *
92
+ * @param {() => void} run - function to run the computation or effect
93
+ * @param {Watcher} mark - function to be called when the state changes
94
+ */
95
+ export const watch = (run: () => void, mark: Watcher): void => {
96
+ const prev = active
97
+ active = mark
98
+ run()
99
+ active = prev
100
+ }
101
+
102
+ /**
103
+ * Enqueue a function to be executed on the next animation frame
104
+ *
105
+ * @param callback
106
+ * @param dedupe
107
+ * @returns
108
+ */
109
+ export const enqueue = <T>(
110
+ update: Updater,
111
+ dedupe?: EnqueueDedupe
112
+ ) => new Promise<T>((resolve, reject) => {
113
+ const wrappedCallback = () => {
114
+ try {
115
+ resolve(update())
116
+ } catch (error) {
117
+ reject(error)
118
+ }
119
+ }
120
+ if (dedupe) {
121
+ const [el, op] = dedupe
122
+ if (!updateMap.has(el)) updateMap.set(el, new Map())
123
+ const elementMap = updateMap.get(el)!
124
+ elementMap.set(op, wrappedCallback)
125
+ }
126
+ requestTick()
127
+ })
package/lib/signal.d.ts CHANGED
@@ -1,9 +1,25 @@
1
1
  import { type State } from "./state";
2
2
  import { type Computed } from "./computed";
3
3
  type Signal<T extends {}> = State<T> | Computed<T>;
4
- type MaybeSignal<T extends {}> = State<T> | Computed<T> | T | ((old?: T) => T);
5
- type Watcher = () => void;
6
- export declare const UNSET: any;
4
+ type MaybeSignal<T extends {}> = Signal<T> | T | (() => T | Promise<T>);
5
+ type InferMaybeSignalType<T> = T extends Signal<infer U> ? U : T extends (() => infer U) ? U : T;
6
+ type OkCallback<T, U extends MaybeSignal<{}>[]> = (...values: {
7
+ [K in keyof U]: InferMaybeSignalType<U[K]>;
8
+ }) => T | Promise<T> | Error;
9
+ type NilCallback<T> = () => T | Promise<T> | Error;
10
+ type ErrCallback<T> = (...errors: Error[]) => T | Promise<T> | Error;
11
+ type ComputedCallbacks<T extends {}, U extends MaybeSignal<{}>[]> = OkCallback<T, U> | {
12
+ ok: OkCallback<T, U>;
13
+ nil?: NilCallback<T>;
14
+ err?: ErrCallback<T>;
15
+ };
16
+ type EffectCallbacks<U extends MaybeSignal<{}>[]> = OkCallback<void, U> | {
17
+ ok: OkCallback<void, U>;
18
+ nil?: NilCallback<void>;
19
+ err?: ErrCallback<void>;
20
+ };
21
+ type CallbackReturnType<T> = T | Promise<T> | Error | void;
22
+ declare const UNSET: any;
7
23
  /**
8
24
  * Check whether a value is a Signal or not
9
25
  *
@@ -20,30 +36,18 @@ declare const isSignal: <T extends {}>(value: any) => value is Signal<T>;
20
36
  * @param memo
21
37
  * @returns {Signal<T>} - converted Signal
22
38
  */
23
- declare const toSignal: <T extends {}>(value: MaybeSignal<T>) => Signal<T>;
39
+ declare const toSignal: <T extends {}>(value: MaybeSignal<T> | ComputedCallbacks<T, []>) => Signal<T>;
24
40
  /**
25
- * Add notify function of active watchers to the set of watchers
41
+ * Resolve signals or functions using signals and apply callbacks based on the results
26
42
  *
27
- * @param {Watcher[]} watchers - set of current watchers
43
+ * @since 0.12.0
44
+ * @param {U} maybeSignals - dependency signals (or functions using signals)
45
+ * @param {Record<string, (...args) => CallbackReturnType<T>} cb - object of ok, nil, err callbacks or just ok callback
46
+ * @returns {CallbackReturnType<T>} - result of chosen callback
28
47
  */
29
- declare const subscribe: (watchers: Watcher[]) => void;
30
- /**
31
- * Notify all subscribers of the state change or add to the pending set if batching is enabled
32
- *
33
- * @param {Watcher[]} watchers
34
- */
35
- declare const notify: (watchers: Watcher[]) => void;
36
- /**
37
- * Run a function in a reactive context
38
- *
39
- * @param {() => void} run - function to run the computation or effect
40
- * @param {Watcher} mark - function to be called when the state changes
41
- */
42
- declare const watch: (run: () => void, mark: Watcher) => void;
43
- /**
44
- * Batch multiple state changes into a single update
45
- *
46
- * @param {() => void} run - function to run the batch of state changes
47
- */
48
- declare const batch: (run: () => void) => void;
49
- export { type Signal, type MaybeSignal, type Watcher, isSignal, toSignal, subscribe, notify, watch, batch };
48
+ declare const resolve: <T, U extends MaybeSignal<{}>[]>(maybeSignals: U, cb: OkCallback<T | Promise<T>, U> | {
49
+ ok: OkCallback<T | Promise<T>, U>;
50
+ nil?: NilCallback<T>;
51
+ err?: ErrCallback<T>;
52
+ }) => CallbackReturnType<T>;
53
+ export { type Signal, type MaybeSignal, type InferMaybeSignalType, type EffectCallbacks, type ComputedCallbacks, type CallbackReturnType, UNSET, isSignal, toSignal, resolve, };
package/lib/signal.ts CHANGED
@@ -1,44 +1,44 @@
1
1
  import { type State, isState, state } from "./state"
2
- import { computed, type Computed, isComputed } from "./computed"
3
- import { isComputeFunction } from "./util"
2
+ import { type Computed, computed, isComputed } from "./computed"
3
+ import { isFunction, toError } from "./util"
4
4
 
5
5
  /* === Types === */
6
6
 
7
7
  type Signal<T extends {}> = State<T> | Computed<T>
8
+ type MaybeSignal<T extends {}> = Signal<T> | T | (() => T | Promise<T>)
9
+ type InferMaybeSignalType<T> = T extends Signal<infer U> ? U :
10
+ T extends (() => infer U) ? U :
11
+ T
12
+
13
+ type OkCallback<T, U extends MaybeSignal<{}>[]> = (...values: {
14
+ [K in keyof U]: InferMaybeSignalType<U[K]>
15
+ }) => T | Promise<T> | Error
16
+ type NilCallback<T> = () => T | Promise<T> | Error
17
+ type ErrCallback<T> = (...errors: Error[]) => T | Promise<T> | Error
18
+
19
+ type ComputedCallbacks<T extends {}, U extends MaybeSignal<{}>[]> = OkCallback<T, U> | {
20
+ ok: OkCallback<T, U>,
21
+ nil?: NilCallback<T>,
22
+ err?: ErrCallback<T>
23
+ }
8
24
 
9
- type MaybeSignal<T extends {}> = State<T> | Computed<T> | T | ((old?: T) => T)
10
-
11
- type Watcher = () => void
12
-
13
- /* === Internals === */
14
-
15
- // Currently active watcher
16
- let active: () => void | undefined
17
-
18
- // Batching state
19
- let batchDepth = 0
25
+ type EffectCallbacks<U extends MaybeSignal<{}>[]> = OkCallback<void, U> | {
26
+ ok: OkCallback<void, U>,
27
+ nil?: NilCallback<void>,
28
+ err?: ErrCallback<void>
29
+ }
20
30
 
21
- // Pending notifications
22
- const markQueue: Set<Watcher> = new Set()
31
+ type CallbackReturnType<T> = T | Promise<T> | Error | void
23
32
 
24
- // Pending runs
25
- const runQueue: Set<() => void> = new Set()
33
+ /* === Constants === */
26
34
 
27
- /**
28
- * Flush pending notifications and runs
29
- */
30
- const flush = () => {
31
- while (markQueue.size || runQueue.size) {
32
- markQueue.forEach(mark => mark())
33
- markQueue.clear()
34
- runQueue.forEach(run => run())
35
- runQueue.clear()
36
- }
37
- }
35
+ const UNSET: any = Symbol()
38
36
 
39
- /* === Constants === */
37
+ /* === Private Functions === */
40
38
 
41
- export const UNSET: any = Symbol()
39
+ const isComputedCallbacks = /*#__PURE__*/ <T extends {}>(value: unknown): value is ComputedCallbacks<T, []> =>
40
+ (isFunction(value) && !value.length)
41
+ || (typeof value === 'object' && value !== null && 'ok' in value && isFunction(value.ok))
42
42
 
43
43
  /* === Exported Functions === */
44
44
 
@@ -61,56 +61,67 @@ const isSignal = /*#__PURE__*/ <T extends {}>(value: any): value is Signal<T> =>
61
61
  * @returns {Signal<T>} - converted Signal
62
62
  */
63
63
  const toSignal = /*#__PURE__*/ <T extends {}>(
64
- value: MaybeSignal<T>
64
+ value: MaybeSignal<T> | ComputedCallbacks<T, []>
65
65
  ): Signal<T> =>
66
66
  isSignal<T>(value) ? value
67
- : isComputeFunction<T>(value) ? computed(value)
68
- : state(value)
69
-
70
- /**
71
- * Add notify function of active watchers to the set of watchers
72
- *
73
- * @param {Watcher[]} watchers - set of current watchers
74
- */
75
- const subscribe = (watchers: Watcher[]) => {
76
- if (active && !watchers.includes(active)) watchers.push(active)
77
- }
78
-
79
- /**
80
- * Notify all subscribers of the state change or add to the pending set if batching is enabled
81
- *
82
- * @param {Watcher[]} watchers
83
- */
84
- const notify = (watchers: Watcher[]) => {
85
- watchers.forEach(mark => batchDepth ? markQueue.add(mark) : mark())
86
- }
67
+ : isComputedCallbacks<T>(value) ? computed(value)
68
+ : state(value as T)
87
69
 
88
- /**
89
- * Run a function in a reactive context
90
- *
91
- * @param {() => void} run - function to run the computation or effect
92
- * @param {Watcher} mark - function to be called when the state changes
93
- */
94
- const watch = (run: () => void, mark: Watcher): void => {
95
- const prev = active
96
- active = mark
97
- run()
98
- active = prev
99
- }
100
70
 
101
71
  /**
102
- * Batch multiple state changes into a single update
72
+ * Resolve signals or functions using signals and apply callbacks based on the results
103
73
  *
104
- * @param {() => void} run - function to run the batch of state changes
74
+ * @since 0.12.0
75
+ * @param {U} maybeSignals - dependency signals (or functions using signals)
76
+ * @param {Record<string, (...args) => CallbackReturnType<T>} cb - object of ok, nil, err callbacks or just ok callback
77
+ * @returns {CallbackReturnType<T>} - result of chosen callback
105
78
  */
106
- const batch = (run: () => void): void => {
107
- batchDepth++
108
- run()
109
- batchDepth--
110
- if (!batchDepth) flush()
79
+ const resolve = <T, U extends MaybeSignal<{}>[]>(
80
+ maybeSignals: U,
81
+ cb: OkCallback<T | Promise<T>, U> | {
82
+ ok: OkCallback<T | Promise<T>, U>
83
+ nil?: NilCallback<T>
84
+ err?: ErrCallback<T>
85
+ }
86
+ ): CallbackReturnType<T> => {
87
+ const { ok, nil, err } = isFunction(cb)
88
+ ? { ok: cb }
89
+ : cb as {
90
+ ok: OkCallback<T | Promise<T>, U>
91
+ nil?: NilCallback<T>
92
+ err?: ErrCallback<T>
93
+ }
94
+ const values = [] as {
95
+ [K in keyof U]: InferMaybeSignalType<U[K]>
96
+ }
97
+ const errors: Error[] = []
98
+ let hasUnset = false
99
+
100
+ for (let i = 0; i < maybeSignals.length; i++) {
101
+ const s = maybeSignals[i]
102
+ try {
103
+ const value = isSignal(s) ? s.get() : isFunction(s) ? s() : s
104
+ if (value === UNSET) hasUnset = true
105
+ values[i] = value as InferMaybeSignalType<typeof s>
106
+ } catch (e) {
107
+ errors.push(toError(e))
108
+ }
109
+ }
110
+
111
+ let result: CallbackReturnType<T> = undefined
112
+ try {
113
+ if (hasUnset && nil) result = nil()
114
+ else if (errors.length) result = err ? err(...errors) : errors[0]
115
+ else if (!hasUnset) result = ok(...values) as CallbackReturnType<T>
116
+ } catch (e) {
117
+ result = toError(e)
118
+ if (err) result = err(result)
119
+ }
120
+ return result
111
121
  }
112
122
 
113
123
  export {
114
- type Signal, type MaybeSignal, type Watcher,
115
- isSignal, toSignal, subscribe, notify, watch, batch
124
+ type Signal, type MaybeSignal, type InferMaybeSignalType,
125
+ type EffectCallbacks, type ComputedCallbacks, type CallbackReturnType,
126
+ UNSET, isSignal, toSignal, resolve,
116
127
  }
package/lib/state.d.ts CHANGED
@@ -1,58 +1,21 @@
1
- import { type Computed } from "./computed";
2
- /**
3
- * Define a reactive state
4
- *
5
- * @since 0.9.0
6
- * @class State
7
- */
8
- export declare class State<T extends {}> {
9
- private value;
10
- private watchers;
11
- constructor(value: T);
12
- /**
13
- * Get the current value of the state
14
- *
15
- * @since 0.9.0
16
- * @method of State<T>
17
- * @returns {T} - current value of the state
18
- */
1
+ import { type ComputedCallbacks, type EffectCallbacks } from './signal';
2
+ import { type Computed } from './computed';
3
+ export type State<T extends {}> = {
4
+ [Symbol.toStringTag]: 'State';
19
5
  get(): T;
20
- /**
21
- * Set a new value of the state
22
- *
23
- * @since 0.9.0
24
- * @method of State<T>
25
- * @param {T} value
26
- * @returns {void}
27
- */
28
- set(value: T): void;
29
- /**
30
- * Update the state with a new value using a function
31
- *
32
- * @since 0.10.0
33
- * @method of State<T>
34
- * @param {(value: T) => T} fn
35
- * @returns {void} - updates the state with the result of the function
36
- */
37
- update(fn: (value: T) => T): void;
38
- /**
39
- * Create a derived state from an existing state
40
- *
41
- * @since 0.9.0
42
- * @method of State<T>
43
- * @param {(value: T) => U} fn
44
- * @returns {Computed<U>} - derived state
45
- */
46
- map<U extends {}>(fn: (value: T) => U): Computed<U>;
47
- }
6
+ set(v: T): void;
7
+ update(fn: (v: T) => T): void;
8
+ map<U extends {}>(cb: ComputedCallbacks<U, [State<T>]>): Computed<U>;
9
+ match: (cb: EffectCallbacks<[State<T>]>) => void;
10
+ };
48
11
  /**
49
12
  * Create a new state signal
50
13
  *
51
14
  * @since 0.9.0
52
- * @param {T} value - initial value of the state
15
+ * @param {T} initialValue - initial value of the state
53
16
  * @returns {State<T>} - new state signal
54
17
  */
55
- export declare const state: <T extends {}>(value: T) => State<T>;
18
+ export declare const state: <T extends {}>(initialValue: T) => State<T>;
56
19
  /**
57
20
  * Check if the provided value is a State instance
58
21
  *
package/lib/state.ts CHANGED
@@ -1,84 +1,104 @@
1
- import { type Watcher, subscribe, notify, UNSET } from "./signal"
2
- import { type Computed, computed } from "./computed"
1
+ import { UNSET, type ComputedCallbacks, type EffectCallbacks } from './signal'
2
+ import { type Computed, computed } from './computed'
3
+ import { isObjectOfType } from './util';
4
+ import { type Watcher, notify, subscribe } from './scheduler'
5
+ import { effect } from './effect';
3
6
 
4
- /* === Class State === */
7
+ /* === Types === */
8
+
9
+ export type State<T extends {}> = {
10
+ [Symbol.toStringTag]: 'State';
11
+ get(): T;
12
+ set(v: T): void;
13
+ update(fn: (v: T) => T): void;
14
+ map<U extends {}>(cb: ComputedCallbacks<U, [State<T>]>): Computed<U>;
15
+ match: (cb: EffectCallbacks<[State<T>]>) => void
16
+ }
17
+
18
+ /* === Constants === */
19
+
20
+ const TYPE_STATE = 'State'
21
+
22
+ /* === State Factory === */
5
23
 
6
24
  /**
7
- * Define a reactive state
25
+ * Create a new state signal
8
26
  *
9
27
  * @since 0.9.0
10
- * @class State
28
+ * @param {T} initialValue - initial value of the state
29
+ * @returns {State<T>} - new state signal
11
30
  */
12
- export class State<T extends {}> {
13
- private watchers: Watcher[] = []
31
+ export const state = /*#__PURE__*/ <T extends {}>(initialValue: T): State<T> => {
32
+ const watchers: Watcher[] = []
33
+ let value: T = initialValue
14
34
 
15
- constructor(private value: T) {}
35
+ const s: State<T> = {
36
+ [Symbol.toStringTag]: TYPE_STATE,
16
37
 
17
- /**
18
- * Get the current value of the state
19
- *
20
- * @since 0.9.0
21
- * @method of State<T>
22
- * @returns {T} - current value of the state
23
- */
24
- get(): T {
25
- subscribe(this.watchers)
26
- return this.value
27
- }
38
+ /**
39
+ * Get the current value of the state
40
+ *
41
+ * @since 0.9.0
42
+ * @returns {T} - current value of the state
43
+ */
44
+ get: (): T => {
45
+ subscribe(watchers)
46
+ return value
47
+ },
28
48
 
29
- /**
30
- * Set a new value of the state
31
- *
32
- * @since 0.9.0
33
- * @method of State<T>
34
- * @param {T} value
35
- * @returns {void}
36
- */
37
- set(value: T): void {
38
- if (Object.is(this.value, value)) return
39
- this.value = value
40
- notify(this.watchers)
49
+ /**
50
+ * Set a new value of the state
51
+ *
52
+ * @since 0.9.0
53
+ * @param {T} v
54
+ * @returns {void}
55
+ */
56
+ set: (v: T): void => {
57
+ if (Object.is(value, v)) return
58
+ value = v
59
+ notify(watchers)
41
60
 
42
- // Setting to UNSET clears the watchers so the signal can be garbage collected
43
- if (UNSET === value) this.watchers = []
44
- }
61
+ // Setting to UNSET clears the watchers so the signal can be garbage collected
62
+ if (UNSET === value) watchers.length = 0 // head = tail = undefined
63
+ },
45
64
 
46
- /**
47
- * Update the state with a new value using a function
48
- *
49
- * @since 0.10.0
50
- * @method of State<T>
51
- * @param {(value: T) => T} fn
52
- * @returns {void} - updates the state with the result of the function
53
- */
54
- update(fn: (value: T) => T): void {
55
- this.set(fn(this.value))
56
- }
65
+ /**
66
+ * Update the state with a new value using a function
67
+ *
68
+ * @since 0.10.0
69
+ * @param {(v: T) => T} fn - function to update the state
70
+ * @returns {void} - updates the state with the result of the function
71
+ */
72
+ update: (fn: (v: T) => T): void => {
73
+ s.set(fn(value))
74
+ },
57
75
 
58
- /**
59
- * Create a derived state from an existing state
60
- *
61
- * @since 0.9.0
62
- * @method of State<T>
63
- * @param {(value: T) => U} fn
64
- * @returns {Computed<U>} - derived state
65
- */
66
- map<U extends {}>(fn: (value: T) => U): Computed<U> {
67
- return computed<U>(() => fn(this.get()))
68
- }
69
- }
76
+ /**
77
+ * Create a computed signal from the current state signal
78
+ *
79
+ * @since 0.9.0
80
+ * @param {ComputedCallbacks<U, [State<T>]>} cb - compute callback or object of ok, nil, err callbacks to map this value to new computed
81
+ * @returns {Computed<U>} - computed signal
82
+ */
83
+ map: <U extends {}>(cb: ComputedCallbacks<U, [State<T>]>): Computed<U> =>
84
+ computed(cb, s),
70
85
 
71
- /* === Helper Functions === */
86
+ /**
87
+ * Case matching for the state signal with effect callbacks
88
+ *
89
+ * @since 0.12.0
90
+ * @method of State<T>
91
+ * @param {EffectCallbacks<[State<T>]>} cb - effect callback or object of ok, nil, err callbacks to be executed when the state changes
92
+ * @returns {State<T>} - self, for chaining effect callbacks
93
+ */
94
+ match: (cb: EffectCallbacks<[State<T>]>): State<T> => {
95
+ effect(cb, s)
96
+ return s
97
+ }
98
+ }
72
99
 
73
- /**
74
- * Create a new state signal
75
- *
76
- * @since 0.9.0
77
- * @param {T} value - initial value of the state
78
- * @returns {State<T>} - new state signal
79
- */
80
- export const state = /*#__PURE__*/ <T extends {}>(value: T): State<T> =>
81
- new State(value)
100
+ return s
101
+ }
82
102
 
83
103
  /**
84
104
  * Check if the provided value is a State instance
@@ -88,4 +108,4 @@ export const state = /*#__PURE__*/ <T extends {}>(value: T): State<T> =>
88
108
  * @returns {boolean} - true if the value is a State instance, false otherwise
89
109
  */
90
110
  export const isState = /*#__PURE__*/ <T extends {}>(value: unknown): value is State<T> =>
91
- value instanceof State
111
+ isObjectOfType(value, TYPE_STATE)
package/lib/util.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  declare const isFunction: <T>(value: unknown) => value is (...args: unknown[]) => T;
2
2
  declare const isAsyncFunction: <T>(value: unknown) => value is (...args: unknown[]) => Promise<T> | PromiseLike<T>;
3
- declare const isComputeFunction: <T>(value: unknown) => value is ((old?: T) => T);
3
+ declare const isObjectOfType: <T>(value: unknown, type: string) => value is T;
4
4
  declare const isInstanceOf: <T>(type: new (...args: any[]) => T) => (value: unknown) => value is T;
5
5
  declare const isError: (value: unknown) => value is Error;
6
6
  declare const isPromise: (value: unknown) => value is Promise<unknown>;
7
7
  declare const toError: (value: unknown) => Error;
8
- export { isFunction, isAsyncFunction, isComputeFunction, isInstanceOf, isError, isPromise, toError };
8
+ export { isFunction, isAsyncFunction, isObjectOfType, isInstanceOf, isError, isPromise, toError };
package/lib/util.ts CHANGED
@@ -6,8 +6,8 @@ const isFunction = /*#__PURE__*/ <T>(value: unknown): value is (...args: unknown
6
6
  const isAsyncFunction = /*#__PURE__*/ <T>(value: unknown): value is (...args: unknown[]) => Promise<T> | PromiseLike<T> =>
7
7
  isFunction(value) && /^async\s+/.test(value.toString())
8
8
 
9
- const isComputeFunction = /*#__PURE__*/ <T>(value: unknown): value is ((old?: T) => T) =>
10
- isFunction(value) && value.length < 2
9
+ const isObjectOfType = /*#__PURE__*/ <T>(value: unknown, type: string): value is T =>
10
+ Object.prototype.toString.call(value) === `[object ${type}]`
11
11
 
12
12
  const isInstanceOf = /*#__PURE__*/ <T>(type: new (...args: any[]) => T) =>
13
13
  (value: unknown): value is T =>
@@ -20,6 +20,6 @@ const toError = (value: unknown): Error =>
20
20
  isError(value) ? value : new Error(String(value))
21
21
 
22
22
  export {
23
- isFunction, isAsyncFunction, isComputeFunction,
24
- isInstanceOf, isError, isPromise, toError
23
+ isFunction, isAsyncFunction,
24
+ isObjectOfType, isInstanceOf, isError, isPromise, toError
25
25
  }
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@zeix/cause-effect",
3
- "version": "0.11.0",
3
+ "version": "0.12.1",
4
4
  "author": "Esther Brunner",
5
5
  "main": "index.js",
6
6
  "module": "index.ts",
7
7
  "devDependencies": {
8
- "@types/bun": "latest"
8
+ "@types/bun": "latest",
9
+ "random": "^5.3.0"
9
10
  },
10
11
  "peerDependencies": {
11
12
  "typescript": "^5.6.3"