@actor-system/behaviors 0.0.17 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/__bundle__/shared/dist/index.js +3 -0
  2. package/dist/index.d.ts +16 -9
  3. package/dist/index.internal.d.ts +16 -9
  4. package/dist/index.js +13 -7
  5. package/dist/intercept.d.ts +5 -7
  6. package/dist/intercept.internal.d.ts +5 -7
  7. package/dist/intercept.js +9 -15
  8. package/dist/named.d.ts +2 -2
  9. package/dist/named.internal.d.ts +2 -2
  10. package/dist/receive.d.ts +5 -5
  11. package/dist/receive.internal.d.ts +5 -5
  12. package/dist/receive.js +13 -11
  13. package/dist/setup.d.ts +1 -1
  14. package/dist/setup.internal.d.ts +1 -1
  15. package/dist/setup.js +1 -2
  16. package/dist/supervision/SupervisorStrategy.d.ts +14 -0
  17. package/dist/supervision/SupervisorStrategy.internal.d.ts +14 -0
  18. package/dist/supervision/SupervisorStrategy.js +12 -0
  19. package/dist/supervision/supervise.d.ts +10 -0
  20. package/dist/supervision/supervise.internal.d.ts +10 -0
  21. package/dist/supervision/supervise.js +44 -0
  22. package/dist/with-stash.d.ts +63 -8
  23. package/dist/with-stash.internal.d.ts +63 -8
  24. package/dist/with-stash.js +106 -39
  25. package/dist/with-timers.d.ts +1 -1
  26. package/dist/with-timers.internal.d.ts +1 -1
  27. package/dist/with-timers.js +6 -5
  28. package/package.json +3 -3
  29. package/dist/empty.d.ts +0 -5
  30. package/dist/empty.internal.d.ts +0 -5
  31. package/dist/empty.js +0 -5
  32. package/dist/restart.d.ts +0 -5
  33. package/dist/restart.internal.d.ts +0 -5
  34. package/dist/restart.js +0 -11
  35. package/dist/same.d.ts +0 -5
  36. package/dist/same.internal.d.ts +0 -5
  37. package/dist/same.js +0 -5
  38. package/dist/stopped.d.ts +0 -5
  39. package/dist/stopped.internal.d.ts +0 -5
  40. package/dist/stopped.js +0 -10
  41. package/dist/supervise.d.ts +0 -14
  42. package/dist/supervise.internal.d.ts +0 -14
  43. package/dist/supervise.js +0 -36
  44. package/dist/unhandled.d.ts +0 -5
  45. package/dist/unhandled.internal.d.ts +0 -5
  46. package/dist/unhandled.js +0 -5
@@ -0,0 +1,3 @@
1
+ const identity = (x) => x;
2
+
3
+ export { identity };
package/dist/index.d.ts CHANGED
@@ -1,13 +1,20 @@
1
- export { empty } from './empty.js';
2
- export { intercept } from './intercept.js';
1
+ export { BehaviorInterceptor, intercept } from './intercept.js';
3
2
  export { named } from './named.js';
4
3
  export { ReceiveMessage, ReceiveSignal, receive, receiveMessage, receiveSignal } from './receive.js';
5
- export { restart } from './restart.js';
6
- export { same } from './same.js';
7
4
  export { setup } from './setup.js';
8
- export { stopped } from './stopped.js';
9
- export { supervise } from './supervise.js';
10
- export { unhandled } from './unhandled.js';
11
- export { Stash, withStash } from './with-stash.js';
5
+ export { supervise } from './supervision/supervise.js';
6
+ export { SupervisorStrategy, SupervisorStrategyContext } from './supervision/SupervisorStrategy.js';
7
+ export { NoSuchElementError, StashBuffer, StashOverflowError, UnstashOptions, withStash } from './with-stash.js';
12
8
  export { Timers, withTimers } from './with-timers.js';
13
- export { Behavior } from '@actor-system/core';
9
+ import { behavior, $restartBehavior } from '@actor-system/core';
10
+
11
+ declare const empty: behavior.EmptyBehavior<never> & (<T>() => behavior.EmptyBehavior<T>);
12
+ declare const restart: {
13
+ <T>(checkpoint: behavior.Behavior<T>): behavior.RestartBehavior<T>;
14
+ _tag: typeof $restartBehavior;
15
+ };
16
+ declare const same: behavior.SameBehavior<never> & (<T>() => behavior.SameBehavior<T>);
17
+ declare const stopped: behavior.StoppedBehavior<never> & (<T>() => behavior.StoppedBehavior<T>);
18
+ declare const unhandled: behavior.UnhandledBehavior<never> & (<T>() => behavior.UnhandledBehavior<T>);
19
+
20
+ export { empty, restart, same, stopped, unhandled };
@@ -1,13 +1,20 @@
1
- export { empty } from './empty.internal.js';
2
- export { intercept } from './intercept.internal.js';
1
+ export { BehaviorInterceptor, intercept } from './intercept.internal.js';
3
2
  export { named } from './named.internal.js';
4
3
  export { ReceiveMessage, ReceiveSignal, receive, receiveMessage, receiveSignal } from './receive.internal.js';
5
- export { restart } from './restart.internal.js';
6
- export { same } from './same.internal.js';
7
4
  export { setup } from './setup.internal.js';
8
- export { stopped } from './stopped.internal.js';
9
- export { supervise } from './supervise.internal.js';
10
- export { unhandled } from './unhandled.internal.js';
11
- export { Stash, withStash } from './with-stash.internal.js';
5
+ export { supervise } from './supervision/supervise.internal.js';
6
+ export { SupervisorStrategy, SupervisorStrategyContext } from './supervision/SupervisorStrategy.internal.js';
7
+ export { NoSuchElementError, StashBuffer, StashOverflowError, UnstashOptions, withStash } from './with-stash.internal.js';
12
8
  export { Timers, withTimers } from './with-timers.internal.js';
13
- export { Behavior } from '@actor-system/core/internal';
9
+ import { behavior, $restartBehavior } from '@actor-system/core/internal';
10
+
11
+ declare const empty: behavior.EmptyBehavior<never> & (<T>() => behavior.EmptyBehavior<T>);
12
+ declare const restart: {
13
+ <T>(checkpoint: behavior.Behavior<T>): behavior.RestartBehavior<T>;
14
+ _tag: typeof $restartBehavior;
15
+ };
16
+ declare const same: behavior.SameBehavior<never> & (<T>() => behavior.SameBehavior<T>);
17
+ declare const stopped: behavior.StoppedBehavior<never> & (<T>() => behavior.StoppedBehavior<T>);
18
+ declare const unhandled: behavior.UnhandledBehavior<never> & (<T>() => behavior.UnhandledBehavior<T>);
19
+
20
+ export { empty, restart, same, stopped, unhandled };
package/dist/index.js CHANGED
@@ -1,12 +1,18 @@
1
- export { empty } from './empty.js';
2
1
  export { intercept } from './intercept.js';
3
2
  export { named } from './named.js';
4
3
  export { receive, receiveMessage, receiveSignal } from './receive.js';
5
- export { restart } from './restart.js';
6
- export { same } from './same.js';
7
4
  export { setup } from './setup.js';
8
- export { stopped } from './stopped.js';
9
- export { supervise } from './supervise.js';
10
- export { unhandled } from './unhandled.js';
11
- export { withStash } from './with-stash.js';
5
+ export { supervise } from './supervision/supervise.js';
6
+ export { SupervisorStrategy } from './supervision/SupervisorStrategy.js';
7
+ export { NoSuchElementError, StashOverflowError, withStash } from './with-stash.js';
12
8
  export { withTimers } from './with-timers.js';
9
+ import { behavior } from '@actor-system/core';
10
+
11
+ /* eslint-enable @typescript-eslint/no-unused-vars */
12
+ const empty = behavior._empty;
13
+ const restart = behavior._restart;
14
+ const same = behavior._same;
15
+ const stopped = behavior._stopped;
16
+ const unhandled = behavior._unhandled;
17
+
18
+ export { empty, restart, same, stopped, unhandled };
@@ -1,10 +1,8 @@
1
- import { behavior, signal, ActorContext } from '@actor-system/core';
2
- import { Bivariant } from './__bundle__/shared/dist/types.js';
1
+ import { signal, behavior, ActorContext } from '@actor-system/core';
3
2
 
4
- type Interceptor<Input, Output = Input> = Bivariant<(post: Output | signal.Signal, context: ActorContext<Output>) => Input | signal.Signal | behavior.Behavior<Input>>;
5
- declare function intercept<Input, Output = Input>(inner: behavior.Folded<Input>, interceptor: Interceptor<Input, Output>): behavior.Folded<Output>;
6
- declare function intercept<Input, Output = Input>(inner: behavior.Control<Input>, interceptor: Interceptor<Input, Output>): behavior.Control<Output>;
7
- declare function intercept<Input, Output = Input>(inner: behavior.Receive<Input>, interceptor: Interceptor<Input, Output>): behavior.Receive<Output>;
8
- declare function intercept<Input, Output = Input>(inner: behavior.Behavior<Input>, interceptor: Interceptor<Input, Output>): behavior.Behavior<Output>;
3
+ type ReceiveTarget<T> = (message: T | signal.Signal) => behavior.Behavior<T>;
4
+ type BehaviorInterceptor<Outer, Inner = Outer> = (message: Outer | signal.Signal, innerReceive: ReceiveTarget<Inner>, context: ActorContext<Inner | Outer>) => behavior.Behavior<Inner>;
5
+ declare const intercept: <Outer, Inner = Outer>(interceptor: BehaviorInterceptor<Outer, Inner>) => (innerBehavior: behavior.Behavior<Inner>) => behavior.Behavior<Outer>;
9
6
 
10
7
  export { intercept };
8
+ export type { BehaviorInterceptor, ReceiveTarget };
@@ -1,10 +1,8 @@
1
- import { behavior, signal, ActorContext } from '@actor-system/core/internal';
2
- import { Bivariant } from './__bundle__/shared/dist/types.internal.js';
1
+ import { signal, behavior, ActorContext } from '@actor-system/core/internal';
3
2
 
4
- type Interceptor<Input, Output = Input> = Bivariant<(post: Output | signal.Signal, context: ActorContext<Output>) => Input | signal.Signal | behavior.Behavior<Input>>;
5
- declare function intercept<Input, Output = Input>(inner: behavior.Folded<Input>, interceptor: Interceptor<Input, Output>): behavior.Folded<Output>;
6
- declare function intercept<Input, Output = Input>(inner: behavior.Control<Input>, interceptor: Interceptor<Input, Output>): behavior.Control<Output>;
7
- declare function intercept<Input, Output = Input>(inner: behavior.Receive<Input>, interceptor: Interceptor<Input, Output>): behavior.Receive<Output>;
8
- declare function intercept<Input, Output = Input>(inner: behavior.Behavior<Input>, interceptor: Interceptor<Input, Output>): behavior.Behavior<Output>;
3
+ type ReceiveTarget<T> = (message: T | signal.Signal) => behavior.Behavior<T>;
4
+ type BehaviorInterceptor<Outer, Inner = Outer> = (message: Outer | signal.Signal, innerReceive: ReceiveTarget<Inner>, context: ActorContext<Inner | Outer>) => behavior.Behavior<Inner>;
5
+ declare const intercept: <Outer, Inner = Outer>(interceptor: BehaviorInterceptor<Outer, Inner>) => (innerBehavior: behavior.Behavior<Inner>) => behavior.Behavior<Outer>;
9
6
 
10
7
  export { intercept };
8
+ export type { BehaviorInterceptor, ReceiveTarget };
package/dist/intercept.js CHANGED
@@ -2,22 +2,16 @@ import { behavior } from '@actor-system/core';
2
2
  import { receive } from './receive.js';
3
3
  import { setup } from './setup.js';
4
4
 
5
- function intercept(inner, interceptor) {
6
- if (behavior.isControl(inner)) {
7
- return inner;
5
+ const intercept = (interceptor) => (innerBehavior) => {
6
+ // if the inner behavior is a folded behavior, unfold it and intercept the result
7
+ if (behavior.isFolded(innerBehavior)) {
8
+ return setup((context) => intercept(interceptor)(behavior.unfold(innerBehavior, context)));
8
9
  }
9
- if (behavior.isFolded(inner)) {
10
- return setup((ctx) => intercept(behavior.unfold(inner, ctx), interceptor));
10
+ // if the inner behavior is a receive behavior, create a new receive behavior that applies the interceptor
11
+ if (behavior.isReceive(innerBehavior)) {
12
+ return receive((message, context) => intercept(interceptor)(interceptor(message, (msg) => innerBehavior._receive(msg, context), context)));
11
13
  }
12
- if (behavior.isReceive(inner)) {
13
- return receive((message, context) => {
14
- const intercepted = interceptor(message, context);
15
- return behavior.isBehavior(intercepted)
16
- ? intercept(intercepted, interceptor)
17
- : intercept(behavior.delegate(inner, intercepted, context), interceptor);
18
- });
19
- }
20
- throw new Error(`Cannot intercept behavior of type ${inner} with interceptor`);
21
- }
14
+ return innerBehavior;
15
+ };
22
16
 
23
17
  export { intercept };
package/dist/named.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { Behavior } from '@actor-system/core';
1
+ import { behavior } from '@actor-system/core';
2
2
 
3
3
  /**
4
4
  * Creates a named version of a behavior using template literal syntax.
5
5
  * This is useful for debugging and behavior change tracking.
6
6
  */
7
- declare const named: (strings: TemplateStringsArray, ...values: unknown[]) => <B extends Behavior<unknown>>(targetBehavior: B) => B;
7
+ declare const named: (strings: TemplateStringsArray, ...values: unknown[]) => <B extends behavior.Behavior<unknown>>(targetBehavior: B) => B;
8
8
 
9
9
  export { named };
@@ -1,9 +1,9 @@
1
- import { Behavior } from '@actor-system/core/internal';
1
+ import { behavior } from '@actor-system/core/internal';
2
2
 
3
3
  /**
4
4
  * Creates a named version of a behavior using template literal syntax.
5
5
  * This is useful for debugging and behavior change tracking.
6
6
  */
7
- declare const named: (strings: TemplateStringsArray, ...values: unknown[]) => <B extends Behavior<unknown>>(targetBehavior: B) => B;
7
+ declare const named: (strings: TemplateStringsArray, ...values: unknown[]) => <B extends behavior.Behavior<unknown>>(targetBehavior: B) => B;
8
8
 
9
9
  export { named };
package/dist/receive.d.ts CHANGED
@@ -1,15 +1,15 @@
1
1
  import { signal, ActorContext, behavior } from '@actor-system/core';
2
2
  import { Bivariant } from './__bundle__/shared/dist/types.js';
3
3
 
4
- interface ReceiveMessage<T> extends behavior.Receive<T> {
5
- receiveSignal(handler: Bivariant<(signal: signal.Signal, ctx: ActorContext<T>) => behavior.Behavior<T> | void>): behavior.Receive<T>;
4
+ interface ReceiveMessage<T = unknown> extends behavior.ReceiveBehavior<T> {
5
+ receiveSignal(handler: Bivariant<(signal: signal.Signal, ctx: ActorContext<T>) => behavior.Behavior<T> | void>): behavior.ReceiveBehavior<T>;
6
6
  }
7
- interface ReceiveSignal<T> extends behavior.Receive<T> {
8
- receiveMessage(handler: Bivariant<(message: T, ctx: ActorContext<T>) => behavior.Behavior<T> | void>): behavior.Receive<T>;
7
+ interface ReceiveSignal<T> extends behavior.ReceiveBehavior<T> {
8
+ receiveMessage(handler: Bivariant<(message: T, ctx: ActorContext<T>) => behavior.Behavior<T> | void>): behavior.ReceiveBehavior<T>;
9
9
  }
10
10
  declare const receiveMessage: <T>(onMessage: Bivariant<(message: T, context: ActorContext<T>) => behavior.Behavior<T> | void>) => ReceiveMessage<T>;
11
11
  declare const receiveSignal: <T>(onSignal: Bivariant<(signal: signal.Signal, context: ActorContext<T>) => behavior.Behavior<T> | void>) => ReceiveSignal<T>;
12
- declare const receive: <T>(handler: Bivariant<(messageOrSignal: T | signal.Signal, context: ActorContext<T>) => behavior.Behavior<T> | void>) => behavior.Receive<T>;
12
+ declare const receive: <T>(handler: Bivariant<(messageOrSignal: T | signal.Signal, context: ActorContext<T>) => behavior.Behavior<T> | void>) => behavior.ReceiveBehavior<T>;
13
13
 
14
14
  export { receive, receiveMessage, receiveSignal };
15
15
  export type { ReceiveMessage, ReceiveSignal };
@@ -1,15 +1,15 @@
1
1
  import { signal, ActorContext, behavior } from '@actor-system/core/internal';
2
2
  import { Bivariant } from './__bundle__/shared/dist/types.internal.js';
3
3
 
4
- interface ReceiveMessage<T> extends behavior.Receive<T> {
5
- receiveSignal(handler: Bivariant<(signal: signal.Signal, ctx: ActorContext<T>) => behavior.Behavior<T> | void>): behavior.Receive<T>;
4
+ interface ReceiveMessage<T = unknown> extends behavior.ReceiveBehavior<T> {
5
+ receiveSignal(handler: Bivariant<(signal: signal.Signal, ctx: ActorContext<T>) => behavior.Behavior<T> | void>): behavior.ReceiveBehavior<T>;
6
6
  }
7
- interface ReceiveSignal<T> extends behavior.Receive<T> {
8
- receiveMessage(handler: Bivariant<(message: T, ctx: ActorContext<T>) => behavior.Behavior<T> | void>): behavior.Receive<T>;
7
+ interface ReceiveSignal<T> extends behavior.ReceiveBehavior<T> {
8
+ receiveMessage(handler: Bivariant<(message: T, ctx: ActorContext<T>) => behavior.Behavior<T> | void>): behavior.ReceiveBehavior<T>;
9
9
  }
10
10
  declare const receiveMessage: <T>(onMessage: Bivariant<(message: T, context: ActorContext<T>) => behavior.Behavior<T> | void>) => ReceiveMessage<T>;
11
11
  declare const receiveSignal: <T>(onSignal: Bivariant<(signal: signal.Signal, context: ActorContext<T>) => behavior.Behavior<T> | void>) => ReceiveSignal<T>;
12
- declare const receive: <T>(handler: Bivariant<(messageOrSignal: T | signal.Signal, context: ActorContext<T>) => behavior.Behavior<T> | void>) => behavior.Receive<T>;
12
+ declare const receive: <T>(handler: Bivariant<(messageOrSignal: T | signal.Signal, context: ActorContext<T>) => behavior.Behavior<T> | void>) => behavior.ReceiveBehavior<T>;
13
13
 
14
14
  export { receive, receiveMessage, receiveSignal };
15
15
  export type { ReceiveMessage, ReceiveSignal };
package/dist/receive.js CHANGED
@@ -1,19 +1,21 @@
1
1
  import { behavior, signal } from '@actor-system/core';
2
- import { same } from './same.js';
3
- import { unhandled } from './unhandled.js';
4
2
 
5
3
  const receiveMessage = (onMessage) => ({
6
- ...behavior.receive((message, ctx) => !signal.isSignal(message) ? (onMessage(message, ctx) ?? unhandled) : same),
7
- receiveSignal: (onSignal) => behavior.receive((message, context) => !signal.isSignal(message)
8
- ? (onMessage(message, context) ?? unhandled)
9
- : (onSignal(message, context) ?? unhandled)),
4
+ ...behavior._receive((message, ctx) => !signal.isSignal(message)
5
+ ? (onMessage(message, ctx) ?? behavior._unhandled)
6
+ : behavior._same),
7
+ receiveSignal: (onSignal) => behavior._receive((message, context) => !signal.isSignal(message)
8
+ ? (onMessage(message, context) ?? behavior._unhandled)
9
+ : (onSignal(message, context) ?? behavior._unhandled)),
10
10
  });
11
11
  const receiveSignal = (onSignal) => ({
12
- ...behavior.receive((message, ctx) => signal.isSignal(message) ? (onSignal(message, ctx) ?? unhandled) : same),
13
- receiveMessage: (onMessage) => behavior.receive((message, context) => signal.isSignal(message)
14
- ? (onSignal(message, context) ?? unhandled)
15
- : (onMessage(message, context) ?? unhandled)),
12
+ ...behavior._receive((message, ctx) => signal.isSignal(message)
13
+ ? (onSignal(message, ctx) ?? behavior._unhandled)
14
+ : behavior._same),
15
+ receiveMessage: (onMessage) => behavior._receive((message, context) => signal.isSignal(message)
16
+ ? (onSignal(message, context) ?? behavior._unhandled)
17
+ : (onMessage(message, context) ?? behavior._unhandled)),
16
18
  });
17
- const receive = (handler) => behavior.receive((message, ctx) => handler(message, ctx) ?? unhandled);
19
+ const receive = (handler) => behavior._receive((message, ctx) => handler(message, ctx) ?? behavior._unhandled);
18
20
 
19
21
  export { receive, receiveMessage, receiveSignal };
package/dist/setup.d.ts CHANGED
@@ -2,7 +2,7 @@ import { ActorContext, behavior } from '@actor-system/core';
2
2
  import { Bivariant } from './__bundle__/shared/dist/types.js';
3
3
 
4
4
  type SetupFactory<T> = Bivariant<(context: ActorContext<T>) => behavior.Behavior<T> | void>;
5
- declare const setup: <T>(factory: SetupFactory<T>) => behavior.Folded<T>;
5
+ declare const setup: <T>(factory: SetupFactory<T>) => behavior.FoldedBehavior<T>;
6
6
 
7
7
  export { setup };
8
8
  export type { SetupFactory };
@@ -2,7 +2,7 @@ import { ActorContext, behavior } from '@actor-system/core/internal';
2
2
  import { Bivariant } from './__bundle__/shared/dist/types.internal.js';
3
3
 
4
4
  type SetupFactory<T> = Bivariant<(context: ActorContext<T>) => behavior.Behavior<T> | void>;
5
- declare const setup: <T>(factory: SetupFactory<T>) => behavior.Folded<T>;
5
+ declare const setup: <T>(factory: SetupFactory<T>) => behavior.FoldedBehavior<T>;
6
6
 
7
7
  export { setup };
8
8
  export type { SetupFactory };
package/dist/setup.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { behavior } from '@actor-system/core';
2
- import { empty } from './empty.js';
3
2
 
4
- const setup = (factory) => behavior.folded((ctx) => factory(ctx) ?? empty);
3
+ const setup = (factory) => behavior._folded((ctx) => factory(ctx) ?? behavior._empty);
5
4
 
6
5
  export { setup };
@@ -0,0 +1,14 @@
1
+ import { ActorContext, behavior } from '@actor-system/core';
2
+
3
+ interface SupervisorStrategyContext<T = unknown> extends ActorContext<T> {
4
+ readonly supervisedBehavior: behavior.Behavior<T>;
5
+ }
6
+ type SupervisorStrategy = <T = any>(error: unknown, context: SupervisorStrategyContext<T>) => behavior.Behavior<T>;
7
+ declare const SupervisorStrategy: {
8
+ readonly stop: SupervisorStrategy;
9
+ readonly resume: SupervisorStrategy;
10
+ readonly restart: SupervisorStrategy;
11
+ };
12
+
13
+ export { SupervisorStrategy };
14
+ export type { SupervisorStrategyContext };
@@ -0,0 +1,14 @@
1
+ import { ActorContext, behavior } from '@actor-system/core/internal';
2
+
3
+ interface SupervisorStrategyContext<T = unknown> extends ActorContext<T> {
4
+ readonly supervisedBehavior: behavior.Behavior<T>;
5
+ }
6
+ type SupervisorStrategy = <T = any>(error: unknown, context: SupervisorStrategyContext<T>) => behavior.Behavior<T>;
7
+ declare const SupervisorStrategy: {
8
+ readonly stop: SupervisorStrategy;
9
+ readonly resume: SupervisorStrategy;
10
+ readonly restart: SupervisorStrategy;
11
+ };
12
+
13
+ export { SupervisorStrategy };
14
+ export type { SupervisorStrategyContext };
@@ -0,0 +1,12 @@
1
+ import { behavior } from '@actor-system/core';
2
+
3
+ const resume = (_e, { supervisedBehavior }) => supervisedBehavior;
4
+ const stop = () => behavior._stopped;
5
+ const restart = (_error, { supervisedBehavior }) => behavior._restart(supervisedBehavior);
6
+ const SupervisorStrategy = {
7
+ stop,
8
+ resume,
9
+ restart,
10
+ };
11
+
12
+ export { SupervisorStrategy };
@@ -0,0 +1,10 @@
1
+ import { behavior } from '@actor-system/core';
2
+ import { SupervisorStrategy } from './SupervisorStrategy.js';
3
+
4
+ interface Supervised<T> {
5
+ onFailure(strategy: SupervisorStrategy): behavior.Behavior<T>;
6
+ }
7
+ declare const supervise: <T>(inner: behavior.Behavior<T>) => Supervised<T>;
8
+
9
+ export { supervise };
10
+ export type { Supervised };
@@ -0,0 +1,10 @@
1
+ import { behavior } from '@actor-system/core/internal';
2
+ import { SupervisorStrategy } from './SupervisorStrategy.internal.js';
3
+
4
+ interface Supervised<T> {
5
+ onFailure(strategy: SupervisorStrategy): behavior.Behavior<T>;
6
+ }
7
+ declare const supervise: <T>(inner: behavior.Behavior<T>) => Supervised<T>;
8
+
9
+ export { supervise };
10
+ export type { Supervised };
@@ -0,0 +1,44 @@
1
+ import { behavior } from '@actor-system/core';
2
+
3
+ const supervise = (inner) => ({
4
+ onFailure: (strategy) => {
5
+ switch (inner._tag) {
6
+ case behavior._folded._tag:
7
+ return behavior._folded((context) => {
8
+ try {
9
+ const unfolded = behavior.unfold(inner, context);
10
+ return supervise(unfolded).onFailure(strategy);
11
+ }
12
+ catch (error) {
13
+ return strategy(error, {
14
+ ...context,
15
+ supervisedBehavior: supervise(inner).onFailure(strategy),
16
+ });
17
+ }
18
+ });
19
+ case behavior._receive._tag:
20
+ return behavior._receive((message, context) => {
21
+ try {
22
+ const next = behavior.interpret(inner, context, message);
23
+ switch (next) {
24
+ case behavior._same:
25
+ case behavior._unhandled:
26
+ return next;
27
+ default:
28
+ return supervise(next).onFailure(strategy);
29
+ }
30
+ }
31
+ catch (error) {
32
+ return strategy(error, {
33
+ ...context,
34
+ supervisedBehavior: supervise(inner).onFailure(strategy),
35
+ });
36
+ }
37
+ });
38
+ default:
39
+ return inner;
40
+ }
41
+ },
42
+ });
43
+
44
+ export { supervise };
@@ -1,12 +1,67 @@
1
+ import { Letter } from '@actor-system/mail';
1
2
  import { ActorContext, behavior } from '@actor-system/core';
2
3
 
3
- interface Stash<T> {
4
- push(msg: T): void;
5
- dropAll(): void;
6
- popAll(): void;
7
- readonly size: number;
4
+ declare const withStash: <T>(capacity: number, factory: (stashBuffer: StashBuffer<T>) => behavior.Behavior<T>) => behavior.Behavior<T>;
5
+ interface UnstashOptions<T> {
6
+ /**
7
+ * Number of messages to unstash.
8
+ * @default Number.POSITIVE_INFINITY
9
+ */
10
+ amount?: number;
11
+ /**
12
+ * Function to transform messages when unstashing.
13
+ */
14
+ map?: (msg: T) => T;
15
+ }
16
+ declare class StashBuffer<T> {
17
+ #private;
18
+ readonly capacity: number;
19
+ static create<T>(capacity: number, context: ActorContext<T>): StashBuffer<T>;
20
+ private constructor();
21
+ get size(): number;
22
+ /**
23
+ * Return the first element of the message buffer without removing it.
24
+ * @returns the first element or throws NoSuchElementError if the buffer is empty
25
+ * @throws {NoSuchElementError} if the buffer is empty
26
+ */
27
+ get head(): T;
28
+ /**
29
+ * Returns an iterable of messages in the buffer in insertion order.
30
+ * @returns An iterable of messages.
31
+ */
32
+ values(): SetIterator<T>;
33
+ /**
34
+ * Removes all messages from the buffer.
35
+ */
36
+ clear(): void;
37
+ /**
38
+ * Add one element to the end of the message buffer.
39
+ * @throws {StashOverflowError} if the buffer is full.
40
+ */
41
+ stash(msg: T): this;
42
+ /**
43
+ * Request replay of up to `numberOfMessages` messages using `map`.
44
+ *
45
+ * If called while another unstash is in progress, it does not replay
46
+ * immediately; it just marks that another replay is requested.
47
+ *
48
+ * Once the current replay finishes, any pending requests are bundled
49
+ * and a single replay pass is run again.
50
+ */
51
+ unstash(behavior: behavior.Behavior<T>, options?: UnstashOptions<T>): behavior.Behavior<T>;
52
+ }
53
+ declare const $noSuchElementError = "@@with-stash.no-such-element-error";
54
+ declare class NoSuchElementError extends Error implements Letter<typeof $noSuchElementError> {
55
+ static readonly label = "@@with-stash.no-such-element-error";
56
+ readonly label: typeof $noSuchElementError;
57
+ constructor();
58
+ }
59
+ declare const $stashOverflowError = "@@with-stash.stash-overflow-error";
60
+ declare class StashOverflowError extends Error implements Letter<typeof $stashOverflowError> {
61
+ static readonly label = "@@with-stash.stash-overflow-error";
62
+ readonly label: typeof $stashOverflowError;
63
+ constructor(message: string);
8
64
  }
9
- declare const withStash: <T>(factory: (stash: Stash<T>, context: ActorContext<T>) => behavior.Behavior<T>) => behavior.Behavior<T>;
10
65
 
11
- export { withStash };
12
- export type { Stash };
66
+ export { NoSuchElementError, StashBuffer, StashOverflowError, withStash };
67
+ export type { UnstashOptions };
@@ -1,12 +1,67 @@
1
+ import { Letter } from '@actor-system/mail/internal';
1
2
  import { ActorContext, behavior } from '@actor-system/core/internal';
2
3
 
3
- interface Stash<T> {
4
- push(msg: T): void;
5
- dropAll(): void;
6
- popAll(): void;
7
- readonly size: number;
4
+ declare const withStash: <T>(capacity: number, factory: (stashBuffer: StashBuffer<T>) => behavior.Behavior<T>) => behavior.Behavior<T>;
5
+ interface UnstashOptions<T> {
6
+ /**
7
+ * Number of messages to unstash.
8
+ * @default Number.POSITIVE_INFINITY
9
+ */
10
+ amount?: number;
11
+ /**
12
+ * Function to transform messages when unstashing.
13
+ */
14
+ map?: (msg: T) => T;
15
+ }
16
+ declare class StashBuffer<T> {
17
+ #private;
18
+ readonly capacity: number;
19
+ static create<T>(capacity: number, context: ActorContext<T>): StashBuffer<T>;
20
+ private constructor();
21
+ get size(): number;
22
+ /**
23
+ * Return the first element of the message buffer without removing it.
24
+ * @returns the first element or throws NoSuchElementError if the buffer is empty
25
+ * @throws {NoSuchElementError} if the buffer is empty
26
+ */
27
+ get head(): T;
28
+ /**
29
+ * Returns an iterable of messages in the buffer in insertion order.
30
+ * @returns An iterable of messages.
31
+ */
32
+ values(): SetIterator<T>;
33
+ /**
34
+ * Removes all messages from the buffer.
35
+ */
36
+ clear(): void;
37
+ /**
38
+ * Add one element to the end of the message buffer.
39
+ * @throws {StashOverflowError} if the buffer is full.
40
+ */
41
+ stash(msg: T): this;
42
+ /**
43
+ * Request replay of up to `numberOfMessages` messages using `map`.
44
+ *
45
+ * If called while another unstash is in progress, it does not replay
46
+ * immediately; it just marks that another replay is requested.
47
+ *
48
+ * Once the current replay finishes, any pending requests are bundled
49
+ * and a single replay pass is run again.
50
+ */
51
+ unstash(behavior: behavior.Behavior<T>, options?: UnstashOptions<T>): behavior.Behavior<T>;
52
+ }
53
+ declare const $noSuchElementError = "@@with-stash.no-such-element-error";
54
+ declare class NoSuchElementError extends Error implements Letter<typeof $noSuchElementError> {
55
+ static readonly label = "@@with-stash.no-such-element-error";
56
+ readonly label: typeof $noSuchElementError;
57
+ constructor();
58
+ }
59
+ declare const $stashOverflowError = "@@with-stash.stash-overflow-error";
60
+ declare class StashOverflowError extends Error implements Letter<typeof $stashOverflowError> {
61
+ static readonly label = "@@with-stash.stash-overflow-error";
62
+ readonly label: typeof $stashOverflowError;
63
+ constructor(message: string);
8
64
  }
9
- declare const withStash: <T>(factory: (stash: Stash<T>, context: ActorContext<T>) => behavior.Behavior<T>) => behavior.Behavior<T>;
10
65
 
11
- export { withStash };
12
- export type { Stash };
66
+ export { NoSuchElementError, StashBuffer, StashOverflowError, withStash };
67
+ export type { UnstashOptions };
@@ -1,45 +1,112 @@
1
- import { signal } from '@actor-system/core';
2
1
  import { setup } from './setup.js';
3
- import { intercept } from './intercept.js';
2
+ import { identity } from './__bundle__/shared/dist/index.js';
4
3
 
5
- const $stash = Symbol("stash");
6
- const withStash = (factory) => setup((context) => {
7
- const stash = useStash(context);
8
- const innerBehavior = factory(stash, context);
9
- return intercept(innerBehavior, (post) => {
10
- if (signal.isPostStop(post)) {
11
- stash.dropAll();
4
+ const withStash = (capacity, factory) => setup((context) => factory(StashBuffer.create(capacity, context)));
5
+ class StashBuffer {
6
+ capacity;
7
+ #stash = [];
8
+ #context;
9
+ // replay control
10
+ #isReplaying = false;
11
+ #pendingReplays = [];
12
+ static create(capacity, context) {
13
+ return new StashBuffer(capacity, context);
14
+ }
15
+ constructor(capacity, context) {
16
+ this.capacity = capacity;
17
+ this.#context = context;
18
+ }
19
+ get size() {
20
+ return this.#stash.length;
21
+ }
22
+ /**
23
+ * Return the first element of the message buffer without removing it.
24
+ * @returns the first element or throws NoSuchElementError if the buffer is empty
25
+ * @throws {NoSuchElementError} if the buffer is empty
26
+ */
27
+ get head() {
28
+ if (this.#stash.length === 0) {
29
+ throw new NoSuchElementError();
12
30
  }
13
- return post;
14
- });
15
- });
16
- const useStash = (context, capacity = 100) => {
17
- if (context[$stash])
18
- return context[$stash];
19
- const stack = [];
20
- const stash = {
21
- /** Stash a message for later processing */
22
- push: (msg) => {
23
- if (stack.length < capacity) {
24
- stack.push(msg);
31
+ return this.#stash[0];
32
+ }
33
+ /**
34
+ * Returns an iterable of messages in the buffer in insertion order.
35
+ * @returns An iterable of messages.
36
+ */
37
+ values() {
38
+ return this.#stash.values();
39
+ }
40
+ /**
41
+ * Removes all messages from the buffer.
42
+ */
43
+ clear() {
44
+ this.#stash.length = 0;
45
+ }
46
+ /**
47
+ * Add one element to the end of the message buffer.
48
+ * @throws {StashOverflowError} if the buffer is full.
49
+ */
50
+ stash(msg) {
51
+ if (this.#stash.length >= this.capacity) {
52
+ throw new StashOverflowError(`Stash overflow: max capacity is ${this.capacity}`);
53
+ }
54
+ this.#stash.push(msg);
55
+ return this;
56
+ }
57
+ /**
58
+ * Request replay of up to `numberOfMessages` messages using `map`.
59
+ *
60
+ * If called while another unstash is in progress, it does not replay
61
+ * immediately; it just marks that another replay is requested.
62
+ *
63
+ * Once the current replay finishes, any pending requests are bundled
64
+ * and a single replay pass is run again.
65
+ */
66
+ unstash(behavior, options = {}) {
67
+ this.#pendingReplays.push(options);
68
+ if (this.#isReplaying)
69
+ return behavior;
70
+ this.#isReplaying = true;
71
+ return this.#unstashBehavior(behavior);
72
+ }
73
+ #unstashBehavior = (behavior) => {
74
+ let nextBehavior = behavior;
75
+ try {
76
+ while (this.#pendingReplays.length > 0 && this.#stash.length > 0) {
77
+ const { amount = Number.POSITIVE_INFINITY, map = identity } = this.#pendingReplays.shift();
78
+ const limit = Math.min(amount, this.#stash.length);
79
+ for (let index = 0; index < limit; index++) {
80
+ if (this.#stash.length === 0)
81
+ break;
82
+ nextBehavior = this.#context.delegate(nextBehavior, map(this.#stash.shift()));
83
+ }
25
84
  }
26
- },
27
- /** Drop all stashed messages */
28
- dropAll: () => {
29
- stack.length = 0;
30
- },
31
- /** Unstash all messages, sending them to the actor's mailbox */
32
- popAll: () => {
33
- stack.forEach((msg) => context.self.tell(msg));
34
- stack.length = 0;
35
- },
36
- /** Get current stash size */
37
- get size() {
38
- return stack.length;
39
- },
85
+ return nextBehavior;
86
+ }
87
+ finally {
88
+ this.#isReplaying = false;
89
+ this.#pendingReplays.length = 0;
90
+ }
40
91
  };
41
- context[$stash] = stash;
42
- return stash;
43
- };
92
+ }
93
+ const $noSuchElementError = "@@with-stash.no-such-element-error";
94
+ class NoSuchElementError extends Error {
95
+ static label = $noSuchElementError;
96
+ label = $noSuchElementError;
97
+ constructor() {
98
+ super("StashBuffer is empty");
99
+ this.name = "NoSuchElementError";
100
+ }
101
+ }
102
+ const $stashOverflowError = "@@with-stash.stash-overflow-error";
103
+ class StashOverflowError extends Error {
104
+ static label = $stashOverflowError;
105
+ label = $stashOverflowError;
106
+ constructor(message) {
107
+ super(message);
108
+ this.name = "StashOverflowError";
109
+ }
110
+ }
44
111
 
45
- export { useStash, withStash };
112
+ export { NoSuchElementError, StashBuffer, StashOverflowError, withStash };
@@ -5,7 +5,7 @@ interface Timers<T> {
5
5
  cancel(key: PropertyKey): void;
6
6
  cancelAll(): void;
7
7
  }
8
- declare const withTimers: <T>(factory: (timers: Timers<T>, context: ActorContext<T>) => behavior.Behavior<T>) => behavior.Folded<T>;
8
+ declare const withTimers: <T>(factory: (timers: Timers<T>, context: ActorContext<T>) => behavior.Behavior<T>) => behavior.FoldedBehavior<T>;
9
9
 
10
10
  export { withTimers };
11
11
  export type { Timers };
@@ -5,7 +5,7 @@ interface Timers<T> {
5
5
  cancel(key: PropertyKey): void;
6
6
  cancelAll(): void;
7
7
  }
8
- declare const withTimers: <T>(factory: (timers: Timers<T>, context: ActorContext<T>) => behavior.Behavior<T>) => behavior.Folded<T>;
8
+ declare const withTimers: <T>(factory: (timers: Timers<T>, context: ActorContext<T>) => behavior.Behavior<T>) => behavior.FoldedBehavior<T>;
9
9
 
10
10
  export { withTimers };
11
11
  export type { Timers };
@@ -5,13 +5,14 @@ import { setup } from './setup.js';
5
5
  const $timers = Symbol("timers");
6
6
  const withTimers = (factory) => setup((context) => {
7
7
  const timers = useTimers(context);
8
- const innerBehavior = factory(timers, context);
9
- return intercept(innerBehavior, (post) => {
10
- if (signal.isPostStop(post)) {
8
+ const interceptor = (msg, next) => {
9
+ const nextBehavior = next(msg);
10
+ if (signal.isPostStop(msg)) {
11
11
  timers.cancelAll();
12
12
  }
13
- return post;
14
- });
13
+ return nextBehavior;
14
+ };
15
+ return intercept(interceptor)(factory(timers, context));
15
16
  });
16
17
  const useTimers = (context) => {
17
18
  if (context[$timers])
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actor-system/behaviors",
3
- "version": "0.0.17",
3
+ "version": "0.0.18",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "type-check": "tsc -b src",
@@ -34,11 +34,11 @@
34
34
  "@actor-system/shared"
35
35
  ],
36
36
  "dependencies": {
37
- "@actor-system/core": "0.1.1"
37
+ "@actor-system/core": "0.1.2"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@actor-system/testing": "0.0.2",
41
- "@actor-system/shared": "0.0.2",
41
+ "@actor-system/shared": "0.0.3",
42
42
  "config": "^1.0.0"
43
43
  }
44
44
  }
package/dist/empty.d.ts DELETED
@@ -1,5 +0,0 @@
1
- import { behavior } from '@actor-system/core';
2
-
3
- declare const empty: behavior.Receive<never>;
4
-
5
- export { empty };
@@ -1,5 +0,0 @@
1
- import { behavior } from '@actor-system/core/internal';
2
-
3
- declare const empty: behavior.Receive<never>;
4
-
5
- export { empty };
package/dist/empty.js DELETED
@@ -1,5 +0,0 @@
1
- import { behavior } from '@actor-system/core';
2
-
3
- const empty = behavior._empty;
4
-
5
- export { empty };
package/dist/restart.d.ts DELETED
@@ -1,5 +0,0 @@
1
- import { behavior } from '@actor-system/core';
2
-
3
- declare const restart: <T>(checkpoint: behavior.Behavior<T>) => behavior.Control<T>;
4
-
5
- export { restart };
@@ -1,5 +0,0 @@
1
- import { behavior } from '@actor-system/core/internal';
2
-
3
- declare const restart: <T>(checkpoint: behavior.Behavior<T>) => behavior.Control<T>;
4
-
5
- export { restart };
package/dist/restart.js DELETED
@@ -1,11 +0,0 @@
1
- import { behavior, $type } from '@actor-system/core';
2
-
3
- const restart = (checkpoint) => ({
4
- [$type]: undefined,
5
- _tag: behavior.$control,
6
- _operation: "restart",
7
- _checkpoint: checkpoint,
8
- _name: "restart",
9
- });
10
-
11
- export { restart };
package/dist/same.d.ts DELETED
@@ -1,5 +0,0 @@
1
- import { behavior } from '@actor-system/core';
2
-
3
- declare const same: behavior.Control<never>;
4
-
5
- export { same };
@@ -1,5 +0,0 @@
1
- import { behavior } from '@actor-system/core/internal';
2
-
3
- declare const same: behavior.Control<never>;
4
-
5
- export { same };
package/dist/same.js DELETED
@@ -1,5 +0,0 @@
1
- import { behavior } from '@actor-system/core';
2
-
3
- const same = behavior._same;
4
-
5
- export { same };
package/dist/stopped.d.ts DELETED
@@ -1,5 +0,0 @@
1
- import { behavior } from '@actor-system/core';
2
-
3
- declare const stopped: behavior.Control<never>;
4
-
5
- export { stopped };
@@ -1,5 +0,0 @@
1
- import { behavior } from '@actor-system/core/internal';
2
-
3
- declare const stopped: behavior.Control<never>;
4
-
5
- export { stopped };
package/dist/stopped.js DELETED
@@ -1,10 +0,0 @@
1
- import { behavior, $type } from '@actor-system/core';
2
-
3
- const stopped = {
4
- [$type]: undefined,
5
- _tag: behavior.$control,
6
- _operation: "stop",
7
- _name: "stop",
8
- };
9
-
10
- export { stopped };
@@ -1,14 +0,0 @@
1
- import { behavior, ActorContext } from '@actor-system/core';
2
-
3
- /**
4
- * Supervision Decision Types
5
- */
6
- type SupervisionDecision = "restart" | "resume" | "stop" | "escalate";
7
- type SupervisionStrategy<T> = (error: unknown, ctx: ActorContext<T>) => SupervisionDecision;
8
- declare function supervise<T>(inner: behavior.Control<T>, strategy: SupervisionStrategy<T> | SupervisionDecision): behavior.Control<T>;
9
- declare function supervise<T>(inner: behavior.Receive<T>, strategy: SupervisionStrategy<T> | SupervisionDecision): behavior.Receive<T>;
10
- declare function supervise<T>(inner: behavior.Folded<T>, strategy: SupervisionStrategy<T> | SupervisionDecision): behavior.Folded<T>;
11
- declare function supervise<T>(inner: behavior.Behavior<T>, strategy: SupervisionStrategy<T> | SupervisionDecision): behavior.Behavior<T>;
12
-
13
- export { supervise };
14
- export type { SupervisionDecision, SupervisionStrategy };
@@ -1,14 +0,0 @@
1
- import { behavior, ActorContext } from '@actor-system/core/internal';
2
-
3
- /**
4
- * Supervision Decision Types
5
- */
6
- type SupervisionDecision = "restart" | "resume" | "stop" | "escalate";
7
- type SupervisionStrategy<T> = (error: unknown, ctx: ActorContext<T>) => SupervisionDecision;
8
- declare function supervise<T>(inner: behavior.Control<T>, strategy: SupervisionStrategy<T> | SupervisionDecision): behavior.Control<T>;
9
- declare function supervise<T>(inner: behavior.Receive<T>, strategy: SupervisionStrategy<T> | SupervisionDecision): behavior.Receive<T>;
10
- declare function supervise<T>(inner: behavior.Folded<T>, strategy: SupervisionStrategy<T> | SupervisionDecision): behavior.Folded<T>;
11
- declare function supervise<T>(inner: behavior.Behavior<T>, strategy: SupervisionStrategy<T> | SupervisionDecision): behavior.Behavior<T>;
12
-
13
- export { supervise };
14
- export type { SupervisionDecision, SupervisionStrategy };
package/dist/supervise.js DELETED
@@ -1,36 +0,0 @@
1
- import { behavior } from '@actor-system/core';
2
- import { restart } from './restart.js';
3
- import { stopped } from './stopped.js';
4
-
5
- function supervise(inner, strategy) {
6
- if (behavior.isControl(inner)) {
7
- return inner;
8
- }
9
- if (behavior.isFolded(inner)) {
10
- return behavior.folded((context) => supervise(behavior.unfold(inner, context), strategy));
11
- }
12
- if (behavior.isReceive(inner)) {
13
- return behavior.receive((message, context) => {
14
- try {
15
- const nextBehavior = inner._receive(message, context);
16
- return supervise(nextBehavior, strategy);
17
- }
18
- catch (error) {
19
- const decision = typeof strategy === "string" ? strategy : strategy(error, context);
20
- switch (decision) {
21
- case "restart":
22
- return restart(supervise(inner, strategy));
23
- case "resume":
24
- return supervise(inner, strategy);
25
- case "stop":
26
- return stopped;
27
- case "escalate":
28
- throw error;
29
- }
30
- }
31
- });
32
- }
33
- throw new Error(`Unknown behavior type: ${inner}`);
34
- }
35
-
36
- export { supervise };
@@ -1,5 +0,0 @@
1
- import { behavior } from '@actor-system/core';
2
-
3
- declare const unhandled: behavior.Control<never>;
4
-
5
- export { unhandled };
@@ -1,5 +0,0 @@
1
- import { behavior } from '@actor-system/core/internal';
2
-
3
- declare const unhandled: behavior.Control<never>;
4
-
5
- export { unhandled };
package/dist/unhandled.js DELETED
@@ -1,5 +0,0 @@
1
- import { behavior } from '@actor-system/core';
2
-
3
- const unhandled = behavior._unhandled;
4
-
5
- export { unhandled };