bansa 0.0.3 → 0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 cgiosy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.ko.md CHANGED
@@ -30,7 +30,7 @@ const $user = $({ name: 'John Doe', age: 30 });
30
30
 
31
31
  #### 파생 상태
32
32
 
33
- 값이 동적이며, 생명 주기를 가지는 상태입니다. 값을 직접 업데이트할 수 없으며, 의존 중인 상태의 값이 바뀔 때에만 재실행될 수 있습니다. 해당 상태를 구독 중인 곳이 존재하는, 활성화된 상태가 아닐 경우 함수는 실행되지 않으며, 의존성 또한 없는 것으로 취급됩니다.
33
+ 값을 함수로 계산하며, 생명 주기를 가지는 상태입니다. 값을 직접 업데이트할 수 없으며, 의존 중인 상태의 값이 바뀔 때에만 재실행될 수 있습니다. 활성화된 상태가 아니라면, 즉 해당 상태를 구독 중인 곳이 존재하지 않는다면 함수는 실행되지 않으며, 의존성 또한 없는 것으로 취급됩니다.
34
34
 
35
35
  `$`에 함수를 전달하여 생성합니다. 전달하는 함수의 인자로는 다른 상태의 값을 읽을 수 있는 `get` 함수와 상태의 수명을 나타내는 `{ signal }`이 주어집니다. `signal`에 대해선 다른 파트에서 더 자세히 다룹니다.
36
36
 
@@ -82,7 +82,7 @@ type AtomState<Value> =
82
82
  console.log($count.get()); // 42
83
83
  console.log($countDouble.get()); // 84
84
84
 
85
- console.log($countDouble.state); // { promise: undefined, error: Symbol(), value: 84 }
85
+ console.log($countDouble.state); // { promise: undefined, error: undefined, value: 84 }
86
86
  ```
87
87
 
88
88
  파생 상태는 `.get()` 했을 때 throw 될 수 있습니다. 비동기 로딩 중일 땐 해당 `Promise`를 throw하며, 오류 상태일 때는 해당 오류를 throw합니다. 값이 성공적으로 계산된 상황 위주로 처리하고, 예외 상황은 전부 `catch` 블록 등으로 밀어넣고 싶은 상황에서 유용합니다.
@@ -213,7 +213,7 @@ const $user = $(
213
213
  );
214
214
 
215
215
  const $user2 = $(
216
- (get) => get($user).name,
216
+ (get) => get($user),
217
217
  { equals: (next, prev) => next.name === prev.name },
218
218
  );
219
219
 
@@ -232,10 +232,10 @@ userAtom.set({ id: 2, name: 'Alice' });
232
232
 
233
233
  ```javascript
234
234
  const timer = (time) => new Promise((resolve) => setTimeout(() => resolve(1), time));
235
- const a = [1, 2, 3, 4, 5].map(() => $(() => timer(1000)));
236
- const merged = $$((get) => a.map(get));
235
+ const timerAtoms = [1, 2, 3, 4, 5].map(() => $(() => timer(1000)));
236
+ const $timers = $$((get) => timerAtoms.map(get));
237
237
  console.time();
238
- merged.subscribe(() => console.timeEnd());
238
+ $timers.subscribe(() => console.timeEnd());
239
239
  ```
240
240
 
241
241
  참고로 `$$`의 `get` 함수가 `Promise`나 에러를 만났을 때 throw 대신 반환하는 값은 다음 과정으로 만들어집니다:
@@ -246,7 +246,7 @@ const toUndefined = () => undefined;
246
246
  Object.setPrototypeOf(o, new Proxy(o, { get: (_, k) => k === Symbol.toPrimitive ? toUndefined : o }));
247
247
  ```
248
248
 
249
- 이 코드의 `o`는 아무리 프로퍼티 접근 및 호출을 해도 같은 값을 반환합니다. `o.a.b.c().d()().asdf()()()() === o`는 `true`입니다. 따라서, 셀렉터와 filter/map/reduce 등 간단한 메서드로 이뤄진 대부분의 상태 병합 함수에서 문제 없이 전체 코드를 실행할 수 있게 만듭니다. 하지만 만능은 아니므로 약간의 주의가 필요하며, 가급적 상태 병합에만 사용해야 합니다.
249
+ 이 코드의 `o`는 아무리 프로퍼티 접근 및 호출을 해도 같은 값을 반환합니다. 예를 들어, `o.a.b.c().d()().asdf()()()() === o`는 `true`입니다. 따라서, 셀렉터와 filter/map/reduce 등 간단한 메서드로 이뤄진 대부분의 상태 병합 함수에서 문제 없이 전체 코드를 실행할 수 있게 만듭니다. 하지만 만능은 아니므로 약간의 주의가 필요하며, 가급적 상태 병합에만 사용해야 합니다.
250
250
 
251
251
  ## 상세
252
252
 
package/README.md CHANGED
@@ -16,7 +16,7 @@ You can create a state with the `$` function. There are two types of states.
16
16
 
17
17
  #### Primitive State
18
18
 
19
- The most basic unit of state. Its value is static and can be updated to any value using the `.set` method.
19
+ The most basic unit of state. It can be updated to any value using the `.set` method.
20
20
 
21
21
  It is created by passing a normal value (number/string/object, etc.) to the `$` function.
22
22
 
@@ -30,7 +30,7 @@ const $user = $({ name: 'John Doe', age: 30 });
30
30
 
31
31
  #### Derived State
32
32
 
33
- A state whose value is dynamic and has a lifecycle. It cannot be updated directly; it can only be re-executed when the value of a state it depends on changes. If the state is not active (i.e., there are no subscribers), the function will not run, and it is treated as having no dependencies.
33
+ A state whose value is computed by a function and has a lifecycle. It cannot be updated directly; it can only be re-executed when the value of a state it depends on changes. If the state is not active (i.e., there are no subscribers), the function will not run, and it is treated as having no dependencies.
34
34
 
35
35
  It is created by passing a function to `$`. The arguments to this function are a `get` function, which can read the values of other states, and `{ signal }`, which represents the state's lifetime. The `signal` will be discussed in more detail in another section.
36
36
 
@@ -82,7 +82,7 @@ You can read the current value of a state using the `atom.get()` method or `atom
82
82
  console.log($count.get()); // 42
83
83
  console.log($countDouble.get()); // 84
84
84
 
85
- console.log($countDouble.state); // { promise: undefined, error: Symbol(), value: 84 }
85
+ console.log($countDouble.state); // { promise: undefined, error: undefined, value: 84 }
86
86
  ```
87
87
 
88
88
  For derived states, `.get()` can throw. It throws the `Promise` during asynchronous loading and throws the error when in an error state. This is useful when you want to primarily handle the success case and push all exception handling into a `catch` block or similar.
@@ -213,7 +213,7 @@ const $user = $(
213
213
  );
214
214
 
215
215
  const $user2 = $(
216
- (get) => get($user).name,
216
+ (get) => get($user),
217
217
  { equals: (next, prev) => next.name === prev.name },
218
218
  );
219
219
 
@@ -246,7 +246,7 @@ const toUndefined = () => undefined;
246
246
  Object.setPrototypeOf(o, new Proxy(o, { get: (_, k) => k === Symbol.toPrimitive ? toUndefined : o }));
247
247
  ```
248
248
 
249
- The `o` in this code returns the same value no matter how many properties are accessed or functions are called. `o.a.b.c().d()().asdf()()()() === o` is `true`. Therefore, it allows most state-merging functions composed of selectors and simple methods like filter/map/reduce to execute without issues. However, it's not a silver bullet, so some caution is needed, and it should preferably be used only for state merging.
249
+ The `o` in this code returns the same value no matter how many properties are accessed or functions are called. For example, `o.a.b.c().d()().asdf()()()() === o` is `true`. Therefore, it allows most state-merging functions composed of selectors and simple methods like filter/map/reduce to execute without issues. However, it's not a silver bullet, so some caution is needed, and it should preferably be used only for state merging.
250
250
 
251
251
  ## In-Depth
252
252
 
@@ -1 +1 @@
1
- var l=function(){};l.prototype.get=function(){if(this.n||(h(this),i(this)),this.state.promise)throw this.state.promise;if(this.state.error)throw this.state.error;return this.state.value};l.prototype.watch=function(e){return this.n||S(this),(this.l??=new Set).add(e),()=>{this.l.delete(e),this.l.size||i(this)}};l.prototype.subscribe=function(e){let t={f:e,V:{get signal(){return(t.t??=P()).signal}}};if(!this.n)S(this);else if(!this.state.promise&&!this.state.error)try{e(this.state.value,t.V)}catch(o){console.error(o)}return(this.s??=new Set).add(t),()=>{this.s.delete(t),t.t&&(t.t.abort(),t.t=void 0),this.s.size||i(this)}};l.prototype[Symbol.toPrimitive]=function(){return this.state.value};var s=function(e,t){this.c=t?.equals,this.state={promise:void 0,error:void 0,value:e},this.state.value=this.a=e};s.prototype.set=function(e){let t=e instanceof Function?e(this.a):e;y(t,this.state.value,this.c)||(this.a=t,A(this))};s.prototype.m=!0;s.prototype.n=!0;s.prototype.o=!1;Object.setPrototypeOf(s.prototype,l.prototype);var u=function(e,t){this.y=e,this.c=t?.equals,this.b=t?.persist,this.state={promise:v,error:void 0,value:void 0};let o=this;this.V={get signal(){return(o.t??=P()).signal}}};u.prototype.m=!1;u.prototype.n=!1;u.prototype.o=!1;u.prototype.i=0;Object.setPrototypeOf(u.prototype,l.prototype);var V=()=>V,g=()=>{};Object.setPrototypeOf(V,new Proxy(V,{get:(e,t)=>t===Symbol.toPrimitive?g:V}));var v=Promise.resolve(),k=(e,t)=>e instanceof Function?new u(e,t):new s(e,t),O=e=>k((t,o)=>{let r,n,m=e(x=>{try{return t(x)}catch(p){if(!p)throw p;b(p)?(r??=[]).push(p):n=p}return V},o);if(n)throw n;if(r)throw Promise.all(r);return m}),f=!1,a=[],S=e=>{e.u||(e.u=!0,A(e))},A=e=>{e.o||(e.o=!0,a.push(e),f||(f=!0,queueMicrotask(_)))},_=()=>{f=!1;{let t=a;a=[];for(let o of t)o.state.promise=void 0,o.state.error=o.A,o.state.value=o.a,I(o)}let e=a;a=[];for(let t=e.length;t--;){let o=e[t];o.d=!1,o.u&&(o.o=!0,h(o)),o.o&&w(o)}},w=e=>{if(e.o=!1,e.r)for(let t of e.r)t.u=!0;if(e.l)for(let t of e.l)t();if(e.s&&!e.state.promise&&!e.state.error)for(let t of e.s){t.t&&(t.t.abort(),t.t=void 0);try{t.f(e.state.value,t.V)}catch(o){console.error(o)}}},I=e=>{if(!e.d){if(e.d=!0,e.r)for(let t of e.r)I(t);a.push(e)}},c=class{e;constructor(t){this.e=t}},h=e=>{let t=++e.i;e.n=!0,e.u=!1,e.state.promise=void 0,e.t&&(e.t.abort(),e.t=void 0);let o=e.p;o&&(e.p=new Set);try{let r=e.y((n,m=!0)=>{if(t!==e.i)throw void 0;if(e!==n&&(n.n||(h(n),n.o&&(n.o=!1,w(n))),o?.delete(n),(e.p??=new Set).add(n),(n.r??=new Set).add(e)),!m)return n.state;if(n.state.promise)throw new c(n.state.promise);if(n.state.error)throw new c(n.state.error);return n.state.value},e.V);b(r)?(e.state.promise=r,r.then(n=>{t===e.i&&(y(n,e.state.value,e.c)?e.state.promise=void 0:(e.a=n,e.A=void 0,A(e)))},n=>{t===e.i&&(n instanceof Promise?e.state.promise=void 0:(e.A=n,A(e)))})):(++e.i,e.state.error=void 0,y(r,e.state.value,e.c)?e.o=!1:e.state.value=e.a=r)}catch(r){++e.i,r?(r instanceof c?r=r.e:console.error(r),b(r)?e.state.promise=r:e.state.error=r):e.o=!1}if(o)for(let r of o)r.r.delete(e),i(r)},d=!1,i=e=>{if(!e.m&&!e.b&&!e.r?.size&&!e.l?.size&&!e.s?.size){if(!d){setTimeout(()=>{d=!0,i(e),d=!1},0);return}if(e.state.promise=v,e.a=e.A=e.state.error=e.state.value=void 0,e.o=e.u=e.n=!1,e.t&&(e.t.abort(),e.t=void 0),e.p){for(let t of e.p)t.r.delete(e),i(t);e.p.clear()}}},y=(e,t,o)=>Object.is(e,t)||o!==void 0&&t!==void 0&&o(e,t),b=e=>typeof e?.then=="function",P=()=>{let e=new AbortController,t=e.signal,o=new Promise(r=>{t.then=n=>o.then(n),t.addEventListener("abort",r,{once:!0,passive:!0})});return{abort:()=>e.abort(),signal:t}};export{k as $,O as $$,v as inactive};
1
+ var s=function(){};s.prototype.get=function(){if(this.n||(v(this),l(this)),this.state.promise)throw this.state.promise;if(this.state.error)throw this.state.error;return this.state.value};s.prototype.watch=function(e){return this.n||w(this),(this.l??=new Set).add(e),()=>{this.l.delete(e),this.l.size||l(this)}};s.prototype.subscribe=function(e){let t={f:e,V:{get signal(){return(t.t??=g()).signal}}};if(!this.n)w(this);else if(!this.state.promise&&!this.state.error)try{e(this.state.value,t.V)}catch(o){m(o)}return(this.s??=new Set).add(t),()=>{this.s.delete(t),t.t&&(t.t.abort(),t.t=void 0),this.s.size||l(this)}};s.prototype[Symbol.toPrimitive]=function(){return this.state.value};var u=function(e,t){this.c=t?.equals,this.state={promise:void 0,error:void 0,value:e},this.state.value=this.a=e};u.prototype.set=function(e){let t=e instanceof Function?e(this.a):e;b(t,this.state.value,this.c)||(this.a=t,A(this))};u.prototype.m=!0;u.prototype.n=!0;u.prototype.o=!1;Object.setPrototypeOf(u.prototype,s.prototype);var p=function(e,t){this.y=e,this.c=t?.equals,this.b=t?.persist,this.state={promise:S,error:void 0,value:void 0};let o=this;this.V={get signal(){return(o.t??=g()).signal}}};p.prototype.m=!1;p.prototype.n=!1;p.prototype.o=!1;p.prototype.i=0;Object.setPrototypeOf(p.prototype,s.prototype);var c=()=>c,k=()=>{};Object.setPrototypeOf(c,new Proxy(c,{get:(e,t)=>t===Symbol.toPrimitive?k:c}));var S=Promise.resolve(),_=(e,t)=>e instanceof Function?new p(e,t):new u(e,t),G=e=>_((t,o)=>{let r,n,d=e(x=>{try{return t(x)}catch(V){if(!V)throw V;h(V)?(r??=[]).push(V):n=V}return c},o);if(n)throw n;if(r)throw Promise.all(r);return d}),y=!1,a=[],w=e=>{e.u||(e.u=!0,A(e))},A=e=>{e.o||(e.o=!0,a.push(e),y||(y=!0,queueMicrotask(O)))},O=()=>{y=!1;{let t=a;a=[];for(let o of t)o.state.promise=void 0,o.state.error=o.A,o.state.value=o.a,P(o)}let e=a;a=[];for(let t=e.length;t--;){let o=e[t];o.d=!1,o.u&&(o.o=!0,v(o)),o.o&&I(o)}},I=e=>{if(e.o=!1,e.r)for(let t of e.r)t.u=!0;if(e.l)for(let t of e.l)t();if(e.s&&!e.state.promise&&!e.state.error)for(let t of e.s){t.t&&(t.t.abort(),t.t=void 0);try{t.f(e.state.value,t.V)}catch(o){m(o)}}},P=e=>{if(!e.d){if(e.d=!0,e.r)for(let t of e.r)P(t);a.push(e)}},i=class{e;constructor(t){this.e=t}},v=e=>{let t=++e.i;e.n=!0,e.u=!1,e.state.promise=void 0,e.t&&(e.t.abort(),e.t=void 0);let o=e.p;o&&(e.p=new Set);try{let r=e.y((n,d=!0)=>{if(t!==e.i)throw void 0;if(e!==n&&(n.n||(v(n),n.o&&(n.o=!1,I(n))),o?.delete(n),(e.p??=new Set).add(n),(n.r??=new Set).add(e)),!d)return n.state;if(n.state.promise)throw new i(n.state.promise);if(n.state.error)throw new i(n.state.error);return n.state.value},e.V);h(r)?(e.state.promise=r,r.then(n=>{t===e.i&&(b(n,e.state.value,e.c)?e.state.promise=void 0:(e.a=n,e.A=void 0,A(e)))},n=>{t===e.i&&(n instanceof Promise?e.state.promise=void 0:(n instanceof i?n=n.e:m(n),e.A=n,A(e)))})):(++e.i,e.state.error=void 0,b(r,e.state.value,e.c)?e.o=!1:e.state.value=e.a=r)}catch(r){++e.i,r?(r instanceof i?r=r.e:m(r),h(r)?e.state.promise=r:e.state.error=r):e.o=!1}if(o)for(let r of o)r.r.delete(e),l(r)},f=!1,l=e=>{if(!e.m&&!e.b&&!e.r?.size&&!e.l?.size&&!e.s?.size){if(!f){setTimeout(()=>{f=!0,l(e),f=!1},0);return}if(e.state.promise=S,e.a=e.A=e.state.error=e.state.value=void 0,e.o=e.u=e.n=!1,e.t&&(e.t.abort(),e.t=void 0),e.p){for(let t of e.p)t.r.delete(e),l(t);e.p.clear()}}},b=(e,t,o)=>Object.is(e,t)||o!==void 0&&t!==void 0&&o(e,t),h=e=>typeof e?.then=="function",g=()=>{let e=new AbortController,t=e.signal,o=new Promise(r=>{t.then=n=>o.then(n),t.addEventListener("abort",r,{once:!0,passive:!0})});return{abort:()=>e.abort(),signal:t}},m=e=>{queueMicrotask(()=>{throw e})};export{_ as $,G as $$,S as inactive};
package/dist/index.js CHANGED
@@ -36,7 +36,7 @@ AtomPrototype.prototype.subscribe = function(subscriber) {
36
36
  try {
37
37
  subscriber(this.state.value, atomSubscriber.l);
38
38
  } catch (e) {
39
- console.error(e);
39
+ logError(e);
40
40
  }
41
41
  }
42
42
  (this.i ??= /* @__PURE__ */ new Set()).add(atomSubscriber);
@@ -199,7 +199,7 @@ const propagate = (atom) => {
199
199
  try {
200
200
  subscriber.q(atom.state.value, subscriber.l);
201
201
  } catch (e) {
202
- console.error(e);
202
+ logError(e);
203
203
  }
204
204
  }
205
205
  }
@@ -273,12 +273,17 @@ const execute = (atom) => {
273
273
  }
274
274
  }
275
275
  },
276
- (error) => {
276
+ (e) => {
277
277
  if (counter === atom.g) {
278
- if (error instanceof Promise) {
278
+ if (e instanceof Promise) {
279
279
  atom.state.promise = void 0;
280
280
  } else {
281
- atom.n = error;
281
+ if (e instanceof Wrapped) {
282
+ e = e.e;
283
+ } else {
284
+ logError(e);
285
+ }
286
+ atom.n = e;
282
287
  requestPropagate(atom);
283
288
  }
284
289
  }
@@ -301,7 +306,7 @@ const execute = (atom) => {
301
306
  if (e instanceof Wrapped) {
302
307
  e = e.e;
303
308
  } else {
304
- console.error(e);
309
+ logError(e);
305
310
  }
306
311
  if (isPromiseLike(e)) {
307
312
  atom.state.promise = e;
@@ -361,6 +366,11 @@ const createThenableSignal = () => {
361
366
  signal
362
367
  };
363
368
  };
369
+ const logError = (e) => {
370
+ queueMicrotask(() => {
371
+ throw e;
372
+ });
373
+ };
364
374
  export {
365
375
  $,
366
376
  $$,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bansa",
3
- "version": "0.0.3",
3
+ "version": "0.0.6",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",