@vielzeug/ledger 2.3.0 → 3.0.0

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/README.md CHANGED
@@ -1,26 +1,17 @@
1
1
  # @vielzeug/ledger
2
2
 
3
- Serialized reversible command history with cancellation ownership and atomic reactive state.
3
+ > Serialized reversible command history with atomic framework-neutral state and cancellation ownership
4
4
 
5
- ## Features
6
-
7
- - **Reversible commands** — every recorded command has `apply()` and `revert()`
8
- - **Atomic state** — one `Readable<LedgerState>` for queue and history observation
9
- - **Composition** — `compose()` combines reversible commands into one history entry
10
- - **Cancellation** — queued cancelled work never starts; active work receives `AbortSignal`
11
- - **Idle ownership** — `whenIdle()` waits for queued and active work to settle
12
- - **History cap** — non-negative safe-integer retained depth
13
-
14
- ## Install
5
+ ## Installation
15
6
 
16
7
  ```sh
17
8
  pnpm add @vielzeug/ledger
9
+ npm install @vielzeug/ledger
10
+ yarn add @vielzeug/ledger
18
11
  ```
19
12
 
20
13
  ## Quick Start
21
14
 
22
- Submit reversible state transitions and dispose the owner at teardown.
23
-
24
15
  ```ts
25
16
  import { createLedger } from '@vielzeug/ledger';
26
17
 
@@ -38,6 +29,14 @@ console.log(ledger.state.value.undo.length); // 0
38
29
  ledger.dispose();
39
30
  ```
40
31
 
41
- Keep irreversible side effects outside Ledger commands. Catch operation failures at your application boundary.
32
+ ## Documentation
33
+
34
+ - [Overview](https://vielzeug.dev/ledger/)
35
+ - [Usage Guide](https://vielzeug.dev/ledger/usage)
36
+ - [API Reference](https://vielzeug.dev/ledger/api)
37
+ - [Examples](https://vielzeug.dev/ledger/examples)
38
+ - [Migration Guide](https://vielzeug.dev/ledger/migration)
39
+
40
+ ## License
42
41
 
43
- [Full documentation](https://vielzeug.dev/ledger/)
42
+ MIT © [Helmuth Saatkamp](https://github.com/helmuthdu) — part of the [Vielzeug](https://github.com/helmuthdu/vielzeug) monorepo.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { compose } from './compose';
2
2
  export { LedgerCancelledError, LedgerConfigurationError, LedgerDisposedError, LedgerError, LedgerExecutionError, LedgerRollbackError, } from './errors';
3
3
  export { createLedger } from './ledger';
4
- export type { CommandContext, HistoryEntry, Ledger, LedgerCallOptions, LedgerOptions, LedgerState, ReversibleCommand, } from './types';
4
+ export type { CommandContext, HistoryEntry, Ledger, LedgerCallOptions, LedgerOptions, LedgerReadable, LedgerState, ReversibleCommand, Unsubscribe, } from './types';
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,mBAAmB,EACnB,WAAW,EACX,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EACV,cAAc,EACd,YAAY,EACZ,MAAM,EACN,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,iBAAiB,GAClB,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,mBAAmB,EACnB,WAAW,EACX,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EACV,cAAc,EACd,YAAY,EACZ,MAAM,EACN,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,WAAW,GACZ,MAAM,SAAS,CAAC"}
package/dist/ledger.cjs CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e){let{apply:t,label:n,meta:r,revert:i}=e;return{apply:t,label:n,meta:r,revert:i}}function t(t,n){let r=t.map(e);return{apply:async e=>{let t=[];try{for(let n of r)await n.apply(e),t.push(n)}catch(n){let r=[];for(let n of[...t].reverse())try{await n.revert(e)}catch(e){r.push(e)}throw r.length>0?AggregateError([n,...r],`Command application and compensation failed`,{cause:n}):n}},label:n,revert:async e=>{let t=[];for(let n of[...r].reverse())try{await n.revert(e)}catch(e){t.push(e)}if(t.length>0)throw AggregateError(t,`Command reversion failed`)}}}var n=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},r=class extends n{},i=class extends n{},a=class extends n{},o=class extends n{},s=class extends n{},c=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},l=class extends c{},u=class extends c{},d=class extends c{},f=class extends c{},p=Symbol.for(`@vielzeug/ripple/reactive`),m=100,h=Symbol(`ripple.unset`),g=class{[p]=!0;dependents=new Set;name;runtime;constructor(e,t){this.runtime=e,this.name=t}subscribe(e){this.runtime.assertActive(),this.peek();let t={dependencies:new Set,onDependencyChanged:()=>this.runtime.enqueueListener(e)};return this.dependents.add(t),()=>this.dependents.delete(t)}notify(){for(let e of[...this.dependents])e.onDependencyChanged()}},_=class extends g{current;equals;constructor(e,t,n){super(e,n?.name),this.current=t,this.equals=n?.equals??Object.is}get value(){return this.runtime.track(this),this.current}set value(e){if(this.runtime.assertActive(),this.equals(this.current,e))return;let t=this.current;this.current=e,this.runtime.emit({kind:`write`,name:this.name,next:e,previous:t}),this.runtime.propagate(()=>this.notify())}peek(){return this.current}update(e){this.value=e(this.current)}},v=class extends g{dependencies=new Set;computing=!1;disposed=!1;dirty=!0;current=h;derive;equals;constructor(e,t,n){super(e,n?.name),this.derive=t,this.equals=n?.equals??Object.is}get value(){return this.runtime.track(this),this.refresh(),this.current}peek(){return this.refresh(),this.current}onDependencyChanged(){this.disposed||(this.dirty||=!0,this.dependents.size>0&&this.refresh()&&this.notify())}dispose(){this.disposed||(this.disposed=!0,this.runtime.clearDependencies(this),this.dependents.clear())}refresh(){if(!this.dirty||this.disposed)return!1;if(this.computing)throw new l(`computed cycle detected${this.name===void 0?``:` "${this.name}"`}`);this.computing=!0,this.runtime.emit({kind:`compute`,name:this.name});try{let e=this.runtime.collect(this,this.derive),t=this.current===h||!this.equals(this.current,e);return this.current=e,this.dirty=!1,t}finally{this.computing=!1}}},y=class{disposalController=new AbortController;owned=new Set;name;isDisposed=!1;runtime;constructor(e,t){this.runtime=e,this.name=t}get disposed(){return this.isDisposed}get disposalSignal(){return this.disposalController.signal}run(e){if(this.isDisposed)throw new d(`Cannot run a disposed scope.`);return this.runtime.withScope(this,e)}dispose(){if(!this.isDisposed){this.isDisposed=!0;for(let e of[...this.owned].reverse())e.dispose();this.owned.clear(),this.disposalController.abort(),this.runtime.emit({kind:`dispose`,name:this.name,node:`scope`})}}[Symbol.dispose](){this.dispose()}},b=class{dependencies=new Set;disposalController=new AbortController;cleanup;isDisposed=!1;owner;scheduled=!1;callback;options;runtime;constructor(e,t,n){this.runtime=e,this.callback=t,this.options=n}get disposed(){return this.isDisposed}get disposalSignal(){return this.disposalController.signal}onDependencyChanged(){if(!this.isDisposed){if(this.options?.scheduler===`microtask`){if(this.scheduled)return;this.scheduled=!0,queueMicrotask(()=>{this.scheduled=!1,this.isDisposed||this.runtime.enqueue(this)});return}this.runtime.enqueue(this)}}run(){if(this.isDisposed)return;this.owner?.dispose(),this.owner=void 0,this.runCleanup(),this.runtime.emit({kind:`effect`,name:this.options?.name});let e=new y(this.runtime);try{let t=this.runtime.withEffectScope(e,()=>this.runtime.collectEffect(this,this.callback));this.owner=e,this.cleanup=typeof t==`function`?t:void 0}catch(t){e.dispose(),this.runtime.report(t,{kind:`effect`,name:this.options?.name})}}dispose(){this.isDisposed||(this.isDisposed=!0,this.owner?.dispose(),this.owner=void 0,this.runtime.clearDependencies(this),this.runCleanup(),this.disposalController.abort(),this.runtime.emit({kind:`dispose`,name:this.options?.name,node:`effect`}))}[Symbol.dispose](){this.dispose()}runCleanup(){let e=this.cleanup;if(this.cleanup=void 0,e!==void 0)try{e()}catch(e){this.runtime.report(e,{kind:`cleanup`,name:this.options?.name})}}},x=class{activeEffectScope;activeObserver;activeScope;isDisposed=!1;flushDepth=0;flushing=!1;pending=new Set;listeners=new Set;rootScope;observer;onError;constructor(e){this.observer=e?.observer,this.onError=e?.onError??(e=>{queueMicrotask(()=>{throw e})}),this.rootScope=new y(this,`runtime`),this.activeScope=this.rootScope}get disposed(){return this.isDisposed}get disposalSignal(){return this.rootScope.disposalSignal}signal=(e,t)=>(this.assertActive(),new _(this,e,t));computed=(e,t)=>{this.assertActive();let n=new v(this,e,t);return(this.activeEffectScope??this.activeScope).owned.add(n),n};effect=(e,t)=>{this.assertActive();let n=new b(this,e,t);return(this.activeEffectScope??this.activeScope).owned.add(n),n.run(),n};createScope=e=>{this.assertActive();let t=new y(this,e);return this.activeScope.owned.add(t),t};batch=e=>(this.assertActive(),this.propagate(e));untrack=e=>(this.assertActive(),this.withObserver(void 0,e));dispose(){this.isDisposed||(this.isDisposed=!0,this.rootScope.dispose())}assertActive(){if(this.isDisposed)throw new u(`Cannot use a disposed Ripple runtime.`)}track(e){let t=this.activeObserver;t?.collecting!==void 0&&t.collecting.add(e)}clearDependencies(e){for(let t of e.dependencies)t.dependents.delete(e);e.dependencies.clear()}collect(e,t){return this.collectWith(e,t,e.dependencies.size===0)}collectEffect(e,t){return this.collectWith(e,t,!0)}withEffectScope(e,t){let n=this.activeEffectScope;this.activeEffectScope=e;try{return t()}finally{this.activeEffectScope=n}}withObserver(e,t){let n=this.activeObserver;this.activeObserver=e;try{return t()}finally{this.activeObserver=n}}withScope(e,t){let n=this.activeEffectScope,r=this.activeScope;this.activeEffectScope=void 0,this.activeScope=e;try{return t()}finally{this.activeEffectScope=n,this.activeScope=r}}enqueue(e){this.pending.add(e),this.flushDepth===0&&this.flush()}enqueueListener(e){this.listeners.add(e),this.flushDepth===0&&this.flush()}propagate(e){this.flushDepth++;try{return e()}finally{this.flushDepth--,this.flushDepth===0&&this.flush()}}emit(e){try{this.observer?.(e)}catch(t){this.report(t,{kind:`observer`,name:e.name})}}report(e,t){try{this.onError(e,t)}catch(e){queueMicrotask(()=>{throw e})}}collectWith(e,t,n){let r=this.activeObserver,i=new Set;e.collecting=i,this.activeObserver=e;try{let n=t();return this.commitDependencies(e,i),n}catch(t){throw n&&this.commitDependencies(e,i),t}finally{e.collecting=void 0,this.activeObserver=r}}commitDependencies(e,t){for(let n of e.dependencies)t.has(n)||n.dependents.delete(e);for(let n of t)e.dependencies.has(n)||n.dependents.add(e);e.dependencies.clear();for(let n of t)e.dependencies.add(n)}flush(){if(this.flushing)return;this.flushing=!0;let e=0;try{for(;this.pending.size>0||this.listeners.size>0;){if(++e>m)throw new f(`infinite reactive flush (>${m} iterations)`);let t=[...this.pending],n=[...this.listeners];this.pending.clear(),this.listeners.clear();for(let e of t)e.run();for(let e of n)try{e()}catch(e){this.report(e,{kind:`listener`})}}}finally{this.flushing=!1}}},S=e=>(t,n,r)=>{let i=e.signal({status:`pending`},{name:r?.name}),a=e.signal(0),o,s=()=>{a.value,o?.abort();let e=i.peek(),r=e.status===`success`?e.value:`previous`in e?e.previous:void 0,s;try{s=t()}catch(e){i.value=r===void 0?{error:e,status:`error`}:{error:e,previous:r,status:`error`};return}let l=new AbortController;o=l,i.value=r===void 0?{status:`pending`}:{previous:r,status:`pending`};let u;try{u=Promise.resolve(n(s,{signal:l.signal}))}catch(e){u=Promise.reject(e)}u.then(e=>{!c.disposed&&!l.signal.aborted&&(i.value={status:`success`,value:e})},e=>{!c.disposed&&!l.signal.aborted&&(i.value=r===void 0?{error:e,status:`error`}:{error:e,previous:r,status:`error`})})},c=e.effect(()=>(s(),()=>o?.abort()),{name:r?.name}),l={get disposalSignal(){return c.disposalSignal},dispose:()=>c.dispose(),get disposed(){return c.disposed},get name(){return i.name},peek:()=>i.peek(),reload:()=>{c.disposed||(a.value=a.peek()+1)},subscribe:e=>i.subscribe(e),[Symbol.dispose](){this.dispose()},get value(){return i.value}};return Object.defineProperty(l,p,{value:!0}),l},C=e=>(t,n,r)=>{let i=typeof t==`function`?t:()=>t.value,a=r?.equals??Object.is,o=!0,s,c=!1,l=e.effect(()=>{let e=i();if(o){o=!1,s=e,r?.immediate&&(n(e,void 0),r?.once&&(c=!0));return}if(a(s,e))return;let t=s;s=e,n(e,t),r?.once&&l.dispose()},{name:r?.name});return c&&l.dispose(),l},w=(e=>{let t=new x(e),n=S(t);return{batch:t.batch,computed:t.computed,createScope:t.createScope,get disposalSignal(){return t.disposalSignal},dispose:()=>t.dispose(),get disposed(){return t.disposed},effect:t.effect,resource:n,signal:t.signal,untrack:t.untrack,watch:C(t),[Symbol.dispose]:()=>t.dispose()}})(),T=w.signal;w.computed,w.effect,w.batch,w.createScope,w.untrack,w.watch,w.resource;function E(e){return e instanceof Error?e.message:String(e)}function D(e){let{apply:t,label:n,meta:r,revert:i}=e;return{apply:t,entry:Object.freeze({label:n,meta:r}),revert:i}}function O(e){return Object.freeze({...e,redo:Object.freeze([...e.redo]),undo:Object.freeze([...e.undo])})}function k(e,t){return t?new i(`Cannot call ${e}() on a disposed ledger.`):new r(`${e}() was cancelled before it started.`)}function A(e={}){let{maxHistory:t=100,runtime:i}=e,c=i?.signal??T;if(!Number.isSafeInteger(t)||t<0)throw new s(`maxHistory must be a non-negative safe integer`);let l=c(O({accepting:!0,queued:0,redo:[],running:0,undo:[]}),{name:`ledger:state`}),u=new WeakMap,d=new AbortController,f=new Set,p=new Set,m=!1,h=Promise.resolve();function g(e){if(l.value=O(e(l.value)),l.value.queued===0&&l.value.running===0){for(let e of f)e();f.clear()}}function _(e,t){e.settled||(e.settled=!0,p.delete(e),e.cancel(),t===void 0?e.resolve():e.reject(t))}function v(e,t,n){if(m)return Promise.reject(k(e,!0));let r=t?AbortSignal.any([t,d.signal]):d.signal;return new Promise((t,i)=>{let a=()=>{o.started||o.settled||m||(g(e=>({...e,queued:e.queued-1})),_(o,k(e,!1)))},o={cancel:()=>r.removeEventListener(`abort`,a),reject:i,resolve:t,settled:!1,start:async()=>{if(!o.settled){if(m||r.aborted){g(e=>({...e,queued:e.queued-1})),_(o,k(e,m));return}o.started=!0,g(e=>({...e,queued:e.queued-1,running:e.running+1}));try{await n({signal:r}),_(o)}catch(e){_(o,e)}finally{g(e=>({...e,running:e.running-1}))}}},started:!1};r.addEventListener(`abort`,a,{once:!0}),p.add(o),g(e=>({...e,queued:e.queued+1})),h=h.then(o.start,o.start)})}async function y(e,n){try{await e.apply(n)}catch(e){throw n.signal.aborted?new r(`do() was cancelled while running.`,{cause:e}):new a(E(e),{cause:e})}if(m||n.signal.aborted)throw new r(`do() was cancelled while running.`);g(n=>{if(t===0)return{...n,redo:[]};let r=[...n.undo,e.entry];return r.length>t&&r.shift(),{...n,redo:[],undo:r}}),u.set(e.entry,e)}async function b(e){let t=l.value.undo[l.value.undo.length-1];if(!t)return;let i=u.get(t);if(!i)throw new n(`Undo history is corrupted.`);try{await i.revert(e)}catch(t){throw e.signal.aborted?new r(`undo() was cancelled while running.`,{cause:t}):new o(E(t),{cause:t})}if(m||e.signal.aborted)throw new r(`undo() was cancelled while running.`);g(e=>({...e,redo:[...e.redo,t],undo:e.undo.slice(0,-1)}))}async function x(e){let t=l.value.redo[l.value.redo.length-1];if(!t)return;let i=u.get(t);if(!i)throw new n(`Redo history is corrupted.`);try{await i.apply(e)}catch(t){throw e.signal.aborted?new r(`redo() was cancelled while running.`,{cause:t}):new a(E(t),{cause:t})}if(m||e.signal.aborted)throw new r(`redo() was cancelled while running.`);g(e=>({...e,redo:e.redo.slice(0,-1),undo:[...e.undo,t]}))}return{clear(){return v(`clear`,void 0,async()=>{g(e=>({...e,redo:[],undo:[]}))})},get disposalSignal(){return d.signal},dispose(){if(m)return;m=!0,d.abort();let e=[...p].filter(e=>!e.started);for(let t of e)_(t,k(`operation`,!0));g(e=>({...e,accepting:!1,queued:0,redo:[],undo:[]}))},get disposed(){return m},do(e,t){let n=D(e);return v(`do`,t?.signal,e=>y(n,e))},redo(e){return v(`redo`,e?.signal,x)},get state(){return l},[Symbol.dispose](){this.dispose()},undo(e){return v(`undo`,e?.signal,b)},whenIdle(){return l.value.queued===0&&l.value.running===0?Promise.resolve():new Promise(e=>f.add(e))}}}exports.LedgerCancelledError=r,exports.LedgerConfigurationError=s,exports.LedgerDisposedError=i,exports.LedgerError=n,exports.LedgerExecutionError=a,exports.LedgerRollbackError=o,exports.compose=t,exports.createLedger=A;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e){let{apply:t,label:n,meta:r,revert:i}=e;return{apply:t,label:n,meta:r,revert:i}}function t(t,n){let r=t.map(e);return{apply:async e=>{let t=[];try{for(let n of r)await n.apply(e),t.push(n)}catch(n){let r=[];for(let n of[...t].reverse())try{await n.revert(e)}catch(e){r.push(e)}throw r.length>0?AggregateError([n,...r],`Command application and compensation failed`,{cause:n}):n}},label:n,revert:async e=>{let t=[];for(let n of[...r].reverse())try{await n.revert(e)}catch(e){t.push(e)}if(t.length>0)throw AggregateError(t,`Command reversion failed`)}}}var n=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},r=class extends n{},i=class extends n{},a=class extends n{},o=class extends n{},s=class extends n{},c=class{currentValue;listeners=new Set;constructor(e){this.currentValue=e}get value(){return this.currentValue}peek(){return this.currentValue}set(e){this.currentValue=e;for(let e of[...this.listeners])try{e()}catch(e){queueMicrotask(()=>{throw e})}}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}};function l(e){return e instanceof Error?e.message:String(e)}function u(e){let{apply:t,label:n,meta:r,revert:i}=e;return{apply:t,entry:Object.freeze({label:n,meta:r}),revert:i}}function d(e){return Object.freeze({...e,redo:Object.freeze([...e.redo]),undo:Object.freeze([...e.undo])})}function f(e,t){return t?new i(`Cannot call ${e}() on a disposed ledger.`):new r(`${e}() was cancelled before it started.`)}function p(e={}){let{maxHistory:t=100}=e;if(!Number.isSafeInteger(t)||t<0)throw new s(`maxHistory must be a non-negative safe integer`);let i=new c(d({accepting:!0,queued:0,redo:[],running:0,undo:[]})),p=new WeakMap,m=new AbortController,h=new Set,g=new Set,_=!1,v=Promise.resolve();function y(e){if(i.set(d(e(i.value))),i.value.queued===0&&i.value.running===0){for(let e of h)e();h.clear()}}function b(e,t){e.settled||(e.settled=!0,g.delete(e),e.cancel(),t===void 0?e.resolve():e.reject(t))}function x(e,t,n){if(_)return Promise.reject(f(e,!0));let r=t?AbortSignal.any([t,m.signal]):m.signal;return new Promise((t,i)=>{let a=()=>{o.started||o.settled||_||(y(e=>({...e,queued:e.queued-1})),b(o,f(e,!1)))},o={cancel:()=>r.removeEventListener(`abort`,a),reject:i,resolve:t,settled:!1,start:async()=>{if(!o.settled){if(_||r.aborted){y(e=>({...e,queued:e.queued-1})),b(o,f(e,_));return}o.started=!0,y(e=>({...e,queued:e.queued-1,running:e.running+1}));try{await n({signal:r}),b(o)}catch(e){b(o,e)}finally{y(e=>({...e,running:e.running-1}))}}},started:!1};r.addEventListener(`abort`,a,{once:!0}),g.add(o),y(e=>({...e,queued:e.queued+1})),v=v.then(o.start,o.start)})}async function S(e,n){try{await e.apply(n)}catch(e){throw n.signal.aborted?new r(`do() was cancelled while running.`,{cause:e}):new a(l(e),{cause:e})}if(_||n.signal.aborted)throw new r(`do() was cancelled while running.`);y(n=>{if(t===0)return{...n,redo:[]};let r=[...n.undo,e.entry];return r.length>t&&r.shift(),{...n,redo:[],undo:r}}),p.set(e.entry,e)}async function C(e){let t=i.value.undo[i.value.undo.length-1];if(!t)return;let a=p.get(t);if(!a)throw new n(`Undo history is corrupted.`);try{await a.revert(e)}catch(t){throw e.signal.aborted?new r(`undo() was cancelled while running.`,{cause:t}):new o(l(t),{cause:t})}if(_||e.signal.aborted)throw new r(`undo() was cancelled while running.`);y(e=>({...e,redo:[...e.redo,t],undo:e.undo.slice(0,-1)}))}async function w(e){let t=i.value.redo[i.value.redo.length-1];if(!t)return;let o=p.get(t);if(!o)throw new n(`Redo history is corrupted.`);try{await o.apply(e)}catch(t){throw e.signal.aborted?new r(`redo() was cancelled while running.`,{cause:t}):new a(l(t),{cause:t})}if(_||e.signal.aborted)throw new r(`redo() was cancelled while running.`);y(e=>({...e,redo:e.redo.slice(0,-1),undo:[...e.undo,t]}))}return{clear(){return x(`clear`,void 0,async()=>{y(e=>({...e,redo:[],undo:[]}))})},get disposalSignal(){return m.signal},dispose(){if(_)return;_=!0,m.abort();let e=[...g].filter(e=>!e.started);for(let t of e)b(t,f(`operation`,!0));y(e=>({...e,accepting:!1,queued:0,redo:[],undo:[]}))},get disposed(){return _},do(e,t){let n=u(e);return x(`do`,t?.signal,e=>S(n,e))},redo(e){return x(`redo`,e?.signal,w)},get state(){return i},[Symbol.dispose](){this.dispose()},undo(e){return x(`undo`,e?.signal,C)},whenIdle(){return i.value.queued===0&&i.value.running===0?Promise.resolve():new Promise(e=>h.add(e))}}}exports.LedgerCancelledError=r,exports.LedgerConfigurationError=s,exports.LedgerDisposedError=i,exports.LedgerError=n,exports.LedgerExecutionError=a,exports.LedgerRollbackError=o,exports.compose=t,exports.createLedger=p;
2
2
  //# sourceMappingURL=ledger.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ledger.cjs","names":["e","t","r","i","i","c","l","e","u","n","d","f","t","r","e","e","n","s"],"sources":["../src/compose.ts","../src/errors.ts","../../ripple/dist/errors.js","../../ripple/dist/runtime.js","../../ripple/dist/_async.js","../../ripple/dist/_watch.js","../../ripple/dist/_default.js","../../ripple/dist/index.js","../src/ledger.ts"],"sourcesContent":["import type { CommandContext, ReversibleCommand } from './types';\n\nfunction snapshotCommand<TMeta>(command: ReversibleCommand<TMeta>): ReversibleCommand<TMeta> {\n const { apply, label, meta, revert } = command;\n\n return { apply, label, meta, revert };\n}\n\n/**\n * Composes reversible commands into one reversible command.\n *\n * `apply` runs each child in order. `revert` runs children in reverse order.\n * A failed child application compensates completed children before rethrowing.\n *\n * @example\n * await ledger.do(compose([\n * { apply: () => { node.x = newX; }, revert: () => { node.x = oldX; } },\n * { apply: () => { node.y = newY; }, revert: () => { node.y = oldY; } },\n * ], 'Move node'));\n */\nexport function compose<TMeta = undefined>(\n commands: readonly ReversibleCommand<TMeta>[],\n label?: string,\n): ReversibleCommand<TMeta> {\n const steps = commands.map(snapshotCommand);\n\n return {\n apply: async (context: CommandContext) => {\n const applied: ReversibleCommand<TMeta>[] = [];\n\n try {\n for (const command of steps) {\n await command.apply(context);\n applied.push(command);\n }\n } catch (error) {\n const compensationFailures: unknown[] = [];\n\n for (const command of [...applied].reverse()) {\n try {\n await command.revert(context);\n } catch (compensationError) {\n compensationFailures.push(compensationError);\n }\n }\n\n if (compensationFailures.length > 0) {\n throw new AggregateError([error, ...compensationFailures], 'Command application and compensation failed', {\n cause: error,\n });\n }\n\n throw error;\n }\n },\n label,\n revert: async (context: CommandContext) => {\n const failures: unknown[] = [];\n\n for (const command of [...steps].reverse()) {\n try {\n await command.revert(context);\n } catch (error) {\n failures.push(error);\n }\n }\n\n if (failures.length > 0) throw new AggregateError(failures, 'Command reversion failed');\n },\n };\n}\n","/** Base class for all ledger errors. Use `instanceof LedgerError` to catch any ledger-originated error. */\nexport class LedgerError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a queued operation is cancelled before user code starts, or an active operation cooperatively stops. */\nexport class LedgerCancelledError extends LedgerError {}\n\n/** Thrown when a method is called on a disposed ledger instance. */\nexport class LedgerDisposedError extends LedgerError {}\n\n/** Thrown when a command's `apply()` function throws. The original error is available via `.cause`. */\nexport class LedgerExecutionError extends LedgerError {}\n\n/** Thrown when a command's `revert()` function throws during an undo operation. The original error is available via `.cause`. */\nexport class LedgerRollbackError extends LedgerError {}\n\n/** Thrown when the ledger is constructed with invalid options. */\nexport class LedgerConfigurationError extends LedgerError {}\n","//#region src/errors.ts\nvar e = class extends Error {\n\tconstructor(e, t) {\n\t\tsuper(e, t), this.name = new.target.name, Object.setPrototypeOf(this, new.target.prototype);\n\t}\n}, t = class extends e {}, n = class extends e {}, r = class extends e {}, i = class extends e {};\n//#endregion\nexport { t as RippleComputedCycleError, n as RippleDisposedRuntimeError, r as RippleDisposedScopeError, e as RippleError, i as RippleInfiniteLoopError };\n\n//# sourceMappingURL=errors.js.map","import { RippleComputedCycleError as e, RippleDisposedRuntimeError as t, RippleDisposedScopeError as n, RippleInfiniteLoopError as r } from \"./errors.js\";\n//#region src/runtime.ts\nvar i = Symbol.for(\"@vielzeug/ripple/reactive\"), a = 100, o = Symbol(\"ripple.unset\"), s = class {\n\t[i] = !0;\n\tdependents = /* @__PURE__ */ new Set();\n\tname;\n\truntime;\n\tconstructor(e, t) {\n\t\tthis.runtime = e, this.name = t;\n\t}\n\tsubscribe(e) {\n\t\tthis.runtime.assertActive(), this.peek();\n\t\tlet t = {\n\t\t\tdependencies: /* @__PURE__ */ new Set(),\n\t\t\tonDependencyChanged: () => this.runtime.enqueueListener(e)\n\t\t};\n\t\treturn this.dependents.add(t), () => this.dependents.delete(t);\n\t}\n\tnotify() {\n\t\tfor (let e of [...this.dependents]) e.onDependencyChanged();\n\t}\n}, c = class extends s {\n\tcurrent;\n\tequals;\n\tconstructor(e, t, n) {\n\t\tsuper(e, n?.name), this.current = t, this.equals = n?.equals ?? Object.is;\n\t}\n\tget value() {\n\t\treturn this.runtime.track(this), this.current;\n\t}\n\tset value(e) {\n\t\tif (this.runtime.assertActive(), this.equals(this.current, e)) return;\n\t\tlet t = this.current;\n\t\tthis.current = e, this.runtime.emit({\n\t\t\tkind: \"write\",\n\t\t\tname: this.name,\n\t\t\tnext: e,\n\t\t\tprevious: t\n\t\t}), this.runtime.propagate(() => this.notify());\n\t}\n\tpeek() {\n\t\treturn this.current;\n\t}\n\tupdate(e) {\n\t\tthis.value = e(this.current);\n\t}\n}, l = class extends s {\n\tdependencies = /* @__PURE__ */ new Set();\n\tcomputing = !1;\n\tdisposed = !1;\n\tdirty = !0;\n\tcurrent = o;\n\tderive;\n\tequals;\n\tconstructor(e, t, n) {\n\t\tsuper(e, n?.name), this.derive = t, this.equals = n?.equals ?? Object.is;\n\t}\n\tget value() {\n\t\treturn this.runtime.track(this), this.refresh(), this.current;\n\t}\n\tpeek() {\n\t\treturn this.refresh(), this.current;\n\t}\n\tonDependencyChanged() {\n\t\tthis.disposed || (this.dirty ||= !0, this.dependents.size > 0 && this.refresh() && this.notify());\n\t}\n\tdispose() {\n\t\tthis.disposed || (this.disposed = !0, this.runtime.clearDependencies(this), this.dependents.clear());\n\t}\n\trefresh() {\n\t\tif (!this.dirty || this.disposed) return !1;\n\t\tif (this.computing) {\n\t\t\tlet t = this.name === void 0 ? \"\" : ` \"${this.name}\"`;\n\t\t\tthrow new e(`computed cycle detected${t}`);\n\t\t}\n\t\tthis.computing = !0, this.runtime.emit({\n\t\t\tkind: \"compute\",\n\t\t\tname: this.name\n\t\t});\n\t\ttry {\n\t\t\tlet e = this.runtime.collect(this, this.derive), t = this.current === o || !this.equals(this.current, e);\n\t\t\treturn this.current = e, this.dirty = !1, t;\n\t\t} finally {\n\t\t\tthis.computing = !1;\n\t\t}\n\t}\n}, u = class {\n\tdisposalController = new AbortController();\n\towned = /* @__PURE__ */ new Set();\n\tname;\n\tisDisposed = !1;\n\truntime;\n\tconstructor(e, t) {\n\t\tthis.runtime = e, this.name = t;\n\t}\n\tget disposed() {\n\t\treturn this.isDisposed;\n\t}\n\tget disposalSignal() {\n\t\treturn this.disposalController.signal;\n\t}\n\trun(e) {\n\t\tif (this.isDisposed) throw new n(\"Cannot run a disposed scope.\");\n\t\treturn this.runtime.withScope(this, e);\n\t}\n\tdispose() {\n\t\tif (!this.isDisposed) {\n\t\t\tthis.isDisposed = !0;\n\t\t\tfor (let e of [...this.owned].reverse()) e.dispose();\n\t\t\tthis.owned.clear(), this.disposalController.abort(), this.runtime.emit({\n\t\t\t\tkind: \"dispose\",\n\t\t\t\tname: this.name,\n\t\t\t\tnode: \"scope\"\n\t\t\t});\n\t\t}\n\t}\n\t[Symbol.dispose]() {\n\t\tthis.dispose();\n\t}\n}, d = class {\n\tdependencies = /* @__PURE__ */ new Set();\n\tdisposalController = new AbortController();\n\tcleanup;\n\tisDisposed = !1;\n\towner;\n\tscheduled = !1;\n\tcallback;\n\toptions;\n\truntime;\n\tconstructor(e, t, n) {\n\t\tthis.runtime = e, this.callback = t, this.options = n;\n\t}\n\tget disposed() {\n\t\treturn this.isDisposed;\n\t}\n\tget disposalSignal() {\n\t\treturn this.disposalController.signal;\n\t}\n\tonDependencyChanged() {\n\t\tif (!this.isDisposed) {\n\t\t\tif (this.options?.scheduler === \"microtask\") {\n\t\t\t\tif (this.scheduled) return;\n\t\t\t\tthis.scheduled = !0, queueMicrotask(() => {\n\t\t\t\t\tthis.scheduled = !1, this.isDisposed || this.runtime.enqueue(this);\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.runtime.enqueue(this);\n\t\t}\n\t}\n\trun() {\n\t\tif (this.isDisposed) return;\n\t\tthis.owner?.dispose(), this.owner = void 0, this.runCleanup(), this.runtime.emit({\n\t\t\tkind: \"effect\",\n\t\t\tname: this.options?.name\n\t\t});\n\t\tlet e = new u(this.runtime);\n\t\ttry {\n\t\t\tlet t = this.runtime.withEffectScope(e, () => this.runtime.collectEffect(this, this.callback));\n\t\t\tthis.owner = e, this.cleanup = typeof t == \"function\" ? t : void 0;\n\t\t} catch (t) {\n\t\t\te.dispose(), this.runtime.report(t, {\n\t\t\t\tkind: \"effect\",\n\t\t\t\tname: this.options?.name\n\t\t\t});\n\t\t}\n\t}\n\tdispose() {\n\t\tthis.isDisposed || (this.isDisposed = !0, this.owner?.dispose(), this.owner = void 0, this.runtime.clearDependencies(this), this.runCleanup(), this.disposalController.abort(), this.runtime.emit({\n\t\t\tkind: \"dispose\",\n\t\t\tname: this.options?.name,\n\t\t\tnode: \"effect\"\n\t\t}));\n\t}\n\t[Symbol.dispose]() {\n\t\tthis.dispose();\n\t}\n\trunCleanup() {\n\t\tlet e = this.cleanup;\n\t\tif (this.cleanup = void 0, e !== void 0) try {\n\t\t\te();\n\t\t} catch (e) {\n\t\t\tthis.runtime.report(e, {\n\t\t\t\tkind: \"cleanup\",\n\t\t\t\tname: this.options?.name\n\t\t\t});\n\t\t}\n\t}\n}, f = class {\n\tactiveEffectScope;\n\tactiveObserver;\n\tactiveScope;\n\tisDisposed = !1;\n\tflushDepth = 0;\n\tflushing = !1;\n\tpending = /* @__PURE__ */ new Set();\n\tlisteners = /* @__PURE__ */ new Set();\n\trootScope;\n\tobserver;\n\tonError;\n\tconstructor(e) {\n\t\tthis.observer = e?.observer, this.onError = e?.onError ?? ((e) => {\n\t\t\tqueueMicrotask(() => {\n\t\t\t\tthrow e;\n\t\t\t});\n\t\t}), this.rootScope = new u(this, \"runtime\"), this.activeScope = this.rootScope;\n\t}\n\tget disposed() {\n\t\treturn this.isDisposed;\n\t}\n\tget disposalSignal() {\n\t\treturn this.rootScope.disposalSignal;\n\t}\n\tsignal = (e, t) => (this.assertActive(), new c(this, e, t));\n\tcomputed = (e, t) => {\n\t\tthis.assertActive();\n\t\tlet n = new l(this, e, t);\n\t\treturn (this.activeEffectScope ?? this.activeScope).owned.add(n), n;\n\t};\n\teffect = (e, t) => {\n\t\tthis.assertActive();\n\t\tlet n = new d(this, e, t);\n\t\treturn (this.activeEffectScope ?? this.activeScope).owned.add(n), n.run(), n;\n\t};\n\tcreateScope = (e) => {\n\t\tthis.assertActive();\n\t\tlet t = new u(this, e);\n\t\treturn this.activeScope.owned.add(t), t;\n\t};\n\tbatch = (e) => (this.assertActive(), this.propagate(e));\n\tuntrack = (e) => (this.assertActive(), this.withObserver(void 0, e));\n\tdispose() {\n\t\tthis.isDisposed || (this.isDisposed = !0, this.rootScope.dispose());\n\t}\n\tassertActive() {\n\t\tif (this.isDisposed) throw new t(\"Cannot use a disposed Ripple runtime.\");\n\t}\n\ttrack(e) {\n\t\tlet t = this.activeObserver;\n\t\tt?.collecting !== void 0 && t.collecting.add(e);\n\t}\n\tclearDependencies(e) {\n\t\tfor (let t of e.dependencies) t.dependents.delete(e);\n\t\te.dependencies.clear();\n\t}\n\tcollect(e, t) {\n\t\treturn this.collectWith(e, t, e.dependencies.size === 0);\n\t}\n\tcollectEffect(e, t) {\n\t\treturn this.collectWith(e, t, !0);\n\t}\n\twithEffectScope(e, t) {\n\t\tlet n = this.activeEffectScope;\n\t\tthis.activeEffectScope = e;\n\t\ttry {\n\t\t\treturn t();\n\t\t} finally {\n\t\t\tthis.activeEffectScope = n;\n\t\t}\n\t}\n\twithObserver(e, t) {\n\t\tlet n = this.activeObserver;\n\t\tthis.activeObserver = e;\n\t\ttry {\n\t\t\treturn t();\n\t\t} finally {\n\t\t\tthis.activeObserver = n;\n\t\t}\n\t}\n\twithScope(e, t) {\n\t\tlet n = this.activeEffectScope, r = this.activeScope;\n\t\tthis.activeEffectScope = void 0, this.activeScope = e;\n\t\ttry {\n\t\t\treturn t();\n\t\t} finally {\n\t\t\tthis.activeEffectScope = n, this.activeScope = r;\n\t\t}\n\t}\n\tenqueue(e) {\n\t\tthis.pending.add(e), this.flushDepth === 0 && this.flush();\n\t}\n\tenqueueListener(e) {\n\t\tthis.listeners.add(e), this.flushDepth === 0 && this.flush();\n\t}\n\tpropagate(e) {\n\t\tthis.flushDepth++;\n\t\ttry {\n\t\t\treturn e();\n\t\t} finally {\n\t\t\tthis.flushDepth--, this.flushDepth === 0 && this.flush();\n\t\t}\n\t}\n\temit(e) {\n\t\ttry {\n\t\t\tthis.observer?.(e);\n\t\t} catch (t) {\n\t\t\tthis.report(t, {\n\t\t\t\tkind: \"observer\",\n\t\t\t\tname: e.name\n\t\t\t});\n\t\t}\n\t}\n\treport(e, t) {\n\t\ttry {\n\t\t\tthis.onError(e, t);\n\t\t} catch (e) {\n\t\t\tqueueMicrotask(() => {\n\t\t\t\tthrow e;\n\t\t\t});\n\t\t}\n\t}\n\tcollectWith(e, t, n) {\n\t\tlet r = this.activeObserver, i = /* @__PURE__ */ new Set();\n\t\te.collecting = i, this.activeObserver = e;\n\t\ttry {\n\t\t\tlet n = t();\n\t\t\treturn this.commitDependencies(e, i), n;\n\t\t} catch (t) {\n\t\t\tthrow n && this.commitDependencies(e, i), t;\n\t\t} finally {\n\t\t\te.collecting = void 0, this.activeObserver = r;\n\t\t}\n\t}\n\tcommitDependencies(e, t) {\n\t\tfor (let n of e.dependencies) t.has(n) || n.dependents.delete(e);\n\t\tfor (let n of t) e.dependencies.has(n) || n.dependents.add(e);\n\t\te.dependencies.clear();\n\t\tfor (let n of t) e.dependencies.add(n);\n\t}\n\tflush() {\n\t\tif (this.flushing) return;\n\t\tthis.flushing = !0;\n\t\tlet e = 0;\n\t\ttry {\n\t\t\tfor (; this.pending.size > 0 || this.listeners.size > 0;) {\n\t\t\t\tif (++e > a) throw new r(`infinite reactive flush (>${a} iterations)`);\n\t\t\t\tlet t = [...this.pending], n = [...this.listeners];\n\t\t\t\tthis.pending.clear(), this.listeners.clear();\n\t\t\t\tfor (let e of t) e.run();\n\t\t\t\tfor (let e of n) try {\n\t\t\t\t\te();\n\t\t\t\t} catch (e) {\n\t\t\t\t\tthis.report(e, { kind: \"listener\" });\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.flushing = !1;\n\t\t}\n\t}\n}, p = (e) => {\n\tif (typeof e != \"object\" || !e || !(i in e)) return !1;\n\tlet t = e;\n\treturn typeof t.peek == \"function\" && typeof t.subscribe == \"function\";\n};\n//#endregion\nexport { i as REACTIVE, f as ReactiveRuntime, p as isReactive };\n\n//# sourceMappingURL=runtime.js.map","import { REACTIVE as e } from \"./runtime.js\";\n//#region src/_async.ts\nvar t = (t) => (n, r, i) => {\n\tlet a = t.signal({ status: \"pending\" }, { name: i?.name }), o = t.signal(0), s, c = () => {\n\t\to.value, s?.abort();\n\t\tlet e = a.peek(), t = e.status === \"success\" ? e.value : \"previous\" in e ? e.previous : void 0, i;\n\t\ttry {\n\t\t\ti = n();\n\t\t} catch (e) {\n\t\t\ta.value = t === void 0 ? {\n\t\t\t\terror: e,\n\t\t\t\tstatus: \"error\"\n\t\t\t} : {\n\t\t\t\terror: e,\n\t\t\t\tprevious: t,\n\t\t\t\tstatus: \"error\"\n\t\t\t};\n\t\t\treturn;\n\t\t}\n\t\tlet c = new AbortController();\n\t\ts = c, a.value = t === void 0 ? { status: \"pending\" } : {\n\t\t\tprevious: t,\n\t\t\tstatus: \"pending\"\n\t\t};\n\t\tlet u;\n\t\ttry {\n\t\t\tu = Promise.resolve(r(i, { signal: c.signal }));\n\t\t} catch (e) {\n\t\t\tu = Promise.reject(e);\n\t\t}\n\t\tu.then((e) => {\n\t\t\t!l.disposed && !c.signal.aborted && (a.value = {\n\t\t\t\tstatus: \"success\",\n\t\t\t\tvalue: e\n\t\t\t});\n\t\t}, (e) => {\n\t\t\t!l.disposed && !c.signal.aborted && (a.value = t === void 0 ? {\n\t\t\t\terror: e,\n\t\t\t\tstatus: \"error\"\n\t\t\t} : {\n\t\t\t\terror: e,\n\t\t\t\tprevious: t,\n\t\t\t\tstatus: \"error\"\n\t\t\t});\n\t\t});\n\t}, l = t.effect(() => (c(), () => s?.abort()), { name: i?.name }), u = {\n\t\tget disposalSignal() {\n\t\t\treturn l.disposalSignal;\n\t\t},\n\t\tdispose: () => l.dispose(),\n\t\tget disposed() {\n\t\t\treturn l.disposed;\n\t\t},\n\t\tget name() {\n\t\t\treturn a.name;\n\t\t},\n\t\tpeek: () => a.peek(),\n\t\treload: () => {\n\t\t\tl.disposed || (o.value = o.peek() + 1);\n\t\t},\n\t\tsubscribe: (e) => a.subscribe(e),\n\t\t[Symbol.dispose]() {\n\t\t\tthis.dispose();\n\t\t},\n\t\tget value() {\n\t\t\treturn a.value;\n\t\t}\n\t};\n\treturn Object.defineProperty(u, e, { value: !0 }), u;\n};\n//#endregion\nexport { t as createResource };\n\n//# sourceMappingURL=_async.js.map","//#region src/_watch.ts\nvar e = (e) => (t, n, r) => {\n\tlet i = typeof t == \"function\" ? t : () => t.value, a = r?.equals ?? Object.is, o = !0, s, c = !1, l = e.effect(() => {\n\t\tlet e = i();\n\t\tif (o) {\n\t\t\to = !1, s = e, r?.immediate && (n(e, void 0), r?.once && (c = !0));\n\t\t\treturn;\n\t\t}\n\t\tif (a(s, e)) return;\n\t\tlet t = s;\n\t\ts = e, n(e, t), r?.once && l.dispose();\n\t}, { name: r?.name });\n\treturn c && l.dispose(), l;\n};\n//#endregion\nexport { e as createWatch };\n\n//# sourceMappingURL=_watch.js.map","import { ReactiveRuntime as e } from \"./runtime.js\";\nimport { createResource as t } from \"./_async.js\";\nimport { createWatch as n } from \"./_watch.js\";\n//#region src/_default.ts\nvar r = (r) => {\n\tlet i = new e(r), a = t(i);\n\treturn {\n\t\tbatch: i.batch,\n\t\tcomputed: i.computed,\n\t\tcreateScope: i.createScope,\n\t\tget disposalSignal() {\n\t\t\treturn i.disposalSignal;\n\t\t},\n\t\tdispose: () => i.dispose(),\n\t\tget disposed() {\n\t\t\treturn i.disposed;\n\t\t},\n\t\teffect: i.effect,\n\t\tresource: a,\n\t\tsignal: i.signal,\n\t\tuntrack: i.untrack,\n\t\twatch: n(i),\n\t\t[Symbol.dispose]: () => i.dispose()\n\t};\n}, i = r();\n//#endregion\nexport { r as createRipple, i as defaultRipple };\n\n//# sourceMappingURL=_default.js.map","import { RippleComputedCycleError as e, RippleDisposedRuntimeError as t, RippleDisposedScopeError as n, RippleError as r, RippleInfiniteLoopError as i } from \"./errors.js\";\nimport { isReactive as a } from \"./runtime.js\";\nimport { createRipple as o, defaultRipple as s } from \"./_default.js\";\n//#region src/index.ts\nvar c = s.signal, l = s.computed, u = s.effect, d = s.batch, f = s.createScope, p = s.untrack, m = s.watch, h = s.resource;\n//#endregion\nexport { e as RippleComputedCycleError, t as RippleDisposedRuntimeError, n as RippleDisposedScopeError, r as RippleError, i as RippleInfiniteLoopError, d as batch, l as computed, o as createRipple, f as createScope, u as effect, a as isReactive, h as resource, c as signal, p as untrack, m as watch };\n\n//# sourceMappingURL=index.js.map","import { signal as defaultSignal } from '@vielzeug/ripple';\nimport {\n LedgerCancelledError,\n LedgerConfigurationError,\n LedgerDisposedError,\n LedgerError,\n LedgerExecutionError,\n LedgerRollbackError,\n} from './errors';\nimport type {\n CommandContext,\n HistoryEntry,\n Ledger,\n LedgerCallOptions,\n LedgerOptions,\n LedgerState,\n ReversibleCommand,\n} from './types';\n\ntype StoredCommand<TMeta> = {\n apply: (context: CommandContext) => Promise<void> | void;\n entry: HistoryEntry<TMeta>;\n revert: (context: CommandContext) => Promise<void> | void;\n};\n\ntype Operation = {\n cancel: () => void;\n reject: (reason?: unknown) => void;\n resolve: () => void;\n settled: boolean;\n start: () => Promise<void>;\n started: boolean;\n};\n\nfunction toMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction snapshotCommand<TMeta>(command: ReversibleCommand<TMeta>): StoredCommand<TMeta> {\n const { apply, label, meta, revert } = command;\n\n return { apply, entry: Object.freeze({ label, meta }), revert };\n}\n\nfunction snapshotState<TMeta>(state: LedgerState<TMeta>): LedgerState<TMeta> {\n return Object.freeze({\n ...state,\n redo: Object.freeze([...state.redo]),\n undo: Object.freeze([...state.undo]),\n });\n}\n\nfunction operationError(method: string, disposed: boolean): LedgerCancelledError | LedgerDisposedError {\n return disposed\n ? new LedgerDisposedError(`Cannot call ${method}() on a disposed ledger.`)\n : new LedgerCancelledError(`${method}() was cancelled before it started.`);\n}\n\n/**\n * Creates a serialized history of reversible commands.\n *\n * Commands are snapshotted when submitted. Queued commands cancelled before their queue turn do\n * not invoke user code. Active commands receive an abort signal and stop cooperatively.\n *\n * @example\n * const ledger = createLedger({ maxHistory: 50 });\n * await ledger.do({\n * apply: () => { item.name = next; },\n * revert: () => { item.name = previous; },\n * });\n * await ledger.undo();\n * await ledger.redo();\n * using ledger = createLedger();\n */\nexport function createLedger<TMeta = undefined>(options: LedgerOptions = {}): Ledger<TMeta> {\n const { maxHistory = 100, runtime } = options;\n const signal = runtime?.signal ?? defaultSignal;\n\n if (!Number.isSafeInteger(maxHistory) || maxHistory < 0) {\n throw new LedgerConfigurationError('maxHistory must be a non-negative safe integer');\n }\n\n const state = signal<LedgerState<TMeta>>(\n snapshotState({ accepting: true, queued: 0, redo: [], running: 0, undo: [] }),\n { name: 'ledger:state' },\n );\n const commandStore = new WeakMap<HistoryEntry<TMeta>, StoredCommand<TMeta>>();\n const disposalController = new AbortController();\n const idleWaiters = new Set<() => void>();\n const operations = new Set<Operation>();\n let disposed = false;\n let queue = Promise.resolve();\n\n function updateState(update: (current: LedgerState<TMeta>) => LedgerState<TMeta>): void {\n state.value = snapshotState(update(state.value));\n\n if (state.value.queued === 0 && state.value.running === 0) {\n for (const resolve of idleWaiters) resolve();\n idleWaiters.clear();\n }\n }\n\n function settle(operation: Operation, error?: unknown): void {\n if (operation.settled) return;\n\n operation.settled = true;\n operations.delete(operation);\n operation.cancel();\n\n if (error === undefined) operation.resolve();\n else operation.reject(error);\n }\n\n function enqueue(\n method: string,\n externalSignal: AbortSignal | undefined,\n task: (context: CommandContext) => Promise<void>,\n ): Promise<void> {\n if (disposed) return Promise.reject(operationError(method, true));\n\n const abortSignal = externalSignal\n ? AbortSignal.any([externalSignal, disposalController.signal])\n : disposalController.signal;\n\n return new Promise<void>((resolve, reject) => {\n const onAbort = (): void => {\n if (operation.started || operation.settled || disposed) return;\n\n updateState((current) => ({ ...current, queued: current.queued - 1 }));\n settle(operation, operationError(method, false));\n };\n\n const operation: Operation = {\n cancel: () => abortSignal.removeEventListener('abort', onAbort),\n reject,\n resolve,\n settled: false,\n start: async () => {\n if (operation.settled) return;\n\n if (disposed || abortSignal.aborted) {\n updateState((current) => ({ ...current, queued: current.queued - 1 }));\n settle(operation, operationError(method, disposed));\n\n return;\n }\n\n operation.started = true;\n updateState((current) => ({ ...current, queued: current.queued - 1, running: current.running + 1 }));\n\n try {\n await task({ signal: abortSignal });\n settle(operation);\n } catch (error) {\n settle(operation, error);\n } finally {\n updateState((current) => ({ ...current, running: current.running - 1 }));\n }\n },\n started: false,\n };\n\n abortSignal.addEventListener('abort', onAbort, { once: true });\n operations.add(operation);\n updateState((current) => ({ ...current, queued: current.queued + 1 }));\n queue = queue.then(operation.start, operation.start);\n });\n }\n\n async function runDo(command: StoredCommand<TMeta>, context: CommandContext): Promise<void> {\n try {\n await command.apply(context);\n } catch (error) {\n throw context.signal.aborted\n ? new LedgerCancelledError('do() was cancelled while running.', { cause: error })\n : new LedgerExecutionError(toMessage(error), { cause: error });\n }\n\n if (disposed || context.signal.aborted) {\n throw new LedgerCancelledError('do() was cancelled while running.');\n }\n\n updateState((current) => {\n if (maxHistory === 0) return { ...current, redo: [] };\n\n const undo = [...current.undo, command.entry];\n\n if (undo.length > maxHistory) undo.shift();\n\n return { ...current, redo: [], undo };\n });\n commandStore.set(command.entry, command);\n }\n\n async function runUndo(context: CommandContext): Promise<void> {\n const entry = state.value.undo[state.value.undo.length - 1];\n\n if (!entry) return;\n\n const command = commandStore.get(entry);\n\n if (!command) throw new LedgerError('Undo history is corrupted.');\n\n try {\n await command.revert(context);\n } catch (error) {\n throw context.signal.aborted\n ? new LedgerCancelledError('undo() was cancelled while running.', { cause: error })\n : new LedgerRollbackError(toMessage(error), { cause: error });\n }\n\n if (disposed || context.signal.aborted) {\n throw new LedgerCancelledError('undo() was cancelled while running.');\n }\n\n updateState((current) => ({ ...current, redo: [...current.redo, entry], undo: current.undo.slice(0, -1) }));\n }\n\n async function runRedo(context: CommandContext): Promise<void> {\n const entry = state.value.redo[state.value.redo.length - 1];\n\n if (!entry) return;\n\n const command = commandStore.get(entry);\n\n if (!command) throw new LedgerError('Redo history is corrupted.');\n\n try {\n await command.apply(context);\n } catch (error) {\n throw context.signal.aborted\n ? new LedgerCancelledError('redo() was cancelled while running.', { cause: error })\n : new LedgerExecutionError(toMessage(error), { cause: error });\n }\n\n if (disposed || context.signal.aborted) {\n throw new LedgerCancelledError('redo() was cancelled while running.');\n }\n\n updateState((current) => ({ ...current, redo: current.redo.slice(0, -1), undo: [...current.undo, entry] }));\n }\n\n return {\n clear(): Promise<void> {\n return enqueue('clear', undefined, async () => {\n updateState((current) => ({ ...current, redo: [], undo: [] }));\n });\n },\n\n get disposalSignal(): AbortSignal {\n return disposalController.signal;\n },\n\n dispose(): void {\n if (disposed) return;\n\n disposed = true;\n disposalController.abort();\n\n const queued = [...operations].filter((operation) => !operation.started);\n\n for (const operation of queued) settle(operation, operationError('operation', true));\n\n updateState((current) => ({ ...current, accepting: false, queued: 0, redo: [], undo: [] }));\n },\n\n get disposed(): boolean {\n return disposed;\n },\n\n do(command: ReversibleCommand<TMeta>, callOptions?: LedgerCallOptions): Promise<void> {\n const snapshot = snapshotCommand(command);\n\n return enqueue('do', callOptions?.signal, (context) => runDo(snapshot, context));\n },\n\n redo(callOptions?: LedgerCallOptions): Promise<void> {\n return enqueue('redo', callOptions?.signal, runRedo);\n },\n\n get state() {\n return state;\n },\n\n [Symbol.dispose](): void {\n this.dispose();\n },\n\n undo(callOptions?: LedgerCallOptions): Promise<void> {\n return enqueue('undo', callOptions?.signal, runUndo);\n },\n\n whenIdle(): Promise<void> {\n if (state.value.queued === 0 && state.value.running === 0) return Promise.resolve();\n\n return new Promise((resolve) => idleWaiters.add(resolve));\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ledger.cjs","names":[],"sources":["../src/compose.ts","../src/errors.ts","../src/ledger.ts"],"sourcesContent":["import type { CommandContext, ReversibleCommand } from './types';\n\nfunction snapshotCommand<TMeta>(command: ReversibleCommand<TMeta>): ReversibleCommand<TMeta> {\n const { apply, label, meta, revert } = command;\n\n return { apply, label, meta, revert };\n}\n\n/**\n * Composes reversible commands into one reversible command.\n *\n * `apply` runs each child in order. `revert` runs children in reverse order.\n * A failed child application compensates completed children before rethrowing.\n *\n * @example\n * await ledger.do(compose([\n * { apply: () => { node.x = newX; }, revert: () => { node.x = oldX; } },\n * { apply: () => { node.y = newY; }, revert: () => { node.y = oldY; } },\n * ], 'Move node'));\n */\nexport function compose<TMeta = undefined>(\n commands: readonly ReversibleCommand<TMeta>[],\n label?: string,\n): ReversibleCommand<TMeta> {\n const steps = commands.map(snapshotCommand);\n\n return {\n apply: async (context: CommandContext) => {\n const applied: ReversibleCommand<TMeta>[] = [];\n\n try {\n for (const command of steps) {\n await command.apply(context);\n applied.push(command);\n }\n } catch (error) {\n const compensationFailures: unknown[] = [];\n\n for (const command of [...applied].reverse()) {\n try {\n await command.revert(context);\n } catch (compensationError) {\n compensationFailures.push(compensationError);\n }\n }\n\n if (compensationFailures.length > 0) {\n throw new AggregateError([error, ...compensationFailures], 'Command application and compensation failed', {\n cause: error,\n });\n }\n\n throw error;\n }\n },\n label,\n revert: async (context: CommandContext) => {\n const failures: unknown[] = [];\n\n for (const command of [...steps].reverse()) {\n try {\n await command.revert(context);\n } catch (error) {\n failures.push(error);\n }\n }\n\n if (failures.length > 0) throw new AggregateError(failures, 'Command reversion failed');\n },\n };\n}\n","/** Base class for all ledger errors. Use `instanceof LedgerError` to catch any ledger-originated error. */\nexport class LedgerError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a queued operation is cancelled before user code starts, or an active operation cooperatively stops. */\nexport class LedgerCancelledError extends LedgerError {}\n\n/** Thrown when a method is called on a disposed ledger instance. */\nexport class LedgerDisposedError extends LedgerError {}\n\n/** Thrown when a command's `apply()` function throws. The original error is available via `.cause`. */\nexport class LedgerExecutionError extends LedgerError {}\n\n/** Thrown when a command's `revert()` function throws during an undo operation. The original error is available via `.cause`. */\nexport class LedgerRollbackError extends LedgerError {}\n\n/** Thrown when the ledger is constructed with invalid options. */\nexport class LedgerConfigurationError extends LedgerError {}\n","import {\n LedgerCancelledError,\n LedgerConfigurationError,\n LedgerDisposedError,\n LedgerError,\n LedgerExecutionError,\n LedgerRollbackError,\n} from './errors';\nimport type {\n CommandContext,\n HistoryEntry,\n Ledger,\n LedgerCallOptions,\n LedgerOptions,\n LedgerReadable,\n LedgerState,\n ReversibleCommand,\n Unsubscribe,\n} from './types';\n\ntype StoredCommand<TMeta> = {\n apply: (context: CommandContext) => Promise<void> | void;\n entry: HistoryEntry<TMeta>;\n revert: (context: CommandContext) => Promise<void> | void;\n};\n\ntype Operation = {\n cancel: () => void;\n reject: (reason?: unknown) => void;\n resolve: () => void;\n settled: boolean;\n start: () => Promise<void>;\n started: boolean;\n};\n\nclass StateStore<T> implements LedgerReadable<T> {\n private currentValue: T;\n private readonly listeners = new Set<() => void>();\n\n constructor(initial: T) {\n this.currentValue = initial;\n }\n\n get value(): T {\n return this.currentValue;\n }\n\n peek(): T {\n return this.currentValue;\n }\n\n set(next: T): void {\n this.currentValue = next;\n\n for (const listener of [...this.listeners]) {\n try {\n listener();\n } catch (error) {\n queueMicrotask(() => {\n throw error;\n });\n }\n }\n }\n\n subscribe(listener: () => void): Unsubscribe {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n}\n\nfunction toMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction snapshotCommand<TMeta>(command: ReversibleCommand<TMeta>): StoredCommand<TMeta> {\n const { apply, label, meta, revert } = command;\n\n return { apply, entry: Object.freeze({ label, meta }), revert };\n}\n\nfunction snapshotState<TMeta>(state: LedgerState<TMeta>): LedgerState<TMeta> {\n return Object.freeze({\n ...state,\n redo: Object.freeze([...state.redo]),\n undo: Object.freeze([...state.undo]),\n });\n}\n\nfunction operationError(method: string, disposed: boolean): LedgerCancelledError | LedgerDisposedError {\n return disposed\n ? new LedgerDisposedError(`Cannot call ${method}() on a disposed ledger.`)\n : new LedgerCancelledError(`${method}() was cancelled before it started.`);\n}\n\n/**\n * Creates a serialized history of reversible commands.\n *\n * Commands are snapshotted when submitted. Queued commands cancelled before their queue turn do\n * not invoke user code. Active commands receive an abort signal and stop cooperatively.\n *\n * @example\n * const ledger = createLedger({ maxHistory: 50 });\n * await ledger.do({\n * apply: () => { item.name = next; },\n * revert: () => { item.name = previous; },\n * });\n * await ledger.undo();\n * await ledger.redo();\n * using ledger = createLedger();\n */\nexport function createLedger<TMeta = undefined>(options: LedgerOptions = {}): Ledger<TMeta> {\n const { maxHistory = 100 } = options;\n\n if (!Number.isSafeInteger(maxHistory) || maxHistory < 0) {\n throw new LedgerConfigurationError('maxHistory must be a non-negative safe integer');\n }\n\n const state = new StateStore<LedgerState<TMeta>>(\n snapshotState({ accepting: true, queued: 0, redo: [], running: 0, undo: [] }),\n );\n const commandStore = new WeakMap<HistoryEntry<TMeta>, StoredCommand<TMeta>>();\n const disposalController = new AbortController();\n const idleWaiters = new Set<() => void>();\n const operations = new Set<Operation>();\n let disposed = false;\n let queue = Promise.resolve();\n\n function updateState(update: (current: LedgerState<TMeta>) => LedgerState<TMeta>): void {\n state.set(snapshotState(update(state.value)));\n\n if (state.value.queued === 0 && state.value.running === 0) {\n for (const resolve of idleWaiters) resolve();\n idleWaiters.clear();\n }\n }\n\n function settle(operation: Operation, error?: unknown): void {\n if (operation.settled) return;\n\n operation.settled = true;\n operations.delete(operation);\n operation.cancel();\n\n if (error === undefined) operation.resolve();\n else operation.reject(error);\n }\n\n function enqueue(\n method: string,\n externalSignal: AbortSignal | undefined,\n task: (context: CommandContext) => Promise<void>,\n ): Promise<void> {\n if (disposed) return Promise.reject(operationError(method, true));\n\n const abortSignal = externalSignal\n ? AbortSignal.any([externalSignal, disposalController.signal])\n : disposalController.signal;\n\n return new Promise<void>((resolve, reject) => {\n const onAbort = (): void => {\n if (operation.started || operation.settled || disposed) return;\n\n updateState((current) => ({ ...current, queued: current.queued - 1 }));\n settle(operation, operationError(method, false));\n };\n\n const operation: Operation = {\n cancel: () => abortSignal.removeEventListener('abort', onAbort),\n reject,\n resolve,\n settled: false,\n start: async () => {\n if (operation.settled) return;\n\n if (disposed || abortSignal.aborted) {\n updateState((current) => ({ ...current, queued: current.queued - 1 }));\n settle(operation, operationError(method, disposed));\n\n return;\n }\n\n operation.started = true;\n updateState((current) => ({ ...current, queued: current.queued - 1, running: current.running + 1 }));\n\n try {\n await task({ signal: abortSignal });\n settle(operation);\n } catch (error) {\n settle(operation, error);\n } finally {\n updateState((current) => ({ ...current, running: current.running - 1 }));\n }\n },\n started: false,\n };\n\n abortSignal.addEventListener('abort', onAbort, { once: true });\n operations.add(operation);\n updateState((current) => ({ ...current, queued: current.queued + 1 }));\n queue = queue.then(operation.start, operation.start);\n });\n }\n\n async function runDo(command: StoredCommand<TMeta>, context: CommandContext): Promise<void> {\n try {\n await command.apply(context);\n } catch (error) {\n throw context.signal.aborted\n ? new LedgerCancelledError('do() was cancelled while running.', { cause: error })\n : new LedgerExecutionError(toMessage(error), { cause: error });\n }\n\n if (disposed || context.signal.aborted) {\n throw new LedgerCancelledError('do() was cancelled while running.');\n }\n\n updateState((current) => {\n if (maxHistory === 0) return { ...current, redo: [] };\n\n const undo = [...current.undo, command.entry];\n\n if (undo.length > maxHistory) undo.shift();\n\n return { ...current, redo: [], undo };\n });\n commandStore.set(command.entry, command);\n }\n\n async function runUndo(context: CommandContext): Promise<void> {\n const entry = state.value.undo[state.value.undo.length - 1];\n\n if (!entry) return;\n\n const command = commandStore.get(entry);\n\n if (!command) throw new LedgerError('Undo history is corrupted.');\n\n try {\n await command.revert(context);\n } catch (error) {\n throw context.signal.aborted\n ? new LedgerCancelledError('undo() was cancelled while running.', { cause: error })\n : new LedgerRollbackError(toMessage(error), { cause: error });\n }\n\n if (disposed || context.signal.aborted) {\n throw new LedgerCancelledError('undo() was cancelled while running.');\n }\n\n updateState((current) => ({ ...current, redo: [...current.redo, entry], undo: current.undo.slice(0, -1) }));\n }\n\n async function runRedo(context: CommandContext): Promise<void> {\n const entry = state.value.redo[state.value.redo.length - 1];\n\n if (!entry) return;\n\n const command = commandStore.get(entry);\n\n if (!command) throw new LedgerError('Redo history is corrupted.');\n\n try {\n await command.apply(context);\n } catch (error) {\n throw context.signal.aborted\n ? new LedgerCancelledError('redo() was cancelled while running.', { cause: error })\n : new LedgerExecutionError(toMessage(error), { cause: error });\n }\n\n if (disposed || context.signal.aborted) {\n throw new LedgerCancelledError('redo() was cancelled while running.');\n }\n\n updateState((current) => ({ ...current, redo: current.redo.slice(0, -1), undo: [...current.undo, entry] }));\n }\n\n return {\n clear(): Promise<void> {\n return enqueue('clear', undefined, async () => {\n updateState((current) => ({ ...current, redo: [], undo: [] }));\n });\n },\n\n get disposalSignal(): AbortSignal {\n return disposalController.signal;\n },\n\n dispose(): void {\n if (disposed) return;\n\n disposed = true;\n disposalController.abort();\n\n const queued = [...operations].filter((operation) => !operation.started);\n\n for (const operation of queued) settle(operation, operationError('operation', true));\n\n updateState((current) => ({ ...current, accepting: false, queued: 0, redo: [], undo: [] }));\n },\n\n get disposed(): boolean {\n return disposed;\n },\n\n do(command: ReversibleCommand<TMeta>, callOptions?: LedgerCallOptions): Promise<void> {\n const snapshot = snapshotCommand(command);\n\n return enqueue('do', callOptions?.signal, (context) => runDo(snapshot, context));\n },\n\n redo(callOptions?: LedgerCallOptions): Promise<void> {\n return enqueue('redo', callOptions?.signal, runRedo);\n },\n\n get state() {\n return state;\n },\n\n [Symbol.dispose](): void {\n this.dispose();\n },\n\n undo(callOptions?: LedgerCallOptions): Promise<void> {\n return enqueue('undo', callOptions?.signal, runUndo);\n },\n\n whenIdle(): Promise<void> {\n if (state.value.queued === 0 && state.value.running === 0) return Promise.resolve();\n\n return new Promise((resolve) => idleWaiters.add(resolve));\n },\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAGV,MAAM,EAEN,aAAa,EAGd,MAAM,SAAS,CAAC;AAyCjB;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,KAAK,GAAG,SAAS,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CAAC,KAAK,CAAC,CAgO1F"}
1
+ {"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAGV,MAAM,EAEN,aAAa,EAKd,MAAM,SAAS,CAAC;AA6EjB;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,KAAK,GAAG,SAAS,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CAAC,KAAK,CAAC,CA8N1F"}
@@ -1,2 +1,2 @@
1
- var Ledger=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});function t(e){let{apply:t,label:n,meta:r,revert:i}=e;return{apply:t,label:n,meta:r,revert:i}}function n(e,n){let r=e.map(t);return{apply:async e=>{let t=[];try{for(let n of r)await n.apply(e),t.push(n)}catch(n){let r=[];for(let n of[...t].reverse())try{await n.revert(e)}catch(e){r.push(e)}throw r.length>0?AggregateError([n,...r],`Command application and compensation failed`,{cause:n}):n}},label:n,revert:async e=>{let t=[];for(let n of[...r].reverse())try{await n.revert(e)}catch(e){t.push(e)}if(t.length>0)throw AggregateError(t,`Command reversion failed`)}}}var r=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},i=class extends r{},a=class extends r{},o=class extends r{},s=class extends r{},c=class extends r{},l=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},u=class extends l{},d=class extends l{},f=class extends l{},p=class extends l{},m=Symbol.for(`@vielzeug/ripple/reactive`),h=100,g=Symbol(`ripple.unset`),_=class{[m]=!0;dependents=new Set;name;runtime;constructor(e,t){this.runtime=e,this.name=t}subscribe(e){this.runtime.assertActive(),this.peek();let t={dependencies:new Set,onDependencyChanged:()=>this.runtime.enqueueListener(e)};return this.dependents.add(t),()=>this.dependents.delete(t)}notify(){for(let e of[...this.dependents])e.onDependencyChanged()}},v=class extends _{current;equals;constructor(e,t,n){super(e,n?.name),this.current=t,this.equals=n?.equals??Object.is}get value(){return this.runtime.track(this),this.current}set value(e){if(this.runtime.assertActive(),this.equals(this.current,e))return;let t=this.current;this.current=e,this.runtime.emit({kind:`write`,name:this.name,next:e,previous:t}),this.runtime.propagate(()=>this.notify())}peek(){return this.current}update(e){this.value=e(this.current)}},y=class extends _{dependencies=new Set;computing=!1;disposed=!1;dirty=!0;current=g;derive;equals;constructor(e,t,n){super(e,n?.name),this.derive=t,this.equals=n?.equals??Object.is}get value(){return this.runtime.track(this),this.refresh(),this.current}peek(){return this.refresh(),this.current}onDependencyChanged(){this.disposed||(this.dirty||=!0,this.dependents.size>0&&this.refresh()&&this.notify())}dispose(){this.disposed||(this.disposed=!0,this.runtime.clearDependencies(this),this.dependents.clear())}refresh(){if(!this.dirty||this.disposed)return!1;if(this.computing)throw new u(`computed cycle detected${this.name===void 0?``:` "${this.name}"`}`);this.computing=!0,this.runtime.emit({kind:`compute`,name:this.name});try{let e=this.runtime.collect(this,this.derive),t=this.current===g||!this.equals(this.current,e);return this.current=e,this.dirty=!1,t}finally{this.computing=!1}}},b=class{disposalController=new AbortController;owned=new Set;name;isDisposed=!1;runtime;constructor(e,t){this.runtime=e,this.name=t}get disposed(){return this.isDisposed}get disposalSignal(){return this.disposalController.signal}run(e){if(this.isDisposed)throw new f(`Cannot run a disposed scope.`);return this.runtime.withScope(this,e)}dispose(){if(!this.isDisposed){this.isDisposed=!0;for(let e of[...this.owned].reverse())e.dispose();this.owned.clear(),this.disposalController.abort(),this.runtime.emit({kind:`dispose`,name:this.name,node:`scope`})}}[Symbol.dispose](){this.dispose()}},x=class{dependencies=new Set;disposalController=new AbortController;cleanup;isDisposed=!1;owner;scheduled=!1;callback;options;runtime;constructor(e,t,n){this.runtime=e,this.callback=t,this.options=n}get disposed(){return this.isDisposed}get disposalSignal(){return this.disposalController.signal}onDependencyChanged(){if(!this.isDisposed){if(this.options?.scheduler===`microtask`){if(this.scheduled)return;this.scheduled=!0,queueMicrotask(()=>{this.scheduled=!1,this.isDisposed||this.runtime.enqueue(this)});return}this.runtime.enqueue(this)}}run(){if(this.isDisposed)return;this.owner?.dispose(),this.owner=void 0,this.runCleanup(),this.runtime.emit({kind:`effect`,name:this.options?.name});let e=new b(this.runtime);try{let t=this.runtime.withEffectScope(e,()=>this.runtime.collectEffect(this,this.callback));this.owner=e,this.cleanup=typeof t==`function`?t:void 0}catch(t){e.dispose(),this.runtime.report(t,{kind:`effect`,name:this.options?.name})}}dispose(){this.isDisposed||(this.isDisposed=!0,this.owner?.dispose(),this.owner=void 0,this.runtime.clearDependencies(this),this.runCleanup(),this.disposalController.abort(),this.runtime.emit({kind:`dispose`,name:this.options?.name,node:`effect`}))}[Symbol.dispose](){this.dispose()}runCleanup(){let e=this.cleanup;if(this.cleanup=void 0,e!==void 0)try{e()}catch(e){this.runtime.report(e,{kind:`cleanup`,name:this.options?.name})}}},S=class{activeEffectScope;activeObserver;activeScope;isDisposed=!1;flushDepth=0;flushing=!1;pending=new Set;listeners=new Set;rootScope;observer;onError;constructor(e){this.observer=e?.observer,this.onError=e?.onError??(e=>{queueMicrotask(()=>{throw e})}),this.rootScope=new b(this,`runtime`),this.activeScope=this.rootScope}get disposed(){return this.isDisposed}get disposalSignal(){return this.rootScope.disposalSignal}signal=(e,t)=>(this.assertActive(),new v(this,e,t));computed=(e,t)=>{this.assertActive();let n=new y(this,e,t);return(this.activeEffectScope??this.activeScope).owned.add(n),n};effect=(e,t)=>{this.assertActive();let n=new x(this,e,t);return(this.activeEffectScope??this.activeScope).owned.add(n),n.run(),n};createScope=e=>{this.assertActive();let t=new b(this,e);return this.activeScope.owned.add(t),t};batch=e=>(this.assertActive(),this.propagate(e));untrack=e=>(this.assertActive(),this.withObserver(void 0,e));dispose(){this.isDisposed||(this.isDisposed=!0,this.rootScope.dispose())}assertActive(){if(this.isDisposed)throw new d(`Cannot use a disposed Ripple runtime.`)}track(e){let t=this.activeObserver;t?.collecting!==void 0&&t.collecting.add(e)}clearDependencies(e){for(let t of e.dependencies)t.dependents.delete(e);e.dependencies.clear()}collect(e,t){return this.collectWith(e,t,e.dependencies.size===0)}collectEffect(e,t){return this.collectWith(e,t,!0)}withEffectScope(e,t){let n=this.activeEffectScope;this.activeEffectScope=e;try{return t()}finally{this.activeEffectScope=n}}withObserver(e,t){let n=this.activeObserver;this.activeObserver=e;try{return t()}finally{this.activeObserver=n}}withScope(e,t){let n=this.activeEffectScope,r=this.activeScope;this.activeEffectScope=void 0,this.activeScope=e;try{return t()}finally{this.activeEffectScope=n,this.activeScope=r}}enqueue(e){this.pending.add(e),this.flushDepth===0&&this.flush()}enqueueListener(e){this.listeners.add(e),this.flushDepth===0&&this.flush()}propagate(e){this.flushDepth++;try{return e()}finally{this.flushDepth--,this.flushDepth===0&&this.flush()}}emit(e){try{this.observer?.(e)}catch(t){this.report(t,{kind:`observer`,name:e.name})}}report(e,t){try{this.onError(e,t)}catch(e){queueMicrotask(()=>{throw e})}}collectWith(e,t,n){let r=this.activeObserver,i=new Set;e.collecting=i,this.activeObserver=e;try{let n=t();return this.commitDependencies(e,i),n}catch(t){throw n&&this.commitDependencies(e,i),t}finally{e.collecting=void 0,this.activeObserver=r}}commitDependencies(e,t){for(let n of e.dependencies)t.has(n)||n.dependents.delete(e);for(let n of t)e.dependencies.has(n)||n.dependents.add(e);e.dependencies.clear();for(let n of t)e.dependencies.add(n)}flush(){if(this.flushing)return;this.flushing=!0;let e=0;try{for(;this.pending.size>0||this.listeners.size>0;){if(++e>h)throw new p(`infinite reactive flush (>${h} iterations)`);let t=[...this.pending],n=[...this.listeners];this.pending.clear(),this.listeners.clear();for(let e of t)e.run();for(let e of n)try{e()}catch(e){this.report(e,{kind:`listener`})}}}finally{this.flushing=!1}}},C=e=>(t,n,r)=>{let i=e.signal({status:`pending`},{name:r?.name}),a=e.signal(0),o,s=()=>{a.value,o?.abort();let e=i.peek(),r=e.status===`success`?e.value:`previous`in e?e.previous:void 0,s;try{s=t()}catch(e){i.value=r===void 0?{error:e,status:`error`}:{error:e,previous:r,status:`error`};return}let l=new AbortController;o=l,i.value=r===void 0?{status:`pending`}:{previous:r,status:`pending`};let u;try{u=Promise.resolve(n(s,{signal:l.signal}))}catch(e){u=Promise.reject(e)}u.then(e=>{!c.disposed&&!l.signal.aborted&&(i.value={status:`success`,value:e})},e=>{!c.disposed&&!l.signal.aborted&&(i.value=r===void 0?{error:e,status:`error`}:{error:e,previous:r,status:`error`})})},c=e.effect(()=>(s(),()=>o?.abort()),{name:r?.name}),l={get disposalSignal(){return c.disposalSignal},dispose:()=>c.dispose(),get disposed(){return c.disposed},get name(){return i.name},peek:()=>i.peek(),reload:()=>{c.disposed||(a.value=a.peek()+1)},subscribe:e=>i.subscribe(e),[Symbol.dispose](){this.dispose()},get value(){return i.value}};return Object.defineProperty(l,m,{value:!0}),l},w=e=>(t,n,r)=>{let i=typeof t==`function`?t:()=>t.value,a=r?.equals??Object.is,o=!0,s,c=!1,l=e.effect(()=>{let e=i();if(o){o=!1,s=e,r?.immediate&&(n(e,void 0),r?.once&&(c=!0));return}if(a(s,e))return;let t=s;s=e,n(e,t),r?.once&&l.dispose()},{name:r?.name});return c&&l.dispose(),l},T=(e=>{let t=new S(e),n=C(t);return{batch:t.batch,computed:t.computed,createScope:t.createScope,get disposalSignal(){return t.disposalSignal},dispose:()=>t.dispose(),get disposed(){return t.disposed},effect:t.effect,resource:n,signal:t.signal,untrack:t.untrack,watch:w(t),[Symbol.dispose]:()=>t.dispose()}})(),E=T.signal;T.computed,T.effect,T.batch,T.createScope,T.untrack,T.watch,T.resource;function D(e){return e instanceof Error?e.message:String(e)}function O(e){let{apply:t,label:n,meta:r,revert:i}=e;return{apply:t,entry:Object.freeze({label:n,meta:r}),revert:i}}function k(e){return Object.freeze({...e,redo:Object.freeze([...e.redo]),undo:Object.freeze([...e.undo])})}function A(e,t){return t?new a(`Cannot call ${e}() on a disposed ledger.`):new i(`${e}() was cancelled before it started.`)}function j(e={}){let{maxHistory:t=100,runtime:n}=e,a=n?.signal??E;if(!Number.isSafeInteger(t)||t<0)throw new c(`maxHistory must be a non-negative safe integer`);let l=a(k({accepting:!0,queued:0,redo:[],running:0,undo:[]}),{name:`ledger:state`}),u=new WeakMap,d=new AbortController,f=new Set,p=new Set,m=!1,h=Promise.resolve();function g(e){if(l.value=k(e(l.value)),l.value.queued===0&&l.value.running===0){for(let e of f)e();f.clear()}}function _(e,t){e.settled||(e.settled=!0,p.delete(e),e.cancel(),t===void 0?e.resolve():e.reject(t))}function v(e,t,n){if(m)return Promise.reject(A(e,!0));let r=t?AbortSignal.any([t,d.signal]):d.signal;return new Promise((t,i)=>{let a=()=>{o.started||o.settled||m||(g(e=>({...e,queued:e.queued-1})),_(o,A(e,!1)))},o={cancel:()=>r.removeEventListener(`abort`,a),reject:i,resolve:t,settled:!1,start:async()=>{if(!o.settled){if(m||r.aborted){g(e=>({...e,queued:e.queued-1})),_(o,A(e,m));return}o.started=!0,g(e=>({...e,queued:e.queued-1,running:e.running+1}));try{await n({signal:r}),_(o)}catch(e){_(o,e)}finally{g(e=>({...e,running:e.running-1}))}}},started:!1};r.addEventListener(`abort`,a,{once:!0}),p.add(o),g(e=>({...e,queued:e.queued+1})),h=h.then(o.start,o.start)})}async function y(e,n){try{await e.apply(n)}catch(e){throw n.signal.aborted?new i(`do() was cancelled while running.`,{cause:e}):new o(D(e),{cause:e})}if(m||n.signal.aborted)throw new i(`do() was cancelled while running.`);g(n=>{if(t===0)return{...n,redo:[]};let r=[...n.undo,e.entry];return r.length>t&&r.shift(),{...n,redo:[],undo:r}}),u.set(e.entry,e)}async function b(e){let t=l.value.undo[l.value.undo.length-1];if(!t)return;let n=u.get(t);if(!n)throw new r(`Undo history is corrupted.`);try{await n.revert(e)}catch(t){throw e.signal.aborted?new i(`undo() was cancelled while running.`,{cause:t}):new s(D(t),{cause:t})}if(m||e.signal.aborted)throw new i(`undo() was cancelled while running.`);g(e=>({...e,redo:[...e.redo,t],undo:e.undo.slice(0,-1)}))}async function x(e){let t=l.value.redo[l.value.redo.length-1];if(!t)return;let n=u.get(t);if(!n)throw new r(`Redo history is corrupted.`);try{await n.apply(e)}catch(t){throw e.signal.aborted?new i(`redo() was cancelled while running.`,{cause:t}):new o(D(t),{cause:t})}if(m||e.signal.aborted)throw new i(`redo() was cancelled while running.`);g(e=>({...e,redo:e.redo.slice(0,-1),undo:[...e.undo,t]}))}return{clear(){return v(`clear`,void 0,async()=>{g(e=>({...e,redo:[],undo:[]}))})},get disposalSignal(){return d.signal},dispose(){if(m)return;m=!0,d.abort();let e=[...p].filter(e=>!e.started);for(let t of e)_(t,A(`operation`,!0));g(e=>({...e,accepting:!1,queued:0,redo:[],undo:[]}))},get disposed(){return m},do(e,t){let n=O(e);return v(`do`,t?.signal,e=>y(n,e))},redo(e){return v(`redo`,e?.signal,x)},get state(){return l},[Symbol.dispose](){this.dispose()},undo(e){return v(`undo`,e?.signal,b)},whenIdle(){return l.value.queued===0&&l.value.running===0?Promise.resolve():new Promise(e=>f.add(e))}}}return e.LedgerCancelledError=i,e.LedgerConfigurationError=c,e.LedgerDisposedError=a,e.LedgerError=r,e.LedgerExecutionError=o,e.LedgerRollbackError=s,e.compose=n,e.createLedger=j,e})({});
1
+ var Ledger=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});function t(e){let{apply:t,label:n,meta:r,revert:i}=e;return{apply:t,label:n,meta:r,revert:i}}function n(e,n){let r=e.map(t);return{apply:async e=>{let t=[];try{for(let n of r)await n.apply(e),t.push(n)}catch(n){let r=[];for(let n of[...t].reverse())try{await n.revert(e)}catch(e){r.push(e)}throw r.length>0?AggregateError([n,...r],`Command application and compensation failed`,{cause:n}):n}},label:n,revert:async e=>{let t=[];for(let n of[...r].reverse())try{await n.revert(e)}catch(e){t.push(e)}if(t.length>0)throw AggregateError(t,`Command reversion failed`)}}}var r=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},i=class extends r{},a=class extends r{},o=class extends r{},s=class extends r{},c=class extends r{},l=class{currentValue;listeners=new Set;constructor(e){this.currentValue=e}get value(){return this.currentValue}peek(){return this.currentValue}set(e){this.currentValue=e;for(let e of[...this.listeners])try{e()}catch(e){queueMicrotask(()=>{throw e})}}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}};function u(e){return e instanceof Error?e.message:String(e)}function d(e){let{apply:t,label:n,meta:r,revert:i}=e;return{apply:t,entry:Object.freeze({label:n,meta:r}),revert:i}}function f(e){return Object.freeze({...e,redo:Object.freeze([...e.redo]),undo:Object.freeze([...e.undo])})}function p(e,t){return t?new a(`Cannot call ${e}() on a disposed ledger.`):new i(`${e}() was cancelled before it started.`)}function m(e={}){let{maxHistory:t=100}=e;if(!Number.isSafeInteger(t)||t<0)throw new c(`maxHistory must be a non-negative safe integer`);let n=new l(f({accepting:!0,queued:0,redo:[],running:0,undo:[]})),a=new WeakMap,m=new AbortController,h=new Set,g=new Set,_=!1,v=Promise.resolve();function y(e){if(n.set(f(e(n.value))),n.value.queued===0&&n.value.running===0){for(let e of h)e();h.clear()}}function b(e,t){e.settled||(e.settled=!0,g.delete(e),e.cancel(),t===void 0?e.resolve():e.reject(t))}function x(e,t,n){if(_)return Promise.reject(p(e,!0));let r=t?AbortSignal.any([t,m.signal]):m.signal;return new Promise((t,i)=>{let a=()=>{o.started||o.settled||_||(y(e=>({...e,queued:e.queued-1})),b(o,p(e,!1)))},o={cancel:()=>r.removeEventListener(`abort`,a),reject:i,resolve:t,settled:!1,start:async()=>{if(!o.settled){if(_||r.aborted){y(e=>({...e,queued:e.queued-1})),b(o,p(e,_));return}o.started=!0,y(e=>({...e,queued:e.queued-1,running:e.running+1}));try{await n({signal:r}),b(o)}catch(e){b(o,e)}finally{y(e=>({...e,running:e.running-1}))}}},started:!1};r.addEventListener(`abort`,a,{once:!0}),g.add(o),y(e=>({...e,queued:e.queued+1})),v=v.then(o.start,o.start)})}async function S(e,n){try{await e.apply(n)}catch(e){throw n.signal.aborted?new i(`do() was cancelled while running.`,{cause:e}):new o(u(e),{cause:e})}if(_||n.signal.aborted)throw new i(`do() was cancelled while running.`);y(n=>{if(t===0)return{...n,redo:[]};let r=[...n.undo,e.entry];return r.length>t&&r.shift(),{...n,redo:[],undo:r}}),a.set(e.entry,e)}async function C(e){let t=n.value.undo[n.value.undo.length-1];if(!t)return;let o=a.get(t);if(!o)throw new r(`Undo history is corrupted.`);try{await o.revert(e)}catch(t){throw e.signal.aborted?new i(`undo() was cancelled while running.`,{cause:t}):new s(u(t),{cause:t})}if(_||e.signal.aborted)throw new i(`undo() was cancelled while running.`);y(e=>({...e,redo:[...e.redo,t],undo:e.undo.slice(0,-1)}))}async function w(e){let t=n.value.redo[n.value.redo.length-1];if(!t)return;let s=a.get(t);if(!s)throw new r(`Redo history is corrupted.`);try{await s.apply(e)}catch(t){throw e.signal.aborted?new i(`redo() was cancelled while running.`,{cause:t}):new o(u(t),{cause:t})}if(_||e.signal.aborted)throw new i(`redo() was cancelled while running.`);y(e=>({...e,redo:e.redo.slice(0,-1),undo:[...e.undo,t]}))}return{clear(){return x(`clear`,void 0,async()=>{y(e=>({...e,redo:[],undo:[]}))})},get disposalSignal(){return m.signal},dispose(){if(_)return;_=!0,m.abort();let e=[...g].filter(e=>!e.started);for(let t of e)b(t,p(`operation`,!0));y(e=>({...e,accepting:!1,queued:0,redo:[],undo:[]}))},get disposed(){return _},do(e,t){let n=d(e);return x(`do`,t?.signal,e=>S(n,e))},redo(e){return x(`redo`,e?.signal,w)},get state(){return n},[Symbol.dispose](){this.dispose()},undo(e){return x(`undo`,e?.signal,C)},whenIdle(){return n.value.queued===0&&n.value.running===0?Promise.resolve():new Promise(e=>h.add(e))}}}return e.LedgerCancelledError=i,e.LedgerConfigurationError=c,e.LedgerDisposedError=a,e.LedgerError=r,e.LedgerExecutionError=o,e.LedgerRollbackError=s,e.compose=n,e.createLedger=m,e})({});
2
2
  //# sourceMappingURL=ledger.iife.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ledger.iife.js","names":["e","t","r","i","i","c","l","e","u","n","d","f","t","r","e","e","n","s"],"sources":["../src/compose.ts","../src/errors.ts","../../ripple/dist/errors.js","../../ripple/dist/runtime.js","../../ripple/dist/_async.js","../../ripple/dist/_watch.js","../../ripple/dist/_default.js","../../ripple/dist/index.js","../src/ledger.ts"],"sourcesContent":["import type { CommandContext, ReversibleCommand } from './types';\n\nfunction snapshotCommand<TMeta>(command: ReversibleCommand<TMeta>): ReversibleCommand<TMeta> {\n const { apply, label, meta, revert } = command;\n\n return { apply, label, meta, revert };\n}\n\n/**\n * Composes reversible commands into one reversible command.\n *\n * `apply` runs each child in order. `revert` runs children in reverse order.\n * A failed child application compensates completed children before rethrowing.\n *\n * @example\n * await ledger.do(compose([\n * { apply: () => { node.x = newX; }, revert: () => { node.x = oldX; } },\n * { apply: () => { node.y = newY; }, revert: () => { node.y = oldY; } },\n * ], 'Move node'));\n */\nexport function compose<TMeta = undefined>(\n commands: readonly ReversibleCommand<TMeta>[],\n label?: string,\n): ReversibleCommand<TMeta> {\n const steps = commands.map(snapshotCommand);\n\n return {\n apply: async (context: CommandContext) => {\n const applied: ReversibleCommand<TMeta>[] = [];\n\n try {\n for (const command of steps) {\n await command.apply(context);\n applied.push(command);\n }\n } catch (error) {\n const compensationFailures: unknown[] = [];\n\n for (const command of [...applied].reverse()) {\n try {\n await command.revert(context);\n } catch (compensationError) {\n compensationFailures.push(compensationError);\n }\n }\n\n if (compensationFailures.length > 0) {\n throw new AggregateError([error, ...compensationFailures], 'Command application and compensation failed', {\n cause: error,\n });\n }\n\n throw error;\n }\n },\n label,\n revert: async (context: CommandContext) => {\n const failures: unknown[] = [];\n\n for (const command of [...steps].reverse()) {\n try {\n await command.revert(context);\n } catch (error) {\n failures.push(error);\n }\n }\n\n if (failures.length > 0) throw new AggregateError(failures, 'Command reversion failed');\n },\n };\n}\n","/** Base class for all ledger errors. Use `instanceof LedgerError` to catch any ledger-originated error. */\nexport class LedgerError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a queued operation is cancelled before user code starts, or an active operation cooperatively stops. */\nexport class LedgerCancelledError extends LedgerError {}\n\n/** Thrown when a method is called on a disposed ledger instance. */\nexport class LedgerDisposedError extends LedgerError {}\n\n/** Thrown when a command's `apply()` function throws. The original error is available via `.cause`. */\nexport class LedgerExecutionError extends LedgerError {}\n\n/** Thrown when a command's `revert()` function throws during an undo operation. The original error is available via `.cause`. */\nexport class LedgerRollbackError extends LedgerError {}\n\n/** Thrown when the ledger is constructed with invalid options. */\nexport class LedgerConfigurationError extends LedgerError {}\n","//#region src/errors.ts\nvar e = class extends Error {\n\tconstructor(e, t) {\n\t\tsuper(e, t), this.name = new.target.name, Object.setPrototypeOf(this, new.target.prototype);\n\t}\n}, t = class extends e {}, n = class extends e {}, r = class extends e {}, i = class extends e {};\n//#endregion\nexport { t as RippleComputedCycleError, n as RippleDisposedRuntimeError, r as RippleDisposedScopeError, e as RippleError, i as RippleInfiniteLoopError };\n\n//# sourceMappingURL=errors.js.map","import { RippleComputedCycleError as e, RippleDisposedRuntimeError as t, RippleDisposedScopeError as n, RippleInfiniteLoopError as r } from \"./errors.js\";\n//#region src/runtime.ts\nvar i = Symbol.for(\"@vielzeug/ripple/reactive\"), a = 100, o = Symbol(\"ripple.unset\"), s = class {\n\t[i] = !0;\n\tdependents = /* @__PURE__ */ new Set();\n\tname;\n\truntime;\n\tconstructor(e, t) {\n\t\tthis.runtime = e, this.name = t;\n\t}\n\tsubscribe(e) {\n\t\tthis.runtime.assertActive(), this.peek();\n\t\tlet t = {\n\t\t\tdependencies: /* @__PURE__ */ new Set(),\n\t\t\tonDependencyChanged: () => this.runtime.enqueueListener(e)\n\t\t};\n\t\treturn this.dependents.add(t), () => this.dependents.delete(t);\n\t}\n\tnotify() {\n\t\tfor (let e of [...this.dependents]) e.onDependencyChanged();\n\t}\n}, c = class extends s {\n\tcurrent;\n\tequals;\n\tconstructor(e, t, n) {\n\t\tsuper(e, n?.name), this.current = t, this.equals = n?.equals ?? Object.is;\n\t}\n\tget value() {\n\t\treturn this.runtime.track(this), this.current;\n\t}\n\tset value(e) {\n\t\tif (this.runtime.assertActive(), this.equals(this.current, e)) return;\n\t\tlet t = this.current;\n\t\tthis.current = e, this.runtime.emit({\n\t\t\tkind: \"write\",\n\t\t\tname: this.name,\n\t\t\tnext: e,\n\t\t\tprevious: t\n\t\t}), this.runtime.propagate(() => this.notify());\n\t}\n\tpeek() {\n\t\treturn this.current;\n\t}\n\tupdate(e) {\n\t\tthis.value = e(this.current);\n\t}\n}, l = class extends s {\n\tdependencies = /* @__PURE__ */ new Set();\n\tcomputing = !1;\n\tdisposed = !1;\n\tdirty = !0;\n\tcurrent = o;\n\tderive;\n\tequals;\n\tconstructor(e, t, n) {\n\t\tsuper(e, n?.name), this.derive = t, this.equals = n?.equals ?? Object.is;\n\t}\n\tget value() {\n\t\treturn this.runtime.track(this), this.refresh(), this.current;\n\t}\n\tpeek() {\n\t\treturn this.refresh(), this.current;\n\t}\n\tonDependencyChanged() {\n\t\tthis.disposed || (this.dirty ||= !0, this.dependents.size > 0 && this.refresh() && this.notify());\n\t}\n\tdispose() {\n\t\tthis.disposed || (this.disposed = !0, this.runtime.clearDependencies(this), this.dependents.clear());\n\t}\n\trefresh() {\n\t\tif (!this.dirty || this.disposed) return !1;\n\t\tif (this.computing) {\n\t\t\tlet t = this.name === void 0 ? \"\" : ` \"${this.name}\"`;\n\t\t\tthrow new e(`computed cycle detected${t}`);\n\t\t}\n\t\tthis.computing = !0, this.runtime.emit({\n\t\t\tkind: \"compute\",\n\t\t\tname: this.name\n\t\t});\n\t\ttry {\n\t\t\tlet e = this.runtime.collect(this, this.derive), t = this.current === o || !this.equals(this.current, e);\n\t\t\treturn this.current = e, this.dirty = !1, t;\n\t\t} finally {\n\t\t\tthis.computing = !1;\n\t\t}\n\t}\n}, u = class {\n\tdisposalController = new AbortController();\n\towned = /* @__PURE__ */ new Set();\n\tname;\n\tisDisposed = !1;\n\truntime;\n\tconstructor(e, t) {\n\t\tthis.runtime = e, this.name = t;\n\t}\n\tget disposed() {\n\t\treturn this.isDisposed;\n\t}\n\tget disposalSignal() {\n\t\treturn this.disposalController.signal;\n\t}\n\trun(e) {\n\t\tif (this.isDisposed) throw new n(\"Cannot run a disposed scope.\");\n\t\treturn this.runtime.withScope(this, e);\n\t}\n\tdispose() {\n\t\tif (!this.isDisposed) {\n\t\t\tthis.isDisposed = !0;\n\t\t\tfor (let e of [...this.owned].reverse()) e.dispose();\n\t\t\tthis.owned.clear(), this.disposalController.abort(), this.runtime.emit({\n\t\t\t\tkind: \"dispose\",\n\t\t\t\tname: this.name,\n\t\t\t\tnode: \"scope\"\n\t\t\t});\n\t\t}\n\t}\n\t[Symbol.dispose]() {\n\t\tthis.dispose();\n\t}\n}, d = class {\n\tdependencies = /* @__PURE__ */ new Set();\n\tdisposalController = new AbortController();\n\tcleanup;\n\tisDisposed = !1;\n\towner;\n\tscheduled = !1;\n\tcallback;\n\toptions;\n\truntime;\n\tconstructor(e, t, n) {\n\t\tthis.runtime = e, this.callback = t, this.options = n;\n\t}\n\tget disposed() {\n\t\treturn this.isDisposed;\n\t}\n\tget disposalSignal() {\n\t\treturn this.disposalController.signal;\n\t}\n\tonDependencyChanged() {\n\t\tif (!this.isDisposed) {\n\t\t\tif (this.options?.scheduler === \"microtask\") {\n\t\t\t\tif (this.scheduled) return;\n\t\t\t\tthis.scheduled = !0, queueMicrotask(() => {\n\t\t\t\t\tthis.scheduled = !1, this.isDisposed || this.runtime.enqueue(this);\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.runtime.enqueue(this);\n\t\t}\n\t}\n\trun() {\n\t\tif (this.isDisposed) return;\n\t\tthis.owner?.dispose(), this.owner = void 0, this.runCleanup(), this.runtime.emit({\n\t\t\tkind: \"effect\",\n\t\t\tname: this.options?.name\n\t\t});\n\t\tlet e = new u(this.runtime);\n\t\ttry {\n\t\t\tlet t = this.runtime.withEffectScope(e, () => this.runtime.collectEffect(this, this.callback));\n\t\t\tthis.owner = e, this.cleanup = typeof t == \"function\" ? t : void 0;\n\t\t} catch (t) {\n\t\t\te.dispose(), this.runtime.report(t, {\n\t\t\t\tkind: \"effect\",\n\t\t\t\tname: this.options?.name\n\t\t\t});\n\t\t}\n\t}\n\tdispose() {\n\t\tthis.isDisposed || (this.isDisposed = !0, this.owner?.dispose(), this.owner = void 0, this.runtime.clearDependencies(this), this.runCleanup(), this.disposalController.abort(), this.runtime.emit({\n\t\t\tkind: \"dispose\",\n\t\t\tname: this.options?.name,\n\t\t\tnode: \"effect\"\n\t\t}));\n\t}\n\t[Symbol.dispose]() {\n\t\tthis.dispose();\n\t}\n\trunCleanup() {\n\t\tlet e = this.cleanup;\n\t\tif (this.cleanup = void 0, e !== void 0) try {\n\t\t\te();\n\t\t} catch (e) {\n\t\t\tthis.runtime.report(e, {\n\t\t\t\tkind: \"cleanup\",\n\t\t\t\tname: this.options?.name\n\t\t\t});\n\t\t}\n\t}\n}, f = class {\n\tactiveEffectScope;\n\tactiveObserver;\n\tactiveScope;\n\tisDisposed = !1;\n\tflushDepth = 0;\n\tflushing = !1;\n\tpending = /* @__PURE__ */ new Set();\n\tlisteners = /* @__PURE__ */ new Set();\n\trootScope;\n\tobserver;\n\tonError;\n\tconstructor(e) {\n\t\tthis.observer = e?.observer, this.onError = e?.onError ?? ((e) => {\n\t\t\tqueueMicrotask(() => {\n\t\t\t\tthrow e;\n\t\t\t});\n\t\t}), this.rootScope = new u(this, \"runtime\"), this.activeScope = this.rootScope;\n\t}\n\tget disposed() {\n\t\treturn this.isDisposed;\n\t}\n\tget disposalSignal() {\n\t\treturn this.rootScope.disposalSignal;\n\t}\n\tsignal = (e, t) => (this.assertActive(), new c(this, e, t));\n\tcomputed = (e, t) => {\n\t\tthis.assertActive();\n\t\tlet n = new l(this, e, t);\n\t\treturn (this.activeEffectScope ?? this.activeScope).owned.add(n), n;\n\t};\n\teffect = (e, t) => {\n\t\tthis.assertActive();\n\t\tlet n = new d(this, e, t);\n\t\treturn (this.activeEffectScope ?? this.activeScope).owned.add(n), n.run(), n;\n\t};\n\tcreateScope = (e) => {\n\t\tthis.assertActive();\n\t\tlet t = new u(this, e);\n\t\treturn this.activeScope.owned.add(t), t;\n\t};\n\tbatch = (e) => (this.assertActive(), this.propagate(e));\n\tuntrack = (e) => (this.assertActive(), this.withObserver(void 0, e));\n\tdispose() {\n\t\tthis.isDisposed || (this.isDisposed = !0, this.rootScope.dispose());\n\t}\n\tassertActive() {\n\t\tif (this.isDisposed) throw new t(\"Cannot use a disposed Ripple runtime.\");\n\t}\n\ttrack(e) {\n\t\tlet t = this.activeObserver;\n\t\tt?.collecting !== void 0 && t.collecting.add(e);\n\t}\n\tclearDependencies(e) {\n\t\tfor (let t of e.dependencies) t.dependents.delete(e);\n\t\te.dependencies.clear();\n\t}\n\tcollect(e, t) {\n\t\treturn this.collectWith(e, t, e.dependencies.size === 0);\n\t}\n\tcollectEffect(e, t) {\n\t\treturn this.collectWith(e, t, !0);\n\t}\n\twithEffectScope(e, t) {\n\t\tlet n = this.activeEffectScope;\n\t\tthis.activeEffectScope = e;\n\t\ttry {\n\t\t\treturn t();\n\t\t} finally {\n\t\t\tthis.activeEffectScope = n;\n\t\t}\n\t}\n\twithObserver(e, t) {\n\t\tlet n = this.activeObserver;\n\t\tthis.activeObserver = e;\n\t\ttry {\n\t\t\treturn t();\n\t\t} finally {\n\t\t\tthis.activeObserver = n;\n\t\t}\n\t}\n\twithScope(e, t) {\n\t\tlet n = this.activeEffectScope, r = this.activeScope;\n\t\tthis.activeEffectScope = void 0, this.activeScope = e;\n\t\ttry {\n\t\t\treturn t();\n\t\t} finally {\n\t\t\tthis.activeEffectScope = n, this.activeScope = r;\n\t\t}\n\t}\n\tenqueue(e) {\n\t\tthis.pending.add(e), this.flushDepth === 0 && this.flush();\n\t}\n\tenqueueListener(e) {\n\t\tthis.listeners.add(e), this.flushDepth === 0 && this.flush();\n\t}\n\tpropagate(e) {\n\t\tthis.flushDepth++;\n\t\ttry {\n\t\t\treturn e();\n\t\t} finally {\n\t\t\tthis.flushDepth--, this.flushDepth === 0 && this.flush();\n\t\t}\n\t}\n\temit(e) {\n\t\ttry {\n\t\t\tthis.observer?.(e);\n\t\t} catch (t) {\n\t\t\tthis.report(t, {\n\t\t\t\tkind: \"observer\",\n\t\t\t\tname: e.name\n\t\t\t});\n\t\t}\n\t}\n\treport(e, t) {\n\t\ttry {\n\t\t\tthis.onError(e, t);\n\t\t} catch (e) {\n\t\t\tqueueMicrotask(() => {\n\t\t\t\tthrow e;\n\t\t\t});\n\t\t}\n\t}\n\tcollectWith(e, t, n) {\n\t\tlet r = this.activeObserver, i = /* @__PURE__ */ new Set();\n\t\te.collecting = i, this.activeObserver = e;\n\t\ttry {\n\t\t\tlet n = t();\n\t\t\treturn this.commitDependencies(e, i), n;\n\t\t} catch (t) {\n\t\t\tthrow n && this.commitDependencies(e, i), t;\n\t\t} finally {\n\t\t\te.collecting = void 0, this.activeObserver = r;\n\t\t}\n\t}\n\tcommitDependencies(e, t) {\n\t\tfor (let n of e.dependencies) t.has(n) || n.dependents.delete(e);\n\t\tfor (let n of t) e.dependencies.has(n) || n.dependents.add(e);\n\t\te.dependencies.clear();\n\t\tfor (let n of t) e.dependencies.add(n);\n\t}\n\tflush() {\n\t\tif (this.flushing) return;\n\t\tthis.flushing = !0;\n\t\tlet e = 0;\n\t\ttry {\n\t\t\tfor (; this.pending.size > 0 || this.listeners.size > 0;) {\n\t\t\t\tif (++e > a) throw new r(`infinite reactive flush (>${a} iterations)`);\n\t\t\t\tlet t = [...this.pending], n = [...this.listeners];\n\t\t\t\tthis.pending.clear(), this.listeners.clear();\n\t\t\t\tfor (let e of t) e.run();\n\t\t\t\tfor (let e of n) try {\n\t\t\t\t\te();\n\t\t\t\t} catch (e) {\n\t\t\t\t\tthis.report(e, { kind: \"listener\" });\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.flushing = !1;\n\t\t}\n\t}\n}, p = (e) => {\n\tif (typeof e != \"object\" || !e || !(i in e)) return !1;\n\tlet t = e;\n\treturn typeof t.peek == \"function\" && typeof t.subscribe == \"function\";\n};\n//#endregion\nexport { i as REACTIVE, f as ReactiveRuntime, p as isReactive };\n\n//# sourceMappingURL=runtime.js.map","import { REACTIVE as e } from \"./runtime.js\";\n//#region src/_async.ts\nvar t = (t) => (n, r, i) => {\n\tlet a = t.signal({ status: \"pending\" }, { name: i?.name }), o = t.signal(0), s, c = () => {\n\t\to.value, s?.abort();\n\t\tlet e = a.peek(), t = e.status === \"success\" ? e.value : \"previous\" in e ? e.previous : void 0, i;\n\t\ttry {\n\t\t\ti = n();\n\t\t} catch (e) {\n\t\t\ta.value = t === void 0 ? {\n\t\t\t\terror: e,\n\t\t\t\tstatus: \"error\"\n\t\t\t} : {\n\t\t\t\terror: e,\n\t\t\t\tprevious: t,\n\t\t\t\tstatus: \"error\"\n\t\t\t};\n\t\t\treturn;\n\t\t}\n\t\tlet c = new AbortController();\n\t\ts = c, a.value = t === void 0 ? { status: \"pending\" } : {\n\t\t\tprevious: t,\n\t\t\tstatus: \"pending\"\n\t\t};\n\t\tlet u;\n\t\ttry {\n\t\t\tu = Promise.resolve(r(i, { signal: c.signal }));\n\t\t} catch (e) {\n\t\t\tu = Promise.reject(e);\n\t\t}\n\t\tu.then((e) => {\n\t\t\t!l.disposed && !c.signal.aborted && (a.value = {\n\t\t\t\tstatus: \"success\",\n\t\t\t\tvalue: e\n\t\t\t});\n\t\t}, (e) => {\n\t\t\t!l.disposed && !c.signal.aborted && (a.value = t === void 0 ? {\n\t\t\t\terror: e,\n\t\t\t\tstatus: \"error\"\n\t\t\t} : {\n\t\t\t\terror: e,\n\t\t\t\tprevious: t,\n\t\t\t\tstatus: \"error\"\n\t\t\t});\n\t\t});\n\t}, l = t.effect(() => (c(), () => s?.abort()), { name: i?.name }), u = {\n\t\tget disposalSignal() {\n\t\t\treturn l.disposalSignal;\n\t\t},\n\t\tdispose: () => l.dispose(),\n\t\tget disposed() {\n\t\t\treturn l.disposed;\n\t\t},\n\t\tget name() {\n\t\t\treturn a.name;\n\t\t},\n\t\tpeek: () => a.peek(),\n\t\treload: () => {\n\t\t\tl.disposed || (o.value = o.peek() + 1);\n\t\t},\n\t\tsubscribe: (e) => a.subscribe(e),\n\t\t[Symbol.dispose]() {\n\t\t\tthis.dispose();\n\t\t},\n\t\tget value() {\n\t\t\treturn a.value;\n\t\t}\n\t};\n\treturn Object.defineProperty(u, e, { value: !0 }), u;\n};\n//#endregion\nexport { t as createResource };\n\n//# sourceMappingURL=_async.js.map","//#region src/_watch.ts\nvar e = (e) => (t, n, r) => {\n\tlet i = typeof t == \"function\" ? t : () => t.value, a = r?.equals ?? Object.is, o = !0, s, c = !1, l = e.effect(() => {\n\t\tlet e = i();\n\t\tif (o) {\n\t\t\to = !1, s = e, r?.immediate && (n(e, void 0), r?.once && (c = !0));\n\t\t\treturn;\n\t\t}\n\t\tif (a(s, e)) return;\n\t\tlet t = s;\n\t\ts = e, n(e, t), r?.once && l.dispose();\n\t}, { name: r?.name });\n\treturn c && l.dispose(), l;\n};\n//#endregion\nexport { e as createWatch };\n\n//# sourceMappingURL=_watch.js.map","import { ReactiveRuntime as e } from \"./runtime.js\";\nimport { createResource as t } from \"./_async.js\";\nimport { createWatch as n } from \"./_watch.js\";\n//#region src/_default.ts\nvar r = (r) => {\n\tlet i = new e(r), a = t(i);\n\treturn {\n\t\tbatch: i.batch,\n\t\tcomputed: i.computed,\n\t\tcreateScope: i.createScope,\n\t\tget disposalSignal() {\n\t\t\treturn i.disposalSignal;\n\t\t},\n\t\tdispose: () => i.dispose(),\n\t\tget disposed() {\n\t\t\treturn i.disposed;\n\t\t},\n\t\teffect: i.effect,\n\t\tresource: a,\n\t\tsignal: i.signal,\n\t\tuntrack: i.untrack,\n\t\twatch: n(i),\n\t\t[Symbol.dispose]: () => i.dispose()\n\t};\n}, i = r();\n//#endregion\nexport { r as createRipple, i as defaultRipple };\n\n//# sourceMappingURL=_default.js.map","import { RippleComputedCycleError as e, RippleDisposedRuntimeError as t, RippleDisposedScopeError as n, RippleError as r, RippleInfiniteLoopError as i } from \"./errors.js\";\nimport { isReactive as a } from \"./runtime.js\";\nimport { createRipple as o, defaultRipple as s } from \"./_default.js\";\n//#region src/index.ts\nvar c = s.signal, l = s.computed, u = s.effect, d = s.batch, f = s.createScope, p = s.untrack, m = s.watch, h = s.resource;\n//#endregion\nexport { e as RippleComputedCycleError, t as RippleDisposedRuntimeError, n as RippleDisposedScopeError, r as RippleError, i as RippleInfiniteLoopError, d as batch, l as computed, o as createRipple, f as createScope, u as effect, a as isReactive, h as resource, c as signal, p as untrack, m as watch };\n\n//# sourceMappingURL=index.js.map","import { signal as defaultSignal } from '@vielzeug/ripple';\nimport {\n LedgerCancelledError,\n LedgerConfigurationError,\n LedgerDisposedError,\n LedgerError,\n LedgerExecutionError,\n LedgerRollbackError,\n} from './errors';\nimport type {\n CommandContext,\n HistoryEntry,\n Ledger,\n LedgerCallOptions,\n LedgerOptions,\n LedgerState,\n ReversibleCommand,\n} from './types';\n\ntype StoredCommand<TMeta> = {\n apply: (context: CommandContext) => Promise<void> | void;\n entry: HistoryEntry<TMeta>;\n revert: (context: CommandContext) => Promise<void> | void;\n};\n\ntype Operation = {\n cancel: () => void;\n reject: (reason?: unknown) => void;\n resolve: () => void;\n settled: boolean;\n start: () => Promise<void>;\n started: boolean;\n};\n\nfunction toMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction snapshotCommand<TMeta>(command: ReversibleCommand<TMeta>): StoredCommand<TMeta> {\n const { apply, label, meta, revert } = command;\n\n return { apply, entry: Object.freeze({ label, meta }), revert };\n}\n\nfunction snapshotState<TMeta>(state: LedgerState<TMeta>): LedgerState<TMeta> {\n return Object.freeze({\n ...state,\n redo: Object.freeze([...state.redo]),\n undo: Object.freeze([...state.undo]),\n });\n}\n\nfunction operationError(method: string, disposed: boolean): LedgerCancelledError | LedgerDisposedError {\n return disposed\n ? new LedgerDisposedError(`Cannot call ${method}() on a disposed ledger.`)\n : new LedgerCancelledError(`${method}() was cancelled before it started.`);\n}\n\n/**\n * Creates a serialized history of reversible commands.\n *\n * Commands are snapshotted when submitted. Queued commands cancelled before their queue turn do\n * not invoke user code. Active commands receive an abort signal and stop cooperatively.\n *\n * @example\n * const ledger = createLedger({ maxHistory: 50 });\n * await ledger.do({\n * apply: () => { item.name = next; },\n * revert: () => { item.name = previous; },\n * });\n * await ledger.undo();\n * await ledger.redo();\n * using ledger = createLedger();\n */\nexport function createLedger<TMeta = undefined>(options: LedgerOptions = {}): Ledger<TMeta> {\n const { maxHistory = 100, runtime } = options;\n const signal = runtime?.signal ?? defaultSignal;\n\n if (!Number.isSafeInteger(maxHistory) || maxHistory < 0) {\n throw new LedgerConfigurationError('maxHistory must be a non-negative safe integer');\n }\n\n const state = signal<LedgerState<TMeta>>(\n snapshotState({ accepting: true, queued: 0, redo: [], running: 0, undo: [] }),\n { name: 'ledger:state' },\n );\n const commandStore = new WeakMap<HistoryEntry<TMeta>, StoredCommand<TMeta>>();\n const disposalController = new AbortController();\n const idleWaiters = new Set<() => void>();\n const operations = new Set<Operation>();\n let disposed = false;\n let queue = Promise.resolve();\n\n function updateState(update: (current: LedgerState<TMeta>) => LedgerState<TMeta>): void {\n state.value = snapshotState(update(state.value));\n\n if (state.value.queued === 0 && state.value.running === 0) {\n for (const resolve of idleWaiters) resolve();\n idleWaiters.clear();\n }\n }\n\n function settle(operation: Operation, error?: unknown): void {\n if (operation.settled) return;\n\n operation.settled = true;\n operations.delete(operation);\n operation.cancel();\n\n if (error === undefined) operation.resolve();\n else operation.reject(error);\n }\n\n function enqueue(\n method: string,\n externalSignal: AbortSignal | undefined,\n task: (context: CommandContext) => Promise<void>,\n ): Promise<void> {\n if (disposed) return Promise.reject(operationError(method, true));\n\n const abortSignal = externalSignal\n ? AbortSignal.any([externalSignal, disposalController.signal])\n : disposalController.signal;\n\n return new Promise<void>((resolve, reject) => {\n const onAbort = (): void => {\n if (operation.started || operation.settled || disposed) return;\n\n updateState((current) => ({ ...current, queued: current.queued - 1 }));\n settle(operation, operationError(method, false));\n };\n\n const operation: Operation = {\n cancel: () => abortSignal.removeEventListener('abort', onAbort),\n reject,\n resolve,\n settled: false,\n start: async () => {\n if (operation.settled) return;\n\n if (disposed || abortSignal.aborted) {\n updateState((current) => ({ ...current, queued: current.queued - 1 }));\n settle(operation, operationError(method, disposed));\n\n return;\n }\n\n operation.started = true;\n updateState((current) => ({ ...current, queued: current.queued - 1, running: current.running + 1 }));\n\n try {\n await task({ signal: abortSignal });\n settle(operation);\n } catch (error) {\n settle(operation, error);\n } finally {\n updateState((current) => ({ ...current, running: current.running - 1 }));\n }\n },\n started: false,\n };\n\n abortSignal.addEventListener('abort', onAbort, { once: true });\n operations.add(operation);\n updateState((current) => ({ ...current, queued: current.queued + 1 }));\n queue = queue.then(operation.start, operation.start);\n });\n }\n\n async function runDo(command: StoredCommand<TMeta>, context: CommandContext): Promise<void> {\n try {\n await command.apply(context);\n } catch (error) {\n throw context.signal.aborted\n ? new LedgerCancelledError('do() was cancelled while running.', { cause: error })\n : new LedgerExecutionError(toMessage(error), { cause: error });\n }\n\n if (disposed || context.signal.aborted) {\n throw new LedgerCancelledError('do() was cancelled while running.');\n }\n\n updateState((current) => {\n if (maxHistory === 0) return { ...current, redo: [] };\n\n const undo = [...current.undo, command.entry];\n\n if (undo.length > maxHistory) undo.shift();\n\n return { ...current, redo: [], undo };\n });\n commandStore.set(command.entry, command);\n }\n\n async function runUndo(context: CommandContext): Promise<void> {\n const entry = state.value.undo[state.value.undo.length - 1];\n\n if (!entry) return;\n\n const command = commandStore.get(entry);\n\n if (!command) throw new LedgerError('Undo history is corrupted.');\n\n try {\n await command.revert(context);\n } catch (error) {\n throw context.signal.aborted\n ? new LedgerCancelledError('undo() was cancelled while running.', { cause: error })\n : new LedgerRollbackError(toMessage(error), { cause: error });\n }\n\n if (disposed || context.signal.aborted) {\n throw new LedgerCancelledError('undo() was cancelled while running.');\n }\n\n updateState((current) => ({ ...current, redo: [...current.redo, entry], undo: current.undo.slice(0, -1) }));\n }\n\n async function runRedo(context: CommandContext): Promise<void> {\n const entry = state.value.redo[state.value.redo.length - 1];\n\n if (!entry) return;\n\n const command = commandStore.get(entry);\n\n if (!command) throw new LedgerError('Redo history is corrupted.');\n\n try {\n await command.apply(context);\n } catch (error) {\n throw context.signal.aborted\n ? new LedgerCancelledError('redo() was cancelled while running.', { cause: error })\n : new LedgerExecutionError(toMessage(error), { cause: error });\n }\n\n if (disposed || context.signal.aborted) {\n throw new LedgerCancelledError('redo() was cancelled while running.');\n }\n\n updateState((current) => ({ ...current, redo: current.redo.slice(0, -1), undo: [...current.undo, entry] }));\n }\n\n return {\n clear(): Promise<void> {\n return enqueue('clear', undefined, async () => {\n updateState((current) => ({ ...current, redo: [], undo: [] }));\n });\n },\n\n get disposalSignal(): AbortSignal {\n return disposalController.signal;\n },\n\n dispose(): void {\n if (disposed) return;\n\n disposed = true;\n disposalController.abort();\n\n const queued = [...operations].filter((operation) => !operation.started);\n\n for (const operation of queued) settle(operation, operationError('operation', true));\n\n updateState((current) => ({ ...current, accepting: false, queued: 0, redo: [], undo: [] }));\n },\n\n get disposed(): boolean {\n return disposed;\n },\n\n do(command: ReversibleCommand<TMeta>, callOptions?: LedgerCallOptions): Promise<void> {\n const snapshot = snapshotCommand(command);\n\n return enqueue('do', callOptions?.signal, (context) => runDo(snapshot, context));\n },\n\n redo(callOptions?: LedgerCallOptions): Promise<void> {\n return enqueue('redo', callOptions?.signal, runRedo);\n },\n\n get state() {\n return state;\n },\n\n [Symbol.dispose](): void {\n this.dispose();\n },\n\n undo(callOptions?: LedgerCallOptions): Promise<void> {\n return enqueue('undo', callOptions?.signal, runUndo);\n },\n\n whenIdle(): Promise<void> {\n if (state.value.queued === 0 && state.value.running === 0) return Promise.resolve();\n\n return new Promise((resolve) => idleWaiters.add(resolve));\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ledger.iife.js","names":[],"sources":["../src/compose.ts","../src/errors.ts","../src/ledger.ts"],"sourcesContent":["import type { CommandContext, ReversibleCommand } from './types';\n\nfunction snapshotCommand<TMeta>(command: ReversibleCommand<TMeta>): ReversibleCommand<TMeta> {\n const { apply, label, meta, revert } = command;\n\n return { apply, label, meta, revert };\n}\n\n/**\n * Composes reversible commands into one reversible command.\n *\n * `apply` runs each child in order. `revert` runs children in reverse order.\n * A failed child application compensates completed children before rethrowing.\n *\n * @example\n * await ledger.do(compose([\n * { apply: () => { node.x = newX; }, revert: () => { node.x = oldX; } },\n * { apply: () => { node.y = newY; }, revert: () => { node.y = oldY; } },\n * ], 'Move node'));\n */\nexport function compose<TMeta = undefined>(\n commands: readonly ReversibleCommand<TMeta>[],\n label?: string,\n): ReversibleCommand<TMeta> {\n const steps = commands.map(snapshotCommand);\n\n return {\n apply: async (context: CommandContext) => {\n const applied: ReversibleCommand<TMeta>[] = [];\n\n try {\n for (const command of steps) {\n await command.apply(context);\n applied.push(command);\n }\n } catch (error) {\n const compensationFailures: unknown[] = [];\n\n for (const command of [...applied].reverse()) {\n try {\n await command.revert(context);\n } catch (compensationError) {\n compensationFailures.push(compensationError);\n }\n }\n\n if (compensationFailures.length > 0) {\n throw new AggregateError([error, ...compensationFailures], 'Command application and compensation failed', {\n cause: error,\n });\n }\n\n throw error;\n }\n },\n label,\n revert: async (context: CommandContext) => {\n const failures: unknown[] = [];\n\n for (const command of [...steps].reverse()) {\n try {\n await command.revert(context);\n } catch (error) {\n failures.push(error);\n }\n }\n\n if (failures.length > 0) throw new AggregateError(failures, 'Command reversion failed');\n },\n };\n}\n","/** Base class for all ledger errors. Use `instanceof LedgerError` to catch any ledger-originated error. */\nexport class LedgerError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a queued operation is cancelled before user code starts, or an active operation cooperatively stops. */\nexport class LedgerCancelledError extends LedgerError {}\n\n/** Thrown when a method is called on a disposed ledger instance. */\nexport class LedgerDisposedError extends LedgerError {}\n\n/** Thrown when a command's `apply()` function throws. The original error is available via `.cause`. */\nexport class LedgerExecutionError extends LedgerError {}\n\n/** Thrown when a command's `revert()` function throws during an undo operation. The original error is available via `.cause`. */\nexport class LedgerRollbackError extends LedgerError {}\n\n/** Thrown when the ledger is constructed with invalid options. */\nexport class LedgerConfigurationError extends LedgerError {}\n","import {\n LedgerCancelledError,\n LedgerConfigurationError,\n LedgerDisposedError,\n LedgerError,\n LedgerExecutionError,\n LedgerRollbackError,\n} from './errors';\nimport type {\n CommandContext,\n HistoryEntry,\n Ledger,\n LedgerCallOptions,\n LedgerOptions,\n LedgerReadable,\n LedgerState,\n ReversibleCommand,\n Unsubscribe,\n} from './types';\n\ntype StoredCommand<TMeta> = {\n apply: (context: CommandContext) => Promise<void> | void;\n entry: HistoryEntry<TMeta>;\n revert: (context: CommandContext) => Promise<void> | void;\n};\n\ntype Operation = {\n cancel: () => void;\n reject: (reason?: unknown) => void;\n resolve: () => void;\n settled: boolean;\n start: () => Promise<void>;\n started: boolean;\n};\n\nclass StateStore<T> implements LedgerReadable<T> {\n private currentValue: T;\n private readonly listeners = new Set<() => void>();\n\n constructor(initial: T) {\n this.currentValue = initial;\n }\n\n get value(): T {\n return this.currentValue;\n }\n\n peek(): T {\n return this.currentValue;\n }\n\n set(next: T): void {\n this.currentValue = next;\n\n for (const listener of [...this.listeners]) {\n try {\n listener();\n } catch (error) {\n queueMicrotask(() => {\n throw error;\n });\n }\n }\n }\n\n subscribe(listener: () => void): Unsubscribe {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n}\n\nfunction toMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction snapshotCommand<TMeta>(command: ReversibleCommand<TMeta>): StoredCommand<TMeta> {\n const { apply, label, meta, revert } = command;\n\n return { apply, entry: Object.freeze({ label, meta }), revert };\n}\n\nfunction snapshotState<TMeta>(state: LedgerState<TMeta>): LedgerState<TMeta> {\n return Object.freeze({\n ...state,\n redo: Object.freeze([...state.redo]),\n undo: Object.freeze([...state.undo]),\n });\n}\n\nfunction operationError(method: string, disposed: boolean): LedgerCancelledError | LedgerDisposedError {\n return disposed\n ? new LedgerDisposedError(`Cannot call ${method}() on a disposed ledger.`)\n : new LedgerCancelledError(`${method}() was cancelled before it started.`);\n}\n\n/**\n * Creates a serialized history of reversible commands.\n *\n * Commands are snapshotted when submitted. Queued commands cancelled before their queue turn do\n * not invoke user code. Active commands receive an abort signal and stop cooperatively.\n *\n * @example\n * const ledger = createLedger({ maxHistory: 50 });\n * await ledger.do({\n * apply: () => { item.name = next; },\n * revert: () => { item.name = previous; },\n * });\n * await ledger.undo();\n * await ledger.redo();\n * using ledger = createLedger();\n */\nexport function createLedger<TMeta = undefined>(options: LedgerOptions = {}): Ledger<TMeta> {\n const { maxHistory = 100 } = options;\n\n if (!Number.isSafeInteger(maxHistory) || maxHistory < 0) {\n throw new LedgerConfigurationError('maxHistory must be a non-negative safe integer');\n }\n\n const state = new StateStore<LedgerState<TMeta>>(\n snapshotState({ accepting: true, queued: 0, redo: [], running: 0, undo: [] }),\n );\n const commandStore = new WeakMap<HistoryEntry<TMeta>, StoredCommand<TMeta>>();\n const disposalController = new AbortController();\n const idleWaiters = new Set<() => void>();\n const operations = new Set<Operation>();\n let disposed = false;\n let queue = Promise.resolve();\n\n function updateState(update: (current: LedgerState<TMeta>) => LedgerState<TMeta>): void {\n state.set(snapshotState(update(state.value)));\n\n if (state.value.queued === 0 && state.value.running === 0) {\n for (const resolve of idleWaiters) resolve();\n idleWaiters.clear();\n }\n }\n\n function settle(operation: Operation, error?: unknown): void {\n if (operation.settled) return;\n\n operation.settled = true;\n operations.delete(operation);\n operation.cancel();\n\n if (error === undefined) operation.resolve();\n else operation.reject(error);\n }\n\n function enqueue(\n method: string,\n externalSignal: AbortSignal | undefined,\n task: (context: CommandContext) => Promise<void>,\n ): Promise<void> {\n if (disposed) return Promise.reject(operationError(method, true));\n\n const abortSignal = externalSignal\n ? AbortSignal.any([externalSignal, disposalController.signal])\n : disposalController.signal;\n\n return new Promise<void>((resolve, reject) => {\n const onAbort = (): void => {\n if (operation.started || operation.settled || disposed) return;\n\n updateState((current) => ({ ...current, queued: current.queued - 1 }));\n settle(operation, operationError(method, false));\n };\n\n const operation: Operation = {\n cancel: () => abortSignal.removeEventListener('abort', onAbort),\n reject,\n resolve,\n settled: false,\n start: async () => {\n if (operation.settled) return;\n\n if (disposed || abortSignal.aborted) {\n updateState((current) => ({ ...current, queued: current.queued - 1 }));\n settle(operation, operationError(method, disposed));\n\n return;\n }\n\n operation.started = true;\n updateState((current) => ({ ...current, queued: current.queued - 1, running: current.running + 1 }));\n\n try {\n await task({ signal: abortSignal });\n settle(operation);\n } catch (error) {\n settle(operation, error);\n } finally {\n updateState((current) => ({ ...current, running: current.running - 1 }));\n }\n },\n started: false,\n };\n\n abortSignal.addEventListener('abort', onAbort, { once: true });\n operations.add(operation);\n updateState((current) => ({ ...current, queued: current.queued + 1 }));\n queue = queue.then(operation.start, operation.start);\n });\n }\n\n async function runDo(command: StoredCommand<TMeta>, context: CommandContext): Promise<void> {\n try {\n await command.apply(context);\n } catch (error) {\n throw context.signal.aborted\n ? new LedgerCancelledError('do() was cancelled while running.', { cause: error })\n : new LedgerExecutionError(toMessage(error), { cause: error });\n }\n\n if (disposed || context.signal.aborted) {\n throw new LedgerCancelledError('do() was cancelled while running.');\n }\n\n updateState((current) => {\n if (maxHistory === 0) return { ...current, redo: [] };\n\n const undo = [...current.undo, command.entry];\n\n if (undo.length > maxHistory) undo.shift();\n\n return { ...current, redo: [], undo };\n });\n commandStore.set(command.entry, command);\n }\n\n async function runUndo(context: CommandContext): Promise<void> {\n const entry = state.value.undo[state.value.undo.length - 1];\n\n if (!entry) return;\n\n const command = commandStore.get(entry);\n\n if (!command) throw new LedgerError('Undo history is corrupted.');\n\n try {\n await command.revert(context);\n } catch (error) {\n throw context.signal.aborted\n ? new LedgerCancelledError('undo() was cancelled while running.', { cause: error })\n : new LedgerRollbackError(toMessage(error), { cause: error });\n }\n\n if (disposed || context.signal.aborted) {\n throw new LedgerCancelledError('undo() was cancelled while running.');\n }\n\n updateState((current) => ({ ...current, redo: [...current.redo, entry], undo: current.undo.slice(0, -1) }));\n }\n\n async function runRedo(context: CommandContext): Promise<void> {\n const entry = state.value.redo[state.value.redo.length - 1];\n\n if (!entry) return;\n\n const command = commandStore.get(entry);\n\n if (!command) throw new LedgerError('Redo history is corrupted.');\n\n try {\n await command.apply(context);\n } catch (error) {\n throw context.signal.aborted\n ? new LedgerCancelledError('redo() was cancelled while running.', { cause: error })\n : new LedgerExecutionError(toMessage(error), { cause: error });\n }\n\n if (disposed || context.signal.aborted) {\n throw new LedgerCancelledError('redo() was cancelled while running.');\n }\n\n updateState((current) => ({ ...current, redo: current.redo.slice(0, -1), undo: [...current.undo, entry] }));\n }\n\n return {\n clear(): Promise<void> {\n return enqueue('clear', undefined, async () => {\n updateState((current) => ({ ...current, redo: [], undo: [] }));\n });\n },\n\n get disposalSignal(): AbortSignal {\n return disposalController.signal;\n },\n\n dispose(): void {\n if (disposed) return;\n\n disposed = true;\n disposalController.abort();\n\n const queued = [...operations].filter((operation) => !operation.started);\n\n for (const operation of queued) settle(operation, operationError('operation', true));\n\n updateState((current) => ({ ...current, accepting: false, queued: 0, redo: [], undo: [] }));\n },\n\n get disposed(): boolean {\n return disposed;\n },\n\n do(command: ReversibleCommand<TMeta>, callOptions?: LedgerCallOptions): Promise<void> {\n const snapshot = snapshotCommand(command);\n\n return enqueue('do', callOptions?.signal, (context) => runDo(snapshot, context));\n },\n\n redo(callOptions?: LedgerCallOptions): Promise<void> {\n return enqueue('redo', callOptions?.signal, runRedo);\n },\n\n get state() {\n return state;\n },\n\n [Symbol.dispose](): void {\n this.dispose();\n },\n\n undo(callOptions?: LedgerCallOptions): Promise<void> {\n return enqueue('undo', callOptions?.signal, runUndo);\n },\n\n whenIdle(): Promise<void> {\n if (state.value.queued === 0 && state.value.running === 0) return Promise.resolve();\n\n return new Promise((resolve) => idleWaiters.add(resolve));\n },\n };\n}\n"],"mappings":"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"}
package/dist/ledger.js CHANGED
@@ -1,2 +1,2 @@
1
- function e(e){let{apply:t,label:n,meta:r,revert:i}=e;return{apply:t,label:n,meta:r,revert:i}}function t(t,n){let r=t.map(e);return{apply:async e=>{let t=[];try{for(let n of r)await n.apply(e),t.push(n)}catch(n){let r=[];for(let n of[...t].reverse())try{await n.revert(e)}catch(e){r.push(e)}throw r.length>0?AggregateError([n,...r],`Command application and compensation failed`,{cause:n}):n}},label:n,revert:async e=>{let t=[];for(let n of[...r].reverse())try{await n.revert(e)}catch(e){t.push(e)}if(t.length>0)throw AggregateError(t,`Command reversion failed`)}}}var n=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},r=class extends n{},i=class extends n{},a=class extends n{},o=class extends n{},s=class extends n{},c=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},l=class extends c{},u=class extends c{},d=class extends c{},f=class extends c{},p=Symbol.for(`@vielzeug/ripple/reactive`),m=100,h=Symbol(`ripple.unset`),g=class{[p]=!0;dependents=new Set;name;runtime;constructor(e,t){this.runtime=e,this.name=t}subscribe(e){this.runtime.assertActive(),this.peek();let t={dependencies:new Set,onDependencyChanged:()=>this.runtime.enqueueListener(e)};return this.dependents.add(t),()=>this.dependents.delete(t)}notify(){for(let e of[...this.dependents])e.onDependencyChanged()}},_=class extends g{current;equals;constructor(e,t,n){super(e,n?.name),this.current=t,this.equals=n?.equals??Object.is}get value(){return this.runtime.track(this),this.current}set value(e){if(this.runtime.assertActive(),this.equals(this.current,e))return;let t=this.current;this.current=e,this.runtime.emit({kind:`write`,name:this.name,next:e,previous:t}),this.runtime.propagate(()=>this.notify())}peek(){return this.current}update(e){this.value=e(this.current)}},v=class extends g{dependencies=new Set;computing=!1;disposed=!1;dirty=!0;current=h;derive;equals;constructor(e,t,n){super(e,n?.name),this.derive=t,this.equals=n?.equals??Object.is}get value(){return this.runtime.track(this),this.refresh(),this.current}peek(){return this.refresh(),this.current}onDependencyChanged(){this.disposed||(this.dirty||=!0,this.dependents.size>0&&this.refresh()&&this.notify())}dispose(){this.disposed||(this.disposed=!0,this.runtime.clearDependencies(this),this.dependents.clear())}refresh(){if(!this.dirty||this.disposed)return!1;if(this.computing)throw new l(`computed cycle detected${this.name===void 0?``:` "${this.name}"`}`);this.computing=!0,this.runtime.emit({kind:`compute`,name:this.name});try{let e=this.runtime.collect(this,this.derive),t=this.current===h||!this.equals(this.current,e);return this.current=e,this.dirty=!1,t}finally{this.computing=!1}}},y=class{disposalController=new AbortController;owned=new Set;name;isDisposed=!1;runtime;constructor(e,t){this.runtime=e,this.name=t}get disposed(){return this.isDisposed}get disposalSignal(){return this.disposalController.signal}run(e){if(this.isDisposed)throw new d(`Cannot run a disposed scope.`);return this.runtime.withScope(this,e)}dispose(){if(!this.isDisposed){this.isDisposed=!0;for(let e of[...this.owned].reverse())e.dispose();this.owned.clear(),this.disposalController.abort(),this.runtime.emit({kind:`dispose`,name:this.name,node:`scope`})}}[Symbol.dispose](){this.dispose()}},b=class{dependencies=new Set;disposalController=new AbortController;cleanup;isDisposed=!1;owner;scheduled=!1;callback;options;runtime;constructor(e,t,n){this.runtime=e,this.callback=t,this.options=n}get disposed(){return this.isDisposed}get disposalSignal(){return this.disposalController.signal}onDependencyChanged(){if(!this.isDisposed){if(this.options?.scheduler===`microtask`){if(this.scheduled)return;this.scheduled=!0,queueMicrotask(()=>{this.scheduled=!1,this.isDisposed||this.runtime.enqueue(this)});return}this.runtime.enqueue(this)}}run(){if(this.isDisposed)return;this.owner?.dispose(),this.owner=void 0,this.runCleanup(),this.runtime.emit({kind:`effect`,name:this.options?.name});let e=new y(this.runtime);try{let t=this.runtime.withEffectScope(e,()=>this.runtime.collectEffect(this,this.callback));this.owner=e,this.cleanup=typeof t==`function`?t:void 0}catch(t){e.dispose(),this.runtime.report(t,{kind:`effect`,name:this.options?.name})}}dispose(){this.isDisposed||(this.isDisposed=!0,this.owner?.dispose(),this.owner=void 0,this.runtime.clearDependencies(this),this.runCleanup(),this.disposalController.abort(),this.runtime.emit({kind:`dispose`,name:this.options?.name,node:`effect`}))}[Symbol.dispose](){this.dispose()}runCleanup(){let e=this.cleanup;if(this.cleanup=void 0,e!==void 0)try{e()}catch(e){this.runtime.report(e,{kind:`cleanup`,name:this.options?.name})}}},x=class{activeEffectScope;activeObserver;activeScope;isDisposed=!1;flushDepth=0;flushing=!1;pending=new Set;listeners=new Set;rootScope;observer;onError;constructor(e){this.observer=e?.observer,this.onError=e?.onError??(e=>{queueMicrotask(()=>{throw e})}),this.rootScope=new y(this,`runtime`),this.activeScope=this.rootScope}get disposed(){return this.isDisposed}get disposalSignal(){return this.rootScope.disposalSignal}signal=(e,t)=>(this.assertActive(),new _(this,e,t));computed=(e,t)=>{this.assertActive();let n=new v(this,e,t);return(this.activeEffectScope??this.activeScope).owned.add(n),n};effect=(e,t)=>{this.assertActive();let n=new b(this,e,t);return(this.activeEffectScope??this.activeScope).owned.add(n),n.run(),n};createScope=e=>{this.assertActive();let t=new y(this,e);return this.activeScope.owned.add(t),t};batch=e=>(this.assertActive(),this.propagate(e));untrack=e=>(this.assertActive(),this.withObserver(void 0,e));dispose(){this.isDisposed||(this.isDisposed=!0,this.rootScope.dispose())}assertActive(){if(this.isDisposed)throw new u(`Cannot use a disposed Ripple runtime.`)}track(e){let t=this.activeObserver;t?.collecting!==void 0&&t.collecting.add(e)}clearDependencies(e){for(let t of e.dependencies)t.dependents.delete(e);e.dependencies.clear()}collect(e,t){return this.collectWith(e,t,e.dependencies.size===0)}collectEffect(e,t){return this.collectWith(e,t,!0)}withEffectScope(e,t){let n=this.activeEffectScope;this.activeEffectScope=e;try{return t()}finally{this.activeEffectScope=n}}withObserver(e,t){let n=this.activeObserver;this.activeObserver=e;try{return t()}finally{this.activeObserver=n}}withScope(e,t){let n=this.activeEffectScope,r=this.activeScope;this.activeEffectScope=void 0,this.activeScope=e;try{return t()}finally{this.activeEffectScope=n,this.activeScope=r}}enqueue(e){this.pending.add(e),this.flushDepth===0&&this.flush()}enqueueListener(e){this.listeners.add(e),this.flushDepth===0&&this.flush()}propagate(e){this.flushDepth++;try{return e()}finally{this.flushDepth--,this.flushDepth===0&&this.flush()}}emit(e){try{this.observer?.(e)}catch(t){this.report(t,{kind:`observer`,name:e.name})}}report(e,t){try{this.onError(e,t)}catch(e){queueMicrotask(()=>{throw e})}}collectWith(e,t,n){let r=this.activeObserver,i=new Set;e.collecting=i,this.activeObserver=e;try{let n=t();return this.commitDependencies(e,i),n}catch(t){throw n&&this.commitDependencies(e,i),t}finally{e.collecting=void 0,this.activeObserver=r}}commitDependencies(e,t){for(let n of e.dependencies)t.has(n)||n.dependents.delete(e);for(let n of t)e.dependencies.has(n)||n.dependents.add(e);e.dependencies.clear();for(let n of t)e.dependencies.add(n)}flush(){if(this.flushing)return;this.flushing=!0;let e=0;try{for(;this.pending.size>0||this.listeners.size>0;){if(++e>m)throw new f(`infinite reactive flush (>${m} iterations)`);let t=[...this.pending],n=[...this.listeners];this.pending.clear(),this.listeners.clear();for(let e of t)e.run();for(let e of n)try{e()}catch(e){this.report(e,{kind:`listener`})}}}finally{this.flushing=!1}}},S=e=>(t,n,r)=>{let i=e.signal({status:`pending`},{name:r?.name}),a=e.signal(0),o,s=()=>{a.value,o?.abort();let e=i.peek(),r=e.status===`success`?e.value:`previous`in e?e.previous:void 0,s;try{s=t()}catch(e){i.value=r===void 0?{error:e,status:`error`}:{error:e,previous:r,status:`error`};return}let l=new AbortController;o=l,i.value=r===void 0?{status:`pending`}:{previous:r,status:`pending`};let u;try{u=Promise.resolve(n(s,{signal:l.signal}))}catch(e){u=Promise.reject(e)}u.then(e=>{!c.disposed&&!l.signal.aborted&&(i.value={status:`success`,value:e})},e=>{!c.disposed&&!l.signal.aborted&&(i.value=r===void 0?{error:e,status:`error`}:{error:e,previous:r,status:`error`})})},c=e.effect(()=>(s(),()=>o?.abort()),{name:r?.name}),l={get disposalSignal(){return c.disposalSignal},dispose:()=>c.dispose(),get disposed(){return c.disposed},get name(){return i.name},peek:()=>i.peek(),reload:()=>{c.disposed||(a.value=a.peek()+1)},subscribe:e=>i.subscribe(e),[Symbol.dispose](){this.dispose()},get value(){return i.value}};return Object.defineProperty(l,p,{value:!0}),l},C=e=>(t,n,r)=>{let i=typeof t==`function`?t:()=>t.value,a=r?.equals??Object.is,o=!0,s,c=!1,l=e.effect(()=>{let e=i();if(o){o=!1,s=e,r?.immediate&&(n(e,void 0),r?.once&&(c=!0));return}if(a(s,e))return;let t=s;s=e,n(e,t),r?.once&&l.dispose()},{name:r?.name});return c&&l.dispose(),l},w=(e=>{let t=new x(e),n=S(t);return{batch:t.batch,computed:t.computed,createScope:t.createScope,get disposalSignal(){return t.disposalSignal},dispose:()=>t.dispose(),get disposed(){return t.disposed},effect:t.effect,resource:n,signal:t.signal,untrack:t.untrack,watch:C(t),[Symbol.dispose]:()=>t.dispose()}})(),T=w.signal;w.computed,w.effect,w.batch,w.createScope,w.untrack,w.watch,w.resource;function E(e){return e instanceof Error?e.message:String(e)}function D(e){let{apply:t,label:n,meta:r,revert:i}=e;return{apply:t,entry:Object.freeze({label:n,meta:r}),revert:i}}function O(e){return Object.freeze({...e,redo:Object.freeze([...e.redo]),undo:Object.freeze([...e.undo])})}function k(e,t){return t?new i(`Cannot call ${e}() on a disposed ledger.`):new r(`${e}() was cancelled before it started.`)}function A(e={}){let{maxHistory:t=100,runtime:i}=e,c=i?.signal??T;if(!Number.isSafeInteger(t)||t<0)throw new s(`maxHistory must be a non-negative safe integer`);let l=c(O({accepting:!0,queued:0,redo:[],running:0,undo:[]}),{name:`ledger:state`}),u=new WeakMap,d=new AbortController,f=new Set,p=new Set,m=!1,h=Promise.resolve();function g(e){if(l.value=O(e(l.value)),l.value.queued===0&&l.value.running===0){for(let e of f)e();f.clear()}}function _(e,t){e.settled||(e.settled=!0,p.delete(e),e.cancel(),t===void 0?e.resolve():e.reject(t))}function v(e,t,n){if(m)return Promise.reject(k(e,!0));let r=t?AbortSignal.any([t,d.signal]):d.signal;return new Promise((t,i)=>{let a=()=>{o.started||o.settled||m||(g(e=>({...e,queued:e.queued-1})),_(o,k(e,!1)))},o={cancel:()=>r.removeEventListener(`abort`,a),reject:i,resolve:t,settled:!1,start:async()=>{if(!o.settled){if(m||r.aborted){g(e=>({...e,queued:e.queued-1})),_(o,k(e,m));return}o.started=!0,g(e=>({...e,queued:e.queued-1,running:e.running+1}));try{await n({signal:r}),_(o)}catch(e){_(o,e)}finally{g(e=>({...e,running:e.running-1}))}}},started:!1};r.addEventListener(`abort`,a,{once:!0}),p.add(o),g(e=>({...e,queued:e.queued+1})),h=h.then(o.start,o.start)})}async function y(e,n){try{await e.apply(n)}catch(e){throw n.signal.aborted?new r(`do() was cancelled while running.`,{cause:e}):new a(E(e),{cause:e})}if(m||n.signal.aborted)throw new r(`do() was cancelled while running.`);g(n=>{if(t===0)return{...n,redo:[]};let r=[...n.undo,e.entry];return r.length>t&&r.shift(),{...n,redo:[],undo:r}}),u.set(e.entry,e)}async function b(e){let t=l.value.undo[l.value.undo.length-1];if(!t)return;let i=u.get(t);if(!i)throw new n(`Undo history is corrupted.`);try{await i.revert(e)}catch(t){throw e.signal.aborted?new r(`undo() was cancelled while running.`,{cause:t}):new o(E(t),{cause:t})}if(m||e.signal.aborted)throw new r(`undo() was cancelled while running.`);g(e=>({...e,redo:[...e.redo,t],undo:e.undo.slice(0,-1)}))}async function x(e){let t=l.value.redo[l.value.redo.length-1];if(!t)return;let i=u.get(t);if(!i)throw new n(`Redo history is corrupted.`);try{await i.apply(e)}catch(t){throw e.signal.aborted?new r(`redo() was cancelled while running.`,{cause:t}):new a(E(t),{cause:t})}if(m||e.signal.aborted)throw new r(`redo() was cancelled while running.`);g(e=>({...e,redo:e.redo.slice(0,-1),undo:[...e.undo,t]}))}return{clear(){return v(`clear`,void 0,async()=>{g(e=>({...e,redo:[],undo:[]}))})},get disposalSignal(){return d.signal},dispose(){if(m)return;m=!0,d.abort();let e=[...p].filter(e=>!e.started);for(let t of e)_(t,k(`operation`,!0));g(e=>({...e,accepting:!1,queued:0,redo:[],undo:[]}))},get disposed(){return m},do(e,t){let n=D(e);return v(`do`,t?.signal,e=>y(n,e))},redo(e){return v(`redo`,e?.signal,x)},get state(){return l},[Symbol.dispose](){this.dispose()},undo(e){return v(`undo`,e?.signal,b)},whenIdle(){return l.value.queued===0&&l.value.running===0?Promise.resolve():new Promise(e=>f.add(e))}}}export{r as LedgerCancelledError,s as LedgerConfigurationError,i as LedgerDisposedError,n as LedgerError,a as LedgerExecutionError,o as LedgerRollbackError,t as compose,A as createLedger};
1
+ function e(e){let{apply:t,label:n,meta:r,revert:i}=e;return{apply:t,label:n,meta:r,revert:i}}function t(t,n){let r=t.map(e);return{apply:async e=>{let t=[];try{for(let n of r)await n.apply(e),t.push(n)}catch(n){let r=[];for(let n of[...t].reverse())try{await n.revert(e)}catch(e){r.push(e)}throw r.length>0?AggregateError([n,...r],`Command application and compensation failed`,{cause:n}):n}},label:n,revert:async e=>{let t=[];for(let n of[...r].reverse())try{await n.revert(e)}catch(e){t.push(e)}if(t.length>0)throw AggregateError(t,`Command reversion failed`)}}}var n=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},r=class extends n{},i=class extends n{},a=class extends n{},o=class extends n{},s=class extends n{},c=class{currentValue;listeners=new Set;constructor(e){this.currentValue=e}get value(){return this.currentValue}peek(){return this.currentValue}set(e){this.currentValue=e;for(let e of[...this.listeners])try{e()}catch(e){queueMicrotask(()=>{throw e})}}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}};function l(e){return e instanceof Error?e.message:String(e)}function u(e){let{apply:t,label:n,meta:r,revert:i}=e;return{apply:t,entry:Object.freeze({label:n,meta:r}),revert:i}}function d(e){return Object.freeze({...e,redo:Object.freeze([...e.redo]),undo:Object.freeze([...e.undo])})}function f(e,t){return t?new i(`Cannot call ${e}() on a disposed ledger.`):new r(`${e}() was cancelled before it started.`)}function p(e={}){let{maxHistory:t=100}=e;if(!Number.isSafeInteger(t)||t<0)throw new s(`maxHistory must be a non-negative safe integer`);let i=new c(d({accepting:!0,queued:0,redo:[],running:0,undo:[]})),p=new WeakMap,m=new AbortController,h=new Set,g=new Set,_=!1,v=Promise.resolve();function y(e){if(i.set(d(e(i.value))),i.value.queued===0&&i.value.running===0){for(let e of h)e();h.clear()}}function b(e,t){e.settled||(e.settled=!0,g.delete(e),e.cancel(),t===void 0?e.resolve():e.reject(t))}function x(e,t,n){if(_)return Promise.reject(f(e,!0));let r=t?AbortSignal.any([t,m.signal]):m.signal;return new Promise((t,i)=>{let a=()=>{o.started||o.settled||_||(y(e=>({...e,queued:e.queued-1})),b(o,f(e,!1)))},o={cancel:()=>r.removeEventListener(`abort`,a),reject:i,resolve:t,settled:!1,start:async()=>{if(!o.settled){if(_||r.aborted){y(e=>({...e,queued:e.queued-1})),b(o,f(e,_));return}o.started=!0,y(e=>({...e,queued:e.queued-1,running:e.running+1}));try{await n({signal:r}),b(o)}catch(e){b(o,e)}finally{y(e=>({...e,running:e.running-1}))}}},started:!1};r.addEventListener(`abort`,a,{once:!0}),g.add(o),y(e=>({...e,queued:e.queued+1})),v=v.then(o.start,o.start)})}async function S(e,n){try{await e.apply(n)}catch(e){throw n.signal.aborted?new r(`do() was cancelled while running.`,{cause:e}):new a(l(e),{cause:e})}if(_||n.signal.aborted)throw new r(`do() was cancelled while running.`);y(n=>{if(t===0)return{...n,redo:[]};let r=[...n.undo,e.entry];return r.length>t&&r.shift(),{...n,redo:[],undo:r}}),p.set(e.entry,e)}async function C(e){let t=i.value.undo[i.value.undo.length-1];if(!t)return;let a=p.get(t);if(!a)throw new n(`Undo history is corrupted.`);try{await a.revert(e)}catch(t){throw e.signal.aborted?new r(`undo() was cancelled while running.`,{cause:t}):new o(l(t),{cause:t})}if(_||e.signal.aborted)throw new r(`undo() was cancelled while running.`);y(e=>({...e,redo:[...e.redo,t],undo:e.undo.slice(0,-1)}))}async function w(e){let t=i.value.redo[i.value.redo.length-1];if(!t)return;let o=p.get(t);if(!o)throw new n(`Redo history is corrupted.`);try{await o.apply(e)}catch(t){throw e.signal.aborted?new r(`redo() was cancelled while running.`,{cause:t}):new a(l(t),{cause:t})}if(_||e.signal.aborted)throw new r(`redo() was cancelled while running.`);y(e=>({...e,redo:e.redo.slice(0,-1),undo:[...e.undo,t]}))}return{clear(){return x(`clear`,void 0,async()=>{y(e=>({...e,redo:[],undo:[]}))})},get disposalSignal(){return m.signal},dispose(){if(_)return;_=!0,m.abort();let e=[...g].filter(e=>!e.started);for(let t of e)b(t,f(`operation`,!0));y(e=>({...e,accepting:!1,queued:0,redo:[],undo:[]}))},get disposed(){return _},do(e,t){let n=u(e);return x(`do`,t?.signal,e=>S(n,e))},redo(e){return x(`redo`,e?.signal,w)},get state(){return i},[Symbol.dispose](){this.dispose()},undo(e){return x(`undo`,e?.signal,C)},whenIdle(){return i.value.queued===0&&i.value.running===0?Promise.resolve():new Promise(e=>h.add(e))}}}export{r as LedgerCancelledError,s as LedgerConfigurationError,i as LedgerDisposedError,n as LedgerError,a as LedgerExecutionError,o as LedgerRollbackError,t as compose,p as createLedger};
2
2
  //# sourceMappingURL=ledger.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ledger.js","names":["e","t","r","i","i","c","l","e","u","n","d","f","t","r","e","e","n","s"],"sources":["../src/compose.ts","../src/errors.ts","../../ripple/dist/errors.js","../../ripple/dist/runtime.js","../../ripple/dist/_async.js","../../ripple/dist/_watch.js","../../ripple/dist/_default.js","../../ripple/dist/index.js","../src/ledger.ts"],"sourcesContent":["import type { CommandContext, ReversibleCommand } from './types';\n\nfunction snapshotCommand<TMeta>(command: ReversibleCommand<TMeta>): ReversibleCommand<TMeta> {\n const { apply, label, meta, revert } = command;\n\n return { apply, label, meta, revert };\n}\n\n/**\n * Composes reversible commands into one reversible command.\n *\n * `apply` runs each child in order. `revert` runs children in reverse order.\n * A failed child application compensates completed children before rethrowing.\n *\n * @example\n * await ledger.do(compose([\n * { apply: () => { node.x = newX; }, revert: () => { node.x = oldX; } },\n * { apply: () => { node.y = newY; }, revert: () => { node.y = oldY; } },\n * ], 'Move node'));\n */\nexport function compose<TMeta = undefined>(\n commands: readonly ReversibleCommand<TMeta>[],\n label?: string,\n): ReversibleCommand<TMeta> {\n const steps = commands.map(snapshotCommand);\n\n return {\n apply: async (context: CommandContext) => {\n const applied: ReversibleCommand<TMeta>[] = [];\n\n try {\n for (const command of steps) {\n await command.apply(context);\n applied.push(command);\n }\n } catch (error) {\n const compensationFailures: unknown[] = [];\n\n for (const command of [...applied].reverse()) {\n try {\n await command.revert(context);\n } catch (compensationError) {\n compensationFailures.push(compensationError);\n }\n }\n\n if (compensationFailures.length > 0) {\n throw new AggregateError([error, ...compensationFailures], 'Command application and compensation failed', {\n cause: error,\n });\n }\n\n throw error;\n }\n },\n label,\n revert: async (context: CommandContext) => {\n const failures: unknown[] = [];\n\n for (const command of [...steps].reverse()) {\n try {\n await command.revert(context);\n } catch (error) {\n failures.push(error);\n }\n }\n\n if (failures.length > 0) throw new AggregateError(failures, 'Command reversion failed');\n },\n };\n}\n","/** Base class for all ledger errors. Use `instanceof LedgerError` to catch any ledger-originated error. */\nexport class LedgerError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a queued operation is cancelled before user code starts, or an active operation cooperatively stops. */\nexport class LedgerCancelledError extends LedgerError {}\n\n/** Thrown when a method is called on a disposed ledger instance. */\nexport class LedgerDisposedError extends LedgerError {}\n\n/** Thrown when a command's `apply()` function throws. The original error is available via `.cause`. */\nexport class LedgerExecutionError extends LedgerError {}\n\n/** Thrown when a command's `revert()` function throws during an undo operation. The original error is available via `.cause`. */\nexport class LedgerRollbackError extends LedgerError {}\n\n/** Thrown when the ledger is constructed with invalid options. */\nexport class LedgerConfigurationError extends LedgerError {}\n","//#region src/errors.ts\nvar e = class extends Error {\n\tconstructor(e, t) {\n\t\tsuper(e, t), this.name = new.target.name, Object.setPrototypeOf(this, new.target.prototype);\n\t}\n}, t = class extends e {}, n = class extends e {}, r = class extends e {}, i = class extends e {};\n//#endregion\nexport { t as RippleComputedCycleError, n as RippleDisposedRuntimeError, r as RippleDisposedScopeError, e as RippleError, i as RippleInfiniteLoopError };\n\n//# sourceMappingURL=errors.js.map","import { RippleComputedCycleError as e, RippleDisposedRuntimeError as t, RippleDisposedScopeError as n, RippleInfiniteLoopError as r } from \"./errors.js\";\n//#region src/runtime.ts\nvar i = Symbol.for(\"@vielzeug/ripple/reactive\"), a = 100, o = Symbol(\"ripple.unset\"), s = class {\n\t[i] = !0;\n\tdependents = /* @__PURE__ */ new Set();\n\tname;\n\truntime;\n\tconstructor(e, t) {\n\t\tthis.runtime = e, this.name = t;\n\t}\n\tsubscribe(e) {\n\t\tthis.runtime.assertActive(), this.peek();\n\t\tlet t = {\n\t\t\tdependencies: /* @__PURE__ */ new Set(),\n\t\t\tonDependencyChanged: () => this.runtime.enqueueListener(e)\n\t\t};\n\t\treturn this.dependents.add(t), () => this.dependents.delete(t);\n\t}\n\tnotify() {\n\t\tfor (let e of [...this.dependents]) e.onDependencyChanged();\n\t}\n}, c = class extends s {\n\tcurrent;\n\tequals;\n\tconstructor(e, t, n) {\n\t\tsuper(e, n?.name), this.current = t, this.equals = n?.equals ?? Object.is;\n\t}\n\tget value() {\n\t\treturn this.runtime.track(this), this.current;\n\t}\n\tset value(e) {\n\t\tif (this.runtime.assertActive(), this.equals(this.current, e)) return;\n\t\tlet t = this.current;\n\t\tthis.current = e, this.runtime.emit({\n\t\t\tkind: \"write\",\n\t\t\tname: this.name,\n\t\t\tnext: e,\n\t\t\tprevious: t\n\t\t}), this.runtime.propagate(() => this.notify());\n\t}\n\tpeek() {\n\t\treturn this.current;\n\t}\n\tupdate(e) {\n\t\tthis.value = e(this.current);\n\t}\n}, l = class extends s {\n\tdependencies = /* @__PURE__ */ new Set();\n\tcomputing = !1;\n\tdisposed = !1;\n\tdirty = !0;\n\tcurrent = o;\n\tderive;\n\tequals;\n\tconstructor(e, t, n) {\n\t\tsuper(e, n?.name), this.derive = t, this.equals = n?.equals ?? Object.is;\n\t}\n\tget value() {\n\t\treturn this.runtime.track(this), this.refresh(), this.current;\n\t}\n\tpeek() {\n\t\treturn this.refresh(), this.current;\n\t}\n\tonDependencyChanged() {\n\t\tthis.disposed || (this.dirty ||= !0, this.dependents.size > 0 && this.refresh() && this.notify());\n\t}\n\tdispose() {\n\t\tthis.disposed || (this.disposed = !0, this.runtime.clearDependencies(this), this.dependents.clear());\n\t}\n\trefresh() {\n\t\tif (!this.dirty || this.disposed) return !1;\n\t\tif (this.computing) {\n\t\t\tlet t = this.name === void 0 ? \"\" : ` \"${this.name}\"`;\n\t\t\tthrow new e(`computed cycle detected${t}`);\n\t\t}\n\t\tthis.computing = !0, this.runtime.emit({\n\t\t\tkind: \"compute\",\n\t\t\tname: this.name\n\t\t});\n\t\ttry {\n\t\t\tlet e = this.runtime.collect(this, this.derive), t = this.current === o || !this.equals(this.current, e);\n\t\t\treturn this.current = e, this.dirty = !1, t;\n\t\t} finally {\n\t\t\tthis.computing = !1;\n\t\t}\n\t}\n}, u = class {\n\tdisposalController = new AbortController();\n\towned = /* @__PURE__ */ new Set();\n\tname;\n\tisDisposed = !1;\n\truntime;\n\tconstructor(e, t) {\n\t\tthis.runtime = e, this.name = t;\n\t}\n\tget disposed() {\n\t\treturn this.isDisposed;\n\t}\n\tget disposalSignal() {\n\t\treturn this.disposalController.signal;\n\t}\n\trun(e) {\n\t\tif (this.isDisposed) throw new n(\"Cannot run a disposed scope.\");\n\t\treturn this.runtime.withScope(this, e);\n\t}\n\tdispose() {\n\t\tif (!this.isDisposed) {\n\t\t\tthis.isDisposed = !0;\n\t\t\tfor (let e of [...this.owned].reverse()) e.dispose();\n\t\t\tthis.owned.clear(), this.disposalController.abort(), this.runtime.emit({\n\t\t\t\tkind: \"dispose\",\n\t\t\t\tname: this.name,\n\t\t\t\tnode: \"scope\"\n\t\t\t});\n\t\t}\n\t}\n\t[Symbol.dispose]() {\n\t\tthis.dispose();\n\t}\n}, d = class {\n\tdependencies = /* @__PURE__ */ new Set();\n\tdisposalController = new AbortController();\n\tcleanup;\n\tisDisposed = !1;\n\towner;\n\tscheduled = !1;\n\tcallback;\n\toptions;\n\truntime;\n\tconstructor(e, t, n) {\n\t\tthis.runtime = e, this.callback = t, this.options = n;\n\t}\n\tget disposed() {\n\t\treturn this.isDisposed;\n\t}\n\tget disposalSignal() {\n\t\treturn this.disposalController.signal;\n\t}\n\tonDependencyChanged() {\n\t\tif (!this.isDisposed) {\n\t\t\tif (this.options?.scheduler === \"microtask\") {\n\t\t\t\tif (this.scheduled) return;\n\t\t\t\tthis.scheduled = !0, queueMicrotask(() => {\n\t\t\t\t\tthis.scheduled = !1, this.isDisposed || this.runtime.enqueue(this);\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.runtime.enqueue(this);\n\t\t}\n\t}\n\trun() {\n\t\tif (this.isDisposed) return;\n\t\tthis.owner?.dispose(), this.owner = void 0, this.runCleanup(), this.runtime.emit({\n\t\t\tkind: \"effect\",\n\t\t\tname: this.options?.name\n\t\t});\n\t\tlet e = new u(this.runtime);\n\t\ttry {\n\t\t\tlet t = this.runtime.withEffectScope(e, () => this.runtime.collectEffect(this, this.callback));\n\t\t\tthis.owner = e, this.cleanup = typeof t == \"function\" ? t : void 0;\n\t\t} catch (t) {\n\t\t\te.dispose(), this.runtime.report(t, {\n\t\t\t\tkind: \"effect\",\n\t\t\t\tname: this.options?.name\n\t\t\t});\n\t\t}\n\t}\n\tdispose() {\n\t\tthis.isDisposed || (this.isDisposed = !0, this.owner?.dispose(), this.owner = void 0, this.runtime.clearDependencies(this), this.runCleanup(), this.disposalController.abort(), this.runtime.emit({\n\t\t\tkind: \"dispose\",\n\t\t\tname: this.options?.name,\n\t\t\tnode: \"effect\"\n\t\t}));\n\t}\n\t[Symbol.dispose]() {\n\t\tthis.dispose();\n\t}\n\trunCleanup() {\n\t\tlet e = this.cleanup;\n\t\tif (this.cleanup = void 0, e !== void 0) try {\n\t\t\te();\n\t\t} catch (e) {\n\t\t\tthis.runtime.report(e, {\n\t\t\t\tkind: \"cleanup\",\n\t\t\t\tname: this.options?.name\n\t\t\t});\n\t\t}\n\t}\n}, f = class {\n\tactiveEffectScope;\n\tactiveObserver;\n\tactiveScope;\n\tisDisposed = !1;\n\tflushDepth = 0;\n\tflushing = !1;\n\tpending = /* @__PURE__ */ new Set();\n\tlisteners = /* @__PURE__ */ new Set();\n\trootScope;\n\tobserver;\n\tonError;\n\tconstructor(e) {\n\t\tthis.observer = e?.observer, this.onError = e?.onError ?? ((e) => {\n\t\t\tqueueMicrotask(() => {\n\t\t\t\tthrow e;\n\t\t\t});\n\t\t}), this.rootScope = new u(this, \"runtime\"), this.activeScope = this.rootScope;\n\t}\n\tget disposed() {\n\t\treturn this.isDisposed;\n\t}\n\tget disposalSignal() {\n\t\treturn this.rootScope.disposalSignal;\n\t}\n\tsignal = (e, t) => (this.assertActive(), new c(this, e, t));\n\tcomputed = (e, t) => {\n\t\tthis.assertActive();\n\t\tlet n = new l(this, e, t);\n\t\treturn (this.activeEffectScope ?? this.activeScope).owned.add(n), n;\n\t};\n\teffect = (e, t) => {\n\t\tthis.assertActive();\n\t\tlet n = new d(this, e, t);\n\t\treturn (this.activeEffectScope ?? this.activeScope).owned.add(n), n.run(), n;\n\t};\n\tcreateScope = (e) => {\n\t\tthis.assertActive();\n\t\tlet t = new u(this, e);\n\t\treturn this.activeScope.owned.add(t), t;\n\t};\n\tbatch = (e) => (this.assertActive(), this.propagate(e));\n\tuntrack = (e) => (this.assertActive(), this.withObserver(void 0, e));\n\tdispose() {\n\t\tthis.isDisposed || (this.isDisposed = !0, this.rootScope.dispose());\n\t}\n\tassertActive() {\n\t\tif (this.isDisposed) throw new t(\"Cannot use a disposed Ripple runtime.\");\n\t}\n\ttrack(e) {\n\t\tlet t = this.activeObserver;\n\t\tt?.collecting !== void 0 && t.collecting.add(e);\n\t}\n\tclearDependencies(e) {\n\t\tfor (let t of e.dependencies) t.dependents.delete(e);\n\t\te.dependencies.clear();\n\t}\n\tcollect(e, t) {\n\t\treturn this.collectWith(e, t, e.dependencies.size === 0);\n\t}\n\tcollectEffect(e, t) {\n\t\treturn this.collectWith(e, t, !0);\n\t}\n\twithEffectScope(e, t) {\n\t\tlet n = this.activeEffectScope;\n\t\tthis.activeEffectScope = e;\n\t\ttry {\n\t\t\treturn t();\n\t\t} finally {\n\t\t\tthis.activeEffectScope = n;\n\t\t}\n\t}\n\twithObserver(e, t) {\n\t\tlet n = this.activeObserver;\n\t\tthis.activeObserver = e;\n\t\ttry {\n\t\t\treturn t();\n\t\t} finally {\n\t\t\tthis.activeObserver = n;\n\t\t}\n\t}\n\twithScope(e, t) {\n\t\tlet n = this.activeEffectScope, r = this.activeScope;\n\t\tthis.activeEffectScope = void 0, this.activeScope = e;\n\t\ttry {\n\t\t\treturn t();\n\t\t} finally {\n\t\t\tthis.activeEffectScope = n, this.activeScope = r;\n\t\t}\n\t}\n\tenqueue(e) {\n\t\tthis.pending.add(e), this.flushDepth === 0 && this.flush();\n\t}\n\tenqueueListener(e) {\n\t\tthis.listeners.add(e), this.flushDepth === 0 && this.flush();\n\t}\n\tpropagate(e) {\n\t\tthis.flushDepth++;\n\t\ttry {\n\t\t\treturn e();\n\t\t} finally {\n\t\t\tthis.flushDepth--, this.flushDepth === 0 && this.flush();\n\t\t}\n\t}\n\temit(e) {\n\t\ttry {\n\t\t\tthis.observer?.(e);\n\t\t} catch (t) {\n\t\t\tthis.report(t, {\n\t\t\t\tkind: \"observer\",\n\t\t\t\tname: e.name\n\t\t\t});\n\t\t}\n\t}\n\treport(e, t) {\n\t\ttry {\n\t\t\tthis.onError(e, t);\n\t\t} catch (e) {\n\t\t\tqueueMicrotask(() => {\n\t\t\t\tthrow e;\n\t\t\t});\n\t\t}\n\t}\n\tcollectWith(e, t, n) {\n\t\tlet r = this.activeObserver, i = /* @__PURE__ */ new Set();\n\t\te.collecting = i, this.activeObserver = e;\n\t\ttry {\n\t\t\tlet n = t();\n\t\t\treturn this.commitDependencies(e, i), n;\n\t\t} catch (t) {\n\t\t\tthrow n && this.commitDependencies(e, i), t;\n\t\t} finally {\n\t\t\te.collecting = void 0, this.activeObserver = r;\n\t\t}\n\t}\n\tcommitDependencies(e, t) {\n\t\tfor (let n of e.dependencies) t.has(n) || n.dependents.delete(e);\n\t\tfor (let n of t) e.dependencies.has(n) || n.dependents.add(e);\n\t\te.dependencies.clear();\n\t\tfor (let n of t) e.dependencies.add(n);\n\t}\n\tflush() {\n\t\tif (this.flushing) return;\n\t\tthis.flushing = !0;\n\t\tlet e = 0;\n\t\ttry {\n\t\t\tfor (; this.pending.size > 0 || this.listeners.size > 0;) {\n\t\t\t\tif (++e > a) throw new r(`infinite reactive flush (>${a} iterations)`);\n\t\t\t\tlet t = [...this.pending], n = [...this.listeners];\n\t\t\t\tthis.pending.clear(), this.listeners.clear();\n\t\t\t\tfor (let e of t) e.run();\n\t\t\t\tfor (let e of n) try {\n\t\t\t\t\te();\n\t\t\t\t} catch (e) {\n\t\t\t\t\tthis.report(e, { kind: \"listener\" });\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.flushing = !1;\n\t\t}\n\t}\n}, p = (e) => {\n\tif (typeof e != \"object\" || !e || !(i in e)) return !1;\n\tlet t = e;\n\treturn typeof t.peek == \"function\" && typeof t.subscribe == \"function\";\n};\n//#endregion\nexport { i as REACTIVE, f as ReactiveRuntime, p as isReactive };\n\n//# sourceMappingURL=runtime.js.map","import { REACTIVE as e } from \"./runtime.js\";\n//#region src/_async.ts\nvar t = (t) => (n, r, i) => {\n\tlet a = t.signal({ status: \"pending\" }, { name: i?.name }), o = t.signal(0), s, c = () => {\n\t\to.value, s?.abort();\n\t\tlet e = a.peek(), t = e.status === \"success\" ? e.value : \"previous\" in e ? e.previous : void 0, i;\n\t\ttry {\n\t\t\ti = n();\n\t\t} catch (e) {\n\t\t\ta.value = t === void 0 ? {\n\t\t\t\terror: e,\n\t\t\t\tstatus: \"error\"\n\t\t\t} : {\n\t\t\t\terror: e,\n\t\t\t\tprevious: t,\n\t\t\t\tstatus: \"error\"\n\t\t\t};\n\t\t\treturn;\n\t\t}\n\t\tlet c = new AbortController();\n\t\ts = c, a.value = t === void 0 ? { status: \"pending\" } : {\n\t\t\tprevious: t,\n\t\t\tstatus: \"pending\"\n\t\t};\n\t\tlet u;\n\t\ttry {\n\t\t\tu = Promise.resolve(r(i, { signal: c.signal }));\n\t\t} catch (e) {\n\t\t\tu = Promise.reject(e);\n\t\t}\n\t\tu.then((e) => {\n\t\t\t!l.disposed && !c.signal.aborted && (a.value = {\n\t\t\t\tstatus: \"success\",\n\t\t\t\tvalue: e\n\t\t\t});\n\t\t}, (e) => {\n\t\t\t!l.disposed && !c.signal.aborted && (a.value = t === void 0 ? {\n\t\t\t\terror: e,\n\t\t\t\tstatus: \"error\"\n\t\t\t} : {\n\t\t\t\terror: e,\n\t\t\t\tprevious: t,\n\t\t\t\tstatus: \"error\"\n\t\t\t});\n\t\t});\n\t}, l = t.effect(() => (c(), () => s?.abort()), { name: i?.name }), u = {\n\t\tget disposalSignal() {\n\t\t\treturn l.disposalSignal;\n\t\t},\n\t\tdispose: () => l.dispose(),\n\t\tget disposed() {\n\t\t\treturn l.disposed;\n\t\t},\n\t\tget name() {\n\t\t\treturn a.name;\n\t\t},\n\t\tpeek: () => a.peek(),\n\t\treload: () => {\n\t\t\tl.disposed || (o.value = o.peek() + 1);\n\t\t},\n\t\tsubscribe: (e) => a.subscribe(e),\n\t\t[Symbol.dispose]() {\n\t\t\tthis.dispose();\n\t\t},\n\t\tget value() {\n\t\t\treturn a.value;\n\t\t}\n\t};\n\treturn Object.defineProperty(u, e, { value: !0 }), u;\n};\n//#endregion\nexport { t as createResource };\n\n//# sourceMappingURL=_async.js.map","//#region src/_watch.ts\nvar e = (e) => (t, n, r) => {\n\tlet i = typeof t == \"function\" ? t : () => t.value, a = r?.equals ?? Object.is, o = !0, s, c = !1, l = e.effect(() => {\n\t\tlet e = i();\n\t\tif (o) {\n\t\t\to = !1, s = e, r?.immediate && (n(e, void 0), r?.once && (c = !0));\n\t\t\treturn;\n\t\t}\n\t\tif (a(s, e)) return;\n\t\tlet t = s;\n\t\ts = e, n(e, t), r?.once && l.dispose();\n\t}, { name: r?.name });\n\treturn c && l.dispose(), l;\n};\n//#endregion\nexport { e as createWatch };\n\n//# sourceMappingURL=_watch.js.map","import { ReactiveRuntime as e } from \"./runtime.js\";\nimport { createResource as t } from \"./_async.js\";\nimport { createWatch as n } from \"./_watch.js\";\n//#region src/_default.ts\nvar r = (r) => {\n\tlet i = new e(r), a = t(i);\n\treturn {\n\t\tbatch: i.batch,\n\t\tcomputed: i.computed,\n\t\tcreateScope: i.createScope,\n\t\tget disposalSignal() {\n\t\t\treturn i.disposalSignal;\n\t\t},\n\t\tdispose: () => i.dispose(),\n\t\tget disposed() {\n\t\t\treturn i.disposed;\n\t\t},\n\t\teffect: i.effect,\n\t\tresource: a,\n\t\tsignal: i.signal,\n\t\tuntrack: i.untrack,\n\t\twatch: n(i),\n\t\t[Symbol.dispose]: () => i.dispose()\n\t};\n}, i = r();\n//#endregion\nexport { r as createRipple, i as defaultRipple };\n\n//# sourceMappingURL=_default.js.map","import { RippleComputedCycleError as e, RippleDisposedRuntimeError as t, RippleDisposedScopeError as n, RippleError as r, RippleInfiniteLoopError as i } from \"./errors.js\";\nimport { isReactive as a } from \"./runtime.js\";\nimport { createRipple as o, defaultRipple as s } from \"./_default.js\";\n//#region src/index.ts\nvar c = s.signal, l = s.computed, u = s.effect, d = s.batch, f = s.createScope, p = s.untrack, m = s.watch, h = s.resource;\n//#endregion\nexport { e as RippleComputedCycleError, t as RippleDisposedRuntimeError, n as RippleDisposedScopeError, r as RippleError, i as RippleInfiniteLoopError, d as batch, l as computed, o as createRipple, f as createScope, u as effect, a as isReactive, h as resource, c as signal, p as untrack, m as watch };\n\n//# sourceMappingURL=index.js.map","import { signal as defaultSignal } from '@vielzeug/ripple';\nimport {\n LedgerCancelledError,\n LedgerConfigurationError,\n LedgerDisposedError,\n LedgerError,\n LedgerExecutionError,\n LedgerRollbackError,\n} from './errors';\nimport type {\n CommandContext,\n HistoryEntry,\n Ledger,\n LedgerCallOptions,\n LedgerOptions,\n LedgerState,\n ReversibleCommand,\n} from './types';\n\ntype StoredCommand<TMeta> = {\n apply: (context: CommandContext) => Promise<void> | void;\n entry: HistoryEntry<TMeta>;\n revert: (context: CommandContext) => Promise<void> | void;\n};\n\ntype Operation = {\n cancel: () => void;\n reject: (reason?: unknown) => void;\n resolve: () => void;\n settled: boolean;\n start: () => Promise<void>;\n started: boolean;\n};\n\nfunction toMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction snapshotCommand<TMeta>(command: ReversibleCommand<TMeta>): StoredCommand<TMeta> {\n const { apply, label, meta, revert } = command;\n\n return { apply, entry: Object.freeze({ label, meta }), revert };\n}\n\nfunction snapshotState<TMeta>(state: LedgerState<TMeta>): LedgerState<TMeta> {\n return Object.freeze({\n ...state,\n redo: Object.freeze([...state.redo]),\n undo: Object.freeze([...state.undo]),\n });\n}\n\nfunction operationError(method: string, disposed: boolean): LedgerCancelledError | LedgerDisposedError {\n return disposed\n ? new LedgerDisposedError(`Cannot call ${method}() on a disposed ledger.`)\n : new LedgerCancelledError(`${method}() was cancelled before it started.`);\n}\n\n/**\n * Creates a serialized history of reversible commands.\n *\n * Commands are snapshotted when submitted. Queued commands cancelled before their queue turn do\n * not invoke user code. Active commands receive an abort signal and stop cooperatively.\n *\n * @example\n * const ledger = createLedger({ maxHistory: 50 });\n * await ledger.do({\n * apply: () => { item.name = next; },\n * revert: () => { item.name = previous; },\n * });\n * await ledger.undo();\n * await ledger.redo();\n * using ledger = createLedger();\n */\nexport function createLedger<TMeta = undefined>(options: LedgerOptions = {}): Ledger<TMeta> {\n const { maxHistory = 100, runtime } = options;\n const signal = runtime?.signal ?? defaultSignal;\n\n if (!Number.isSafeInteger(maxHistory) || maxHistory < 0) {\n throw new LedgerConfigurationError('maxHistory must be a non-negative safe integer');\n }\n\n const state = signal<LedgerState<TMeta>>(\n snapshotState({ accepting: true, queued: 0, redo: [], running: 0, undo: [] }),\n { name: 'ledger:state' },\n );\n const commandStore = new WeakMap<HistoryEntry<TMeta>, StoredCommand<TMeta>>();\n const disposalController = new AbortController();\n const idleWaiters = new Set<() => void>();\n const operations = new Set<Operation>();\n let disposed = false;\n let queue = Promise.resolve();\n\n function updateState(update: (current: LedgerState<TMeta>) => LedgerState<TMeta>): void {\n state.value = snapshotState(update(state.value));\n\n if (state.value.queued === 0 && state.value.running === 0) {\n for (const resolve of idleWaiters) resolve();\n idleWaiters.clear();\n }\n }\n\n function settle(operation: Operation, error?: unknown): void {\n if (operation.settled) return;\n\n operation.settled = true;\n operations.delete(operation);\n operation.cancel();\n\n if (error === undefined) operation.resolve();\n else operation.reject(error);\n }\n\n function enqueue(\n method: string,\n externalSignal: AbortSignal | undefined,\n task: (context: CommandContext) => Promise<void>,\n ): Promise<void> {\n if (disposed) return Promise.reject(operationError(method, true));\n\n const abortSignal = externalSignal\n ? AbortSignal.any([externalSignal, disposalController.signal])\n : disposalController.signal;\n\n return new Promise<void>((resolve, reject) => {\n const onAbort = (): void => {\n if (operation.started || operation.settled || disposed) return;\n\n updateState((current) => ({ ...current, queued: current.queued - 1 }));\n settle(operation, operationError(method, false));\n };\n\n const operation: Operation = {\n cancel: () => abortSignal.removeEventListener('abort', onAbort),\n reject,\n resolve,\n settled: false,\n start: async () => {\n if (operation.settled) return;\n\n if (disposed || abortSignal.aborted) {\n updateState((current) => ({ ...current, queued: current.queued - 1 }));\n settle(operation, operationError(method, disposed));\n\n return;\n }\n\n operation.started = true;\n updateState((current) => ({ ...current, queued: current.queued - 1, running: current.running + 1 }));\n\n try {\n await task({ signal: abortSignal });\n settle(operation);\n } catch (error) {\n settle(operation, error);\n } finally {\n updateState((current) => ({ ...current, running: current.running - 1 }));\n }\n },\n started: false,\n };\n\n abortSignal.addEventListener('abort', onAbort, { once: true });\n operations.add(operation);\n updateState((current) => ({ ...current, queued: current.queued + 1 }));\n queue = queue.then(operation.start, operation.start);\n });\n }\n\n async function runDo(command: StoredCommand<TMeta>, context: CommandContext): Promise<void> {\n try {\n await command.apply(context);\n } catch (error) {\n throw context.signal.aborted\n ? new LedgerCancelledError('do() was cancelled while running.', { cause: error })\n : new LedgerExecutionError(toMessage(error), { cause: error });\n }\n\n if (disposed || context.signal.aborted) {\n throw new LedgerCancelledError('do() was cancelled while running.');\n }\n\n updateState((current) => {\n if (maxHistory === 0) return { ...current, redo: [] };\n\n const undo = [...current.undo, command.entry];\n\n if (undo.length > maxHistory) undo.shift();\n\n return { ...current, redo: [], undo };\n });\n commandStore.set(command.entry, command);\n }\n\n async function runUndo(context: CommandContext): Promise<void> {\n const entry = state.value.undo[state.value.undo.length - 1];\n\n if (!entry) return;\n\n const command = commandStore.get(entry);\n\n if (!command) throw new LedgerError('Undo history is corrupted.');\n\n try {\n await command.revert(context);\n } catch (error) {\n throw context.signal.aborted\n ? new LedgerCancelledError('undo() was cancelled while running.', { cause: error })\n : new LedgerRollbackError(toMessage(error), { cause: error });\n }\n\n if (disposed || context.signal.aborted) {\n throw new LedgerCancelledError('undo() was cancelled while running.');\n }\n\n updateState((current) => ({ ...current, redo: [...current.redo, entry], undo: current.undo.slice(0, -1) }));\n }\n\n async function runRedo(context: CommandContext): Promise<void> {\n const entry = state.value.redo[state.value.redo.length - 1];\n\n if (!entry) return;\n\n const command = commandStore.get(entry);\n\n if (!command) throw new LedgerError('Redo history is corrupted.');\n\n try {\n await command.apply(context);\n } catch (error) {\n throw context.signal.aborted\n ? new LedgerCancelledError('redo() was cancelled while running.', { cause: error })\n : new LedgerExecutionError(toMessage(error), { cause: error });\n }\n\n if (disposed || context.signal.aborted) {\n throw new LedgerCancelledError('redo() was cancelled while running.');\n }\n\n updateState((current) => ({ ...current, redo: current.redo.slice(0, -1), undo: [...current.undo, entry] }));\n }\n\n return {\n clear(): Promise<void> {\n return enqueue('clear', undefined, async () => {\n updateState((current) => ({ ...current, redo: [], undo: [] }));\n });\n },\n\n get disposalSignal(): AbortSignal {\n return disposalController.signal;\n },\n\n dispose(): void {\n if (disposed) return;\n\n disposed = true;\n disposalController.abort();\n\n const queued = [...operations].filter((operation) => !operation.started);\n\n for (const operation of queued) settle(operation, operationError('operation', true));\n\n updateState((current) => ({ ...current, accepting: false, queued: 0, redo: [], undo: [] }));\n },\n\n get disposed(): boolean {\n return disposed;\n },\n\n do(command: ReversibleCommand<TMeta>, callOptions?: LedgerCallOptions): Promise<void> {\n const snapshot = snapshotCommand(command);\n\n return enqueue('do', callOptions?.signal, (context) => runDo(snapshot, context));\n },\n\n redo(callOptions?: LedgerCallOptions): Promise<void> {\n return enqueue('redo', callOptions?.signal, runRedo);\n },\n\n get state() {\n return state;\n },\n\n [Symbol.dispose](): void {\n this.dispose();\n },\n\n undo(callOptions?: LedgerCallOptions): Promise<void> {\n return enqueue('undo', callOptions?.signal, runUndo);\n },\n\n whenIdle(): Promise<void> {\n if (state.value.queued === 0 && state.value.running === 0) return Promise.resolve();\n\n return new Promise((resolve) => idleWaiters.add(resolve));\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ledger.js","names":[],"sources":["../src/compose.ts","../src/errors.ts","../src/ledger.ts"],"sourcesContent":["import type { CommandContext, ReversibleCommand } from './types';\n\nfunction snapshotCommand<TMeta>(command: ReversibleCommand<TMeta>): ReversibleCommand<TMeta> {\n const { apply, label, meta, revert } = command;\n\n return { apply, label, meta, revert };\n}\n\n/**\n * Composes reversible commands into one reversible command.\n *\n * `apply` runs each child in order. `revert` runs children in reverse order.\n * A failed child application compensates completed children before rethrowing.\n *\n * @example\n * await ledger.do(compose([\n * { apply: () => { node.x = newX; }, revert: () => { node.x = oldX; } },\n * { apply: () => { node.y = newY; }, revert: () => { node.y = oldY; } },\n * ], 'Move node'));\n */\nexport function compose<TMeta = undefined>(\n commands: readonly ReversibleCommand<TMeta>[],\n label?: string,\n): ReversibleCommand<TMeta> {\n const steps = commands.map(snapshotCommand);\n\n return {\n apply: async (context: CommandContext) => {\n const applied: ReversibleCommand<TMeta>[] = [];\n\n try {\n for (const command of steps) {\n await command.apply(context);\n applied.push(command);\n }\n } catch (error) {\n const compensationFailures: unknown[] = [];\n\n for (const command of [...applied].reverse()) {\n try {\n await command.revert(context);\n } catch (compensationError) {\n compensationFailures.push(compensationError);\n }\n }\n\n if (compensationFailures.length > 0) {\n throw new AggregateError([error, ...compensationFailures], 'Command application and compensation failed', {\n cause: error,\n });\n }\n\n throw error;\n }\n },\n label,\n revert: async (context: CommandContext) => {\n const failures: unknown[] = [];\n\n for (const command of [...steps].reverse()) {\n try {\n await command.revert(context);\n } catch (error) {\n failures.push(error);\n }\n }\n\n if (failures.length > 0) throw new AggregateError(failures, 'Command reversion failed');\n },\n };\n}\n","/** Base class for all ledger errors. Use `instanceof LedgerError` to catch any ledger-originated error. */\nexport class LedgerError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a queued operation is cancelled before user code starts, or an active operation cooperatively stops. */\nexport class LedgerCancelledError extends LedgerError {}\n\n/** Thrown when a method is called on a disposed ledger instance. */\nexport class LedgerDisposedError extends LedgerError {}\n\n/** Thrown when a command's `apply()` function throws. The original error is available via `.cause`. */\nexport class LedgerExecutionError extends LedgerError {}\n\n/** Thrown when a command's `revert()` function throws during an undo operation. The original error is available via `.cause`. */\nexport class LedgerRollbackError extends LedgerError {}\n\n/** Thrown when the ledger is constructed with invalid options. */\nexport class LedgerConfigurationError extends LedgerError {}\n","import {\n LedgerCancelledError,\n LedgerConfigurationError,\n LedgerDisposedError,\n LedgerError,\n LedgerExecutionError,\n LedgerRollbackError,\n} from './errors';\nimport type {\n CommandContext,\n HistoryEntry,\n Ledger,\n LedgerCallOptions,\n LedgerOptions,\n LedgerReadable,\n LedgerState,\n ReversibleCommand,\n Unsubscribe,\n} from './types';\n\ntype StoredCommand<TMeta> = {\n apply: (context: CommandContext) => Promise<void> | void;\n entry: HistoryEntry<TMeta>;\n revert: (context: CommandContext) => Promise<void> | void;\n};\n\ntype Operation = {\n cancel: () => void;\n reject: (reason?: unknown) => void;\n resolve: () => void;\n settled: boolean;\n start: () => Promise<void>;\n started: boolean;\n};\n\nclass StateStore<T> implements LedgerReadable<T> {\n private currentValue: T;\n private readonly listeners = new Set<() => void>();\n\n constructor(initial: T) {\n this.currentValue = initial;\n }\n\n get value(): T {\n return this.currentValue;\n }\n\n peek(): T {\n return this.currentValue;\n }\n\n set(next: T): void {\n this.currentValue = next;\n\n for (const listener of [...this.listeners]) {\n try {\n listener();\n } catch (error) {\n queueMicrotask(() => {\n throw error;\n });\n }\n }\n }\n\n subscribe(listener: () => void): Unsubscribe {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n}\n\nfunction toMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction snapshotCommand<TMeta>(command: ReversibleCommand<TMeta>): StoredCommand<TMeta> {\n const { apply, label, meta, revert } = command;\n\n return { apply, entry: Object.freeze({ label, meta }), revert };\n}\n\nfunction snapshotState<TMeta>(state: LedgerState<TMeta>): LedgerState<TMeta> {\n return Object.freeze({\n ...state,\n redo: Object.freeze([...state.redo]),\n undo: Object.freeze([...state.undo]),\n });\n}\n\nfunction operationError(method: string, disposed: boolean): LedgerCancelledError | LedgerDisposedError {\n return disposed\n ? new LedgerDisposedError(`Cannot call ${method}() on a disposed ledger.`)\n : new LedgerCancelledError(`${method}() was cancelled before it started.`);\n}\n\n/**\n * Creates a serialized history of reversible commands.\n *\n * Commands are snapshotted when submitted. Queued commands cancelled before their queue turn do\n * not invoke user code. Active commands receive an abort signal and stop cooperatively.\n *\n * @example\n * const ledger = createLedger({ maxHistory: 50 });\n * await ledger.do({\n * apply: () => { item.name = next; },\n * revert: () => { item.name = previous; },\n * });\n * await ledger.undo();\n * await ledger.redo();\n * using ledger = createLedger();\n */\nexport function createLedger<TMeta = undefined>(options: LedgerOptions = {}): Ledger<TMeta> {\n const { maxHistory = 100 } = options;\n\n if (!Number.isSafeInteger(maxHistory) || maxHistory < 0) {\n throw new LedgerConfigurationError('maxHistory must be a non-negative safe integer');\n }\n\n const state = new StateStore<LedgerState<TMeta>>(\n snapshotState({ accepting: true, queued: 0, redo: [], running: 0, undo: [] }),\n );\n const commandStore = new WeakMap<HistoryEntry<TMeta>, StoredCommand<TMeta>>();\n const disposalController = new AbortController();\n const idleWaiters = new Set<() => void>();\n const operations = new Set<Operation>();\n let disposed = false;\n let queue = Promise.resolve();\n\n function updateState(update: (current: LedgerState<TMeta>) => LedgerState<TMeta>): void {\n state.set(snapshotState(update(state.value)));\n\n if (state.value.queued === 0 && state.value.running === 0) {\n for (const resolve of idleWaiters) resolve();\n idleWaiters.clear();\n }\n }\n\n function settle(operation: Operation, error?: unknown): void {\n if (operation.settled) return;\n\n operation.settled = true;\n operations.delete(operation);\n operation.cancel();\n\n if (error === undefined) operation.resolve();\n else operation.reject(error);\n }\n\n function enqueue(\n method: string,\n externalSignal: AbortSignal | undefined,\n task: (context: CommandContext) => Promise<void>,\n ): Promise<void> {\n if (disposed) return Promise.reject(operationError(method, true));\n\n const abortSignal = externalSignal\n ? AbortSignal.any([externalSignal, disposalController.signal])\n : disposalController.signal;\n\n return new Promise<void>((resolve, reject) => {\n const onAbort = (): void => {\n if (operation.started || operation.settled || disposed) return;\n\n updateState((current) => ({ ...current, queued: current.queued - 1 }));\n settle(operation, operationError(method, false));\n };\n\n const operation: Operation = {\n cancel: () => abortSignal.removeEventListener('abort', onAbort),\n reject,\n resolve,\n settled: false,\n start: async () => {\n if (operation.settled) return;\n\n if (disposed || abortSignal.aborted) {\n updateState((current) => ({ ...current, queued: current.queued - 1 }));\n settle(operation, operationError(method, disposed));\n\n return;\n }\n\n operation.started = true;\n updateState((current) => ({ ...current, queued: current.queued - 1, running: current.running + 1 }));\n\n try {\n await task({ signal: abortSignal });\n settle(operation);\n } catch (error) {\n settle(operation, error);\n } finally {\n updateState((current) => ({ ...current, running: current.running - 1 }));\n }\n },\n started: false,\n };\n\n abortSignal.addEventListener('abort', onAbort, { once: true });\n operations.add(operation);\n updateState((current) => ({ ...current, queued: current.queued + 1 }));\n queue = queue.then(operation.start, operation.start);\n });\n }\n\n async function runDo(command: StoredCommand<TMeta>, context: CommandContext): Promise<void> {\n try {\n await command.apply(context);\n } catch (error) {\n throw context.signal.aborted\n ? new LedgerCancelledError('do() was cancelled while running.', { cause: error })\n : new LedgerExecutionError(toMessage(error), { cause: error });\n }\n\n if (disposed || context.signal.aborted) {\n throw new LedgerCancelledError('do() was cancelled while running.');\n }\n\n updateState((current) => {\n if (maxHistory === 0) return { ...current, redo: [] };\n\n const undo = [...current.undo, command.entry];\n\n if (undo.length > maxHistory) undo.shift();\n\n return { ...current, redo: [], undo };\n });\n commandStore.set(command.entry, command);\n }\n\n async function runUndo(context: CommandContext): Promise<void> {\n const entry = state.value.undo[state.value.undo.length - 1];\n\n if (!entry) return;\n\n const command = commandStore.get(entry);\n\n if (!command) throw new LedgerError('Undo history is corrupted.');\n\n try {\n await command.revert(context);\n } catch (error) {\n throw context.signal.aborted\n ? new LedgerCancelledError('undo() was cancelled while running.', { cause: error })\n : new LedgerRollbackError(toMessage(error), { cause: error });\n }\n\n if (disposed || context.signal.aborted) {\n throw new LedgerCancelledError('undo() was cancelled while running.');\n }\n\n updateState((current) => ({ ...current, redo: [...current.redo, entry], undo: current.undo.slice(0, -1) }));\n }\n\n async function runRedo(context: CommandContext): Promise<void> {\n const entry = state.value.redo[state.value.redo.length - 1];\n\n if (!entry) return;\n\n const command = commandStore.get(entry);\n\n if (!command) throw new LedgerError('Redo history is corrupted.');\n\n try {\n await command.apply(context);\n } catch (error) {\n throw context.signal.aborted\n ? new LedgerCancelledError('redo() was cancelled while running.', { cause: error })\n : new LedgerExecutionError(toMessage(error), { cause: error });\n }\n\n if (disposed || context.signal.aborted) {\n throw new LedgerCancelledError('redo() was cancelled while running.');\n }\n\n updateState((current) => ({ ...current, redo: current.redo.slice(0, -1), undo: [...current.undo, entry] }));\n }\n\n return {\n clear(): Promise<void> {\n return enqueue('clear', undefined, async () => {\n updateState((current) => ({ ...current, redo: [], undo: [] }));\n });\n },\n\n get disposalSignal(): AbortSignal {\n return disposalController.signal;\n },\n\n dispose(): void {\n if (disposed) return;\n\n disposed = true;\n disposalController.abort();\n\n const queued = [...operations].filter((operation) => !operation.started);\n\n for (const operation of queued) settle(operation, operationError('operation', true));\n\n updateState((current) => ({ ...current, accepting: false, queued: 0, redo: [], undo: [] }));\n },\n\n get disposed(): boolean {\n return disposed;\n },\n\n do(command: ReversibleCommand<TMeta>, callOptions?: LedgerCallOptions): Promise<void> {\n const snapshot = snapshotCommand(command);\n\n return enqueue('do', callOptions?.signal, (context) => runDo(snapshot, context));\n },\n\n redo(callOptions?: LedgerCallOptions): Promise<void> {\n return enqueue('redo', callOptions?.signal, runRedo);\n },\n\n get state() {\n return state;\n },\n\n [Symbol.dispose](): void {\n this.dispose();\n },\n\n undo(callOptions?: LedgerCallOptions): Promise<void> {\n return enqueue('undo', callOptions?.signal, runUndo);\n },\n\n whenIdle(): Promise<void> {\n if (state.value.queued === 0 && state.value.running === 0) return Promise.resolve();\n\n return new Promise((resolve) => idleWaiters.add(resolve));\n },\n };\n}\n"],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -1,4 +1,9 @@
1
- import type { Readable, Ripple } from '@vielzeug/ripple';
1
+ export type Unsubscribe = () => void;
2
+ export interface LedgerReadable<T> {
3
+ peek(): T;
4
+ subscribe(listener: () => void): Unsubscribe;
5
+ readonly value: T;
6
+ }
2
7
  export interface CommandContext {
3
8
  readonly signal: AbortSignal;
4
9
  }
@@ -17,7 +22,6 @@ export interface LedgerCallOptions {
17
22
  }
18
23
  export interface LedgerOptions {
19
24
  maxHistory?: number;
20
- runtime?: Pick<Ripple, 'signal'>;
21
25
  }
22
26
  export interface LedgerState<TMeta = undefined> {
23
27
  readonly accepting: boolean;
@@ -33,7 +37,7 @@ export interface Ledger<TMeta = undefined> {
33
37
  readonly disposed: boolean;
34
38
  do(command: ReversibleCommand<TMeta>, options?: LedgerCallOptions): Promise<void>;
35
39
  redo(options?: LedgerCallOptions): Promise<void>;
36
- readonly state: Readable<LedgerState<TMeta>>;
40
+ readonly state: LedgerReadable<LedgerState<TMeta>>;
37
41
  undo(options?: LedgerCallOptions): Promise<void>;
38
42
  whenIdle(): Promise<void>;
39
43
  [Symbol.dispose](): void;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEzD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB,CAAC,KAAK,GAAG,SAAS;IAClD,QAAQ,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAClE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACpE;AAED,MAAM,WAAW,YAAY,CAAC,KAAK,GAAG,SAAS;IAC7C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,SAAS,CAAC;CAClC;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,WAAW,CAAC,KAAK,GAAG,SAAS;IAC5C,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,SAAS,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;CAC/C;AAED,MAAM,WAAW,MAAM,CAAC,KAAK,GAAG,SAAS;IACvC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,OAAO,IAAI,IAAI,CAAC;IAChB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,EAAE,CAAC,OAAO,EAAE,iBAAiB,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClF,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7C,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;CAC1B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAErC,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,IAAI,IAAI,CAAC,CAAC;IACV,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,WAAW,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB,CAAC,KAAK,GAAG,SAAS;IAClD,QAAQ,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAClE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACpE;AAED,MAAM,WAAW,YAAY,CAAC,KAAK,GAAG,SAAS;IAC7C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,SAAS,CAAC;CAClC;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW,CAAC,KAAK,GAAG,SAAS;IAC5C,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,SAAS,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;CAC/C;AAED,MAAM,WAAW,MAAM,CAAC,KAAK,GAAG,SAAS;IACvC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,OAAO,IAAI,IAAI,CAAC;IAChB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,EAAE,CAAC,OAAO,EAAE,iBAAiB,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClF,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;IACnD,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;CAC1B"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vielzeug/ledger",
3
- "version": "2.3.0",
4
- "description": "Serialized reversible command history with atomic Ripple state and cancellation ownership",
3
+ "version": "3.0.0",
4
+ "description": "Serialized reversible command history with atomic state and cancellation ownership",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/helmuthdu/vielzeug",
@@ -30,21 +30,18 @@
30
30
  "registry": "https://registry.npmjs.org/"
31
31
  },
32
32
  "scripts": {
33
- "build": "vite build && pnpm run build:bundle && pnpm run build:types",
33
+ "build": "vite build && pnpm --silent run build:bundle && pnpm --silent run build:types",
34
34
  "build:bundle": "vite build --config vite.bundle.config.ts",
35
35
  "build:types": "tsc -p tsconfig.declarations.json",
36
36
  "fix": "biome check --write src",
37
37
  "lint": "biome ci src",
38
- "prepublishOnly": "pnpm run build",
38
+ "prepublishOnly": "pnpm --silent run build",
39
39
  "test": "vitest"
40
40
  },
41
- "dependencies": {
42
- "@vielzeug/ripple": "2.3.0"
43
- },
44
41
  "devDependencies": {
45
- "@types/node": "^26.2.0",
42
+ "@types/node": "^26.4.1",
46
43
  "typescript": "^6.0.3",
47
- "vite": "^8.2.1",
48
- "vitest": "^4.1.10"
44
+ "vite": "^8.2.2",
45
+ "vitest": "^5.0.0"
49
46
  }
50
47
  }