muya 2.0.4 → 2.0.6

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/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var g=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var z=Object.prototype.hasOwnProperty;var H=(e,t)=>{for(var r in t)g(e,r,{get:t[r],enumerable:!0})},M=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of L(t))!z.call(e,o)&&o!==r&&g(e,o,{get:()=>t[o],enumerable:!(n=R(t,o))||n.enumerable});return e};var j=e=>M(g({},"__esModule",{value:!0}),e);var Y={};H(Y,{EMPTY_SELECTOR:()=>k,create:()=>U,select:()=>h,shallow:()=>q,useValue:()=>x});module.exports=j(Y);var k=e=>e;function d(e){return e instanceof Promise}function C(e){return typeof e=="function"}function V(e){return e instanceof Map}function P(e){return e instanceof Set}function O(e){return Array.isArray(e)}function p(e,t){return e===t?!0:!!Object.is(e,t)}function I(e){return typeof e=="function"}function v(e){return e instanceof T}function A(e){return e instanceof Error}function f(e){return e===void 0}var T=class extends Error{static Error="AbortError"};function N(e,t){t&&t.abort();let r=new AbortController,{signal:n}=r;return{promise:new Promise((i,s)=>{n.addEventListener("abort",()=>{s(new T)}),e.then(i).catch(s)}),controller:r}}function b(e,t=p){if(!f(e.current)){if(!f(e.previous)&&t(e.current,e.previous))return!1;e.previous=e.current}return!0}function m(e,t,r){if(!d(r))return r;e.abortController&&e.abortController.abort();let{promise:n,controller:o}=N(r,e.abortController);return e.abortController=o,n.then(i=>{e.current=i,t()}).catch(i=>{v(i)||(e.current=i,t())})}function G(){let e=new Map,t=new Set,r=performance.now(),n=!1;function o(){let s=performance.now(),a=s-r,{size:u}=t;if(a<.2&&u>0&&u<10){r=s,i();return}n||(n=!0,Promise.resolve().then(()=>{n=!1,r=performance.now(),i()}))}function i(){if(t.size===0)return;let s=new Set;for(let a of t){if(e.has(a.id)){s.add(a.id);let{onResolveItem:u}=e.get(a.id);u&&u(a.value)}t.delete(a)}if(t.size>0){o();return}for(let a of s)e.get(a)?.onFinish()}return{add(s,a){return e.set(s,a),()=>{e.delete(s)}},schedule(s,a){t.add({value:a,id:s}),o()}}}function h(e,t,r){let n={};function o(){let c=e.map(l=>l.get());return t(...c)}function i(){if(f(n.current)){let c=o();n.current=m(n,a.emitter.emit,c)}return n.current}let s=[];for(let c of e){let l=c.emitter.subscribe(()=>{S.schedule(a.id,null)});s.push(l)}let a=y({destroy(){for(let c of s)c();u(),a.emitter.clear(),n.current=void 0},get:i}),u=S.add(a.id,{onFinish(){let c=o();n.current=m(n,a.emitter.emit,c),b(n,r)&&a.emitter.emit()}});return a}var w=require("react");function x(e,t=k){let{emitter:r}=e,n=(0,w.useSyncExternalStore)(e.emitter.subscribe,()=>t(r.getSnapshot()),()=>t(r.getInitialSnapshot?r.getInitialSnapshot():r.getSnapshot()));if((0,w.useDebugValue)(n),d(n)||A(n))throw n;return n}function D(e,t){let r=new Set,n=[];return{clear:()=>{for(let o of n)o();r.clear()},subscribe:o=>(r.add(o),()=>{r.delete(o)}),emit:(...o)=>{for(let i of r)i(...o)},contains:o=>r.has(o),getSnapshot:e,getInitialSnapshot:t,getSize:()=>r.size,subscribeToOtherEmitter(o){let i=o.subscribe(()=>{this.emit()});n.push(i)}}}var _=0;function K(){return _++}function y(e){let{get:t,destroy:r,set:n}=e,o=!!n,i=function(s){return x(i,s)};return i.isSet=o,i.id=K(),i.emitter=D(t),i.destroy=r,i.listen=function(s){return this.emitter.subscribe(()=>{s(t())})},i.withName=function(s){return this.stateName=s,this},i.select=function(s,a=p){return h([i],s,a)},i.get=t,i.set=n,i}var S=G();function U(e,t=p){let r={};function n(){try{if(f(r.current)){let u=C(e)?e():e,c=m(r,s.emitter.emit,u);return r.current=c,r.current}return r.current}catch(u){r.current=u}return r.current}async function o(u,c){await u;let l=c(r.current),E=m(r,s.emitter.emit,l);r.current=E}function i(u){let c=n(),l=I(u);if(l&&d(c)){o(c,u);return}r.abortController&&r.abortController.abort();let E=l?u(c):u,F=m(r,s.emitter.emit,E);r.current=F}let s=y({get:n,destroy(){n(),a(),s.emitter.clear(),r.current=void 0},set(u){S.schedule(s.id,u)}}),a=S.add(s.id,{onFinish(){r.current=n(),b(r,t)&&s.emitter.emit()},onResolveItem:i});return C(e)||n(),s}function q(e,t){if(e==t)return!0;if(typeof e!="object"||e==null||typeof t!="object"||t==null)return!1;if(V(e)&&V(t)){if(e.size!==t.size)return!1;for(let[o,i]of e)if(!Object.is(i,t.get(o)))return!1;return!0}if(P(e)&&P(t)){if(e.size!==t.size)return!1;for(let o of e)if(!t.has(o))return!1;return!0}if(O(e)&&O(t)){if(e.length!==t.length)return!1;for(let[o,i]of e.entries())if(!Object.is(i,t[o]))return!1;return!0}let r=Object.keys(e),n=Object.keys(t);if(r.length!==n.length)return!1;for(let o of r)if(!Object.prototype.hasOwnProperty.call(t,o)||!Object.is(e[o],t[o]))return!1;return!0}
1
+ "use strict";var P=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var z=Object.prototype.hasOwnProperty;var H=(e,t)=>{for(var r in t)P(e,r,{get:t[r],enumerable:!0})},M=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of L(t))!z.call(e,o)&&o!==r&&P(e,o,{get:()=>t[o],enumerable:!(n=R(t,o))||n.enumerable});return e};var j=e=>M(P({},"__esModule",{value:!0}),e);var J={};H(J,{EMPTY_SELECTOR:()=>v,create:()=>U,isAbortError:()=>O,isArray:()=>x,isEqualBase:()=>p,isError:()=>A,isFunction:()=>S,isMap:()=>y,isPromise:()=>l,isSet:()=>w,isSetValueFunction:()=>I,isState:()=>_,isUndefined:()=>d,select:()=>E,shallow:()=>q,useValue:()=>C});module.exports=j(J);var T=class extends Error{static Error="AbortError"};function N(e,t){t&&t.abort();let r=new AbortController,{signal:n}=r;return{promise:new Promise((i,s)=>{n.addEventListener("abort",()=>{s(new T)}),e.then(i).catch(s)}),controller:r}}function h(e,t=p){if(!d(e.current)){if(!d(e.previous)&&t(e.current,e.previous))return!1;e.previous=e.current}return!0}function m(e,t,r){if(!l(r))return r;e.abortController&&e.abortController.abort();let{promise:n,controller:o}=N(r,e.abortController);return e.abortController=o,n.then(i=>{e.current=i,t()}).catch(i=>{O(i)||(e.current=i,t())})}function l(e){return e instanceof Promise}function S(e){return typeof e=="function"}function y(e){return e instanceof Map}function w(e){return e instanceof Set}function x(e){return Array.isArray(e)}function p(e,t){return e===t?!0:!!Object.is(e,t)}function I(e){return typeof e=="function"}function O(e){return e instanceof T}function A(e){return e instanceof Error}function d(e){return e===void 0}function _(e){return S(e)&&"get"in e&&"set"in e&&"isSet"in e&&e.isSet===!0}var v=e=>e;function G(){let e=new Map,t=new Set,r=performance.now(),n=!1;function o(){let s=performance.now(),a=s-r,{size:u}=t;if(a<.2&&u>0&&u<10){r=s,i();return}n||(n=!0,Promise.resolve().then(()=>{n=!1,r=performance.now(),i()}))}function i(){if(t.size===0)return;let s=new Set;for(let a of t){if(e.has(a.id)){s.add(a.id);let{onResolveItem:u}=e.get(a.id);u&&u(a.value)}t.delete(a)}if(t.size>0){o();return}for(let a of s)e.get(a)?.onFinish()}return{add(s,a){return e.set(s,a),()=>{e.delete(s)}},schedule(s,a){t.add({value:a,id:s}),o()}}}function E(e,t,r){let n={};function o(){let c=e.map(f=>f.get());return t(...c)}function i(){if(d(n.current)){let c=o();n.current=m(n,a.emitter.emit,c)}return n.current}let s=[];for(let c of e){let f=c.emitter.subscribe(()=>{b.schedule(a.id,null)});s.push(f)}let a=g({destroy(){for(let c of s)c();u(),a.emitter.clear(),n.current=void 0},get:i}),u=b.add(a.id,{onFinish(){let c=o();n.current=m(n,a.emitter.emit,c),h(n,r)&&a.emitter.emit()}});return a}var k=require("react");function C(e,t=v){let{emitter:r}=e,n=(0,k.useSyncExternalStore)(e.emitter.subscribe,()=>t(r.getSnapshot()),()=>t(r.getInitialSnapshot?r.getInitialSnapshot():r.getSnapshot()));if((0,k.useDebugValue)(n),l(n)||A(n))throw n;return n}function D(e,t){let r=new Set,n=[];return{clear:()=>{for(let o of n)o();r.clear()},subscribe:o=>(r.add(o),()=>{r.delete(o)}),emit:(...o)=>{for(let i of r)i(...o)},contains:o=>r.has(o),getSnapshot:e,getInitialSnapshot:t,getSize:()=>r.size,subscribeToOtherEmitter(o){let i=o.subscribe(()=>{this.emit()});n.push(i)}}}var K=0;function Y(){return K++}function g(e){let{get:t,destroy:r,set:n}=e,o=!!n,i=function(s){return C(i,s)};return i.isSet=o,i.id=Y(),i.emitter=D(t),i.destroy=r,i.listen=function(s){return this.emitter.subscribe(()=>{let a=t();l(a)||s(t())})},i.withName=function(s){return this.stateName=s,this},i.select=function(s,a=p){return E([i],s,a)},i.get=t,i.set=n,i}var b=G();function U(e,t=p){let r={};function n(){try{if(d(r.current)){let u=S(e)?e():e,c=m(r,s.emitter.emit,u);return r.current=c,r.current}return r.current}catch(u){r.current=u}return r.current}async function o(u,c){await u;let f=c(r.current),V=m(r,s.emitter.emit,f);r.current=V}function i(u){let c=n(),f=I(u);if(f&&l(c)){o(c,u);return}r.abortController&&r.abortController.abort();let V=f?u(c):u,F=m(r,s.emitter.emit,V);r.current=F}let s=g({get:n,destroy(){n(),a(),s.emitter.clear(),r.current=void 0},set(u){b.schedule(s.id,u)}}),a=b.add(s.id,{onFinish(){r.current=n(),h(r,t)&&s.emitter.emit()},onResolveItem:i});return S(e)||n(),s}function q(e,t){if(e==t)return!0;if(typeof e!="object"||e==null||typeof t!="object"||t==null)return!1;if(y(e)&&y(t)){if(e.size!==t.size)return!1;for(let[o,i]of e)if(!Object.is(i,t.get(o)))return!1;return!0}if(w(e)&&w(t)){if(e.size!==t.size)return!1;for(let o of e)if(!t.has(o))return!1;return!0}if(x(e)&&x(t)){if(e.length!==t.length)return!1;for(let[o,i]of e.entries())if(!Object.is(i,t[o]))return!1;return!0}let r=Object.keys(e),n=Object.keys(t);if(r.length!==n.length)return!1;for(let o of r)if(!Object.prototype.hasOwnProperty.call(t,o)||!Object.is(e[o],t[o]))return!1;return!0}
@@ -1 +1 @@
1
- import{select as u}from"./select";import{useValue as l}from"./use-value";import{createEmitter as S}from"./utils/create-emitter";import{isEqualBase as c}from"./utils/is";let m=0;function d(){return m++}function G(a){const{get:r,destroy:n,set:s}=a,i=!!s,t=function(e){return l(t,e)};return t.isSet=i,t.id=d(),t.emitter=S(r),t.destroy=n,t.listen=function(e){return this.emitter.subscribe(()=>{e(r())})},t.withName=function(e){return this.stateName=e,this},t.select=function(e,o=c){return u([t],e,o)},t.get=r,t.set=s,t}export{G as createState};
1
+ import{select as u}from"./select";import{useValue as l}from"./use-value";import{createEmitter as S}from"./utils/create-emitter";import{isEqualBase as c,isPromise as m}from"./utils/is";let d=0;function f(){return d++}function g(i){const{get:r,destroy:n,set:a}=i,o=!!a,t=function(e){return l(t,e)};return t.isSet=o,t.id=f(),t.emitter=S(r),t.destroy=n,t.listen=function(e){return this.emitter.subscribe(()=>{const s=r();m(s)||e(r())})},t.withName=function(e){return this.stateName=e,this},t.select=function(e,s=c){return u([t],e,s)},t.get=r,t.set=a,t}export{g as createState};
package/esm/index.js CHANGED
@@ -1 +1 @@
1
- export*from"./types";import{create as t}from"./create";import{select as m}from"./select";import{useValue as x}from"./use-value";import{shallow as a}from"./utils/shallow";export{t as create,m as select,a as shallow,x as useValue};
1
+ export*from"./utils/is";export*from"./types";import{create as f}from"./create";import{select as p}from"./select";import{useValue as l}from"./use-value";import{shallow as s}from"./utils/shallow";export{f as create,p as select,s as shallow,l as useValue};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "muya",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "author": "samuel.gjabel@gmail.com",
5
5
  "repository": "https://github.com/samuelgjabel/muya",
6
6
  "main": "cjs/index.js",
@@ -95,6 +95,33 @@ describe('select', () => {
95
95
  expect(listener).toHaveBeenCalledWith(1)
96
96
  })
97
97
  })
98
+ it('should handle async updates with nested selects', async () => {
99
+ const state = create(longPromise(100))
100
+ const selectedState = select([state], async (value) => {
101
+ await longPromise(100)
102
+ return (await value) + 1
103
+ })
104
+ const selectedState2 = selectedState.select(async (value) => (await value) + 1)
105
+ const listener = jest.fn()
106
+ selectedState2.listen(listener)
107
+ await waitFor(() => {
108
+ expect(selectedState2.get()).toBe(2)
109
+ expect(listener).toHaveBeenCalledWith(2)
110
+ })
111
+ })
112
+ it('should handle async updates with async state', async () => {
113
+ const state = create(longPromise(100))
114
+ const selectedState = select([state], async (value) => {
115
+ // await longPromise(100)
116
+ return (await value) + 1
117
+ })
118
+ const listener = jest.fn()
119
+ selectedState.listen(listener)
120
+ await waitFor(() => {
121
+ expect(selectedState.get()).toBe(1)
122
+ expect(listener).toHaveBeenCalledWith(1)
123
+ })
124
+ })
98
125
  it('should handle sync state updates when one of par is changed', async () => {
99
126
  const state1Atom = create(0)
100
127
  const state2Atom = create(0)
@@ -124,4 +151,22 @@ describe('select', () => {
124
151
  expect(listener).toHaveBeenCalledWith(3)
125
152
  })
126
153
  })
154
+ it('should select state from async initial state', async () => {
155
+ const state = create(longPromise(100))
156
+ const selectedState = state.select(async (value) => {
157
+ return (await value) + 2
158
+ })
159
+ await waitFor(() => {
160
+ expect(selectedState.get()).toBe(2)
161
+ })
162
+ })
163
+ it('should select state from sync initial state', async () => {
164
+ const state = create(0)
165
+ const selectedState = state.select((value) => {
166
+ return value + 2
167
+ })
168
+ await waitFor(() => {
169
+ expect(selectedState.get()).toBe(2)
170
+ })
171
+ })
127
172
  })
@@ -2,6 +2,7 @@ import { renderHook, act } from '@testing-library/react-hooks'
2
2
  import { create } from '../create'
3
3
  import { useValue } from '../use-value'
4
4
  import { waitFor } from '@testing-library/react'
5
+ import { longPromise } from './test-utils'
5
6
 
6
7
  describe('useValue', () => {
7
8
  it('should get the initial state value', () => {
@@ -75,4 +76,26 @@ describe('useValue', () => {
75
76
  await waitFor(() => {})
76
77
  expect(renders).toHaveBeenCalledTimes(2)
77
78
  })
79
+
80
+ it('should check how many times the hook re-render when the state is promise', async () => {
81
+ const state = create(longPromise(100))
82
+
83
+ const render = jest.fn()
84
+ const renderAfter = jest.fn()
85
+
86
+ const { result } = renderHook(() => {
87
+ render()
88
+ const stateResult = state()
89
+ renderAfter()
90
+ return stateResult
91
+ })
92
+
93
+ await waitFor(() => {
94
+ expect(result.current).toBe(0)
95
+ // when it render, it will return a promise - hit the suspense, so it should be called twice
96
+ expect(render).toHaveBeenCalledTimes(2)
97
+ // after the promise resolved, it will re-render again, this part should be called once
98
+ expect(renderAfter).toHaveBeenCalledTimes(1)
99
+ })
100
+ })
78
101
  })
@@ -2,7 +2,7 @@ import { select } from './select'
2
2
  import type { GetState, SetValue, State } from './types'
3
3
  import { useValue } from './use-value'
4
4
  import { createEmitter } from './utils/create-emitter'
5
- import { isEqualBase } from './utils/is'
5
+ import { isEqualBase, isPromise } from './utils/is'
6
6
 
7
7
  interface GetStateOptions<T> {
8
8
  readonly get: () => T
@@ -33,7 +33,11 @@ export function createState<T>(options: GetStateOptions<T>): FullState<T> {
33
33
  state.destroy = destroy
34
34
  state.listen = function (listener) {
35
35
  return this.emitter.subscribe(() => {
36
- listener(get())
36
+ const value = get()
37
+ if (isPromise(value)) {
38
+ return
39
+ }
40
+ listener(get() as Awaited<T>)
37
41
  })
38
42
  }
39
43
  state.withName = function (name) {
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './utils/is'
1
2
  export * from './types'
2
3
  export { create } from './create'
3
4
  export { select } from './select'
package/src/types.ts CHANGED
@@ -30,7 +30,7 @@ export interface GetState<T> {
30
30
  /**
31
31
  * Listen to changes in the state.
32
32
  */
33
- listen: Listener<T>
33
+ listen: Listener<Awaited<T>>
34
34
  /**
35
35
  * Destroy / cleanup the state.
36
36
  * Clean all listeners and make cache value undefined.
@@ -48,7 +48,7 @@ export interface GetState<T> {
48
48
  * Select particular slice of the state.
49
49
  * It will create "another" state in read-only mode (without set).
50
50
  */
51
- select: <S>(selector: (state: T) => S, isEqual?: IsEqual<S>) => GetState<S>
51
+ select: <S>(selector: (state: Awaited<T> | T) => S, isEqual?: IsEqual<S>) => GetState<S>
52
52
  }
53
53
 
54
54
  export interface State<T> extends GetState<T> {
package/types/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './utils/is';
1
2
  export * from './types';
2
3
  export { create } from './create';
3
4
  export { select } from './select';
package/types/types.d.ts CHANGED
@@ -27,7 +27,7 @@ export interface GetState<T> {
27
27
  /**
28
28
  * Listen to changes in the state.
29
29
  */
30
- listen: Listener<T>;
30
+ listen: Listener<Awaited<T>>;
31
31
  /**
32
32
  * Destroy / cleanup the state.
33
33
  * Clean all listeners and make cache value undefined.
@@ -45,7 +45,7 @@ export interface GetState<T> {
45
45
  * Select particular slice of the state.
46
46
  * It will create "another" state in read-only mode (without set).
47
47
  */
48
- select: <S>(selector: (state: T) => S, isEqual?: IsEqual<S>) => GetState<S>;
48
+ select: <S>(selector: (state: Awaited<T> | T) => S, isEqual?: IsEqual<S>) => GetState<S>;
49
49
  }
50
50
  export interface State<T> extends GetState<T> {
51
51
  /**