@artstesh/postboy 3.5.0 β†’ 3.5.2

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/AI_SKILL.md ADDED
@@ -0,0 +1,229 @@
1
+ # AI_SKILL.md β€” @artstesh/postboy v3.5 (Context Document for AI Agents)
2
+
3
+ > Source of truth: `src/index.ts` + `src/**/*.ts` of this repository. This document targets **consumers** of the library (code written against `@artstesh/postboy`), not contributors.
4
+
5
+ ## 1. πŸš€ SCOPE & IMPORTS
6
+
7
+ `@artstesh/postboy` is a framework-agnostic, strongly-typed message bus for TypeScript. Use it for decoupled pub/sub (`fire`/`sub`), synchronous command execution (`exec`), async request/response (`fireCallback`), a staged middleware pipeline with cancellation, and namespaced feature registrators with lifecycle (`up`/`down`). Sole runtime dependency: `rxjs` >= 7 (peer dependency).
8
+
9
+ Package entry (dual-format build since 3.4, produced with `tsup`):
10
+
11
+ ```json
12
+ {
13
+ "main": "lib/index.cjs",
14
+ "module": "lib/index.mjs",
15
+ "types": "lib/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./lib/index.d.ts",
19
+ "import": "./lib/index.mjs",
20
+ "require": "./lib/index.cjs"
21
+ }
22
+ }
23
+ }
24
+ ```
25
+
26
+ ```ts
27
+ // ESM / TypeScript (named exports only β€” there is no default export)
28
+ import { PostboyService, PostboyGenericMessage, PostboyCallbackMessage, PostboyExecutor } from '@artstesh/postboy';
29
+
30
+ // CommonJS
31
+ const { PostboyService } = require('@artstesh/postboy');
32
+ ```
33
+
34
+ Everything below is exported from the package root: `PostboyService`, `PostboyAbstractRegistrator`, `MessageType`, `IPostboyDependingService`, `PostboyMessage`, `PostboyGenericMessage`, `PostboyCallbackMessage`, `PostboyExecutor`, `PostboyExecutionHandler`, `PostboyMiddleware`, `PostboySubscription`, `PostboyMessageMetadata`, `PostboyMessageContext`, `PostboyMiddlewareService`, `PostboyMessageStore`, `PostboyNamespaceStore`, the pipeline types (`MiddlewareStage`, `MiddlewareDecision`, `MiddlewareDecisionType`, `PipelineContext`, `PipelineResult`, `CancelDetails`, `CancelError`), and the infrastructure messages `AddMiddleware`, `RemoveMiddleware`, `AddNamespace`, `EliminateNamespace`, `ConnectMessage`, `ConnectExecutor`, `ConnectHandler`, `DisconnectMessage`, `LockMessage`, `UnlockMessage`.
35
+
36
+ ## 2. πŸ› οΈ CORE API REFERENCE
37
+
38
+ ### PostboyService
39
+
40
+ ```ts
41
+ class PostboyService {
42
+ constructor(resolver?: PostboyDependencyResolver) // omit in app code
43
+
44
+ // Messaging
45
+ fire(message: PostboyGenericMessage): void // throws CancelError if middleware interrupts; throws if type not registered
46
+ fireCallback<T>(message: PostboyCallbackMessage<T>, action?: (e: T) => void): Observable<T> // action is invoked exactly once per emitted value; without action the dispatch is lazy (see Β§4)
47
+ sub<T extends PostboyGenericMessage>(type: MessageType<T>): Observable<T>
48
+ once<T extends PostboyGenericMessage>(type: MessageType<T>): Observable<T> // = sub(type).pipe(first())
49
+ exec<T>(executor: PostboyExecutor<T>): T // synchronous; throws if executor not registered or cancelled
50
+ dispose(): void // disposes namespaces, store, middleware
51
+
52
+ // Bus mutations β€” @deprecated since v3; use exec(new XxxMessage(...)) equivalents below
53
+ record<T>(type: MessageType<T>, sub: Subject<T>): void
54
+ recordWithPipe<T>(type: MessageType<T>, sub: Subject<T>, pipe: (s: Subject<T>) => Observable<T>): void
55
+ recordExecutor<E extends PostboyExecutor<T>, T>(type: MessageType<E>, exec: (e: E) => T): void
56
+ recordHandler<E extends PostboyExecutor<R>, R>(executor: new (...a: any[]) => E, handler: PostboyExecutionHandler<R, E>): void
57
+ }
58
+ ```
59
+
60
+ > Removed in v3.5: `lock`, `unlock`, `addMiddleware`, `removeMiddleware`, `addNamespace`, `eliminateNamespace`, `unregister` no longer exist on `PostboyService` β€” the message-driven flow is the **only** way to perform these operations.
61
+
62
+ ### Infrastructure messages (the only way to mutate the bus)
63
+
64
+ All extend `PostboyExecutor<void>`-like executors, have a static readonly `ID`, and are dispatched via `postboy.exec(...)`:
65
+
66
+ | Message | Constructor | Purpose |
67
+ |---|---|---|
68
+ | `ConnectMessage<T>` | `(type: MessageType<T>, sub: Subject<T>, pipe?: (s: Subject<T>) => Observable<T>)` | register a message subject (replaces deprecated `record` / `recordWithPipe`) |
69
+ | `ConnectExecutor<E, T>` | `(type: MessageType<E>, exec: (e: E) => T)` | register an executor function (replaces `recordExecutor`) |
70
+ | `ConnectHandler<E, R>` | `(executor: new (...a: any[]) => E, handler: PostboyExecutionHandler<R, E>)` | register a handler object (replaces `recordHandler`) |
71
+ | `DisconnectMessage` | `(messageId: string)` β€” the static `ID` to remove; closes subscriptions and blocks further fire/sub |
72
+ | `AddMiddleware` / `RemoveMiddleware` | `(middleware: PostboyMiddleware)` | manage the middleware pipeline |
73
+ | `LockMessage<T>` / `UnlockMessage<T>` | `(type: MessageType<T>)` | locked message types are silently not dispatched (registration still works) |
74
+ | `AddNamespace` | `(space: string)` β€” returns the created `PostboyAbstractRegistrator` |
75
+ | `EliminateNamespace` | `(space: string)` |
76
+
77
+ ### Middleware pipeline (v3.5)
78
+
79
+ Middleware is an abstract class with a staged lifecycle. Every `fire` / `fireCallback` / `exec` passes through it:
80
+
81
+ ```ts
82
+ enum MiddlewareStage { Publish = 1, Callback, Execute }
83
+ enum MiddlewareDecisionType { Continue = 1, Interrupt }
84
+ interface MiddlewareDecision { type: MiddlewareDecisionType }
85
+ interface PipelineContext<T extends PostboyMessage = PostboyMessage> { stage: MiddlewareStage; message: T }
86
+
87
+ abstract class PostboyMiddleware {
88
+ readonly name: string; // defaults to class name
89
+ canHandle(context: PipelineContext): boolean // filter by stage/message; default true
90
+ before(context: PipelineContext): MiddlewareDecision // return { type: MiddlewareDecisionType.Interrupt } to CANCEL
91
+ after(context: PipelineContext, result?: unknown): void // post-hook; `result` set for the Execute stage
92
+ dispose(): void // called on removal / bus dispose
93
+ }
94
+
95
+ class CancelError extends Error { // thrown when a middleware interrupts
96
+ readonly details: CancelDetails; // { stage, middleware, messageId, namespace?, reason? }
97
+ name = 'PostboyCancelError';
98
+ }
99
+ ```
100
+
101
+ Key rules:
102
+
103
+ - An `Interrupt` returned from `before(...)` throws `CancelError` from `fire`/`exec`/`fireCallback` β€” the operation does NOT run and `after` hooks for it are not called.
104
+ - `canHandle` is consulted for both `before` and `after`; use `context.stage` to distinguish Publish/Callback/Execute.
105
+ - Middleware runs for infrastructure messages too β€” filter with `canHandle` if needed.
106
+ - Registration/removal via `exec(new AddMiddleware(mw))` / `exec(new RemoveMiddleware(mw))`; `RemoveMiddleware` calls `mw.dispose()`.
107
+
108
+ ### PostboyAbstractRegistrator
109
+
110
+ Groups registrations under a namespace; auto-disconnects everything on `down()`.
111
+
112
+ ```ts
113
+ abstract class PostboyAbstractRegistrator {
114
+ constructor(postboy: PostboyService, namespace?: string | null) // null β†’ generated id
115
+ get namespace(): string
116
+ registerServices(services: IPostboyDependingService[]): void
117
+ up(): void // calls abstract protected _up(), then services' up()
118
+ down(): void // calls services' down(), then exec(new DisconnectMessage(id)) for each recorded id
119
+ protected abstract _up(): void
120
+
121
+ // chainable (return this); NOT deprecated β€” internally use the v3 Connect* messages:
122
+ record<T>(type: MessageType<T>, sub: Subject<T>): this
123
+ recordWithPipe<T>(type, sub, pipe: (s: Subject<T>) => Observable<T>): this
124
+ recordExecutor<E extends PostboyExecutor<T>, T>(type: MessageType<E>, exec: (e: E) => T): this
125
+ recordHandler<E extends PostboyExecutor<R>, R>(executor: ctor, handler: PostboyExecutionHandler<R, E>): this
126
+ recordReplay<T>(type: MessageType<T>, bufferSize = 1): this // ReplaySubject
127
+ recordBehavior<T>(type: MessageType<T>, initial: T): this // BehaviorSubject
128
+ recordSubject<T>(type: MessageType<T>): this // plain Subject
129
+ }
130
+ ```
131
+
132
+ ## 3. πŸ“ TYPESCRIPT TYPES
133
+
134
+ ```ts
135
+ // Every message and executor MUST declare: static readonly ID = '<unique-string>';
136
+ type MessageType<T extends PostboyGenericMessage> = new (...args: any[]) => T;
137
+
138
+ abstract class PostboyMessage {
139
+ metadata: PostboyMessageMetadata;
140
+ get id(): string; // = constructor.ID
141
+ setMetadata(m: Partial<PostboyMessageMetadata>): this;
142
+ }
143
+ abstract class PostboyGenericMessage extends PostboyMessage {} // base for pub/sub messages
144
+ abstract class PostboyCallbackMessage<T> extends PostboyGenericMessage {
145
+ result: Observable<T>; // readonly observable over an internal Subject
146
+ next(value: T): void; // emit partial result
147
+ finish(value: T): void; // emit final value + complete
148
+ complete(): void;
149
+ }
150
+ abstract class PostboyExecutor<T> extends PostboyMessage {} // base for sync commands
151
+ abstract class PostboyExecutionHandler<R, E extends PostboyExecutor<R>> {
152
+ abstract handle(executor: E): R;
153
+ }
154
+
155
+ interface PostboyMessageMetadata { correlationId?: string; causationId?: string; tags?: Set<string>; [key: string]: any }
156
+ interface PostboyMessageContext { correlationId: string; currentMessageId: string; parentMessageId?: string; depth: number; startedAt: Date; tags?: Set<string> }
157
+ interface IPostboyDependingService { up(): void; down?(): void }
158
+ ```
159
+
160
+ Note: `PostboyContextService` exists in `src/services/` (correlation-context tracking based on `node:async_hooks`) but is **not exported** from the package root β€” do not reference it.
161
+
162
+ ## 4. πŸ’‘ BEST PRACTICES & IDIOMATIC USAGE
163
+
164
+ Canonical wiring order: **define class with static ID β†’ register (registrator or ConnectMessage) β†’ subscribe β†’ fire/exec**.
165
+
166
+ ```ts
167
+ import { PostboyService, PostboyGenericMessage, PostboyCallbackMessage, PostboyExecutor } from '@artstesh/postboy';
168
+ import { Subject } from 'rxjs';
169
+
170
+ // 1. Define messages (static ID is mandatory)
171
+ class PingMessage extends PostboyGenericMessage { static readonly ID = 'app.ping'; constructor(public text: string) { super(); } }
172
+ class FetchDataMessage extends PostboyCallbackMessage<string> { static readonly ID = 'app.fetch-data'; }
173
+ class GetDataExecutor extends PostboyExecutor<string> { static readonly ID = 'app.get-data'; }
174
+
175
+ const postboy = new PostboyService();
176
+
177
+ // 2. Register (v3 style β€” via infrastructure messages)
178
+ postboy.exec(new ConnectMessage(PingMessage, new Subject<PingMessage>()));
179
+ postboy.exec(new ConnectExecutor(GetDataExecutor, (e) => 'some-data'));
180
+
181
+ // 3. Subscribe / execute
182
+ postboy.sub(PingMessage).subscribe((m) => console.log(m.text));
183
+ postboy.fire(new PingMessage('hello'));
184
+ const data: string = postboy.exec(new GetDataExecutor()); // synchronous
185
+
186
+ // 4. Async request/response: the responder subscribes to the callback message and completes it
187
+ postboy.sub(FetchDataMessage).subscribe((m) => m.finish('payload'));
188
+ const result = await postboy.fireCallback(new FetchDataMessage()).toPromise(); // or firstValueFrom(...)
189
+
190
+ // 5. Feature-scoped registrator with lifecycle
191
+ class FeatureRegistrator extends PostboyAbstractRegistrator {
192
+ protected _up(): void { this.recordSubject(PingMessage); }
193
+ }
194
+ const reg = new FeatureRegistrator(postboy, 'feature-a');
195
+ reg.up(); // registrations active
196
+ reg.down(); // auto-disconnects everything recorded by this registrator
197
+ ```
198
+
199
+ Rules of composition:
200
+
201
+ - One registration per message ID; re-registering overwrites silently. Group a feature's registrations in one `PostboyAbstractRegistrator` subclass so `down()` cleans them all.
202
+ - Use `recordReplay` for "latest value on subscribe" semantics and `recordBehavior` for state; use `recordWithPipe`/`ConnectMessage` with a pipe for shared/debounced streams.
203
+ - Prefer registrators over bare `exec(new ConnectMessage(...))` in application code β€” they track IDs and dispose.
204
+ - Middleware: move validation/gating to `before` (return `Interrupt` to cancel), logging/side effects to `after`. Catch `CancelError` at call sites where cancellation is expected and check `error.details` (stage, middleware, messageId, reason).
205
+ - `fireCallback` with no `action` argument dispatches the message **lazily** β€” the subject fires only when the returned Observable is subscribed. Pass `action` (or subscribe immediately) when the request must be sent right away. When `action` IS passed, it is invoked exactly once per emitted value, no matter how many subscriptions the returned Observable has β€” do not add extra `subscribe(action)` calls on the result. `after` middleware hooks for the Callback stage fire on each result emission.
206
+ - Error handling: `checkId` throws `"<ClassName> should have a static ID field"`; `fire` throws for unregistered message IDs; `exec` throws for unregistered executor IDs (TypeError calling undefined). Wrap `exec`/`fire` in try/catch at call sites where registration is not guaranteed; treat a locked message as a no-op, not an error.
207
+
208
+ ## 5. ⚠️ ANTI-PATTERNS & PITFALLS
209
+
210
+ **Do NOT use these (common LLM hallucinations):**
211
+
212
+ - `postboy.lock(...)` / `unlock(...)` / `addMiddleware(...)` / `removeMiddleware(...)` / `addNamespace(...)` / `eliminateNamespace(...)` / `unregister(...)` β€” **removed in v3.5**, they no longer exist. Generate `exec(new LockMessage/UnlockMessage/AddMiddleware/RemoveMiddleware/AddNamespace/EliminateNamespace/DisconnectMessage(...))` instead.
213
+ - `postboy.record(...)`, `recordExecutor`, `recordHandler` β€” still present but `@deprecated`; generate `exec(new ConnectMessage/ConnectExecutor/ConnectHandler(...))` instead. (Exception: the chainable `record*` methods on `PostboyAbstractRegistrator` are NOT deprecated β€” use those.)
214
+ - Old single-hook middleware (`interface PostboyMiddleware { handle(message) }`) β€” replaced in v3.5 by the abstract class with `canHandle`/`before`/`after`/`dispose` and stage-based `PipelineContext`. There is no `handle()` anymore.
215
+ - `PostboyContextService` β€” not exported from the package root (and it depends on `node:async_hooks`, server-only). Do not import or emulate it.
216
+ - `postboy.subscribe(...)` / `postboy.on(...)` / `postboy.emit(...)` β€” do not exist. The verbs are `sub`, `once`, `fire`, `fireCallback`, `exec`.
217
+ - `new PostboyService(someConfig)` β€” the optional constructor arg is a `PostboyDependencyResolver`, not settings. Construct with no arguments.
218
+ - `PostboyMessage` without a static `ID` β€” `checkId` throws. `ID` must be `static readonly` on the class itself (inheriting a parent's `ID` causes ID collisions and cross-talk).
219
+ - Mocking helper assumptions: `postboy.sub(type)` returns `Observable<T>` (not a `Subject`). Do not call `.next()` on it.
220
+ - `isCancelError(...)` exists in sources but is not exported from the package root β€” use `error.name === 'PostboyCancelError'` or `error instanceof CancelError`.
221
+
222
+ **Hard constraints:**
223
+
224
+ - Never `fire`/`sub` a message before it is registered (throws / cold no-op respectively). Register in `up()` / module init, subscribe after.
225
+ - Never fire `LockMessage`/`DisconnectMessage` for infrastructure IDs you don't own β€” locked messages are silently dropped, which looks like data loss.
226
+ - Never reuse the same `ID` string across two message classes; all routing is keyed by static `ID`, not class identity.
227
+ - Never fire a callback message's `result` from outside: the responder calls `message.next/finish` in its `sub` handler; calling `fireCallback` again with the same instance re-subscribes `action`.
228
+ - Do not forget `registrator.down()` / `postboy.dispose()` on teardown β€” Subjects are not auto-completed otherwise. `dispose()` also calls `dispose()` on every registered middleware.
229
+ - `exec` is synchronous and returns `T` directly β€” do not `await` it or treat its result as an `Observable`. For async results use `PostboyCallbackMessage` + `fireCallback`.
package/README.md CHANGED
@@ -14,6 +14,8 @@ Modern web development often feels like a survival race: components are scattere
14
14
 
15
15
  Postboy doesn’t aim to replace NgRx or Akitaβ€”it solves a narrower set of problems but does so with minimal entry barriers.
16
16
 
17
+ > **Note for AI-assisted development:** the package ships with an `AI_SKILL.md` file (also available in the repository root) β€” a compact, up-to-date reference of the library's API, idiomatic usage patterns, and common pitfalls, written specifically for AI coding agents. If you use an AI assistant to work with `@artstesh/postboy`, feed it this file as context.
18
+
17
19
  ---
18
20
 
19
21
  ## 1.2. Core Concepts
package/lib/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var rxjs=require('rxjs');var d=class{constructor(){this.metadata={};}get id(){return this.constructor.ID}setMetadata(e){return this.metadata={...this.metadata,...e},this}};var P=class extends d{};function i(o){if(!o.ID)throw new Error(`${o.name} should have a static ID field`);return o.ID}var l=class{constructor(e,t){this.subscription=e;this._subscription=t?t(e):e.asObservable();}sub(){return this._subscription}fire(e){this.subscription.next(e);}finish(){this.subscription.complete();}};var M=(r=>(r[r.Publish=1]="Publish",r[r.Callback=2]="Callback",r[r.Execute=3]="Execute",r))(M||{});var j=(t=>(t[t.Continue=1]="Continue",t[t.Interrupt=2]="Interrupt",t))(j||{});var T=class extends Error{constructor(e){super(e.reason??`Postboy operation was cancelled at stage "${M[e.stage]}"`),this.name="PostboyCancelError",this.details=e;}};var E=class{constructor(){this.middlewares=[];}addMiddleware(e){this.middlewares.push(e);}removeMiddleware(e){this.middlewares=this.middlewares.filter(t=>t!==e?true:(t.dispose(),false));}dispose(){this.middlewares.forEach(e=>e.dispose()),this.middlewares=[];}before(e,t){for(let r of this.middlewares){let a=this.buildContext(e,t);r.canHandle(a)&&r.before(a).type===2&&this.throwIfCancelled(e,r.name,t.id);}}after(e,t,r){for(let a of this.middlewares){let g=this.buildContext(e,t);a.canHandle(g)&&a.after(g,r);}}beforePublish(e){this.before(1,e);}afterPublish(e){this.after(1,e);}beforeCallback(e){this.before(2,e);}afterCallback(e,t){this.after(2,e,t);}beforeExecute(e){this.before(3,e);}afterExecute(e,t){this.after(3,e,t);}buildContext(e,t){return {stage:e,message:t}}throwIfCancelled(e,t,r,a){throw new T({stage:e,middleware:t,messageId:r,namespace:a,reason:t?`Cancelled by middleware "${t}"`:void 0})}};var w=class{constructor(){this.messages=new Map;this.executors=new Map;this.callbacks=new Map;}registerMessage(e,t){this.messages.has(e)&&console.warn(`Message with id ${e} already registered. Overriding...`),this.messages.set(e,t);}registerExecutor(e,t){this.executors.has(e)&&console.warn(`Executor with id ${e} already registered. Overriding...`),this.executors.set(e,t);}callbackFired(e){let t=this.callbacks.get(e.id);t?t.push(()=>e.complete()):this.callbacks.set(e.id,[()=>e.complete()]);}getMessage(e,t){let r=this.messages.get(e);if(!r)throw new Error(`There is no registered event ${t}`);return r}getExecutor(e){let t=this.executors.get(e);if(!t)throw new Error(`There is no registered executor with id ${e}`);return t}unregister(e){this.messages.get(e)?.finish(),this.messages.delete(e),this.callbacks.get(e)?.forEach(t=>t()),this.callbacks.delete(e),this.executors.delete(e);}dispose(){this.messages.forEach((e,t)=>this.unregister(t)),this.callbacks.forEach(e=>e.forEach(t=>t())),this.messages.clear(),this.executors.clear(),this.callbacks.clear();}};var C=class C{static get(){let e=[];for(let t=0;t<7;t++)e.push(C.collection.sort(()=>.5-Math.random()).slice(0,5).join(""));return e.join("-")}};C.collection="ABCDEFGHIJKLMNOPQRSTUVWXTZ0123456789".split("");var S=C;var s=class extends d{};var c=class extends s{constructor(t,r,a){super();this.type=t;this.sub=r;this.pipe=a;}};c.ID="aa03a192-bdc7-402d-9f2f-bf3748229ea2";var n=class extends s{constructor(t){super();this.messageId=t;}};n.ID="94579e43-5bc9-4517-bcda-b595bcda1ae7";var p=class extends s{constructor(t,r){super();this.type=t;this.exec=r;}};p.ID="cb80e8ad-b68c-4b2d-8c44-617ea6017cb3";var b=class extends s{constructor(t,r){super();this.executor=t;this.handler=r;}};b.ID="bf618cea-6f32-417c-9548-8eafe937378b";var D=class{constructor(e,t=null){this.postboy=e;this.ids=[];this.services=[];this._namespace=t??S.get();}get namespace(){return this._namespace}registerServices(e){this.services=e;}up(){this._up?.(),this.services.forEach(e=>e.up());}down(){this.services.forEach(e=>!!e.down&&e.down()),this.services=[],this.ids.forEach(e=>this.postboy.exec(new n(e)));}record(e,t){return this.ids.push(i(e)),this.postboy.exec(new c(e,t)),this}recordWithPipe(e,t,r){return this.ids.push(i(e)),this.postboy.exec(new c(e,t,r)),this}recordExecutor(e,t){return this.ids.push(i(e)),this.postboy.exec(new p(e,t)),this}recordHandler(e,t){return this.ids.push(i(e)),this.postboy.exec(new b(e,t)),this}recordReplay(e,t=1){return this.record(e,new rxjs.ReplaySubject(t)),this}recordBehavior(e,t){return this.record(e,new rxjs.BehaviorSubject(t)),this}recordSubject(e){return this.record(e,new rxjs.Subject),this}};var I=class extends D{constructor(e){super(e);}_up(){}};var v=class{constructor(){this.spaces=new Map;}addSpace(e,t){if(this.spaces.has(e))return this.spaces.get(e);let r=new I(t);return this.spaces.set(e,r),r}eliminateSpace(e){this.spaces.has(e)&&(this.spaces.get(e)?.down(),this.spaces.delete(e));}dispose(){this.spaces.forEach(e=>e.down()),this.spaces.clear();}};var R=class{constructor(){this.getMiddlewareService=()=>new E;this.getMessageStore=()=>new w;this.getNamespaceStore=()=>new v;}};var u=class extends s{constructor(t){super();this.space=t;}};u.ID="6d1a6f7d-6b6e-4c4d-8af8-9cc9a32e850c";var m=class extends s{constructor(t){super();this.space=t;}};m.ID="03bb03bb-53e0-4b74-9aad-64d5c54a8972";var f=class extends s{constructor(t){super();this.middleware=t;}};f.ID="0a8cfe0a-6193-4082-8440-d0793367b21d";var x=class extends s{constructor(t){super();this.middleware=t;}};x.ID="c25c708c-53c9-498d-a28b-936fbaf68b91";var y=class extends s{constructor(t){super();this.type=t;}};y.ID="477df3e2-1f99-4476-9a3b-afd1fa426436";var h=class extends s{constructor(t){super();this.type=t;}};h.ID="d71d25e3-90ac-4009-b972-9e6c6b05611e";var H=class{constructor(e){this.locked=new Set;this.dependencyResolver=e||new R,this.middleware=this.dependencyResolver.getMiddlewareService(),this.store=this.dependencyResolver.getMessageStore(),this.namespaceStore=this.dependencyResolver.getNamespaceStore(),this.registerInfrastructureMessages();}registerInfrastructureMessages(){this.store.registerExecutor(n.ID,e=>this.store.unregister(e.messageId)),this.store.registerExecutor(h.ID,e=>this.locked.delete(i(e.type))),this.store.registerExecutor(y.ID,e=>this.locked.add(i(e.type))),this.store.registerExecutor(f.ID,e=>this.middleware.addMiddleware(e.middleware)),this.store.registerExecutor(x.ID,e=>this.middleware.removeMiddleware(e.middleware)),this.store.registerExecutor(u.ID,e=>this.namespaceStore.addSpace(e.space,this)),this.store.registerExecutor(m.ID,e=>this.namespaceStore.eliminateSpace(e.space)),this.store.registerExecutor(c.ID,e=>{let{type:t,sub:r,pipe:a}=e;this.store.registerMessage(i(t),new l(r,a));}),this.store.registerExecutor(p.ID,e=>{let{type:t,exec:r}=e;this.store.registerExecutor(i(t),r);}),this.store.registerExecutor(b.ID,e=>{let{executor:t,handler:r}=e;this.store.registerExecutor(i(t),a=>r.handle(a));});}fire(e){this.middleware.beforePublish(e),this.locked.has(e.id)||this.store.getMessage(e.id,e.constructor.name).fire(e),this.middleware.afterPublish(e);}fireCallback(e,t){this.middleware.beforeCallback(e),t&&e.result.subscribe(t),this.store.callbackFired(e);let r=t?e.result.pipe(rxjs.tap(t)):e.result,a=this.store.getMessage(e.id,e.constructor.name),g=new rxjs.Observable($=>{let _=r.pipe(rxjs.tap(()=>this.middleware.afterCallback(e))).subscribe($);return this.locked.has(e.id)||a.fire(e),()=>_.unsubscribe()});return t&&g.subscribe(),g}exec(e){this.middleware.beforeExecute(e);let t=this.store.getExecutor(e.id)(e);return this.middleware.afterExecute(e,t),t}sub(e){return this.store.getMessage(i(e),e.name).sub()}once(e){return this.sub(e).pipe(rxjs.first())}record(e,t){this.store.registerMessage(i(e),new l(t,r=>r.asObservable()));}recordWithPipe(e,t,r){this.store.registerMessage(i(e),new l(t,r));}recordExecutor(e,t){this.store.registerExecutor(i(e),t);}recordHandler(e,t){this.store.registerExecutor(i(e),r=>t.handle(r));}dispose(){this.namespaceStore?.dispose(),this.store.dispose(),this.middleware.dispose();}};var A=class{constructor(e){this.name=e??this.constructor.name;}canHandle(e){return true}before(e){return {type:1}}after(e,t){}dispose(){}};var k=class extends P{constructor(){super(...arguments);this.result$=new rxjs.Subject;this.result=this.result$.asObservable();this.next=t=>this.result$.next(t);}finish(t){this.result$.next(t),this.result$.complete();}complete(){this.result$.complete();}};var O=class{};exports.AddMiddleware=f;exports.AddNamespace=u;exports.CancelError=T;exports.ConnectExecutor=p;exports.ConnectHandler=b;exports.ConnectMessage=c;exports.DisconnectMessage=n;exports.EliminateNamespace=m;exports.LockMessage=y;exports.MiddlewareDecisionType=j;exports.MiddlewareStage=M;exports.PostboyAbstractRegistrator=D;exports.PostboyCallbackMessage=k;exports.PostboyExecutionHandler=O;exports.PostboyExecutor=s;exports.PostboyGenericMessage=P;exports.PostboyMessage=d;exports.PostboyMessageStore=w;exports.PostboyMiddleware=A;exports.PostboyMiddlewareService=E;exports.PostboyNamespaceStore=v;exports.PostboyService=H;exports.PostboySubscription=l;exports.RemoveMiddleware=x;exports.UnlockMessage=h;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var rxjs=require('rxjs');var d=class{constructor(){this.metadata={};}get id(){return this.constructor.ID}setMetadata(e){return this.metadata={...this.metadata,...e},this}};var g=class extends d{};function i(s){if(!s.ID)throw new Error(`${s.name} should have a static ID field`);return s.ID}var l=class{constructor(e,t){this.subscription=e;this._subscription=t?t(e):e.asObservable();}sub(){return this._subscription}fire(e){this.subscription.next(e);}finish(){this.subscription.complete();}};var M=(r=>(r[r.Publish=1]="Publish",r[r.Callback=2]="Callback",r[r.Execute=3]="Execute",r))(M||{});var j=(t=>(t[t.Continue=1]="Continue",t[t.Interrupt=2]="Interrupt",t))(j||{});var P=class extends Error{constructor(e){super(e.reason??`Postboy operation was cancelled at stage "${M[e.stage]}"`),this.name="PostboyCancelError",this.details=e;}};var E=class{constructor(){this.middlewares=[];}addMiddleware(e){this.middlewares.push(e);}removeMiddleware(e){this.middlewares=this.middlewares.filter(t=>t!==e?true:(t.dispose(),false));}dispose(){this.middlewares.forEach(e=>e.dispose()),this.middlewares=[];}before(e,t){for(let r of this.middlewares){let a=this.buildContext(e,t);r.canHandle(a)&&r.before(a).type===2&&this.throwIfCancelled(e,r.name,t.id);}}after(e,t,r){for(let a of this.middlewares){let v=this.buildContext(e,t);a.canHandle(v)&&a.after(v,r);}}beforePublish(e){this.before(1,e);}afterPublish(e){this.after(1,e);}beforeCallback(e){this.before(2,e);}afterCallback(e,t){this.after(2,e,t);}beforeExecute(e){this.before(3,e);}afterExecute(e,t){this.after(3,e,t);}buildContext(e,t){return {stage:e,message:t}}throwIfCancelled(e,t,r,a){throw new P({stage:e,middleware:t,messageId:r,namespace:a,reason:t?`Cancelled by middleware "${t}"`:void 0})}};var w=class{constructor(){this.messages=new Map;this.executors=new Map;this.callbacks=new Map;}registerMessage(e,t){this.messages.has(e)&&console.warn(`Message with id ${e} already registered. Overriding...`),this.messages.set(e,t);}registerExecutor(e,t){this.executors.has(e)&&console.warn(`Executor with id ${e} already registered. Overriding...`),this.executors.set(e,t);}callbackFired(e){let t=this.callbacks.get(e.id);t?t.push(()=>e.complete()):this.callbacks.set(e.id,[()=>e.complete()]);}getMessage(e,t){let r=this.messages.get(e);if(!r)throw new Error(`There is no registered event ${t}`);return r}getExecutor(e){let t=this.executors.get(e);if(!t)throw new Error(`There is no registered executor with id ${e}`);return t}unregister(e){this.messages.get(e)?.finish(),this.messages.delete(e),this.callbacks.get(e)?.forEach(t=>t()),this.callbacks.delete(e),this.executors.delete(e);}dispose(){this.messages.forEach((e,t)=>this.unregister(t)),this.callbacks.forEach(e=>e.forEach(t=>t())),this.messages.clear(),this.executors.clear(),this.callbacks.clear();}};var C=class C{static get(){let e=[];for(let t=0;t<7;t++)e.push(C.collection.sort(()=>.5-Math.random()).slice(0,5).join(""));return e.join("-")}};C.collection="ABCDEFGHIJKLMNOPQRSTUVWXTZ0123456789".split("");var S=C;var o=class extends d{};var c=class extends o{constructor(t,r,a){super();this.type=t;this.sub=r;this.pipe=a;}};c.ID="aa03a192-bdc7-402d-9f2f-bf3748229ea2";var n=class extends o{constructor(t){super();this.messageId=t;}};n.ID="94579e43-5bc9-4517-bcda-b595bcda1ae7";var p=class extends o{constructor(t,r){super();this.type=t;this.exec=r;}};p.ID="cb80e8ad-b68c-4b2d-8c44-617ea6017cb3";var b=class extends o{constructor(t,r){super();this.executor=t;this.handler=r;}};b.ID="bf618cea-6f32-417c-9548-8eafe937378b";var D=class{constructor(e,t=null){this.postboy=e;this.ids=[];this.services=[];this._namespace=t??S.get();}get namespace(){return this._namespace}registerServices(e){this.services=e;}up(){this._up?.(),this.services.forEach(e=>e.up());}down(){this.services.forEach(e=>!!e.down&&e.down()),this.services=[],this.ids.forEach(e=>this.postboy.exec(new n(e)));}record(e,t){return this.ids.push(i(e)),this.postboy.exec(new c(e,t)),this}recordWithPipe(e,t,r){return this.ids.push(i(e)),this.postboy.exec(new c(e,t,r)),this}recordExecutor(e,t){return this.ids.push(i(e)),this.postboy.exec(new p(e,t)),this}recordHandler(e,t){return this.ids.push(i(e)),this.postboy.exec(new b(e,t)),this}recordReplay(e,t=1){return this.record(e,new rxjs.ReplaySubject(t)),this}recordBehavior(e,t){return this.record(e,new rxjs.BehaviorSubject(t)),this}recordSubject(e){return this.record(e,new rxjs.Subject),this}};var I=class extends D{constructor(e){super(e);}_up(){}};var T=class{constructor(){this.spaces=new Map;}addSpace(e,t){if(this.spaces.has(e))return this.spaces.get(e);let r=new I(t);return this.spaces.set(e,r),r}eliminateSpace(e){this.spaces.has(e)&&(this.spaces.get(e)?.down(),this.spaces.delete(e));}dispose(){this.spaces.forEach(e=>e.down()),this.spaces.clear();}};var R=class{constructor(){this.getMiddlewareService=()=>new E;this.getMessageStore=()=>new w;this.getNamespaceStore=()=>new T;}};var u=class extends o{constructor(t){super();this.space=t;}};u.ID="6d1a6f7d-6b6e-4c4d-8af8-9cc9a32e850c";var m=class extends o{constructor(t){super();this.space=t;}};m.ID="03bb03bb-53e0-4b74-9aad-64d5c54a8972";var f=class extends o{constructor(t){super();this.middleware=t;}};f.ID="0a8cfe0a-6193-4082-8440-d0793367b21d";var x=class extends o{constructor(t){super();this.middleware=t;}};x.ID="c25c708c-53c9-498d-a28b-936fbaf68b91";var y=class extends o{constructor(t){super();this.type=t;}};y.ID="477df3e2-1f99-4476-9a3b-afd1fa426436";var h=class extends o{constructor(t){super();this.type=t;}};h.ID="d71d25e3-90ac-4009-b972-9e6c6b05611e";var G=class{constructor(e){this.locked=new Set;this.dependencyResolver=e||new R,this.middleware=this.dependencyResolver.getMiddlewareService(),this.store=this.dependencyResolver.getMessageStore(),this.namespaceStore=this.dependencyResolver.getNamespaceStore(),this.registerInfrastructureMessages();}registerInfrastructureMessages(){this.store.registerExecutor(n.ID,e=>this.store.unregister(e.messageId)),this.store.registerExecutor(h.ID,e=>this.locked.delete(i(e.type))),this.store.registerExecutor(y.ID,e=>this.locked.add(i(e.type))),this.store.registerExecutor(f.ID,e=>this.middleware.addMiddleware(e.middleware)),this.store.registerExecutor(x.ID,e=>this.middleware.removeMiddleware(e.middleware)),this.store.registerExecutor(u.ID,e=>this.namespaceStore.addSpace(e.space,this)),this.store.registerExecutor(m.ID,e=>this.namespaceStore.eliminateSpace(e.space)),this.store.registerExecutor(c.ID,e=>{let{type:t,sub:r,pipe:a}=e;this.store.registerMessage(i(t),new l(r,a));}),this.store.registerExecutor(p.ID,e=>{let{type:t,exec:r}=e;this.store.registerExecutor(i(t),r);}),this.store.registerExecutor(b.ID,e=>{let{executor:t,handler:r}=e;this.store.registerExecutor(i(t),a=>r.handle(a));});}fire(e){this.middleware.beforePublish(e),this.locked.has(e.id)||this.store.getMessage(e.id,e.constructor.name).fire(e),this.middleware.afterPublish(e);}fireCallback(e,t){this.middleware.beforeCallback(e),this.store.callbackFired(e),t&&e.result.subscribe(t);let r=this.store.getMessage(e.id,e.constructor.name),a=new rxjs.Observable(v=>{let H=e.result.pipe(rxjs.tap(()=>this.middleware.afterCallback(e))).subscribe(v);return this.locked.has(e.id)||r.fire(e),()=>H.unsubscribe()});return t&&a.subscribe(),a}exec(e){this.middleware.beforeExecute(e);let t=this.store.getExecutor(e.id)(e);return this.middleware.afterExecute(e,t),t}sub(e){return this.store.getMessage(i(e),e.name).sub()}once(e){return this.sub(e).pipe(rxjs.first())}record(e,t){this.store.registerMessage(i(e),new l(t,r=>r.asObservable()));}recordWithPipe(e,t,r){this.store.registerMessage(i(e),new l(t,r));}recordExecutor(e,t){this.store.registerExecutor(i(e),t);}recordHandler(e,t){this.store.registerExecutor(i(e),r=>t.handle(r));}dispose(){this.namespaceStore?.dispose(),this.store.dispose(),this.middleware.dispose();}};var A=class{constructor(e){this.name=e??this.constructor.name;}canHandle(e){return true}before(e){return {type:1}}after(e,t){}dispose(){}};var k=class extends g{constructor(){super(...arguments);this.result$=new rxjs.Subject;this.result=this.result$.asObservable();this.next=t=>this.result$.next(t);}finish(t){this.result$.next(t),this.result$.complete();}complete(){this.result$.complete();}};var O=class{};exports.AddMiddleware=f;exports.AddNamespace=u;exports.CancelError=P;exports.ConnectExecutor=p;exports.ConnectHandler=b;exports.ConnectMessage=c;exports.DisconnectMessage=n;exports.EliminateNamespace=m;exports.LockMessage=y;exports.MiddlewareDecisionType=j;exports.MiddlewareStage=M;exports.PostboyAbstractRegistrator=D;exports.PostboyCallbackMessage=k;exports.PostboyExecutionHandler=O;exports.PostboyExecutor=o;exports.PostboyGenericMessage=g;exports.PostboyMessage=d;exports.PostboyMessageStore=w;exports.PostboyMiddleware=A;exports.PostboyMiddlewareService=E;exports.PostboyNamespaceStore=T;exports.PostboyService=G;exports.PostboySubscription=l;exports.RemoveMiddleware=x;exports.UnlockMessage=h;//# sourceMappingURL=index.cjs.map
2
2
  //# sourceMappingURL=index.cjs.map