muya 2.0.7 → 2.0.8

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 I=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var _=(e,t)=>{for(var r in t)I(e,r,{get:t[r],enumerable:!0})},K=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of j(t))!N.call(e,o)&&o!==r&&I(e,o,{get:()=>t[o],enumerable:!(n=M(t,o))||n.enumerable});return e};var Y=e=>K(I({},"__esModule",{value:!0}),e);var Z={};_(Z,{EMPTY_SELECTOR:()=>D,create:()=>R,isAbortError:()=>v,isArray:()=>k,isEqualBase:()=>T,isError:()=>G,isFunction:()=>b,isMap:()=>E,isPromise:()=>l,isSet:()=>g,isSetValueFunction:()=>A,isState:()=>Q,isUndefined:()=>m,select:()=>C,shallow:()=>L,useValue:()=>O});module.exports=Y(Z);var d=class extends Error{static Error="AbortError"};function J(e,t){t&&t.abort();let r=new AbortController,{signal:n}=r;return{promise:new Promise((s,i)=>{n.addEventListener("abort",()=>{i(new d)}),e.then(s).catch(i)}),controller:r}}function x(e,t=T){if(!m(e.current)){if(!m(e.previous)&&t(e.current,e.previous))return!1;e.previous=e.current}return!0}function p(e,t,r){if(!l(r))return r;e.abortController&&e.abortController.abort();let{promise:n,controller:o}=J(r,e.abortController);return e.abortController=o,n.then(s=>{e.current=s,t()}).catch(s=>{v(s)||(e.current=s,t())})}function l(e){return e instanceof Promise}function b(e){return typeof e=="function"}function E(e){return e instanceof Map}function g(e){return e instanceof Set}function k(e){return Array.isArray(e)}function T(e,t){return e===t?!0:!!Object.is(e,t)}function A(e){return typeof e=="function"}function v(e){return e instanceof d}function G(e){return e instanceof Error}function m(e){return e===void 0}function Q(e){return b(e)&&"get"in e&&"set"in e&&"isSet"in e&&e.isSet===!0}var D=e=>e;function q(){let e=new Map,t=new Set,r=performance.now(),n=!1;function o(){let i=performance.now(),a=i-r,{size:u}=t;if(a<.2&&u>0&&u<10){r=i,s();return}n||(n=!0,Promise.resolve().then(()=>{n=!1,r=performance.now(),s()}))}function s(){if(t.size===0)return;let i=new Set;for(let a of t){if(e.has(a.id)){i.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 i)e.get(a)?.onFinish()}return{add(i,a){return e.set(i,a),()=>{e.delete(i)}},schedule(i,a){t.add({value:a,id:i}),o()}}}function C(e,t,r){let n={};function o(){let c=[],f=!1;for(let S of e){let y=S.get();l(y)&&(f=!0),c.push(y)}return f?new Promise((S,y)=>{Promise.all(c).then(U=>{if(U.some(H=>m(H)))return y(new d);let z=t(...U);S(z)})}):t(...c)}function s(){if(m(n.current)){let c=o();n.current=p(n,a.emitter.emit,c)}return n.current}let i=[];for(let c of e){let f=c.emitter.subscribe(()=>{h.schedule(a.id,null)});i.push(f)}let a=P({destroy(){for(let c of i)c();u(),a.emitter.clear(),n.current=void 0},get:s}),u=h.add(a.id,{onFinish(){let c=o();n.current=p(n,a.emitter.emit,c),x(n,r)&&a.emitter.emit()}});return a}var V=require("react");function O(e,t=D){let{emitter:r}=e,n=(0,V.useSyncExternalStore)(e.emitter.subscribe,()=>t(r.getSnapshot()),()=>t(r.getInitialSnapshot?r.getInitialSnapshot():r.getSnapshot()));if((0,V.useDebugValue)(n),l(n)||G(n))throw n;return n}function F(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 s of r)s(...o)},contains:o=>r.has(o),getSnapshot:e,getInitialSnapshot:t,getSize:()=>r.size,subscribeToOtherEmitter(o){let s=o.subscribe(()=>{this.emit()});n.push(s)}}}var W=0;function X(){return W++}function P(e){let{get:t,destroy:r,set:n}=e,o=!!n,s=function(i){return O(s,i)};return s.isSet=o,s.id=X(),s.emitter=F(t),s.destroy=r,s.listen=function(i){return this.emitter.subscribe(()=>{let a=t();l(a)||i(t())})},s.withName=function(i){return this.stateName=i,this},s.select=function(i,a=T){return C([s],i,a)},s.get=t,s.set=n,s}var h=q();function R(e,t=T){let r={};function n(){try{if(m(r.current)){let u=b(e)?e():e,c=p(r,i.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),w=p(r,i.emitter.emit,f);r.current=w}function s(u){let c=n(),f=A(u);if(f&&l(c)){o(c,u);return}r.abortController&&r.abortController.abort();let w=f?u(c):u,S=p(r,i.emitter.emit,w);r.current=S}let i=P({get:n,destroy(){n(),a(),i.emitter.clear(),r.current=void 0},set(u){h.schedule(i.id,u)}}),a=h.add(i.id,{onFinish(){r.current=n(),x(r,t)&&i.emitter.emit()},onResolveItem:s});return b(e)||n(),i}function L(e,t){if(e==t)return!0;if(typeof e!="object"||e==null||typeof t!="object"||t==null)return!1;if(E(e)&&E(t)){if(e.size!==t.size)return!1;for(let[o,s]of e)if(!Object.is(s,t.get(o)))return!1;return!0}if(g(e)&&g(t)){if(e.size!==t.size)return!1;for(let o of e)if(!t.has(o))return!1;return!0}if(k(e)&&k(t)){if(e.length!==t.length)return!1;for(let[o,s]of e.entries())if(!Object.is(s,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 v=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var _=Object.prototype.hasOwnProperty;var K=(e,t)=>{for(var r in t)v(e,r,{get:t[r],enumerable:!0})},Y=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of N(t))!_.call(e,o)&&o!==r&&v(e,o,{get:()=>t[o],enumerable:!(n=j(t,o))||n.enumerable});return e};var J=e=>Y(v({},"__esModule",{value:!0}),e);var $={};K($,{EMPTY_SELECTOR:()=>F,create:()=>L,isAbortError:()=>A,isArray:()=>P,isEqualBase:()=>S,isError:()=>D,isFunction:()=>h,isMap:()=>E,isPromise:()=>f,isSet:()=>g,isSetValueFunction:()=>G,isState:()=>W,isUndefined:()=>m,select:()=>k,shallow:()=>z,useValue:()=>O});module.exports=J($);var T=class extends Error{static Error="AbortError"};function Q(e,t){t&&t.abort();let r=new AbortController,{signal:n}=r;return{promise:new Promise((u,s)=>{n.addEventListener("abort",()=>{s(new T)}),e.then(u).catch(s)}),controller:r}}function x(e,t=S){if(!m(e.current)){if(!m(e.previous)&&t(e.current,e.previous))return!1;e.previous=e.current}return!0}function p(e,t,r){if(!f(r))return r;e.abortController&&e.abortController.abort();let{promise:n,controller:o}=Q(r,e.abortController);return e.abortController=o,n.then(u=>{e.current=u,t()}).catch(u=>{A(u)||(e.current=u,t())})}function f(e){return e instanceof Promise}function h(e){return typeof e=="function"}function E(e){return e instanceof Map}function g(e){return e instanceof Set}function P(e){return Array.isArray(e)}function S(e,t){return e===t?!0:!!Object.is(e,t)}function G(e){return typeof e=="function"}function A(e){return e instanceof T}function D(e){return e instanceof Error}function m(e){return e===void 0}function W(e){return h(e)&&"get"in e&&"set"in e&&"isSet"in e&&e.isSet===!0}var F=e=>e;function q(){let e=new Map,t=new Set,r=performance.now(),n=!1;function o(){let s=performance.now(),a=s-r,{size:i}=t;if(a<.2&&i>0&&i<10){r=s,u();return}n||(n=!0,Promise.resolve().then(()=>{n=!1,r=performance.now(),u()}))}function u(){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:i}=e.get(a.id);i&&i(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 k(e,t,r){let n={};function o(){let c=[],l=!1;for(let I of e){let y=I.get();f(y)&&(l=!0),c.push(y)}return l?new Promise((I,y)=>{Promise.all(c).then(U=>{if(U.some(H=>m(H)))return y(new T);let M=t(...U);I(M)})}):t(...c)}function u(){if(m(n.current)){let c=o();n.current=p(n,i.emitter.emit,c)}return n.current}function s(){if(m(n.current)){let l=o();n.current=p(n,i.emitter.emit,l)}let{current:c}=n;return f(c)?new Promise(l=>{c.then(b=>{if(m(b)){l(s());return}l(b)})}):n.current}let a=[];for(let c of e){let l=c.emitter.subscribe(()=>{w.schedule(i.id,null)});a.push(l)}let i=C({destroy(){for(let c of a)c();d(),i.emitter.clear(),n.current=void 0},get:s,getSnapshot:u}),d=w.add(i.id,{onFinish(){let c=o();n.current=p(n,i.emitter.emit,c),x(n,r)&&i.emitter.emit()}});return i}var V=require("react");function O(e,t=F){let{emitter:r}=e,n=(0,V.useSyncExternalStore)(e.emitter.subscribe,()=>t(r.getSnapshot()),()=>t(r.getInitialSnapshot?r.getInitialSnapshot():r.getSnapshot()));if((0,V.useDebugValue)(n),f(n)||D(n))throw n;return n}function R(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 u of r)u(...o)},contains:o=>r.has(o),getSnapshot:e,getInitialSnapshot:t,getSize:()=>r.size,subscribeToOtherEmitter(o){let u=o.subscribe(()=>{this.emit()});n.push(u)}}}var X=0;function Z(){return X++}function C(e){let{get:t,destroy:r,set:n,getSnapshot:o}=e,u=!!n,s=function(a){return O(s,a)};return s.isSet=u,s.id=Z(),s.emitter=R(o),s.destroy=r,s.listen=function(a){return this.emitter.subscribe(()=>{let i=t();f(i)||a(t())})},s.withName=function(a){return this.stateName=a,this},s.select=function(a,i=S){return k([s],a,i)},s.get=t,s.set=n,s}var w=q();function L(e,t=S){let r={};function n(){try{if(m(r.current)){let i=h(e)?e():e,d=p(r,s.emitter.emit,i);return r.current=d,r.current}return r.current}catch(i){r.current=i}return r.current}async function o(i,d){await i;let c=d(r.current),l=p(r,s.emitter.emit,c);r.current=l}function u(i){let d=n(),c=G(i);if(c&&f(d)){o(d,i);return}r.abortController&&r.abortController.abort();let l=c?i(d):i,b=p(r,s.emitter.emit,l);r.current=b}let s=C({get:n,destroy(){n(),a(),s.emitter.clear(),r.current=void 0},set(i){w.schedule(s.id,i)},getSnapshot:n}),a=w.add(s.id,{onFinish(){r.current=n(),x(r,t)&&s.emitter.emit()},onResolveItem:u});return h(e)||n(),s}function z(e,t){if(e==t)return!0;if(typeof e!="object"||e==null||typeof t!="object"||t==null)return!1;if(E(e)&&E(t)){if(e.size!==t.size)return!1;for(let[o,u]of e)if(!Object.is(u,t.get(o)))return!1;return!0}if(g(e)&&g(t)){if(e.size!==t.size)return!1;for(let o of e)if(!t.has(o))return!1;return!0}if(P(e)&&P(t)){if(e.length!==t.length)return!1;for(let[o,u]of e.entries())if(!Object.is(u,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,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};
1
+ import{select as l}from"./select";import{useValue as S}from"./use-value";import{createEmitter as c}from"./utils/create-emitter";import{isEqualBase as d,isPromise as m}from"./utils/is";let T=0;function f(){return T++}function h(n){const{get:r,destroy:o,set:a,getSnapshot:i}=n,u=!!a,t=function(e){return S(t,e)};return t.isSet=u,t.id=f(),t.emitter=c(i),t.destroy=o,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=d){return l([t],e,s)},t.get=r,t.set=a,t}export{h as createState};
package/esm/create.js CHANGED
@@ -1 +1 @@
1
- import{canUpdate as p,handleAsyncUpdate as u}from"./utils/common";import{isEqualBase as V,isFunction as i,isPromise as h,isSetValueFunction as b,isUndefined as y}from"./utils/is";import{createScheduler as C}from"./scheduler";import{subscribeToDevelopmentTools as w}from"./debug/development-tools";import{createState as v}from"./create-state";const l=C();function I(c,m=V){const e={};function o(){try{if(y(e.current)){const t=i(c)?c():c,n=u(e,r.emitter.emit,t);return e.current=n,e.current}return e.current}catch(t){e.current=t}return e.current}async function d(t,n){await t;const a=n(e.current),s=u(e,r.emitter.emit,a);e.current=s}function f(t){const n=o(),a=b(t);if(a&&h(n)){d(n,t);return}e.abortController&&e.abortController.abort();const s=a?t(n):t,S=u(e,r.emitter.emit,s);e.current=S}const r=v({get:o,destroy(){o(),T(),r.emitter.clear(),e.current=void 0},set(t){l.schedule(r.id,t)}}),T=l.add(r.id,{onFinish(){e.current=o(),p(e,m)&&r.emitter.emit()},onResolveItem:f});return i(c)||o(),w(r),r}export{I as create,l as stateScheduler};
1
+ import{canUpdate as p,handleAsyncUpdate as u}from"./utils/common";import{isEqualBase as h,isFunction as i,isPromise as V,isSetValueFunction as b,isUndefined as y}from"./utils/is";import{createScheduler as C}from"./scheduler";import{subscribeToDevelopmentTools as w}from"./debug/development-tools";import{createState as v}from"./create-state";const l=C();function E(c,m=h){const e={};function o(){try{if(y(e.current)){const t=i(c)?c():c,n=u(e,r.emitter.emit,t);return e.current=n,e.current}return e.current}catch(t){e.current=t}return e.current}async function d(t,n){await t;const a=n(e.current),s=u(e,r.emitter.emit,a);e.current=s}function f(t){const n=o(),a=b(t);if(a&&V(n)){d(n,t);return}e.abortController&&e.abortController.abort();const s=a?t(n):t,S=u(e,r.emitter.emit,s);e.current=S}const r=v({get:o,destroy(){o(),T(),r.emitter.clear(),e.current=void 0},set(t){l.schedule(r.id,t)},getSnapshot:o}),T=l.add(r.id,{onFinish(){e.current=o(),p(e,m)&&r.emitter.emit()},onResolveItem:f});return i(c)||o(),w(r),r}export{E as create,l as stateScheduler};
package/esm/select.js CHANGED
@@ -1 +1 @@
1
- import{stateScheduler as m}from"./create";import{createState as w}from"./create-state";import{subscribeToDevelopmentTools as b}from"./debug/development-tools";import{AbortError as k,canUpdate as v,handleAsyncUpdate as f}from"./utils/common";import{isPromise as A,isUndefined as d}from"./utils/is";function U(c,u,p){const t={};function a(){const e=[];let r=!1;for(const s of c){const o=s.get();A(o)&&(r=!0),e.push(o)}return r?new Promise((s,o)=>{Promise.all(e).then(l=>{if(l.some(y=>d(y)))return o(new k);const h=u(...l);s(h)})}):u(...e)}function S(){if(d(t.current)){const e=a();t.current=f(t,n.emitter.emit,e)}return t.current}const i=[];for(const e of c){const r=e.emitter.subscribe(()=>{m.schedule(n.id,null)});i.push(r)}const n=w({destroy(){for(const e of i)e();T(),n.emitter.clear(),t.current=void 0},get:S}),T=m.add(n.id,{onFinish(){const e=a();t.current=f(t,n.emitter.emit,e),v(t,p)&&n.emitter.emit()}});return b(n),n}export{U as select};
1
+ import{stateScheduler as T}from"./create";import{createState as A}from"./create-state";import{subscribeToDevelopmentTools as P}from"./debug/development-tools";import{AbortError as g,canUpdate as V,handleAsyncUpdate as a}from"./utils/common";import{isPromise as S,isUndefined as s}from"./utils/is";function U(m,f,h){const t={};function c(){const e=[];let r=!1;for(const i of m){const o=i.get();S(o)&&(r=!0),e.push(o)}return r?new Promise((i,o)=>{Promise.all(e).then(p=>{if(p.some(b=>s(b)))return o(new g);const k=f(...p);i(k)})}):f(...e)}function w(){if(s(t.current)){const e=c();t.current=a(t,n.emitter.emit,e)}return t.current}function l(){if(s(t.current)){const r=c();t.current=a(t,n.emitter.emit,r)}const{current:e}=t;return S(e)?new Promise(r=>{e.then(u=>{if(s(u)){r(l());return}r(u)})}):t.current}const d=[];for(const e of m){const r=e.emitter.subscribe(()=>{T.schedule(n.id,null)});d.push(r)}const n=A({destroy(){for(const e of d)e();y(),n.emitter.clear(),t.current=void 0},get:l,getSnapshot:w}),y=T.add(n.id,{onFinish(){const e=c();t.current=a(t,n.emitter.emit,e),V(t,h)&&n.emitter.emit()}});return P(n),n}export{U as select};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "muya",
3
- "version": "2.0.7",
3
+ "version": "2.0.8",
4
4
  "author": "samuel.gjabel@gmail.com",
5
5
  "repository": "https://github.com/samuelgjabel/muya",
6
6
  "main": "cjs/index.js",
@@ -0,0 +1,68 @@
1
+ import { act, renderHook } from '@testing-library/react-hooks'
2
+ import { create } from '../create'
3
+ import { longPromise } from './test-utils'
4
+ import { waitFor } from '@testing-library/react'
5
+ import { atom, useAtom, useSetAtom } from 'jotai'
6
+
7
+ describe('compare', () => {
8
+ it('should render async value with sync selector', async () => {
9
+ const state = create(longPromise(100))
10
+ const selectedState = state.select((value) => {
11
+ return value + 2
12
+ })
13
+ const listen = jest.fn()
14
+
15
+ const { result } = renderHook(() => {
16
+ listen()
17
+ const value = selectedState()
18
+ return value
19
+ })
20
+
21
+ await waitFor(() => {
22
+ expect(result.current).toBe(2)
23
+ expect(listen).toHaveBeenCalledTimes(2)
24
+ })
25
+
26
+ state.set(1)
27
+
28
+ await waitFor(() => {
29
+ expect(result.current).toBe(3)
30
+ // muya re-render only 3 times
31
+ expect(listen).toHaveBeenCalledTimes(3)
32
+ })
33
+ })
34
+ it('should render async value with sync selector with jotai', async () => {
35
+ const state = atom(longPromise(100))
36
+
37
+ const selectedState = atom(async (get) => {
38
+ const value = get(state)
39
+ return (await value) + 2
40
+ })
41
+
42
+ const listen = jest.fn()
43
+ const { result: setResult } = renderHook(() => {
44
+ const value = useSetAtom(state)
45
+ return value
46
+ })
47
+ const { result } = renderHook(() => {
48
+ listen()
49
+ const value = useAtom(selectedState)
50
+ return value
51
+ })
52
+
53
+ await waitFor(() => {
54
+ expect(result.current[0]).toBe(2)
55
+ expect(listen).toHaveBeenCalledTimes(3)
56
+ })
57
+
58
+ act(() => {
59
+ setResult.current(1 as never)
60
+ })
61
+
62
+ await waitFor(() => {
63
+ expect(result.current[0]).toBe(3)
64
+ // OH it render 5 times, sad.
65
+ expect(listen).toHaveBeenCalledTimes(5)
66
+ })
67
+ })
68
+ })
@@ -205,4 +205,31 @@ describe('select', () => {
205
205
  expect(render).toHaveBeenCalledTimes(3)
206
206
  })
207
207
  })
208
+
209
+ it('should get value when initial value is promise', async () => {
210
+ const state = create(longPromise(100))
211
+ const selectedState = state.select((value) => {
212
+ return value + 2
213
+ })
214
+ expect(await selectedState.get()).toBe(2)
215
+ })
216
+
217
+ it('should have sync get method sync', async () => {
218
+ const state = create(100)
219
+ const selectedState = state.select((value) => {
220
+ return value + 2
221
+ })
222
+ expect(selectedState.get()).toBe(102)
223
+ })
224
+
225
+ it('should have async get method sync', async () => {
226
+ const state = create(100)
227
+ const selectedState = state.select((value) => {
228
+ return value + 2
229
+ })
230
+ const selectedState2 = selectedState.select(async (value) => {
231
+ return value + 2
232
+ })
233
+ expect(await selectedState2.get()).toBe(104)
234
+ })
208
235
  })
@@ -8,6 +8,7 @@ interface GetStateOptions<T> {
8
8
  readonly get: () => T
9
9
  readonly set?: (value: SetValue<T>) => void
10
10
  readonly destroy: () => void
11
+ readonly getSnapshot: () => T
11
12
  }
12
13
 
13
14
  let stateId = 0
@@ -20,7 +21,7 @@ type FullState<T> = GetStateOptions<T>['set'] extends undefined ? GetState<T> :
20
21
  * This is just utility function to create state base data
21
22
  */
22
23
  export function createState<T>(options: GetStateOptions<T>): FullState<T> {
23
- const { get, destroy, set } = options
24
+ const { get, destroy, set, getSnapshot } = options
24
25
  const isSet = !!set
25
26
 
26
27
  const state: FullState<T> = function (selector) {
@@ -29,7 +30,7 @@ export function createState<T>(options: GetStateOptions<T>): FullState<T> {
29
30
  }
30
31
  state.isSet = isSet as true
31
32
  state.id = getStateId()
32
- state.emitter = createEmitter<T>(get)
33
+ state.emitter = createEmitter<T>(getSnapshot)
33
34
  state.destroy = destroy
34
35
  state.listen = function (listener) {
35
36
  return this.emitter.subscribe(() => {
@@ -44,10 +45,10 @@ export function createState<T>(options: GetStateOptions<T>): FullState<T> {
44
45
  this.stateName = name
45
46
  return this
46
47
  }
47
- state.select = function (selector, isSelectorEqual = isEqualBase) {
48
+ state.select = function (selector: never, isSelectorEqual = isEqualBase) {
48
49
  return select([state as never], selector, isSelectorEqual)
49
- }
50
- state.get = get
50
+ } as never
51
+ state.get = get as never
51
52
  state.set = set as State<T>['set']
52
53
 
53
54
  return state
package/src/create.ts CHANGED
@@ -65,6 +65,7 @@ export function create<T>(initialValue: DefaultValue<T>, isEqual: IsEqual<T> = i
65
65
  set(value: SetValue<T>) {
66
66
  stateScheduler.schedule(state.id, value)
67
67
  },
68
+ getSnapshot: getValue,
68
69
  })
69
70
 
70
71
  const clearScheduler = stateScheduler.add(state.id, {
package/src/select.ts CHANGED
@@ -48,12 +48,31 @@ export function select<T = unknown, S extends Array<unknown> = []>(
48
48
  const result = selector(...(values as S))
49
49
  return result
50
50
  }
51
-
51
+ function getSnapshot(): T {
52
+ if (isUndefined(cache.current)) {
53
+ const newValue = computedValue()
54
+ cache.current = handleAsyncUpdate(cache, state.emitter.emit, newValue)
55
+ }
56
+ return cache.current
57
+ }
52
58
  function getValue(): T {
53
59
  if (isUndefined(cache.current)) {
54
60
  const newValue = computedValue()
55
61
  cache.current = handleAsyncUpdate(cache, state.emitter.emit, newValue)
56
62
  }
63
+ const { current } = cache
64
+ if (isPromise(current)) {
65
+ return new Promise((resolve) => {
66
+ current.then((value: unknown) => {
67
+ if (isUndefined(value)) {
68
+ resolve(getValue())
69
+ return
70
+ }
71
+
72
+ resolve(value)
73
+ })
74
+ }) as T
75
+ }
57
76
  return cache.current
58
77
  }
59
78
 
@@ -75,6 +94,7 @@ export function select<T = unknown, S extends Array<unknown> = []>(
75
94
  cache.current = undefined
76
95
  },
77
96
  get: getValue,
97
+ getSnapshot,
78
98
  })
79
99
 
80
100
  const clearScheduler = stateScheduler.add(state.id, {
package/src/types.ts CHANGED
@@ -13,12 +13,12 @@ export interface Cache<T> {
13
13
 
14
14
  export const EMPTY_SELECTOR = <T, S>(stateValue: T) => stateValue as unknown as S
15
15
 
16
- export interface GetState<T> {
16
+ export interface GetState<T, IsFroMPromise extends boolean = false> {
17
17
  <S>(selector?: (stateValue: T) => S): Awaited<undefined extends S ? T : S>
18
18
  /**
19
19
  * Get the cached state value.
20
20
  */
21
- get: () => T
21
+ get: () => IsFroMPromise extends true ? Promise<T> : T
22
22
  /**
23
23
  * Get the unique id of the state.
24
24
  */
@@ -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: Awaited<T>) => S, isEqual?: IsEqual<S>) => GetState<S>
51
+ select: <S>(selector: (state: Awaited<T>) => S, isEqual?: IsEqual<S>) => GetState<S, T extends Promise<unknown> ? true : false>
52
52
  }
53
53
 
54
54
  export interface State<T> extends GetState<T> {
@@ -3,6 +3,7 @@ interface GetStateOptions<T> {
3
3
  readonly get: () => T;
4
4
  readonly set?: (value: SetValue<T>) => void;
5
5
  readonly destroy: () => void;
6
+ readonly getSnapshot: () => T;
6
7
  }
7
8
  type FullState<T> = GetStateOptions<T>['set'] extends undefined ? GetState<T> : State<T>;
8
9
  /**
package/types/types.d.ts CHANGED
@@ -10,12 +10,12 @@ export interface Cache<T> {
10
10
  abortController?: AbortController;
11
11
  }
12
12
  export declare const EMPTY_SELECTOR: <T, S>(stateValue: T) => S;
13
- export interface GetState<T> {
13
+ export interface GetState<T, IsFroMPromise extends boolean = false> {
14
14
  <S>(selector?: (stateValue: T) => S): Awaited<undefined extends S ? T : S>;
15
15
  /**
16
16
  * Get the cached state value.
17
17
  */
18
- get: () => T;
18
+ get: () => IsFroMPromise extends true ? Promise<T> : T;
19
19
  /**
20
20
  * Get the unique id of the state.
21
21
  */
@@ -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: Awaited<T>) => S, isEqual?: IsEqual<S>) => GetState<S>;
48
+ select: <S>(selector: (state: Awaited<T>) => S, isEqual?: IsEqual<S>) => GetState<S, T extends Promise<unknown> ? true : false>;
49
49
  }
50
50
  export interface State<T> extends GetState<T> {
51
51
  /**