@cratis/arc 20.24.14 → 20.26.1

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 (54) hide show
  1. package/dist/cjs/index.d.ts +2 -1
  2. package/dist/cjs/index.d.ts.map +1 -1
  3. package/dist/cjs/index.js +8 -6
  4. package/dist/cjs/index.js.map +1 -1
  5. package/dist/cjs/messaging/IMessenger.d.ts +10 -0
  6. package/dist/cjs/messaging/IMessenger.d.ts.map +1 -0
  7. package/dist/cjs/messaging/IMessenger.js +7 -0
  8. package/dist/cjs/messaging/IMessenger.js.map +1 -0
  9. package/dist/cjs/messaging/Message.d.ts +7 -0
  10. package/dist/cjs/messaging/Message.d.ts.map +1 -0
  11. package/dist/cjs/messaging/Message.js +13 -0
  12. package/dist/cjs/messaging/Message.js.map +1 -0
  13. package/dist/cjs/messaging/Messenger.d.ts +20 -0
  14. package/dist/cjs/messaging/Messenger.d.ts.map +1 -0
  15. package/dist/cjs/messaging/Messenger.js +67 -0
  16. package/dist/cjs/messaging/Messenger.js.map +1 -0
  17. package/dist/cjs/messaging/for_Messenger/when_scoping_messages.d.ts +2 -0
  18. package/dist/cjs/messaging/for_Messenger/when_scoping_messages.d.ts.map +1 -0
  19. package/dist/cjs/messaging/index.d.ts +4 -0
  20. package/dist/cjs/messaging/index.d.ts.map +1 -0
  21. package/dist/cjs/messaging/index.js +12 -0
  22. package/dist/cjs/messaging/index.js.map +1 -0
  23. package/dist/esm/index.d.ts +2 -1
  24. package/dist/esm/index.d.ts.map +1 -1
  25. package/dist/esm/index.js +8 -6
  26. package/dist/esm/index.js.map +1 -1
  27. package/dist/esm/messaging/IMessenger.d.ts +10 -0
  28. package/dist/esm/messaging/IMessenger.d.ts.map +1 -0
  29. package/dist/esm/messaging/IMessenger.js +5 -0
  30. package/dist/esm/messaging/IMessenger.js.map +1 -0
  31. package/dist/esm/messaging/Message.d.ts +7 -0
  32. package/dist/esm/messaging/Message.d.ts.map +1 -0
  33. package/dist/esm/messaging/Message.js +11 -0
  34. package/dist/esm/messaging/Message.js.map +1 -0
  35. package/dist/esm/messaging/Messenger.d.ts +20 -0
  36. package/dist/esm/messaging/Messenger.d.ts.map +1 -0
  37. package/dist/esm/messaging/Messenger.js +65 -0
  38. package/dist/esm/messaging/Messenger.js.map +1 -0
  39. package/dist/esm/messaging/for_Messenger/when_scoping_messages.d.ts +2 -0
  40. package/dist/esm/messaging/for_Messenger/when_scoping_messages.d.ts.map +1 -0
  41. package/dist/esm/messaging/for_Messenger/when_scoping_messages.js +62 -0
  42. package/dist/esm/messaging/for_Messenger/when_scoping_messages.js.map +1 -0
  43. package/dist/esm/messaging/index.d.ts +4 -0
  44. package/dist/esm/messaging/index.d.ts.map +1 -0
  45. package/dist/esm/messaging/index.js +4 -0
  46. package/dist/esm/messaging/index.js.map +1 -0
  47. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  48. package/index.ts +2 -0
  49. package/messaging/IMessenger.ts +40 -0
  50. package/messaging/Message.ts +18 -0
  51. package/messaging/Messenger.ts +87 -0
  52. package/messaging/for_Messenger/when_scoping_messages.ts +74 -0
  53. package/messaging/index.ts +6 -0
  54. package/package.json +8 -2
package/index.ts CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  import * as commands from './commands';
5
5
  import * as identity from './identity';
6
+ import * as messaging from './messaging';
6
7
  import * as queries from './queries';
7
8
  import * as validation from './validation';
8
9
  import * as reflection from './reflection';
@@ -15,6 +16,7 @@ export * from './GetHttpHeaders';
15
16
  export {
16
17
  commands,
17
18
  identity,
19
+ messaging,
18
20
  queries,
19
21
  validation,
20
22
  reflection,
@@ -0,0 +1,40 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { Constructor } from '@cratis/fundamentals';
5
+ import { Subscription } from 'rxjs';
6
+
7
+ /**
8
+ * Represents a message handler.
9
+ */
10
+ export type MessageHandler<T> = (message: T) => void;
11
+
12
+ /**
13
+ * Defines a system for publishing and subscribing to messages.
14
+ */
15
+ export abstract class IMessenger {
16
+
17
+ /**
18
+ * Gets or sets whether published messages should bubble to the parent messenger.
19
+ * Defaults to false.
20
+ */
21
+ abstract bubbleToParent: boolean;
22
+
23
+ /**
24
+ * Gets or sets whether messages should trickle down to child messengers.
25
+ * Defaults to true.
26
+ */
27
+ abstract trickleDownToChildren: boolean;
28
+
29
+ /**
30
+ * Publish a message.
31
+ * @param {*} message Message to publish.
32
+ */
33
+ abstract publish<TMessage extends object>(message: TMessage): void;
34
+
35
+ /**
36
+ * Subscribe to a specific message type.
37
+ * @param {MessageHandler} callback Callback that gets called when message arrives.
38
+ */
39
+ abstract subscribe<TMessage extends object>(type: Constructor<TMessage>, callback: MessageHandler<TMessage>): Subscription;
40
+ }
@@ -0,0 +1,18 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { Constructor } from '@cratis/fundamentals';
5
+
6
+ /**
7
+ * Represents a message published on the {@link Messenger}.
8
+ */
9
+ export class Message {
10
+
11
+ /**
12
+ * Initializes a new instance of {@link Message}.
13
+ * @param {Constructor} type Type of the content in the message.
14
+ * @param {*} content The actual content.
15
+ */
16
+ constructor(readonly type: Constructor, readonly content: object) {
17
+ }
18
+ }
@@ -0,0 +1,87 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { Constructor } from '@cratis/fundamentals';
5
+ import { filter, Subject, Subscription } from 'rxjs';
6
+ import { IMessenger } from './IMessenger';
7
+ import { Message } from './Message';
8
+
9
+ /**
10
+ * Represents an implementation of {@link IMessenger}.
11
+ */
12
+ export class Messenger extends IMessenger {
13
+ bubbleToParent = false;
14
+ trickleDownToChildren = true;
15
+
16
+ private readonly _messages = new Subject<Message>();
17
+ private readonly _children = new Set<Messenger>();
18
+
19
+ constructor(private readonly _parent?: Messenger) {
20
+ super();
21
+ this._parent?._children.add(this);
22
+ }
23
+
24
+ /**
25
+ * Dispose this messenger and remove it from its parent.
26
+ */
27
+ dispose() {
28
+ this._parent?._children.delete(this);
29
+ }
30
+
31
+ /** @inheritdoc */
32
+ publish<TMessage extends object>(message: TMessage): void {
33
+ this._publishFromSelf(message);
34
+ }
35
+
36
+ /** @inheritdoc */
37
+ subscribe<TMessage extends object>(type: Constructor<TMessage>, callback: (message: TMessage) => void): Subscription {
38
+ const observable = this._messages.pipe(filter(m => m.type === type));
39
+ const subscription = observable.subscribe(m => callback(m.content as TMessage));
40
+ return subscription;
41
+ }
42
+
43
+ private _publishFromSelf<TMessage extends object>(message: TMessage) {
44
+ this._publishLocally(message);
45
+
46
+ if (this.bubbleToParent && this._parent) {
47
+ this._parent._publishFromChild(message, this);
48
+ }
49
+
50
+ if (this.trickleDownToChildren) {
51
+ this._publishToChildren(message);
52
+ }
53
+ }
54
+
55
+ private _publishFromParent<TMessage extends object>(message: TMessage) {
56
+ this._publishLocally(message);
57
+
58
+ if (this.trickleDownToChildren) {
59
+ this._publishToChildren(message);
60
+ }
61
+ }
62
+
63
+ private _publishFromChild<TMessage extends object>(message: TMessage, child: Messenger) {
64
+ this._publishLocally(message);
65
+
66
+ if (this.bubbleToParent && this._parent) {
67
+ this._parent._publishFromChild(message, this);
68
+ }
69
+
70
+ if (this.trickleDownToChildren) {
71
+ this._publishToChildren(message, child);
72
+ }
73
+ }
74
+
75
+ private _publishLocally<TMessage extends object>(message: TMessage) {
76
+ this._messages.next(new Message(message.constructor as Constructor, message));
77
+ }
78
+
79
+ private _publishToChildren<TMessage extends object>(message: TMessage, excludedChild?: Messenger) {
80
+ this._children.forEach(child => {
81
+ if (child === excludedChild) {
82
+ return;
83
+ }
84
+ child._publishFromParent(message);
85
+ });
86
+ }
87
+ }
@@ -0,0 +1,74 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { Messenger } from '../Messenger';
5
+
6
+ class MessageToSend {
7
+ constructor(readonly something: string) { }
8
+ }
9
+
10
+ describe('when scoping messages', () => {
11
+ let root: Messenger;
12
+ let child: Messenger;
13
+ let grandchild: Messenger;
14
+ let rootMessages: MessageToSend[];
15
+ let childMessages: MessageToSend[];
16
+ let grandchildMessages: MessageToSend[];
17
+
18
+ beforeEach(() => {
19
+ root = new Messenger();
20
+ child = new Messenger(root);
21
+ grandchild = new Messenger(child);
22
+ rootMessages = [];
23
+ childMessages = [];
24
+ grandchildMessages = [];
25
+
26
+ root.subscribe(MessageToSend, message => rootMessages.push(message));
27
+ child.subscribe(MessageToSend, message => childMessages.push(message));
28
+ grandchild.subscribe(MessageToSend, message => grandchildMessages.push(message));
29
+ });
30
+
31
+ afterEach(() => {
32
+ grandchild.dispose();
33
+ child.dispose();
34
+ root.dispose();
35
+ });
36
+
37
+ describe('and publishing from child with default options', () => {
38
+ beforeEach(() => child.publish(new MessageToSend('forty two')));
39
+
40
+ it('should publish locally', () => childMessages.length.should.equal(1));
41
+ it('should not bubble to parent', () => rootMessages.length.should.equal(0));
42
+ it('should trickle to child messengers', () => grandchildMessages.length.should.equal(1));
43
+ });
44
+
45
+ describe('and publishing from parent with default options', () => {
46
+ beforeEach(() => root.publish(new MessageToSend('forty two')));
47
+
48
+ it('should trickle recursively to child messengers', () => {
49
+ childMessages.length.should.equal(1);
50
+ grandchildMessages.length.should.equal(1);
51
+ });
52
+ });
53
+
54
+ describe('and child enables bubbling to parent', () => {
55
+ beforeEach(() => {
56
+ child.bubbleToParent = true;
57
+ child.publish(new MessageToSend('forty two'));
58
+ });
59
+
60
+ it('should bubble to parent', () => rootMessages.length.should.equal(1));
61
+ });
62
+
63
+ describe('and parent disables trickling to children', () => {
64
+ beforeEach(() => {
65
+ root.trickleDownToChildren = false;
66
+ root.publish(new MessageToSend('forty two'));
67
+ });
68
+
69
+ it('should not forward to any child messengers', () => {
70
+ childMessages.length.should.equal(0);
71
+ grandchildMessages.length.should.equal(0);
72
+ });
73
+ });
74
+ });
@@ -0,0 +1,6 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ export * from './IMessenger';
5
+ export * from './Message';
6
+ export * from './Messenger';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cratis/arc",
3
- "version": "20.24.14",
3
+ "version": "20.26.1",
4
4
  "description": "",
5
5
  "author": "Cratis",
6
6
  "license": "MIT",
@@ -36,6 +36,11 @@
36
36
  "import": "./dist/esm/identity/index.js",
37
37
  "require": "./dist/cjs/identity/index.js"
38
38
  },
39
+ "./messaging": {
40
+ "types": "./dist/esm/messaging/index.d.ts",
41
+ "import": "./dist/esm/messaging/index.js",
42
+ "require": "./dist/cjs/messaging/index.js"
43
+ },
39
44
  "./queries": {
40
45
  "types": "./dist/esm/queries/index.d.ts",
41
46
  "import": "./dist/esm/queries/index.js",
@@ -64,6 +69,7 @@
64
69
  "up": "yarn g:up"
65
70
  },
66
71
  "dependencies": {
67
- "@cratis/fundamentals": "^7.9.2"
72
+ "@cratis/fundamentals": "^7.9.2",
73
+ "rxjs": "^7.8.2"
68
74
  }
69
75
  }