Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 2x 2x 2x 2x 2x | import { Subject, from, switchMap } from 'rxjs';
import { Bus } from '../bus/bus';
import { BusHandler } from './handler';
/**
* Prototype property decorator factory. This decorator **Publish**es a newly
* instantiated {@link Subject} under the supplied `handle` and assigns it to
* the decorated property. Depending on the value of the `suffix` parameter,
* this newly instantiated {@link Subject} is either assigned directly to the
* prototype and **Publish**ed using the supplied `handle`, or, if a truthy
* value is supplied for the `suffix` parameter, this value is assumed to
* reference another property of the class containing this decorated property.
* The first truthy value assigned to this `suffix` property on an instance of
* the class containing this **Publish** decorator will then be used to suffix
* the supplied `handle` upon **Publish**ment of the newly instantiated
* {@link Subject}, which is assigned to the decorated instance property.
*
* Through these two different modes of operation, the {@link Subject} that will
* be **Publish**ed can be assigned statically to the prototype of the class
* containing the decorated property, or this assignment can be deferred until
* an instance of the class containing the decorated property is constructed and
* a truthy value is assigned to its `suffix` property.
*
* This decorator is more or less the opposite of the {@link Observe} decorator,
* while both rely on the {@link BusHandler} to fulfill contracts. Furthermore,
* precautions should be taken to ensure the completion of the **Publish**ed
* {@link Subject} as memory leaks may occur due to dangling subscriptions.
*
* @param handle - The {@link Bus.Handle} to **Publish**.
* @param suffix - An optional `suffix` property for the `handle`.
* @returns A prototype property decorator.
*
* @example
* **Publish** the `'io.github.sgrud.example'` stream:
* ```ts
* import { Publish } from '@sgrud/bus';
* import { type Subject } from 'rxjs';
*
* export class Publisher {
*
* @Publish('io.github.sgrud.example')
* public readonly stream!: Subject<unknown>;
*
* }
*
* Publisher.prototype.stream.next('value');
* Publisher.prototype.stream.complete();
* ```
*
* @example
* **Publish** the `'io.github.sgrud.example'` stream:
* ```ts
* import { Publish } from '@sgrud/bus';
* import { type Subject } from 'rxjs';
*
* export class Publisher {
*
* @Publish('io.github.sgrud', 'suffix')
* public readonly stream: Subject<unknown>;
*
* public constructor(
* private readonly suffix: string
* ) {}
*
* }
*
* const publisher = new Publisher('example');
* publisher.stream.next('value');
* publisher.stream.complete();
* ```
*
* @see {@link BusHandler}
* @see {@link Observe}
* @see {@link Stream}
*/
export function Publish(handle: Bus.Handle, suffix?: PropertyKey) {
/**
* @param prototype - The `prototype` to be decorated.
* @param propertyKey - The `prototype` property to be decorated.
*/
return function(prototype: object, propertyKey: PropertyKey): void {
if (!suffix) {
const stream = new Subject<unknown>();
from(BusHandler).pipe(switchMap((handler) => {
return handler.publish(handle, stream);
})).subscribe();
Object.defineProperty(prototype, propertyKey, {
enumerable: true,
get: (): Subject<unknown> => stream,
set: Function.prototype as (...args: any[]) => any
});
} else {
Object.defineProperty(prototype, suffix, {
enumerable: true,
set(this: object, value: string): void {
if (value) {
const scoped = `${handle}.${value}` as Bus.Handle;
const stream = new Subject<unknown>();
from(BusHandler).pipe(switchMap((handler) => {
return handler.publish(scoped, stream);
})).subscribe();
Object.defineProperties(this, {
[suffix]: {
enumerable: true,
value
},
[propertyKey]: {
enumerable: true,
get: (): Subject<unknown> => stream,
set: Function.prototype as (...args: any[]) => any
}
});
}
}
});
}
};
}
|