bansa 0.0.17 → 0.0.19

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,80 @@
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 declare const isPrimitiveAtom: (x: unknown) => x is PrimitiveAtom<unknown>;
78
+ export type AtomValuePair<Value> = [Atom<Value>, Value | PrimitiveAtom<Value>] | [DerivedAtom<Value>, Value | Atom<Value>];
79
+ export declare const createScope: <T extends AtomValuePair<unknown>[]>(parentScope?: AtomScope | null, atomValuePairs?: T) => AtomScope;
80
+ export {};
package/dist/atom.js ADDED
@@ -0,0 +1,416 @@
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 isPrimitiveAtom = (x) => x instanceof PrimitiveAtomInternal;
125
+ const createScope = (parentScope, atomValuePairs) => {
126
+ const scopeMap = /* @__PURE__ */ new WeakMap();
127
+ const atomMap = /* @__PURE__ */ new WeakMap();
128
+ const scope = ((baseAtom, strict = false) => {
129
+ let scopedAtom = scopeMap.get(baseAtom);
130
+ if (!strict) scopedAtom ||= atomMap.get(baseAtom);
131
+ if (!scopedAtom) {
132
+ const parentAtom = parentScope?.(baseAtom, true);
133
+ if (strict) return parentAtom;
134
+ const realBaseAtom = parentAtom || baseAtom;
135
+ atomMap.set(
136
+ baseAtom,
137
+ scopedAtom = realBaseAtom.l instanceof Function ? $((get, options) => realBaseAtom.l(
138
+ (atom, unwrap) => get(scope(atom), unwrap),
139
+ options
140
+ ), {
141
+ equals: realBaseAtom.m,
142
+ persist: realBaseAtom.s
143
+ }) : parentAtom || $(realBaseAtom.l)
144
+ );
145
+ }
146
+ return scopedAtom;
147
+ });
148
+ if (atomValuePairs) {
149
+ for (const [atom, value] of atomValuePairs) {
150
+ scopeMap.set(atom, isAtom(value) ? scope(value) : $(value));
151
+ }
152
+ }
153
+ return scope;
154
+ };
155
+ let pendingUpdateAtoms = false;
156
+ let updateQueue = [];
157
+ let stack = [];
158
+ const requestActivate = (atom) => {
159
+ if (!atom.i) {
160
+ atom.i = true;
161
+ requestPropagate(atom);
162
+ }
163
+ };
164
+ const requestPropagate = (atom) => {
165
+ if (!atom.c) {
166
+ atom.c = true;
167
+ updateQueue.push(atom);
168
+ if (!pendingUpdateAtoms) {
169
+ pendingUpdateAtoms = true;
170
+ queueMicrotask(updateAtoms);
171
+ }
172
+ }
173
+ };
174
+ const updateAtoms = () => {
175
+ pendingUpdateAtoms = false;
176
+ {
177
+ const updatedAtoms = updateQueue;
178
+ updateQueue = [];
179
+ for (const atom of updatedAtoms) {
180
+ atom.state.promise = void 0;
181
+ atom.state.error = atom.o;
182
+ atom.state.value = atom.d;
183
+ mark(atom);
184
+ }
185
+ }
186
+ const markedAtoms = stack;
187
+ stack = [];
188
+ for (let i = markedAtoms.length; i--; ) {
189
+ const atom = markedAtoms[i];
190
+ atom.q = false;
191
+ if (atom.i) {
192
+ atom.c = true;
193
+ execute(atom);
194
+ }
195
+ if (atom.c) {
196
+ propagate(atom);
197
+ }
198
+ }
199
+ };
200
+ const propagate = (atom) => {
201
+ atom.c = false;
202
+ if (atom.f) {
203
+ for (const watcher of atom.f) {
204
+ try {
205
+ watcher();
206
+ } catch (e) {
207
+ logError(e);
208
+ }
209
+ }
210
+ }
211
+ if (!atom.state.error && !atom.state.promise) {
212
+ if (atom.g) {
213
+ for (const subscriber of atom.g) {
214
+ if (subscriber.a) {
215
+ subscriber.a.abort();
216
+ subscriber.a = void 0;
217
+ }
218
+ try {
219
+ subscriber.t(atom.state.value, subscriber.p);
220
+ } catch (e) {
221
+ logError(e);
222
+ }
223
+ }
224
+ }
225
+ if (atom.b) {
226
+ for (const child of atom.b) {
227
+ child.i = true;
228
+ }
229
+ }
230
+ }
231
+ };
232
+ const mark = (atom) => {
233
+ if (!atom.q) {
234
+ atom.q = true;
235
+ if (atom.b) {
236
+ for (const child of atom.b) {
237
+ mark(child);
238
+ }
239
+ }
240
+ stack.push(atom);
241
+ }
242
+ };
243
+ class Wrapped {
244
+ e;
245
+ constructor(e) {
246
+ this.e = e;
247
+ }
248
+ }
249
+ const expired = Symbol();
250
+ const execute = (atom) => {
251
+ const counter = ++atom.n;
252
+ atom.h = true;
253
+ atom.i = false;
254
+ atom.state.promise = void 0;
255
+ if (atom.a) {
256
+ atom.a.abort();
257
+ atom.a = void 0;
258
+ }
259
+ try {
260
+ const value = atom.l(
261
+ (anotherAtom, unwrap = true) => {
262
+ if (counter !== atom.n) throw expired;
263
+ if (atom !== anotherAtom) {
264
+ if (!anotherAtom.h) {
265
+ execute(anotherAtom);
266
+ if (anotherAtom.c) {
267
+ propagate(anotherAtom);
268
+ }
269
+ }
270
+ (atom.k ||= /* @__PURE__ */ new Set()).add(anotherAtom);
271
+ (anotherAtom.b ||= /* @__PURE__ */ new Set()).add(atom);
272
+ }
273
+ if (!unwrap) return anotherAtom.state;
274
+ if (anotherAtom.state.error)
275
+ throw new Wrapped(anotherAtom.state.error);
276
+ if (anotherAtom.state.promise)
277
+ throw new Wrapped(anotherAtom.state.promise);
278
+ return anotherAtom.state.value;
279
+ },
280
+ atom.p
281
+ );
282
+ if (isPromiseLike(value)) {
283
+ atom.state.promise = value;
284
+ value.then(
285
+ (value2) => {
286
+ if (counter === atom.n) {
287
+ finalizeExecution(atom);
288
+ if (equals(value2, atom.state.value, atom.m)) {
289
+ atom.state.promise = void 0;
290
+ } else {
291
+ atom.d = value2;
292
+ atom.o = void 0;
293
+ }
294
+ requestPropagate(atom);
295
+ }
296
+ },
297
+ (e) => {
298
+ if (counter === atom.n) {
299
+ finalizeExecution(atom);
300
+ if (e instanceof Wrapped) {
301
+ e = e.e;
302
+ } else {
303
+ logError(e);
304
+ }
305
+ atom.o = e;
306
+ requestPropagate(atom);
307
+ }
308
+ }
309
+ );
310
+ } else {
311
+ finalizeExecution(atom);
312
+ atom.state.error = void 0;
313
+ if (equals(value, atom.state.value, atom.m)) {
314
+ atom.c = false;
315
+ } else {
316
+ atom.state.value = atom.d = value;
317
+ }
318
+ }
319
+ } catch (e) {
320
+ finalizeExecution(atom);
321
+ if (e === expired) {
322
+ atom.c = false;
323
+ } else {
324
+ if (e instanceof Wrapped) {
325
+ e = e.e;
326
+ } else {
327
+ logError(e);
328
+ }
329
+ atom.state.error = e;
330
+ }
331
+ }
332
+ };
333
+ const finalizeExecution = (atom) => {
334
+ ++atom.n;
335
+ const oldDependencies = atom.j;
336
+ atom.j = atom.k;
337
+ if (oldDependencies) {
338
+ for (const dep of oldDependencies) {
339
+ if (!atom.j?.has(dep)) {
340
+ dep.b.delete(atom);
341
+ disableAtom(dep);
342
+ }
343
+ }
344
+ oldDependencies.clear();
345
+ }
346
+ atom.k = oldDependencies;
347
+ };
348
+ let runningGc = false;
349
+ let gcCandidates = /* @__PURE__ */ new Set();
350
+ const disableAtom = (atom) => {
351
+ if (!atom.r && !atom.s && !atom.b?.size && !atom.f?.size && !atom.g?.size) {
352
+ gcCandidates.add(atom);
353
+ if (!runningGc) {
354
+ runningGc = true;
355
+ setTimeout(gc, 0);
356
+ }
357
+ }
358
+ };
359
+ const gc = () => {
360
+ for (const atom of gcCandidates) {
361
+ if (!atom.r && !atom.s && !atom.b?.size && !atom.f?.size && !atom.g?.size) {
362
+ atom.state.promise = inactive;
363
+ atom.d = atom.o = atom.state.error = atom.state.value = void 0;
364
+ atom.c = atom.i = atom.h = false;
365
+ if (atom.a) {
366
+ atom.a.abort();
367
+ atom.a = void 0;
368
+ }
369
+ if (atom.j) {
370
+ for (const dep of atom.j) {
371
+ dep.b.delete(atom);
372
+ disableAtom(dep);
373
+ }
374
+ atom.j.clear();
375
+ if (atom.k) {
376
+ for (const dep of atom.k) {
377
+ dep.b.delete(atom);
378
+ disableAtom(dep);
379
+ }
380
+ atom.k.clear();
381
+ }
382
+ }
383
+ }
384
+ }
385
+ gcCandidates.clear();
386
+ runningGc = false;
387
+ };
388
+ const equals = (value, prevValue, equalsFn) => Object.is(value, prevValue) || equalsFn !== void 0 && prevValue !== void 0 && equalsFn(value, prevValue);
389
+ const isPromiseLike = (x) => typeof x?.then === "function";
390
+ const createThenableSignal = () => {
391
+ const ctrl = new AbortController();
392
+ const signal = ctrl.signal;
393
+ const promise = new Promise((resolve) => {
394
+ signal.then = (f) => promise.then(f);
395
+ signal.addEventListener("abort", resolve, {
396
+ once: true,
397
+ passive: true
398
+ });
399
+ });
400
+ return {
401
+ abort: () => ctrl.abort(),
402
+ signal
403
+ };
404
+ };
405
+ const logError = (e) => {
406
+ queueMicrotask(() => {
407
+ throw e;
408
+ });
409
+ };
410
+ export {
411
+ $,
412
+ createScope,
413
+ inactive,
414
+ isAtom,
415
+ isPrimitiveAtom
416
+ };
@@ -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),R=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:C}),z=e=>e instanceof f,$=(e,t)=>{let a=new WeakMap,n=new WeakMap,r=((l,s=!1)=>{let o=a.get(l);if(s||(o||=n.get(l)),!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,z(s)?r(s):m(s));return r},C=(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(M)))},M=()=>{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);U(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(W,0)))},W=()=>{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),U=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 $,R as $$,$ as createScope,k as inactive,z as isAtom};
1
+ var p=class{a;m;n;r;s;get(){if(this.l||(P(this),d(this)),this.state.error)throw this.state.error;if(this.state.promise)throw this.state.promise;return this.state.value}watch(t){return this.l||O(this),(this.r||=new Set).add(t),()=>{this.r.delete(t),this.r.size||d(this)}}subscribe(t){let n={v:t,A:{get signal(){return(n.t||=j()).signal}}};if(!this.l)O(this);else if(!this.state.error&&!this.state.promise)try{t(this.state.value,n.A)}catch(o){m(o)}return(this.s||=new Set).add(n),()=>{this.s.delete(n),n.t&&(n.t.abort(),n.t=void 0),this.s.size||d(this)}}[Symbol.toPrimitive](){return this.state.value}},i=class extends p{o=!1;V=!1;constructor(t,n){super(),this.d=t,this.f=n?.equals,this.a=t,this.state={promise:void 0,error:void 0,value:t}}set(t){let n=t instanceof Function?t(this.a):t;g(n,this.state.value,this.f)||(this.a=n,b(this))}};i.prototype.y=!0;i.prototype.l=!0;i.prototype.i=!1;var y=class extends p{l=!1;i=!1;o=!1;V=!1;p=0;t;u;c;constructor(t,n){super(),this.d=t,this.f=n?.equals,this.b=!!n?.persist;let o=this;this.A={get signal(){return(o.t||=j()).signal}},this.state={promise:I,error:void 0,value:void 0}}};y.prototype.y=!1;var I=Promise.reject();I.catch(()=>{});var c=(e,t)=>e instanceof Function?new y(e,t):new i(e,t),v=e=>e instanceof p,_=e=>e instanceof i,H=(e,t)=>{let n=new WeakMap,o=new WeakMap,a=((r,l=!1)=>{let s=n.get(r);if(l||(s||=o.get(r)),!s){let h=e?.(r,!0);if(l)return h;let f=h||r;o.set(r,s=f.d instanceof Function?c((K,z)=>f.d((E,L)=>K(a(E),L),z),{equals:f.f,persist:f.b}):h||c(f.d))}return s});if(t)for(let[r,l]of t)n.set(r,v(l)?a(l):c(l));return a},S=!1,x=[],w=[],O=e=>{e.i||(e.i=!0,b(e))},b=e=>{e.o||(e.o=!0,x.push(e),S||(S=!0,queueMicrotask(M)))},M=()=>{S=!1;{let t=x;x=[];for(let n of t)n.state.promise=void 0,n.state.error=n.m,n.state.value=n.a,q(n)}let e=w;w=[];for(let t=e.length;t--;){let n=e[t];n.V=!1,n.i&&(n.o=!0,P(n)),n.o&&D(n)}},D=e=>{if(e.o=!1,e.r)for(let t of e.r)try{t()}catch(n){m(n)}if(!e.state.error&&!e.state.promise){if(e.s)for(let t of e.s){t.t&&(t.t.abort(),t.t=void 0);try{t.v(e.state.value,t.A)}catch(n){m(n)}}if(e.n)for(let t of e.n)t.i=!0}},q=e=>{if(!e.V){if(e.V=!0,e.n)for(let t of e.n)q(t);w.push(e)}},u=class{e;constructor(t){this.e=t}},G=Symbol(),P=e=>{let t=++e.p;e.l=!0,e.i=!1,e.state.promise=void 0,e.t&&(e.t.abort(),e.t=void 0);try{let n=e.d((o,a=!0)=>{if(t!==e.p)throw G;if(e!==o&&(o.l||(P(o),o.o&&D(o)),(e.c||=new Set).add(o),(o.n||=new Set).add(e)),!a)return o.state;if(o.state.error)throw new u(o.state.error);if(o.state.promise)throw new u(o.state.promise);return o.state.value},e.A);W(n)?(e.state.promise=n,n.then(o=>{t===e.p&&(V(e),g(o,e.state.value,e.f)?e.state.promise=void 0:(e.a=o,e.m=void 0),b(e))},o=>{t===e.p&&(V(e),o instanceof u?o=o.e:m(o),e.m=o,b(e))})):(V(e),e.state.error=void 0,g(n,e.state.value,e.f)?e.o=!1:e.state.value=e.a=n)}catch(n){V(e),n===G?e.o=!1:(n instanceof u?n=n.e:m(n),e.state.error=n)}},V=e=>{++e.p;let t=e.u;if(e.u=e.c,t){for(let n of t)e.u?.has(n)||(n.n.delete(e),d(n));t.clear()}e.c=t},k=!1,T=new Set,d=e=>{!e.y&&!e.b&&!e.n?.size&&!e.r?.size&&!e.s?.size&&(T.add(e),k||(k=!0,setTimeout(U,0)))},U=()=>{for(let e of T)if(!e.y&&!e.b&&!e.n?.size&&!e.r?.size&&!e.s?.size&&(e.state.promise=I,e.a=e.m=e.state.error=e.state.value=void 0,e.o=e.i=e.l=!1,e.t&&(e.t.abort(),e.t=void 0),e.u)){for(let t of e.u)t.n.delete(e),d(t);if(e.u.clear(),e.c){for(let t of e.c)t.n.delete(e),d(t);e.c.clear()}}T.clear(),k=!1},g=(e,t,n)=>Object.is(e,t)||n!==void 0&&t!==void 0&&n(e,t),W=e=>typeof e?.then=="function",j=()=>{let e=new AbortController,t=e.signal,n=new Promise(o=>{t.then=a=>n.then(a),t.addEventListener("abort",o,{once:!0,passive:!0})});return{abort:()=>e.abort(),signal:t}},m=e=>{queueMicrotask(()=>{throw e})};var A=()=>A,R=()=>{};Object.setPrototypeOf(A,new Proxy(A,{get:(e,t)=>t===Symbol.toPrimitive?R:A}));var C=e=>{if(typeof e!="object"||e===null)return c(e);if(Array.isArray(e))return e.map(C);let t=Object.create(null);for(let n in e)t[n]=C(e[n]);return t},$=e=>e.get(),F=(e,t=$)=>{let n=o=>{if(typeof o!="object"||o===null)return o;if(v(o))return t(o);if(Array.isArray(o))return o.map(n);let a=Object.create(null);for(let r in o)a[r]=n(o[r]);return a};return n(e)},X=(e,t)=>{let n=(o,a)=>{if(typeof o=="object"&&o!==null)if(v(o))_(o)&&o.set(a);else for(let r in a)n(o[r],a[r])};n(e,t)},B=e=>e instanceof Function?c((t,n)=>{let o,a,r=e(l=>{let s=t(l,!1);if(s.error)a=s.error;else if(s.promise)(o||=[]).push(s.promise);else return s.value;return A},n);if(a)throw a;if(o)throw Promise.all(o);return r},{equals:Q}):B(t=>F(e,t)),Q=(e,t)=>{if(typeof e!="object"||typeof t!="object"||!e||!t)return!1;let n=e.constructor;if(n!==t.constructor)return!1;if(n===Array){let a=e.length;if(a!==t.length)return!1;for(;(a=a-1|0)>=0;)if(!Object.is(e[a],t[a]))return!1;return!0}let o=0;for(let a in e){if(!(a in t&&Object.is(e[a],t[a])))return!1;o=o+1|0}for(let a in t)if((o=o-1|0)<0)return!1;return!0};export{c as $,B as $$,C as atomize,F as collectAtoms,H as createScope,I as inactive,v as isAtom,_ as isPrimitiveAtom,X as setAtoms};
package/dist/index.d.ts CHANGED
@@ -1,80 +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 declare const isAtom: (x: unknown) => x is Atom<unknown>;
78
- export type AtomValuePair<Value> = [Atom<Value>, Value | PrimitiveAtom<Value>] | [DerivedAtom<Value>, Value | Atom<Value>];
79
- export declare const createScope: <T extends AtomValuePair<unknown>[]>(parentScope?: AtomScope | null, atomValuePairs?: T) => AtomScope;
80
- export {};
1
+ export * from './atom';
2
+ export * from './utils';
package/dist/index.js CHANGED
@@ -1,456 +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 isAtom = (x) => x instanceof CommonAtomInternal;
147
- const createScope = (parentScope, atomValuePairs) => {
148
- const scopeMap = /* @__PURE__ */ new WeakMap();
149
- const atomMap = /* @__PURE__ */ new WeakMap();
150
- const scope = ((baseAtom, strict = false) => {
151
- let scopedAtom = scopeMap.get(baseAtom);
152
- if (!strict) scopedAtom ||= atomMap.get(baseAtom);
153
- if (!scopedAtom) {
154
- const parentAtom = parentScope?.(baseAtom, true);
155
- if (strict) return parentAtom;
156
- const realBaseAtom = parentAtom || baseAtom;
157
- atomMap.set(
158
- baseAtom,
159
- scopedAtom = realBaseAtom.l instanceof Function ? $((get, options) => realBaseAtom.l(
160
- (atom, unwrap) => get(scope(atom), unwrap),
161
- options
162
- ), {
163
- equals: realBaseAtom.m,
164
- persist: realBaseAtom.s
165
- }) : parentAtom || $(realBaseAtom.l)
166
- );
167
- }
168
- return scopedAtom;
169
- });
170
- if (atomValuePairs) {
171
- for (const [atom, value] of atomValuePairs) {
172
- scopeMap.set(atom, isAtom(value) ? scope(value) : $(value));
173
- }
174
- }
175
- return scope;
176
- };
177
- const shallowEquals = (a, b) => {
178
- if (typeof a !== "object" || typeof b !== "object" || !a || !b) return false;
179
- const c = a.constructor;
180
- if (c !== b.constructor) return false;
181
- if (c === Array) {
182
- let i = a.length;
183
- if (i !== b.length) return false;
184
- while ((i = i - 1 | 0) >= 0) if (!Object.is(a[i], b[i])) return false;
185
- return true;
186
- }
187
- let n = 0;
188
- for (const k in a) {
189
- if (!(k in b && Object.is(a[k], b[k]))) return false;
190
- n = n + 1 | 0;
191
- }
192
- for (const _ in b) if ((n = n - 1 | 0) < 0) return false;
193
- return true;
194
- };
195
- let pendingUpdateAtoms = false;
196
- let updateQueue = [];
197
- let stack = [];
198
- const requestActivate = (atom) => {
199
- if (!atom.i) {
200
- atom.i = true;
201
- requestPropagate(atom);
202
- }
203
- };
204
- const requestPropagate = (atom) => {
205
- if (!atom.c) {
206
- atom.c = true;
207
- updateQueue.push(atom);
208
- if (!pendingUpdateAtoms) {
209
- pendingUpdateAtoms = true;
210
- queueMicrotask(updateAtoms);
211
- }
212
- }
213
- };
214
- const updateAtoms = () => {
215
- pendingUpdateAtoms = false;
216
- {
217
- const updatedAtoms = updateQueue;
218
- updateQueue = [];
219
- for (const atom of updatedAtoms) {
220
- atom.state.promise = void 0;
221
- atom.state.error = atom.o;
222
- atom.state.value = atom.d;
223
- mark(atom);
224
- }
225
- }
226
- const markedAtoms = stack;
227
- stack = [];
228
- for (let i = markedAtoms.length; i--; ) {
229
- const atom = markedAtoms[i];
230
- atom.q = false;
231
- if (atom.i) {
232
- atom.c = true;
233
- execute(atom);
234
- }
235
- if (atom.c) {
236
- propagate(atom);
237
- }
238
- }
239
- };
240
- const propagate = (atom) => {
241
- atom.c = false;
242
- if (atom.f) {
243
- for (const watcher of atom.f) {
244
- try {
245
- watcher();
246
- } catch (e) {
247
- logError(e);
248
- }
249
- }
250
- }
251
- if (!atom.state.error && !atom.state.promise) {
252
- if (atom.g) {
253
- for (const subscriber of atom.g) {
254
- if (subscriber.a) {
255
- subscriber.a.abort();
256
- subscriber.a = void 0;
257
- }
258
- try {
259
- subscriber.t(atom.state.value, subscriber.p);
260
- } catch (e) {
261
- logError(e);
262
- }
263
- }
264
- }
265
- if (atom.b) {
266
- for (const child of atom.b) {
267
- child.i = true;
268
- }
269
- }
270
- }
271
- };
272
- const mark = (atom) => {
273
- if (!atom.q) {
274
- atom.q = true;
275
- if (atom.b) {
276
- for (const child of atom.b) {
277
- mark(child);
278
- }
279
- }
280
- stack.push(atom);
281
- }
282
- };
283
- class Wrapped {
284
- e;
285
- constructor(e) {
286
- this.e = e;
287
- }
288
- }
289
- const expired = Symbol();
290
- const execute = (atom) => {
291
- const counter = ++atom.n;
292
- atom.h = true;
293
- atom.i = false;
294
- atom.state.promise = void 0;
295
- if (atom.a) {
296
- atom.a.abort();
297
- atom.a = void 0;
298
- }
299
- try {
300
- const value = atom.l(
301
- (anotherAtom, unwrap = true) => {
302
- if (counter !== atom.n) throw expired;
303
- if (atom !== anotherAtom) {
304
- if (!anotherAtom.h) {
305
- execute(anotherAtom);
306
- if (anotherAtom.c) {
307
- propagate(anotherAtom);
308
- }
309
- }
310
- (atom.k ||= /* @__PURE__ */ new Set()).add(anotherAtom);
311
- (anotherAtom.b ||= /* @__PURE__ */ new Set()).add(atom);
312
- }
313
- if (!unwrap) return anotherAtom.state;
314
- if (anotherAtom.state.error)
315
- throw new Wrapped(anotherAtom.state.error);
316
- if (anotherAtom.state.promise)
317
- throw new Wrapped(anotherAtom.state.promise);
318
- return anotherAtom.state.value;
319
- },
320
- atom.p
321
- );
322
- if (isPromiseLike(value)) {
323
- atom.state.promise = value;
324
- value.then(
325
- (value2) => {
326
- if (counter === atom.n) {
327
- finalizeExecution(atom);
328
- if (equals(value2, atom.state.value, atom.m)) {
329
- atom.state.promise = void 0;
330
- } else {
331
- atom.d = value2;
332
- atom.o = void 0;
333
- }
334
- requestPropagate(atom);
335
- }
336
- },
337
- (e) => {
338
- if (counter === atom.n) {
339
- finalizeExecution(atom);
340
- if (e instanceof Wrapped) {
341
- e = e.e;
342
- } else {
343
- logError(e);
344
- }
345
- atom.o = e;
346
- requestPropagate(atom);
347
- }
348
- }
349
- );
350
- } else {
351
- finalizeExecution(atom);
352
- atom.state.error = void 0;
353
- if (equals(value, atom.state.value, atom.m)) {
354
- atom.c = false;
355
- } else {
356
- atom.state.value = atom.d = value;
357
- }
358
- }
359
- } catch (e) {
360
- finalizeExecution(atom);
361
- if (e === expired) {
362
- atom.c = false;
363
- } else {
364
- if (e instanceof Wrapped) {
365
- e = e.e;
366
- } else {
367
- logError(e);
368
- }
369
- atom.state.error = e;
370
- }
371
- }
372
- };
373
- const finalizeExecution = (atom) => {
374
- ++atom.n;
375
- const oldDependencies = atom.j;
376
- atom.j = atom.k;
377
- if (oldDependencies) {
378
- for (const dep of oldDependencies) {
379
- if (!atom.j?.has(dep)) {
380
- dep.b.delete(atom);
381
- disableAtom(dep);
382
- }
383
- }
384
- oldDependencies.clear();
385
- }
386
- atom.k = oldDependencies;
387
- };
388
- let runningGc = false;
389
- let gcCandidates = /* @__PURE__ */ new Set();
390
- const disableAtom = (atom) => {
391
- if (!atom.r && !atom.s && !atom.b?.size && !atom.f?.size && !atom.g?.size) {
392
- gcCandidates.add(atom);
393
- if (!runningGc) {
394
- runningGc = true;
395
- setTimeout(gc, 0);
396
- }
397
- }
398
- };
399
- const gc = () => {
400
- for (const atom of gcCandidates) {
401
- if (!atom.r && !atom.s && !atom.b?.size && !atom.f?.size && !atom.g?.size) {
402
- atom.state.promise = inactive;
403
- atom.d = atom.o = atom.state.error = atom.state.value = void 0;
404
- atom.c = atom.i = atom.h = false;
405
- if (atom.a) {
406
- atom.a.abort();
407
- atom.a = void 0;
408
- }
409
- if (atom.j) {
410
- for (const dep of atom.j) {
411
- dep.b.delete(atom);
412
- disableAtom(dep);
413
- }
414
- atom.j.clear();
415
- if (atom.k) {
416
- for (const dep of atom.k) {
417
- dep.b.delete(atom);
418
- disableAtom(dep);
419
- }
420
- atom.k.clear();
421
- }
422
- }
423
- }
424
- }
425
- gcCandidates.clear();
426
- runningGc = false;
427
- };
428
- const equals = (value, prevValue, equalsFn) => Object.is(value, prevValue) || equalsFn !== void 0 && prevValue !== void 0 && equalsFn(value, prevValue);
429
- const isPromiseLike = (x) => typeof x?.then === "function";
430
- const createThenableSignal = () => {
431
- const ctrl = new AbortController();
432
- const signal = ctrl.signal;
433
- const promise = new Promise((resolve) => {
434
- signal.then = (f) => promise.then(f);
435
- signal.addEventListener("abort", resolve, {
436
- once: true,
437
- passive: true
438
- });
439
- });
440
- return {
441
- abort: () => ctrl.abort(),
442
- signal
443
- };
444
- };
445
- const logError = (e) => {
446
- queueMicrotask(() => {
447
- throw e;
448
- });
449
- };
450
- export {
451
- $,
452
- $$,
453
- createScope,
454
- inactive,
455
- isAtom
456
- };
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,19 @@
1
+ import { type PrimitiveAtom, type Atom, type AtomGetter, type DerivedAtom } from "./atom";
2
+ export type Atomized<T> = T extends object ? {
3
+ [K in keyof T]: Atomized<T[K]>;
4
+ } : PrimitiveAtom<T>;
5
+ export 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 type RecursiveOptional<T> = T | (T extends object ? {
13
+ [P in keyof T]: RecursiveOptional<T[P]>;
14
+ } : never);
15
+ export declare const atomize: <T>(tree: T) => Atomized<T>;
16
+ export declare const collectAtoms: <T>(tree: T, get?: <T_1>(atom: Atom<T_1>) => T_1) => CollectedAtoms<T>;
17
+ export declare const setAtoms: <T>(tree: T, values: RecursiveOptional<CollectedAtoms<T>>) => void;
18
+ export declare const $$: CollectAtom;
19
+ export {};
package/dist/utils.js ADDED
@@ -0,0 +1,80 @@
1
+ import { $, isAtom, isPrimitiveAtom } 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 setAtoms = (tree, values) => {
30
+ const recurse = (t, v) => {
31
+ if (typeof t === "object" && t !== null) {
32
+ if (isAtom(t)) {
33
+ if (isPrimitiveAtom(t)) t.set(v);
34
+ } else {
35
+ for (const k in v) recurse(t[k], v[k]);
36
+ }
37
+ }
38
+ };
39
+ recurse(tree, values);
40
+ };
41
+ const $$ = (init) => init instanceof Function ? $((get, options) => {
42
+ let promises;
43
+ let error;
44
+ const result = init((atom) => {
45
+ const state = get(atom, false);
46
+ if (state.error) error = state.error;
47
+ else if (state.promise) (promises ||= []).push(state.promise);
48
+ else return state.value;
49
+ return ouroboros;
50
+ }, options);
51
+ if (error) throw error;
52
+ if (promises) throw Promise.all(promises);
53
+ return result;
54
+ }, {
55
+ equals: shallowEquals
56
+ }) : $$((get) => collectAtoms(init, get));
57
+ const shallowEquals = (a, b) => {
58
+ if (typeof a !== "object" || typeof b !== "object" || !a || !b) return false;
59
+ const c = a.constructor;
60
+ if (c !== b.constructor) return false;
61
+ if (c === Array) {
62
+ let i = a.length;
63
+ if (i !== b.length) return false;
64
+ while ((i = i - 1 | 0) >= 0) if (!Object.is(a[i], b[i])) return false;
65
+ return true;
66
+ }
67
+ let n = 0;
68
+ for (const k in a) {
69
+ if (!(k in b && Object.is(a[k], b[k]))) return false;
70
+ n = n + 1 | 0;
71
+ }
72
+ for (const _ in b) if ((n = n - 1 | 0) < 0) return false;
73
+ return true;
74
+ };
75
+ export {
76
+ $$,
77
+ atomize,
78
+ collectAtoms,
79
+ setAtoms
80
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bansa",
3
- "version": "0.0.17",
3
+ "version": "0.0.19",
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"