bansa 0.0.16 → 0.0.18

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/dist/atom.d.ts ADDED
@@ -0,0 +1,79 @@
1
+ export type Atom<Value> = PrimitiveAtom<Value> | DerivedAtom<Value>;
2
+ export type CommonAtom<Value> = {
3
+ readonly get: () => Value;
4
+ readonly watch: (watcher: AtomWatcher) => () => void;
5
+ readonly subscribe: (subscriber: AtomSubscribe<Value>) => () => void;
6
+ readonly state: AtomState<Value>;
7
+ };
8
+ export type PrimitiveAtom<Value> = CommonAtom<Value> & {
9
+ readonly set: (value: AtomUpdater<Value>) => void;
10
+ readonly state: AtomSuccessState<Value>;
11
+ };
12
+ export type DerivedAtom<Value> = CommonAtom<Value>;
13
+ export type AtomWatcher = () => void;
14
+ export type AtomSubscribe<Value> = (value: Value, options: AtomSubscriberOptions) => void;
15
+ export type AtomInit<Value> = Value | AtomGetter<Value>;
16
+ export type AtomUpdater<Value> = Value | AtomReducer<Value>;
17
+ export type AtomInactiveState<Value> = {
18
+ promise: typeof inactive;
19
+ error: any;
20
+ value?: Value;
21
+ };
22
+ export type AtomPromiseState<Value> = {
23
+ promise: PromiseLike<Value>;
24
+ error: any;
25
+ value?: Value;
26
+ };
27
+ export type AtomSuccessState<Value> = {
28
+ promise: undefined;
29
+ error: undefined;
30
+ value: Value;
31
+ };
32
+ export type AtomErrorState<Value> = {
33
+ promise: undefined;
34
+ error: any;
35
+ value?: Value;
36
+ };
37
+ export type AtomState<Value> = AtomInactiveState<Value> | AtomPromiseState<Value> | AtomSuccessState<Value> | AtomErrorState<Value>;
38
+ export type AtomSubscriberOptions = {
39
+ readonly signal: ThenableSignal;
40
+ };
41
+ export type AtomGetter<Value> = (get: GetAtom, options: AtomGetOptions) => Value | PromiseLike<Value>;
42
+ export type AtomReducer<Value> = (value: Value) => Value;
43
+ export type AtomGetOptions = {
44
+ readonly signal: ThenableSignal;
45
+ };
46
+ export type ThenableSignal = AbortSignal & {
47
+ then: (f: () => void) => void;
48
+ };
49
+ export type GetAtom = {
50
+ <Value>(anotherAtom: Atom<Value>, unwrap?: true): Value;
51
+ <Value>(anotherAtom: Atom<Value>, unwrap: false): AtomState<Value>;
52
+ };
53
+ type CreateAtom = {
54
+ <Value>(init: AtomGetter<Value>, options?: AtomOptions<Value>): DerivedAtom<Value>;
55
+ <Value>(init: Value, options?: AtomOptions<Value>): PrimitiveAtom<Value>;
56
+ <Value>(init: Value | AtomGetter<Value>, options?: AtomOptions<Value>): Atom<Value>;
57
+ };
58
+ export type AtomOptions<Value> = {
59
+ equals?: AtomEquals<Value>;
60
+ persist?: boolean;
61
+ eager?: boolean;
62
+ };
63
+ export type AtomEquals<Value> = (value: Value, prevValue: Value) => boolean;
64
+ export type AtomScope = {
65
+ <Value>(baseAtom: PrimitiveAtom<Value>): PrimitiveAtom<Value>;
66
+ <Value>(baseAtom: DerivedAtom<Value>): DerivedAtom<Value>;
67
+ <Value>(baseAtom: Atom<Value>): Atom<Value>;
68
+ <Value>(baseAtom: PrimitiveAtom<Value>, strict: true): PrimitiveAtom<Value> | undefined;
69
+ <Value>(baseAtom: DerivedAtom<Value>, strict: true): DerivedAtom<Value> | undefined;
70
+ <Value>(baseAtom: Atom<Value>, strict: true): Atom<Value> | undefined;
71
+ };
72
+ export type SetLike<Key> = Key[] | Set<Key> | (Key extends object ? WeakSet<Key> : never);
73
+ export type MapLike<Key, Value> = Map<Key, Value> | (Key extends object ? WeakMap<Key, Value> : never) | (Key extends string | number | symbol ? Record<Key, Value> : never);
74
+ export declare const inactive: Promise<never>;
75
+ export declare const $: CreateAtom;
76
+ export declare const isAtom: (x: unknown) => x is Atom<unknown>;
77
+ export type AtomValuePair<Value> = [Atom<Value>, Value | PrimitiveAtom<Value>] | [DerivedAtom<Value>, Value | Atom<Value>];
78
+ export declare const createScope: <T extends AtomValuePair<unknown>[]>(parentScope?: AtomScope | null, atomValuePairs?: T) => AtomScope;
79
+ export {};
package/dist/atom.js ADDED
@@ -0,0 +1,414 @@
1
+ class CommonAtomInternal {
2
+ d;
3
+ o;
4
+ b;
5
+ f;
6
+ g;
7
+ get() {
8
+ if (!this.h) {
9
+ execute(this);
10
+ disableAtom(this);
11
+ }
12
+ if (this.state.error) throw this.state.error;
13
+ if (this.state.promise) throw this.state.promise;
14
+ return this.state.value;
15
+ }
16
+ watch(watcher) {
17
+ if (!this.h) {
18
+ requestActivate(this);
19
+ }
20
+ (this.f ||= /* @__PURE__ */ new Set()).add(watcher);
21
+ return () => {
22
+ this.f.delete(watcher);
23
+ if (!this.f.size) {
24
+ disableAtom(this);
25
+ }
26
+ };
27
+ }
28
+ subscribe(subscriber) {
29
+ const atomSubscriber = {
30
+ t: subscriber,
31
+ p: {
32
+ get signal() {
33
+ return (atomSubscriber.a ||= createThenableSignal()).signal;
34
+ }
35
+ }
36
+ };
37
+ if (!this.h) {
38
+ requestActivate(this);
39
+ } else if (!this.state.error && !this.state.promise) {
40
+ try {
41
+ subscriber(this.state.value, atomSubscriber.p);
42
+ } catch (e) {
43
+ logError(e);
44
+ }
45
+ }
46
+ (this.g ||= /* @__PURE__ */ new Set()).add(atomSubscriber);
47
+ return () => {
48
+ this.g.delete(atomSubscriber);
49
+ if (atomSubscriber.a) {
50
+ atomSubscriber.a.abort();
51
+ atomSubscriber.a = void 0;
52
+ }
53
+ if (!this.g.size) {
54
+ disableAtom(this);
55
+ }
56
+ };
57
+ }
58
+ [Symbol.toPrimitive]() {
59
+ return this.state.value;
60
+ }
61
+ }
62
+ class PrimitiveAtomInternal extends CommonAtomInternal {
63
+ c = false;
64
+ q = false;
65
+ constructor(init, options) {
66
+ super();
67
+ this.l = init;
68
+ this.m = options?.equals;
69
+ this.d = init;
70
+ this.state = {
71
+ promise: void 0,
72
+ error: void 0,
73
+ value: init
74
+ };
75
+ }
76
+ set(value) {
77
+ const nextValue = value instanceof Function ? value(this.d) : value;
78
+ if (!equals(nextValue, this.state.value, this.m)) {
79
+ this.d = nextValue;
80
+ requestPropagate(this);
81
+ }
82
+ }
83
+ }
84
+ PrimitiveAtomInternal.prototype.r = true;
85
+ PrimitiveAtomInternal.prototype.h = true;
86
+ PrimitiveAtomInternal.prototype.i = false;
87
+ class DerivedAtomInternal extends CommonAtomInternal {
88
+ h = false;
89
+ i = false;
90
+ c = false;
91
+ q = false;
92
+ n = 0;
93
+ a;
94
+ j;
95
+ k;
96
+ constructor(init, options) {
97
+ super();
98
+ this.l = init;
99
+ this.m = options?.equals;
100
+ this.s = !!options?.persist;
101
+ const self = this;
102
+ this.p = {
103
+ get signal() {
104
+ return (self.a ||= createThenableSignal()).signal;
105
+ }
106
+ };
107
+ this.state = {
108
+ promise: inactive,
109
+ error: void 0,
110
+ value: void 0
111
+ };
112
+ }
113
+ }
114
+ DerivedAtomInternal.prototype.r = false;
115
+ const inactive = Promise.reject();
116
+ inactive.catch(() => {
117
+ });
118
+ const $ = (init, options) => {
119
+ if (init instanceof Function)
120
+ return new DerivedAtomInternal(init, options);
121
+ return new PrimitiveAtomInternal(init, options);
122
+ };
123
+ const isAtom = (x) => x instanceof CommonAtomInternal;
124
+ const createScope = (parentScope, atomValuePairs) => {
125
+ const scopeMap = /* @__PURE__ */ new WeakMap();
126
+ const atomMap = /* @__PURE__ */ new WeakMap();
127
+ const scope = ((baseAtom, strict = false) => {
128
+ let scopedAtom = scopeMap.get(baseAtom);
129
+ if (!strict) scopedAtom ||= atomMap.get(baseAtom);
130
+ if (!scopedAtom) {
131
+ const parentAtom = parentScope?.(baseAtom, true);
132
+ if (strict) return parentAtom;
133
+ const realBaseAtom = parentAtom || baseAtom;
134
+ atomMap.set(
135
+ baseAtom,
136
+ scopedAtom = realBaseAtom.l instanceof Function ? $((get, options) => realBaseAtom.l(
137
+ (atom, unwrap) => get(scope(atom), unwrap),
138
+ options
139
+ ), {
140
+ equals: realBaseAtom.m,
141
+ persist: realBaseAtom.s
142
+ }) : parentAtom || $(realBaseAtom.l)
143
+ );
144
+ }
145
+ return scopedAtom;
146
+ });
147
+ if (atomValuePairs) {
148
+ for (const [atom, value] of atomValuePairs) {
149
+ scopeMap.set(atom, isAtom(value) ? scope(value) : $(value));
150
+ }
151
+ }
152
+ return scope;
153
+ };
154
+ let pendingUpdateAtoms = false;
155
+ let updateQueue = [];
156
+ let stack = [];
157
+ const requestActivate = (atom) => {
158
+ if (!atom.i) {
159
+ atom.i = true;
160
+ requestPropagate(atom);
161
+ }
162
+ };
163
+ const requestPropagate = (atom) => {
164
+ if (!atom.c) {
165
+ atom.c = true;
166
+ updateQueue.push(atom);
167
+ if (!pendingUpdateAtoms) {
168
+ pendingUpdateAtoms = true;
169
+ queueMicrotask(updateAtoms);
170
+ }
171
+ }
172
+ };
173
+ const updateAtoms = () => {
174
+ pendingUpdateAtoms = false;
175
+ {
176
+ const updatedAtoms = updateQueue;
177
+ updateQueue = [];
178
+ for (const atom of updatedAtoms) {
179
+ atom.state.promise = void 0;
180
+ atom.state.error = atom.o;
181
+ atom.state.value = atom.d;
182
+ mark(atom);
183
+ }
184
+ }
185
+ const markedAtoms = stack;
186
+ stack = [];
187
+ for (let i = markedAtoms.length; i--; ) {
188
+ const atom = markedAtoms[i];
189
+ atom.q = false;
190
+ if (atom.i) {
191
+ atom.c = true;
192
+ execute(atom);
193
+ }
194
+ if (atom.c) {
195
+ propagate(atom);
196
+ }
197
+ }
198
+ };
199
+ const propagate = (atom) => {
200
+ atom.c = false;
201
+ if (atom.f) {
202
+ for (const watcher of atom.f) {
203
+ try {
204
+ watcher();
205
+ } catch (e) {
206
+ logError(e);
207
+ }
208
+ }
209
+ }
210
+ if (!atom.state.error && !atom.state.promise) {
211
+ if (atom.g) {
212
+ for (const subscriber of atom.g) {
213
+ if (subscriber.a) {
214
+ subscriber.a.abort();
215
+ subscriber.a = void 0;
216
+ }
217
+ try {
218
+ subscriber.t(atom.state.value, subscriber.p);
219
+ } catch (e) {
220
+ logError(e);
221
+ }
222
+ }
223
+ }
224
+ if (atom.b) {
225
+ for (const child of atom.b) {
226
+ child.i = true;
227
+ }
228
+ }
229
+ }
230
+ };
231
+ const mark = (atom) => {
232
+ if (!atom.q) {
233
+ atom.q = true;
234
+ if (atom.b) {
235
+ for (const child of atom.b) {
236
+ mark(child);
237
+ }
238
+ }
239
+ stack.push(atom);
240
+ }
241
+ };
242
+ class Wrapped {
243
+ e;
244
+ constructor(e) {
245
+ this.e = e;
246
+ }
247
+ }
248
+ const expired = Symbol();
249
+ const execute = (atom) => {
250
+ const counter = ++atom.n;
251
+ atom.h = true;
252
+ atom.i = false;
253
+ atom.state.promise = void 0;
254
+ if (atom.a) {
255
+ atom.a.abort();
256
+ atom.a = void 0;
257
+ }
258
+ try {
259
+ const value = atom.l(
260
+ (anotherAtom, unwrap = true) => {
261
+ if (counter !== atom.n) throw expired;
262
+ if (atom !== anotherAtom) {
263
+ if (!anotherAtom.h) {
264
+ execute(anotherAtom);
265
+ if (anotherAtom.c) {
266
+ propagate(anotherAtom);
267
+ }
268
+ }
269
+ (atom.k ||= /* @__PURE__ */ new Set()).add(anotherAtom);
270
+ (anotherAtom.b ||= /* @__PURE__ */ new Set()).add(atom);
271
+ }
272
+ if (!unwrap) return anotherAtom.state;
273
+ if (anotherAtom.state.error)
274
+ throw new Wrapped(anotherAtom.state.error);
275
+ if (anotherAtom.state.promise)
276
+ throw new Wrapped(anotherAtom.state.promise);
277
+ return anotherAtom.state.value;
278
+ },
279
+ atom.p
280
+ );
281
+ if (isPromiseLike(value)) {
282
+ atom.state.promise = value;
283
+ value.then(
284
+ (value2) => {
285
+ if (counter === atom.n) {
286
+ finalizeExecution(atom);
287
+ if (equals(value2, atom.state.value, atom.m)) {
288
+ atom.state.promise = void 0;
289
+ } else {
290
+ atom.d = value2;
291
+ atom.o = void 0;
292
+ }
293
+ requestPropagate(atom);
294
+ }
295
+ },
296
+ (e) => {
297
+ if (counter === atom.n) {
298
+ finalizeExecution(atom);
299
+ if (e instanceof Wrapped) {
300
+ e = e.e;
301
+ } else {
302
+ logError(e);
303
+ }
304
+ atom.o = e;
305
+ requestPropagate(atom);
306
+ }
307
+ }
308
+ );
309
+ } else {
310
+ finalizeExecution(atom);
311
+ atom.state.error = void 0;
312
+ if (equals(value, atom.state.value, atom.m)) {
313
+ atom.c = false;
314
+ } else {
315
+ atom.state.value = atom.d = value;
316
+ }
317
+ }
318
+ } catch (e) {
319
+ finalizeExecution(atom);
320
+ if (e === expired) {
321
+ atom.c = false;
322
+ } else {
323
+ if (e instanceof Wrapped) {
324
+ e = e.e;
325
+ } else {
326
+ logError(e);
327
+ }
328
+ atom.state.error = e;
329
+ }
330
+ }
331
+ };
332
+ const finalizeExecution = (atom) => {
333
+ ++atom.n;
334
+ const oldDependencies = atom.j;
335
+ atom.j = atom.k;
336
+ if (oldDependencies) {
337
+ for (const dep of oldDependencies) {
338
+ if (!atom.j?.has(dep)) {
339
+ dep.b.delete(atom);
340
+ disableAtom(dep);
341
+ }
342
+ }
343
+ oldDependencies.clear();
344
+ }
345
+ atom.k = oldDependencies;
346
+ };
347
+ let runningGc = false;
348
+ let gcCandidates = /* @__PURE__ */ new Set();
349
+ const disableAtom = (atom) => {
350
+ if (!atom.r && !atom.s && !atom.b?.size && !atom.f?.size && !atom.g?.size) {
351
+ gcCandidates.add(atom);
352
+ if (!runningGc) {
353
+ runningGc = true;
354
+ setTimeout(gc, 0);
355
+ }
356
+ }
357
+ };
358
+ const gc = () => {
359
+ for (const atom of gcCandidates) {
360
+ if (!atom.r && !atom.s && !atom.b?.size && !atom.f?.size && !atom.g?.size) {
361
+ atom.state.promise = inactive;
362
+ atom.d = atom.o = atom.state.error = atom.state.value = void 0;
363
+ atom.c = atom.i = atom.h = false;
364
+ if (atom.a) {
365
+ atom.a.abort();
366
+ atom.a = void 0;
367
+ }
368
+ if (atom.j) {
369
+ for (const dep of atom.j) {
370
+ dep.b.delete(atom);
371
+ disableAtom(dep);
372
+ }
373
+ atom.j.clear();
374
+ if (atom.k) {
375
+ for (const dep of atom.k) {
376
+ dep.b.delete(atom);
377
+ disableAtom(dep);
378
+ }
379
+ atom.k.clear();
380
+ }
381
+ }
382
+ }
383
+ }
384
+ gcCandidates.clear();
385
+ runningGc = false;
386
+ };
387
+ const equals = (value, prevValue, equalsFn) => Object.is(value, prevValue) || equalsFn !== void 0 && prevValue !== void 0 && equalsFn(value, prevValue);
388
+ const isPromiseLike = (x) => typeof x?.then === "function";
389
+ const createThenableSignal = () => {
390
+ const ctrl = new AbortController();
391
+ const signal = ctrl.signal;
392
+ const promise = new Promise((resolve) => {
393
+ signal.then = (f) => promise.then(f);
394
+ signal.addEventListener("abort", resolve, {
395
+ once: true,
396
+ passive: true
397
+ });
398
+ });
399
+ return {
400
+ abort: () => ctrl.abort(),
401
+ signal
402
+ };
403
+ };
404
+ const logError = (e) => {
405
+ queueMicrotask(() => {
406
+ throw e;
407
+ });
408
+ };
409
+ export {
410
+ $,
411
+ createScope,
412
+ inactive,
413
+ isAtom
414
+ };
@@ -1 +1 @@
1
- var f=class{r;p;a;o;l;get(){if(this.s||(P(this),i(this)),this.state.error)throw this.state.error;if(this.state.promise)throw this.state.promise;return this.state.value}watch(t){return this.s||_(this),(this.o||=new Set).add(t),()=>{this.o.delete(t),this.o.size||i(this)}}subscribe(t){let a={h:t,A:{get signal(){return(a.t||=T()).signal}}};if(!this.s)_(this);else if(!this.state.error&&!this.state.promise)try{t(this.state.value,a.A)}catch(n){p(n)}return(this.l||=new Set).add(a),()=>{this.l.delete(a),a.t&&(a.t.abort(),a.t=void 0),this.l.size||i(this)}}[Symbol.toPrimitive](){return this.state.value}},c=class extends f{n=!1;m=!1;constructor(t,a){super(),this.d=t,this.V=a?.equals,this.r=t,this.state={promise:void 0,error:void 0,value:t}}set(t){let a=t instanceof Function?t(this.r):t;I(a,this.state.value,this.V)||(this.r=a,b(this))}};c.prototype.y=!0;c.prototype.s=!0;c.prototype.u=!1;var y=class extends f{s=!1;u=!1;n=!1;m=!1;f=0;t;i;c;constructor(t,a){super(),this.d=t,this.V=a?.equals,this.b=!!a?.persist;let n=this;this.A={get signal(){return(n.t||=T()).signal}},this.state={promise:k,error:void 0,value:void 0}}};y.prototype.y=!1;var V=()=>V,O=()=>{};Object.setPrototypeOf(V,new Proxy(V,{get:(e,t)=>t===Symbol.toPrimitive?O:V}));var k=Promise.reject();k.catch(O);var m=(e,t)=>e instanceof Function?new y(e,t):new c(e,t),U=e=>m((t,a)=>{let n,r,l=e(s=>{let o=t(s,!1);if(o.error)r=o.error;else if(o.promise)(n||=[]).push(o.promise);else return o.value;return V},a);if(r)throw r;if(n)throw Promise.all(n);return l},{equals:z}),R=(e,t)=>{let a=new WeakMap,n=new WeakMap,r=((l,s=!1)=>{let o=a.get(l);if(!o){let h=e?.(l,!0);if(s)return h;let d=h||l;n.set(l,o=d.d instanceof Function?m((E,K)=>d.d((L,j)=>E(r(L),j),K),{equals:d.V,persist:d.b}):h||m(d.d))}return o});if(t)for(let[l,s]of t)a.set(l,s instanceof f?r(s):m(s));return r},z=(e,t)=>{if(typeof e!="object"||typeof t!="object"||!e||!t)return!1;let a=e.constructor;if(a!==t.constructor)return!1;if(a===Array){let r=e.length;if(r!==t.length)return!1;for(;(r=r-1|0)>=0;)if(!Object.is(e[r],t[r]))return!1;return!0}let n=0;for(let r in e){if(!(r in t&&Object.is(e[r],t[r])))return!1;n=n+1|0}for(let r in t)if((n=n-1|0)<0)return!1;return!0},v=!1,S=[],w=[],_=e=>{e.u||(e.u=!0,b(e))},b=e=>{e.n||(e.n=!0,S.push(e),v||(v=!0,queueMicrotask(C)))},C=()=>{v=!1;{let t=S;S=[];for(let a of t)a.state.promise=void 0,a.state.error=a.p,a.state.value=a.r,D(a)}let e=w;w=[];for(let t=e.length;t--;){let a=e[t];a.m=!1,a.u&&(a.n=!0,P(a)),a.n&&q(a)}},q=e=>{if(e.n=!1,e.o)for(let t of e.o)try{t()}catch(a){p(a)}if(!e.state.error&&!e.state.promise){if(e.l)for(let t of e.l){t.t&&(t.t.abort(),t.t=void 0);try{t.h(e.state.value,t.A)}catch(a){p(a)}}if(e.a)for(let t of e.a)t.u=!0}},D=e=>{if(!e.m){if(e.m=!0,e.a)for(let t of e.a)D(t);w.push(e)}},u=class{e;constructor(t){this.e=t}},G=Symbol(),P=e=>{let t=++e.f;e.s=!0,e.u=!1,e.state.promise=void 0,e.t&&(e.t.abort(),e.t=void 0);try{let a=e.d((n,r=!0)=>{if(t!==e.f)throw G;if(e!==n&&(n.s||(P(n),n.n&&q(n)),(e.c||=new Set).add(n),(n.a||=new Set).add(e)),!r)return n.state;if(n.state.error)throw new u(n.state.error);if(n.state.promise)throw new u(n.state.promise);return n.state.value},e.A);W(a)?(e.state.promise=a,a.then(n=>{t===e.f&&(A(e),I(n,e.state.value,e.V)?e.state.promise=void 0:(e.r=n,e.p=void 0),b(e))},n=>{t===e.f&&(A(e),n instanceof u?n=n.e:p(n),e.p=n,b(e))})):(A(e),e.state.error=void 0,I(a,e.state.value,e.V)?e.n=!1:e.state.value=e.r=a)}catch(a){A(e),a===G?e.n=!1:(a instanceof u?a=a.e:p(a),e.state.error=a)}},A=e=>{++e.f;let t=e.i;if(e.i=e.c,t){for(let a of t)e.i?.has(a)||(a.a.delete(e),i(a));t.clear()}e.c=t},x=!1,g=new Set,i=e=>{!e.y&&!e.b&&!e.a?.size&&!e.o?.size&&!e.l?.size&&(g.add(e),x||(x=!0,setTimeout(M,0)))},M=()=>{for(let e of g)if(!e.y&&!e.b&&!e.a?.size&&!e.o?.size&&!e.l?.size&&(e.state.promise=k,e.r=e.p=e.state.error=e.state.value=void 0,e.n=e.u=e.s=!1,e.t&&(e.t.abort(),e.t=void 0),e.i)){for(let t of e.i)t.a.delete(e),i(t);if(e.i.clear(),e.c){for(let t of e.c)t.a.delete(e),i(t);e.c.clear()}}g.clear(),x=!1},I=(e,t,a)=>Object.is(e,t)||a!==void 0&&t!==void 0&&a(e,t),W=e=>typeof e?.then=="function",T=()=>{let e=new AbortController,t=e.signal,a=new Promise(n=>{t.then=r=>a.then(r),t.addEventListener("abort",n,{once:!0,passive:!0})});return{abort:()=>e.abort(),signal:t}},p=e=>{queueMicrotask(()=>{throw e})};export{m as $,U as $$,R as createScope,k as inactive};
1
+ var V=class{o;p;a;r;l;get(){if(this.s||(P(this),c(this)),this.state.error)throw this.state.error;if(this.state.promise)throw this.state.promise;return this.state.value}watch(t){return this.s||G(this),(this.r||=new Set).add(t),()=>{this.r.delete(t),this.r.size||c(this)}}subscribe(t){let a={v:t,m:{get signal(){return(a.t||=q()).signal}}};if(!this.s)G(this);else if(!this.state.error&&!this.state.promise)try{t(this.state.value,a.m)}catch(n){p(n)}return(this.l||=new Set).add(a),()=>{this.l.delete(a),a.t&&(a.t.abort(),a.t=void 0),this.l.size||c(this)}}[Symbol.toPrimitive](){return this.state.value}},d=class extends V{n=!1;A=!1;constructor(t,a){super(),this.d=t,this.f=a?.equals,this.o=t,this.state={promise:void 0,error:void 0,value:t}}set(t){let a=t instanceof Function?t(this.o):t;k(a,this.state.value,this.f)||(this.o=a,b(this))}};d.prototype.y=!0;d.prototype.s=!0;d.prototype.i=!1;var y=class extends V{s=!1;i=!1;n=!1;A=!1;V=0;t;u;c;constructor(t,a){super(),this.d=t,this.f=a?.equals,this.b=!!a?.persist;let n=this;this.m={get signal(){return(n.t||=q()).signal}},this.state={promise:I,error:void 0,value:void 0}}};y.prototype.y=!1;var I=Promise.reject();I.catch(()=>{});var u=(e,t)=>e instanceof Function?new y(e,t):new d(e,t),T=e=>e instanceof V,Q=(e,t)=>{let a=new WeakMap,n=new WeakMap,o=((r,s=!1)=>{let l=a.get(r);if(s||(l||=n.get(r)),!l){let v=e?.(r,!0);if(s)return v;let f=v||r;n.set(r,l=f.d instanceof Function?u((j,K)=>f.d((z,E)=>j(o(z),E),K),{equals:f.f,persist:f.b}):v||u(f.d))}return l});if(t)for(let[r,s]of t)a.set(r,T(s)?o(s):u(s));return o},h=!1,S=[],x=[],G=e=>{e.i||(e.i=!0,b(e))},b=e=>{e.n||(e.n=!0,S.push(e),h||(h=!0,queueMicrotask(L)))},L=()=>{h=!1;{let t=S;S=[];for(let a of t)a.state.promise=void 0,a.state.error=a.p,a.state.value=a.o,O(a)}let e=x;x=[];for(let t=e.length;t--;){let a=e[t];a.A=!1,a.i&&(a.n=!0,P(a)),a.n&&D(a)}},D=e=>{if(e.n=!1,e.r)for(let t of e.r)try{t()}catch(a){p(a)}if(!e.state.error&&!e.state.promise){if(e.l)for(let t of e.l){t.t&&(t.t.abort(),t.t=void 0);try{t.v(e.state.value,t.m)}catch(a){p(a)}}if(e.a)for(let t of e.a)t.i=!0}},O=e=>{if(!e.A){if(e.A=!0,e.a)for(let t of e.a)O(t);x.push(e)}},i=class{e;constructor(t){this.e=t}},_=Symbol(),P=e=>{let t=++e.V;e.s=!0,e.i=!1,e.state.promise=void 0,e.t&&(e.t.abort(),e.t=void 0);try{let a=e.d((n,o=!0)=>{if(t!==e.V)throw _;if(e!==n&&(n.s||(P(n),n.n&&D(n)),(e.c||=new Set).add(n),(n.a||=new Set).add(e)),!o)return n.state;if(n.state.error)throw new i(n.state.error);if(n.state.promise)throw new i(n.state.promise);return n.state.value},e.m);U(a)?(e.state.promise=a,a.then(n=>{t===e.V&&(A(e),k(n,e.state.value,e.f)?e.state.promise=void 0:(e.o=n,e.p=void 0),b(e))},n=>{t===e.V&&(A(e),n instanceof i?n=n.e:p(n),e.p=n,b(e))})):(A(e),e.state.error=void 0,k(a,e.state.value,e.f)?e.n=!1:e.state.value=e.o=a)}catch(a){A(e),a===_?e.n=!1:(a instanceof i?a=a.e:p(a),e.state.error=a)}},A=e=>{++e.V;let t=e.u;if(e.u=e.c,t){for(let a of t)e.u?.has(a)||(a.a.delete(e),c(a));t.clear()}e.c=t},w=!1,g=new Set,c=e=>{!e.y&&!e.b&&!e.a?.size&&!e.r?.size&&!e.l?.size&&(g.add(e),w||(w=!0,setTimeout(M,0)))},M=()=>{for(let e of g)if(!e.y&&!e.b&&!e.a?.size&&!e.r?.size&&!e.l?.size&&(e.state.promise=I,e.o=e.p=e.state.error=e.state.value=void 0,e.n=e.i=e.s=!1,e.t&&(e.t.abort(),e.t=void 0),e.u)){for(let t of e.u)t.a.delete(e),c(t);if(e.u.clear(),e.c){for(let t of e.c)t.a.delete(e),c(t);e.c.clear()}}g.clear(),w=!1},k=(e,t,a)=>Object.is(e,t)||a!==void 0&&t!==void 0&&a(e,t),U=e=>typeof e?.then=="function",q=()=>{let e=new AbortController,t=e.signal,a=new Promise(n=>{t.then=o=>a.then(o),t.addEventListener("abort",n,{once:!0,passive:!0})});return{abort:()=>e.abort(),signal:t}},p=e=>{queueMicrotask(()=>{throw e})};var m=()=>m,W=()=>{};Object.setPrototypeOf(m,new Proxy(m,{get:(e,t)=>t===Symbol.toPrimitive?W:m}));var C=e=>{if(typeof e!="object"||e===null)return u(e);if(Array.isArray(e))return e.map(C);let t=Object.create(null);for(let a in e)t[a]=C(e[a]);return t},$=e=>e.get(),F=(e,t=$)=>{let a=n=>{if(typeof n!="object"||n===null)return n;if(T(n))return t(n);if(Array.isArray(n))return n.map(a);let o=Object.create(null);for(let r in n)o[r]=a(n[r]);return o};return a(e)},R=e=>e instanceof Function?u((t,a)=>{let n,o,r=e(s=>{let l=t(s,!1);if(l.error)o=l.error;else if(l.promise)(n||=[]).push(l.promise);else return l.value;return m},a);if(o)throw o;if(n)throw Promise.all(n);return r},{equals:B}):R(t=>F(e,t)),B=(e,t)=>{if(typeof e!="object"||typeof t!="object"||!e||!t)return!1;let a=e.constructor;if(a!==t.constructor)return!1;if(a===Array){let o=e.length;if(o!==t.length)return!1;for(;(o=o-1|0)>=0;)if(!Object.is(e[o],t[o]))return!1;return!0}let n=0;for(let o in e){if(!(o in t&&Object.is(e[o],t[o])))return!1;n=n+1|0}for(let o in t)if((n=n-1|0)<0)return!1;return!0};export{u as $,R as $$,C as atomize,F as collectAtoms,Q as createScope,I as inactive,T as isAtom};
package/dist/index.d.ts CHANGED
@@ -1,79 +1,2 @@
1
- export type Atom<Value> = PrimitiveAtom<Value> | DerivedAtom<Value>;
2
- export type CommonAtom<Value> = {
3
- readonly get: () => Value;
4
- readonly watch: (watcher: AtomWatcher) => () => void;
5
- readonly subscribe: (subscriber: AtomSubscribe<Value>) => () => void;
6
- readonly state: AtomState<Value>;
7
- };
8
- export type PrimitiveAtom<Value> = CommonAtom<Value> & {
9
- readonly set: (value: AtomUpdater<Value>) => void;
10
- readonly state: AtomSuccessState<Value>;
11
- };
12
- export type DerivedAtom<Value> = CommonAtom<Value>;
13
- export type AtomWatcher = () => void;
14
- export type AtomSubscribe<Value> = (value: Value, options: AtomSubscriberOptions) => void;
15
- export type AtomInit<Value> = Value | AtomGetter<Value>;
16
- export type AtomUpdater<Value> = Value | AtomReducer<Value>;
17
- export type AtomInactiveState<Value> = {
18
- promise: typeof inactive;
19
- error: any;
20
- value?: Value;
21
- };
22
- export type AtomPromiseState<Value> = {
23
- promise: PromiseLike<Value>;
24
- error: any;
25
- value?: Value;
26
- };
27
- export type AtomSuccessState<Value> = {
28
- promise: undefined;
29
- error: undefined;
30
- value: Value;
31
- };
32
- export type AtomErrorState<Value> = {
33
- promise: undefined;
34
- error: any;
35
- value?: Value;
36
- };
37
- export type AtomState<Value> = AtomInactiveState<Value> | AtomPromiseState<Value> | AtomSuccessState<Value> | AtomErrorState<Value>;
38
- export type AtomSubscriberOptions = {
39
- readonly signal: ThenableSignal;
40
- };
41
- export type AtomGetter<Value> = (get: GetAtom, options: AtomGetOptions) => Value | PromiseLike<Value>;
42
- export type AtomReducer<Value> = (value: Value) => Value;
43
- export type AtomGetOptions = {
44
- readonly signal: ThenableSignal;
45
- };
46
- export type ThenableSignal = AbortSignal & {
47
- then: (f: () => void) => void;
48
- };
49
- export type GetAtom = {
50
- <Value>(anotherAtom: Atom<Value>, unwrap?: true): Value;
51
- <Value>(anotherAtom: Atom<Value>, unwrap: false): AtomState<Value>;
52
- };
53
- type CreateAtom = {
54
- <Value>(init: AtomGetter<Value>, options?: AtomOptions<Value>): DerivedAtom<Value>;
55
- <Value>(init: Value, options?: AtomOptions<Value>): PrimitiveAtom<Value>;
56
- <Value>(init: Value | AtomGetter<Value>, options?: AtomOptions<Value>): Atom<Value>;
57
- };
58
- export type AtomOptions<Value> = {
59
- equals?: AtomEquals<Value>;
60
- persist?: boolean;
61
- eager?: boolean;
62
- };
63
- export type AtomEquals<Value> = (value: Value, prevValue: Value) => boolean;
64
- export type AtomScope = {
65
- <Value>(baseAtom: PrimitiveAtom<Value>): PrimitiveAtom<Value>;
66
- <Value>(baseAtom: DerivedAtom<Value>): DerivedAtom<Value>;
67
- <Value>(baseAtom: Atom<Value>): Atom<Value>;
68
- <Value>(baseAtom: PrimitiveAtom<Value>, strict: true): PrimitiveAtom<Value> | undefined;
69
- <Value>(baseAtom: DerivedAtom<Value>, strict: true): DerivedAtom<Value> | undefined;
70
- <Value>(baseAtom: Atom<Value>, strict: true): Atom<Value> | undefined;
71
- };
72
- export type SetLike<Key> = Key[] | Set<Key> | (Key extends object ? WeakSet<Key> : never);
73
- export type MapLike<Key, Value> = Map<Key, Value> | (Key extends object ? WeakMap<Key, Value> : never) | (Key extends string | number | symbol ? Record<Key, Value> : never);
74
- export declare const inactive: Promise<never>;
75
- export declare const $: CreateAtom;
76
- export declare const $$: <Value>(init: AtomGetter<Value>) => DerivedAtom<Value>;
77
- export type AtomValuePair<Value> = [Atom<Value>, Value | PrimitiveAtom<Value>] | [DerivedAtom<Value>, Value | Atom<Value>];
78
- export declare const createScope: <T extends AtomValuePair<unknown>[]>(parentScope?: AtomScope | null, atomValuePairs?: T) => AtomScope;
79
- export {};
1
+ export * from './atom';
2
+ export * from './utils';
package/dist/index.js CHANGED
@@ -1,453 +1,2 @@
1
- class CommonAtomInternal {
2
- d;
3
- o;
4
- b;
5
- f;
6
- g;
7
- get() {
8
- if (!this.h) {
9
- execute(this);
10
- disableAtom(this);
11
- }
12
- if (this.state.error) throw this.state.error;
13
- if (this.state.promise) throw this.state.promise;
14
- return this.state.value;
15
- }
16
- watch(watcher) {
17
- if (!this.h) {
18
- requestActivate(this);
19
- }
20
- (this.f ||= /* @__PURE__ */ new Set()).add(watcher);
21
- return () => {
22
- this.f.delete(watcher);
23
- if (!this.f.size) {
24
- disableAtom(this);
25
- }
26
- };
27
- }
28
- subscribe(subscriber) {
29
- const atomSubscriber = {
30
- t: subscriber,
31
- p: {
32
- get signal() {
33
- return (atomSubscriber.a ||= createThenableSignal()).signal;
34
- }
35
- }
36
- };
37
- if (!this.h) {
38
- requestActivate(this);
39
- } else if (!this.state.error && !this.state.promise) {
40
- try {
41
- subscriber(this.state.value, atomSubscriber.p);
42
- } catch (e) {
43
- logError(e);
44
- }
45
- }
46
- (this.g ||= /* @__PURE__ */ new Set()).add(atomSubscriber);
47
- return () => {
48
- this.g.delete(atomSubscriber);
49
- if (atomSubscriber.a) {
50
- atomSubscriber.a.abort();
51
- atomSubscriber.a = void 0;
52
- }
53
- if (!this.g.size) {
54
- disableAtom(this);
55
- }
56
- };
57
- }
58
- [Symbol.toPrimitive]() {
59
- return this.state.value;
60
- }
61
- }
62
- class PrimitiveAtomInternal extends CommonAtomInternal {
63
- c = false;
64
- q = false;
65
- constructor(init, options) {
66
- super();
67
- this.l = init;
68
- this.m = options?.equals;
69
- this.d = init;
70
- this.state = {
71
- promise: void 0,
72
- error: void 0,
73
- value: init
74
- };
75
- }
76
- set(value) {
77
- const nextValue = value instanceof Function ? value(this.d) : value;
78
- if (!equals(nextValue, this.state.value, this.m)) {
79
- this.d = nextValue;
80
- requestPropagate(this);
81
- }
82
- }
83
- }
84
- PrimitiveAtomInternal.prototype.r = true;
85
- PrimitiveAtomInternal.prototype.h = true;
86
- PrimitiveAtomInternal.prototype.i = false;
87
- class DerivedAtomInternal extends CommonAtomInternal {
88
- h = false;
89
- i = false;
90
- c = false;
91
- q = false;
92
- n = 0;
93
- a;
94
- j;
95
- k;
96
- constructor(init, options) {
97
- super();
98
- this.l = init;
99
- this.m = options?.equals;
100
- this.s = !!options?.persist;
101
- const self = this;
102
- this.p = {
103
- get signal() {
104
- return (self.a ||= createThenableSignal()).signal;
105
- }
106
- };
107
- this.state = {
108
- promise: inactive,
109
- error: void 0,
110
- value: void 0
111
- };
112
- }
113
- }
114
- DerivedAtomInternal.prototype.r = false;
115
- const ouroboros = () => ouroboros;
116
- const toUndefined = () => void 0;
117
- Object.setPrototypeOf(
118
- ouroboros,
119
- new Proxy(ouroboros, {
120
- get: (_, k) => k === Symbol.toPrimitive ? toUndefined : ouroboros
121
- })
122
- );
123
- const inactive = Promise.reject();
124
- inactive.catch(toUndefined);
125
- const $ = (init, options) => {
126
- if (init instanceof Function)
127
- return new DerivedAtomInternal(init, options);
128
- return new PrimitiveAtomInternal(init, options);
129
- };
130
- const $$ = (init) => $((get, options) => {
131
- let promises;
132
- let error;
133
- const result = init((atom) => {
134
- const state = get(atom, false);
135
- if (state.error) error = state.error;
136
- else if (state.promise) (promises ||= []).push(state.promise);
137
- else return state.value;
138
- return ouroboros;
139
- }, options);
140
- if (error) throw error;
141
- if (promises) throw Promise.all(promises);
142
- return result;
143
- }, {
144
- equals: shallowEquals
145
- });
146
- const createScope = (parentScope, atomValuePairs) => {
147
- const scopeMap = /* @__PURE__ */ new WeakMap();
148
- const atomMap = /* @__PURE__ */ new WeakMap();
149
- const scope = ((baseAtom, strict = false) => {
150
- let scopedAtom = scopeMap.get(baseAtom);
151
- if (!scopedAtom) {
152
- const parentAtom = parentScope?.(baseAtom, true);
153
- if (strict) return parentAtom;
154
- const realBaseAtom = parentAtom || baseAtom;
155
- atomMap.set(
156
- baseAtom,
157
- scopedAtom = realBaseAtom.l instanceof Function ? $((get, options) => realBaseAtom.l(
158
- (atom, unwrap) => get(scope(atom), unwrap),
159
- options
160
- ), {
161
- equals: realBaseAtom.m,
162
- persist: realBaseAtom.s
163
- }) : parentAtom || $(realBaseAtom.l)
164
- );
165
- }
166
- return scopedAtom;
167
- });
168
- if (atomValuePairs) {
169
- for (const [atom, value] of atomValuePairs) {
170
- scopeMap.set(atom, value instanceof CommonAtomInternal ? scope(value) : $(value));
171
- }
172
- }
173
- return scope;
174
- };
175
- const shallowEquals = (a, b) => {
176
- if (typeof a !== "object" || typeof b !== "object" || !a || !b) return false;
177
- const c = a.constructor;
178
- if (c !== b.constructor) return false;
179
- if (c === Array) {
180
- let i = a.length;
181
- if (i !== b.length) return false;
182
- while ((i = i - 1 | 0) >= 0) if (!Object.is(a[i], b[i])) return false;
183
- return true;
184
- }
185
- let n = 0;
186
- for (const k in a) {
187
- if (!(k in b && Object.is(a[k], b[k]))) return false;
188
- n = n + 1 | 0;
189
- }
190
- for (const _ in b) if ((n = n - 1 | 0) < 0) return false;
191
- return true;
192
- };
193
- let pendingUpdateAtoms = false;
194
- let updateQueue = [];
195
- let stack = [];
196
- const requestActivate = (atom) => {
197
- if (!atom.i) {
198
- atom.i = true;
199
- requestPropagate(atom);
200
- }
201
- };
202
- const requestPropagate = (atom) => {
203
- if (!atom.c) {
204
- atom.c = true;
205
- updateQueue.push(atom);
206
- if (!pendingUpdateAtoms) {
207
- pendingUpdateAtoms = true;
208
- queueMicrotask(updateAtoms);
209
- }
210
- }
211
- };
212
- const updateAtoms = () => {
213
- pendingUpdateAtoms = false;
214
- {
215
- const updatedAtoms = updateQueue;
216
- updateQueue = [];
217
- for (const atom of updatedAtoms) {
218
- atom.state.promise = void 0;
219
- atom.state.error = atom.o;
220
- atom.state.value = atom.d;
221
- mark(atom);
222
- }
223
- }
224
- const markedAtoms = stack;
225
- stack = [];
226
- for (let i = markedAtoms.length; i--; ) {
227
- const atom = markedAtoms[i];
228
- atom.q = false;
229
- if (atom.i) {
230
- atom.c = true;
231
- execute(atom);
232
- }
233
- if (atom.c) {
234
- propagate(atom);
235
- }
236
- }
237
- };
238
- const propagate = (atom) => {
239
- atom.c = false;
240
- if (atom.f) {
241
- for (const watcher of atom.f) {
242
- try {
243
- watcher();
244
- } catch (e) {
245
- logError(e);
246
- }
247
- }
248
- }
249
- if (!atom.state.error && !atom.state.promise) {
250
- if (atom.g) {
251
- for (const subscriber of atom.g) {
252
- if (subscriber.a) {
253
- subscriber.a.abort();
254
- subscriber.a = void 0;
255
- }
256
- try {
257
- subscriber.t(atom.state.value, subscriber.p);
258
- } catch (e) {
259
- logError(e);
260
- }
261
- }
262
- }
263
- if (atom.b) {
264
- for (const child of atom.b) {
265
- child.i = true;
266
- }
267
- }
268
- }
269
- };
270
- const mark = (atom) => {
271
- if (!atom.q) {
272
- atom.q = true;
273
- if (atom.b) {
274
- for (const child of atom.b) {
275
- mark(child);
276
- }
277
- }
278
- stack.push(atom);
279
- }
280
- };
281
- class Wrapped {
282
- e;
283
- constructor(e) {
284
- this.e = e;
285
- }
286
- }
287
- const expired = Symbol();
288
- const execute = (atom) => {
289
- const counter = ++atom.n;
290
- atom.h = true;
291
- atom.i = false;
292
- atom.state.promise = void 0;
293
- if (atom.a) {
294
- atom.a.abort();
295
- atom.a = void 0;
296
- }
297
- try {
298
- const value = atom.l(
299
- (anotherAtom, unwrap = true) => {
300
- if (counter !== atom.n) throw expired;
301
- if (atom !== anotherAtom) {
302
- if (!anotherAtom.h) {
303
- execute(anotherAtom);
304
- if (anotherAtom.c) {
305
- propagate(anotherAtom);
306
- }
307
- }
308
- (atom.k ||= /* @__PURE__ */ new Set()).add(anotherAtom);
309
- (anotherAtom.b ||= /* @__PURE__ */ new Set()).add(atom);
310
- }
311
- if (!unwrap) return anotherAtom.state;
312
- if (anotherAtom.state.error)
313
- throw new Wrapped(anotherAtom.state.error);
314
- if (anotherAtom.state.promise)
315
- throw new Wrapped(anotherAtom.state.promise);
316
- return anotherAtom.state.value;
317
- },
318
- atom.p
319
- );
320
- if (isPromiseLike(value)) {
321
- atom.state.promise = value;
322
- value.then(
323
- (value2) => {
324
- if (counter === atom.n) {
325
- finalizeExecution(atom);
326
- if (equals(value2, atom.state.value, atom.m)) {
327
- atom.state.promise = void 0;
328
- } else {
329
- atom.d = value2;
330
- atom.o = void 0;
331
- }
332
- requestPropagate(atom);
333
- }
334
- },
335
- (e) => {
336
- if (counter === atom.n) {
337
- finalizeExecution(atom);
338
- if (e instanceof Wrapped) {
339
- e = e.e;
340
- } else {
341
- logError(e);
342
- }
343
- atom.o = e;
344
- requestPropagate(atom);
345
- }
346
- }
347
- );
348
- } else {
349
- finalizeExecution(atom);
350
- atom.state.error = void 0;
351
- if (equals(value, atom.state.value, atom.m)) {
352
- atom.c = false;
353
- } else {
354
- atom.state.value = atom.d = value;
355
- }
356
- }
357
- } catch (e) {
358
- finalizeExecution(atom);
359
- if (e === expired) {
360
- atom.c = false;
361
- } else {
362
- if (e instanceof Wrapped) {
363
- e = e.e;
364
- } else {
365
- logError(e);
366
- }
367
- atom.state.error = e;
368
- }
369
- }
370
- };
371
- const finalizeExecution = (atom) => {
372
- ++atom.n;
373
- const oldDependencies = atom.j;
374
- atom.j = atom.k;
375
- if (oldDependencies) {
376
- for (const dep of oldDependencies) {
377
- if (!atom.j?.has(dep)) {
378
- dep.b.delete(atom);
379
- disableAtom(dep);
380
- }
381
- }
382
- oldDependencies.clear();
383
- }
384
- atom.k = oldDependencies;
385
- };
386
- let runningGc = false;
387
- let gcCandidates = /* @__PURE__ */ new Set();
388
- const disableAtom = (atom) => {
389
- if (!atom.r && !atom.s && !atom.b?.size && !atom.f?.size && !atom.g?.size) {
390
- gcCandidates.add(atom);
391
- if (!runningGc) {
392
- runningGc = true;
393
- setTimeout(gc, 0);
394
- }
395
- }
396
- };
397
- const gc = () => {
398
- for (const atom of gcCandidates) {
399
- if (!atom.r && !atom.s && !atom.b?.size && !atom.f?.size && !atom.g?.size) {
400
- atom.state.promise = inactive;
401
- atom.d = atom.o = atom.state.error = atom.state.value = void 0;
402
- atom.c = atom.i = atom.h = false;
403
- if (atom.a) {
404
- atom.a.abort();
405
- atom.a = void 0;
406
- }
407
- if (atom.j) {
408
- for (const dep of atom.j) {
409
- dep.b.delete(atom);
410
- disableAtom(dep);
411
- }
412
- atom.j.clear();
413
- if (atom.k) {
414
- for (const dep of atom.k) {
415
- dep.b.delete(atom);
416
- disableAtom(dep);
417
- }
418
- atom.k.clear();
419
- }
420
- }
421
- }
422
- }
423
- gcCandidates.clear();
424
- runningGc = false;
425
- };
426
- const equals = (value, prevValue, equalsFn) => Object.is(value, prevValue) || equalsFn !== void 0 && prevValue !== void 0 && equalsFn(value, prevValue);
427
- const isPromiseLike = (x) => typeof x?.then === "function";
428
- const createThenableSignal = () => {
429
- const ctrl = new AbortController();
430
- const signal = ctrl.signal;
431
- const promise = new Promise((resolve) => {
432
- signal.then = (f) => promise.then(f);
433
- signal.addEventListener("abort", resolve, {
434
- once: true,
435
- passive: true
436
- });
437
- });
438
- return {
439
- abort: () => ctrl.abort(),
440
- signal
441
- };
442
- };
443
- const logError = (e) => {
444
- queueMicrotask(() => {
445
- throw e;
446
- });
447
- };
448
- export {
449
- $,
450
- $$,
451
- createScope,
452
- inactive
453
- };
1
+ export * from "./atom";
2
+ export * from "./utils";
package/dist/react.d.ts CHANGED
@@ -6,7 +6,7 @@ export declare const ScopeProvider: ({ value, children }: {
6
6
  children: React.ReactNode;
7
7
  }) => import("react/jsx-runtime").JSX.Element;
8
8
  export declare const useAtomValue: <Value>(atom: Atom<Value>) => Value;
9
- export declare const useAtomState: <Value>(atom: DerivedAtom<Value>) => import(".").AtomState<Value>;
9
+ export declare const useAtomState: <Value>(atom: DerivedAtom<Value>) => import("./atom").AtomState<Value>;
10
10
  export declare const useAtom: <Value>(atom: PrimitiveAtom<Value>) => readonly [Value, (newState: Value) => void];
11
11
  export declare const useLocalAtom: typeof $;
12
12
  export declare const useLocalAtomValue: <Value>(init: Value | AtomGetter<Value>, options?: AtomOptions<Value>) => Value;
@@ -0,0 +1,15 @@
1
+ import { type PrimitiveAtom, type Atom, type AtomGetter, type DerivedAtom } from "./atom";
2
+ type Atomized<T> = T extends object ? {
3
+ [K in keyof T]: Atomized<T[K]>;
4
+ } : PrimitiveAtom<T>;
5
+ type CollectedAtoms<T> = T extends Atom<infer U> ? U : T extends object ? {
6
+ [K in keyof T]: CollectedAtoms<T[K]>;
7
+ } : T;
8
+ type CollectAtom = {
9
+ <Value>(init: AtomGetter<Value>): DerivedAtom<Value>;
10
+ <Value>(init: Value): DerivedAtom<CollectedAtoms<Value>>;
11
+ };
12
+ export declare const atomize: <T>(tree: T) => Atomized<T>;
13
+ export declare const collectAtoms: <T>(tree: T, get?: <T_1>(atom: Atom<T_1>) => T_1) => CollectedAtoms<T>;
14
+ export declare const $$: CollectAtom;
15
+ export {};
package/dist/utils.js ADDED
@@ -0,0 +1,67 @@
1
+ import { $, isAtom } from "./atom";
2
+ const ouroboros = () => ouroboros;
3
+ const toUndefined = () => void 0;
4
+ Object.setPrototypeOf(
5
+ ouroboros,
6
+ new Proxy(ouroboros, {
7
+ get: (_, k) => k === Symbol.toPrimitive ? toUndefined : ouroboros
8
+ })
9
+ );
10
+ const atomize = (tree) => {
11
+ if (typeof tree !== "object" || tree === null) return $(tree);
12
+ if (Array.isArray(tree)) return tree.map(atomize);
13
+ const result = /* @__PURE__ */ Object.create(null);
14
+ for (const k in tree) result[k] = atomize(tree[k]);
15
+ return result;
16
+ };
17
+ const getAtom = (atom) => atom.get();
18
+ const collectAtoms = (tree, get = getAtom) => {
19
+ const recurse = (t) => {
20
+ if (typeof t !== "object" || t === null) return t;
21
+ if (isAtom(t)) return get(t);
22
+ if (Array.isArray(t)) return t.map(recurse);
23
+ const result = /* @__PURE__ */ Object.create(null);
24
+ for (const k in t) result[k] = recurse(t[k]);
25
+ return result;
26
+ };
27
+ return recurse(tree);
28
+ };
29
+ const $$ = (init) => init instanceof Function ? $((get, options) => {
30
+ let promises;
31
+ let error;
32
+ const result = init((atom) => {
33
+ const state = get(atom, false);
34
+ if (state.error) error = state.error;
35
+ else if (state.promise) (promises ||= []).push(state.promise);
36
+ else return state.value;
37
+ return ouroboros;
38
+ }, options);
39
+ if (error) throw error;
40
+ if (promises) throw Promise.all(promises);
41
+ return result;
42
+ }, {
43
+ equals: shallowEquals
44
+ }) : $$((get) => collectAtoms(init, get));
45
+ const shallowEquals = (a, b) => {
46
+ if (typeof a !== "object" || typeof b !== "object" || !a || !b) return false;
47
+ const c = a.constructor;
48
+ if (c !== b.constructor) return false;
49
+ if (c === Array) {
50
+ let i = a.length;
51
+ if (i !== b.length) return false;
52
+ while ((i = i - 1 | 0) >= 0) if (!Object.is(a[i], b[i])) return false;
53
+ return true;
54
+ }
55
+ let n = 0;
56
+ for (const k in a) {
57
+ if (!(k in b && Object.is(a[k], b[k]))) return false;
58
+ n = n + 1 | 0;
59
+ }
60
+ for (const _ in b) if ((n = n - 1 | 0) < 0) return false;
61
+ return true;
62
+ };
63
+ export {
64
+ $$,
65
+ atomize,
66
+ collectAtoms
67
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bansa",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -55,7 +55,9 @@
55
55
  "build": "pnpm run \"/^build:.*/\"",
56
56
  "build:types": "tsc --noEmit false --emitDeclarationOnly --outDir dist",
57
57
  "build:index": "esbuild src/index.ts --mangle-props=^_ --format=esm --target=es2022 --outfile=dist/index.js",
58
- "build:index-browser": "esbuild src/index.ts --mangle-props=^_ --minify --bundle --format=esm --target=es2022 --platform=browser --outfile=dist/index.browser.js",
58
+ "build:index-browser": "esbuild src/index.ts --bundle --mangle-props=^_ --minify --bundle --format=esm --target=es2022 --platform=browser --outfile=dist/index.browser.js",
59
+ "build:atom": "esbuild src/atom.ts --mangle-props=^_ --format=esm --target=es2022 --outfile=dist/atom.js",
60
+ "build:utils": "esbuild src/utils.ts --mangle-props=^_ --format=esm --target=es2022 --outfile=dist/utils.js",
59
61
  "build:react": "esbuild src/react.tsx --mangle-props=^_ --format=esm --target=es2022 --outfile=dist/react.js",
60
62
  "test": "vitest",
61
63
  "format": "biome format --write ./src"
@@ -1109,7 +1109,7 @@ describe('Bansa Documentation Examples as Tests', () => {
1109
1109
  ]);
1110
1110
 
1111
1111
  const $y2 = scope($y);
1112
- expect(scope($x)).toBe($x2);
1112
+ expect(scope($x).get()).toBe($x2.get());
1113
1113
  expect($y2).not.toBe($y);
1114
1114
  expect($y2).toBe(scope($y));
1115
1115
 
@@ -1207,7 +1207,7 @@ describe('Bansa Documentation Examples as Tests', () => {
1207
1207
  expect($x.get()).toBe(10);
1208
1208
  expect($y.get()).toBe(11);
1209
1209
  expect($x2.get()).toBe(1000);
1210
- expect($y2.get()).toBe(1001);
1210
+ expect($y2.get()).toBe(101);
1211
1211
  });
1212
1212
  });
1213
1213
 
Binary file