@thi.ng/csp 2.1.115 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -1
- package/README.md +50 -183
- package/api.d.ts +12 -20
- package/channel.d.ts +37 -145
- package/channel.js +131 -480
- package/idgen.d.ts +3 -0
- package/idgen.js +5 -0
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/mult.d.ts +12 -20
- package/mult.js +42 -80
- package/ops.d.ts +23 -0
- package/ops.js +117 -0
- package/package.json +19 -17
- package/pubsub.d.ts +14 -20
- package/pubsub.js +32 -49
- package/buffer.d.ts +0 -24
- package/buffer.js +0 -67
package/mult.d.ts
CHANGED
|
@@ -1,25 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { Transducer } from "@thi.ng/transducers";
|
|
3
|
-
import type { IWriteableChannel } from "./api.js";
|
|
1
|
+
import type { IClosable, IWriteable } from "./api.js";
|
|
4
2
|
import { Channel } from "./channel.js";
|
|
5
|
-
export declare
|
|
6
|
-
|
|
3
|
+
export declare const mult: <T>(arg?: string | Channel<T>) => Mult<T>;
|
|
4
|
+
export declare class Mult<T> implements IWriteable<T>, IClosable {
|
|
7
5
|
protected src: Channel<any>;
|
|
8
|
-
protected taps:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
channel(): Channel<any>;
|
|
18
|
-
write(val: any): Promise<boolean>;
|
|
19
|
-
close(flush?: boolean): Promise<void> | undefined;
|
|
20
|
-
tap<R>(ch?: Channel<R> | Transducer<T, R>): Channel<R> | undefined;
|
|
21
|
-
untap(ch: Channel<any>): boolean;
|
|
22
|
-
untapAll(close?: boolean): boolean;
|
|
6
|
+
protected taps: Channel<any>[];
|
|
7
|
+
constructor(arg?: string | Channel<T>);
|
|
8
|
+
writable(): boolean;
|
|
9
|
+
write(val: T): Promise<boolean>;
|
|
10
|
+
close(): void;
|
|
11
|
+
closed(): boolean;
|
|
12
|
+
subscribe(ch?: Channel<T>): Channel<T>;
|
|
13
|
+
unsubscribe(ch: Channel<T>): boolean;
|
|
14
|
+
unsubscribeAll(close?: boolean): void;
|
|
23
15
|
protected process(): Promise<void>;
|
|
24
16
|
}
|
|
25
17
|
//# sourceMappingURL=mult.d.ts.map
|
package/mult.js
CHANGED
|
@@ -1,109 +1,71 @@
|
|
|
1
|
-
import { DCons } from "@thi.ng/dcons/dcons";
|
|
2
|
-
import { illegalArity } from "@thi.ng/errors/illegal-arity";
|
|
3
1
|
import { Channel } from "./channel.js";
|
|
2
|
+
import { __nextID } from "./idgen.js";
|
|
3
|
+
const mult = (arg) => new Mult(arg);
|
|
4
4
|
class Mult {
|
|
5
|
-
static nextID = 0;
|
|
6
5
|
src;
|
|
7
|
-
taps;
|
|
8
|
-
|
|
9
|
-
constructor(...args) {
|
|
6
|
+
taps = [];
|
|
7
|
+
constructor(arg) {
|
|
10
8
|
let id, src;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
id = args[0];
|
|
14
|
-
src = args[1];
|
|
15
|
-
break;
|
|
16
|
-
case 1:
|
|
17
|
-
if (typeof args[0] === "string") {
|
|
18
|
-
id = args[0];
|
|
19
|
-
} else {
|
|
20
|
-
src = args[0];
|
|
21
|
-
}
|
|
22
|
-
break;
|
|
23
|
-
case 0:
|
|
24
|
-
id = "mult" + Mult.nextID++;
|
|
25
|
-
break;
|
|
26
|
-
default:
|
|
27
|
-
illegalArity(args.length);
|
|
28
|
-
}
|
|
29
|
-
if (src instanceof Channel) {
|
|
30
|
-
this.src = src;
|
|
9
|
+
if (typeof arg === "string") {
|
|
10
|
+
id = arg;
|
|
31
11
|
} else {
|
|
32
|
-
|
|
12
|
+
src = arg;
|
|
33
13
|
}
|
|
34
|
-
this.
|
|
14
|
+
this.src = src instanceof Channel ? src : new Channel({ id: id ?? `mult${__nextID()}` });
|
|
35
15
|
this.process();
|
|
36
16
|
}
|
|
37
|
-
|
|
38
|
-
return this.src
|
|
39
|
-
}
|
|
40
|
-
set id(id) {
|
|
41
|
-
this.src && (this.src.id = id);
|
|
42
|
-
}
|
|
43
|
-
channel() {
|
|
44
|
-
return this.src;
|
|
17
|
+
writable() {
|
|
18
|
+
return this.src.writable();
|
|
45
19
|
}
|
|
46
20
|
write(val) {
|
|
47
|
-
|
|
48
|
-
return this.src.write(val);
|
|
49
|
-
}
|
|
50
|
-
return Promise.resolve(false);
|
|
21
|
+
return this.src.write(val);
|
|
51
22
|
}
|
|
52
|
-
close(
|
|
53
|
-
return this.src
|
|
23
|
+
close() {
|
|
24
|
+
return this.src.close();
|
|
54
25
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
26
|
+
closed() {
|
|
27
|
+
return this.src.closed();
|
|
28
|
+
}
|
|
29
|
+
subscribe(ch) {
|
|
30
|
+
if (!ch) {
|
|
31
|
+
ch = new Channel({
|
|
32
|
+
id: `${this.src.id}-tap${__nextID()}`
|
|
33
|
+
});
|
|
34
|
+
} else if (this.taps.includes(ch)) {
|
|
63
35
|
return ch;
|
|
64
36
|
}
|
|
37
|
+
this.taps.push(ch);
|
|
38
|
+
return ch;
|
|
65
39
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return true;
|
|
72
|
-
}
|
|
40
|
+
unsubscribe(ch) {
|
|
41
|
+
const idx = this.taps.indexOf(ch);
|
|
42
|
+
if (idx >= 0) {
|
|
43
|
+
this.taps.splice(idx, 1);
|
|
44
|
+
return true;
|
|
73
45
|
}
|
|
74
46
|
return false;
|
|
75
47
|
}
|
|
76
|
-
|
|
77
|
-
if (
|
|
78
|
-
let
|
|
79
|
-
|
|
80
|
-
close && tap.value.close();
|
|
81
|
-
this.taps.remove(tap);
|
|
82
|
-
tap = tap.next;
|
|
83
|
-
}
|
|
84
|
-
return true;
|
|
48
|
+
unsubscribeAll(close = true) {
|
|
49
|
+
if (close) {
|
|
50
|
+
for (let t of this.taps)
|
|
51
|
+
t.close();
|
|
85
52
|
}
|
|
86
|
-
|
|
53
|
+
this.taps.length = 0;
|
|
87
54
|
}
|
|
88
55
|
async process() {
|
|
89
56
|
let x;
|
|
90
|
-
while ((x =
|
|
91
|
-
let t
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
this.taps.remove(t);
|
|
57
|
+
while ((x = await this.src.read()) !== void 0) {
|
|
58
|
+
for (let t of this.taps) {
|
|
59
|
+
if (!await t.write(x)) {
|
|
60
|
+
this.unsubscribe(t);
|
|
95
61
|
}
|
|
96
|
-
t = t.next;
|
|
97
62
|
}
|
|
63
|
+
x = null;
|
|
98
64
|
}
|
|
99
|
-
|
|
100
|
-
await t.close();
|
|
101
|
-
}
|
|
102
|
-
delete this.src;
|
|
103
|
-
delete this.taps;
|
|
104
|
-
delete this.tapID;
|
|
65
|
+
this.unsubscribeAll();
|
|
105
66
|
}
|
|
106
67
|
}
|
|
107
68
|
export {
|
|
108
|
-
Mult
|
|
69
|
+
Mult,
|
|
70
|
+
mult
|
|
109
71
|
};
|
package/ops.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Fn2, Maybe } from "@thi.ng/api";
|
|
2
|
+
import type { IClosable, IWriteable } from "./api.js";
|
|
3
|
+
import { Channel } from "./channel.js";
|
|
4
|
+
export declare const broadcast: <T>(src: Channel<T>, dest: Channel<T>[], close?: boolean) => Promise<void>;
|
|
5
|
+
export declare const concat: <T>(dest: IWriteable<T> & IClosable, chans: Iterable<Channel<T>>, close?: boolean) => Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Consumes & collects all future values written to channel `chan` until
|
|
8
|
+
* closed or the max. number of values has been collected (whatever comes
|
|
9
|
+
* first). Returns a promise of the result array.
|
|
10
|
+
*
|
|
11
|
+
* @param chan
|
|
12
|
+
* @param res
|
|
13
|
+
* @param num
|
|
14
|
+
*/
|
|
15
|
+
export declare const consume: <T>(chan: Channel<T>, res?: T[], num?: number) => Promise<T[]>;
|
|
16
|
+
export declare const consumeWith: <T>(chan: Channel<T>, fn: Fn2<T, Channel<T>, void>, num?: number) => Promise<void>;
|
|
17
|
+
export declare const drain: <T>(chan: Channel<T>) => Promise<Awaited<T>[]>;
|
|
18
|
+
export declare const fromAsyncIterable: <T>(src: AsyncIterable<T>, close?: boolean) => Channel<T>;
|
|
19
|
+
export declare const merge: <T>(src: Channel<T>[], dest?: Channel<T>, close?: boolean) => Channel<T>;
|
|
20
|
+
export declare const pipe: <T, DEST extends IWriteable<T> & IClosable>(src: Channel<T>, dest: DEST, close?: boolean) => DEST;
|
|
21
|
+
export declare const select: <T>(input: Channel<T>, ...xs: Channel<T>[]) => Promise<[Maybe<T>, Channel<T>]>;
|
|
22
|
+
export declare const timeout: (delay: number) => Channel<any>;
|
|
23
|
+
//# sourceMappingURL=ops.d.ts.map
|
package/ops.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { assert } from "@thi.ng/errors/assert";
|
|
2
|
+
import { Channel } from "./channel.js";
|
|
3
|
+
const broadcast = async (src, dest, close = true) => {
|
|
4
|
+
for await (let x of src) {
|
|
5
|
+
for (let chan of dest)
|
|
6
|
+
chan.write(x);
|
|
7
|
+
}
|
|
8
|
+
if (close) {
|
|
9
|
+
for (let chan of dest)
|
|
10
|
+
chan.close();
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
const concat = async (dest, chans, close = true) => {
|
|
14
|
+
return (async () => {
|
|
15
|
+
for (let c of chans) {
|
|
16
|
+
await consumeWith(c, (x) => dest.write(x));
|
|
17
|
+
}
|
|
18
|
+
close && dest.close();
|
|
19
|
+
})();
|
|
20
|
+
};
|
|
21
|
+
const consume = async (chan, res = [], num = Infinity) => {
|
|
22
|
+
for (let n = 0; !chan.closed() && n < num; n++) {
|
|
23
|
+
const x = await chan.read();
|
|
24
|
+
if (x == void 0)
|
|
25
|
+
break;
|
|
26
|
+
res.push(x);
|
|
27
|
+
}
|
|
28
|
+
return res;
|
|
29
|
+
};
|
|
30
|
+
const consumeWith = async (chan, fn, num = Infinity) => {
|
|
31
|
+
for (let n = 0; !chan.closed() && n < num; n++) {
|
|
32
|
+
const x = await chan.read();
|
|
33
|
+
if (x == void 0)
|
|
34
|
+
break;
|
|
35
|
+
fn(x, chan);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const drain = async (chan) => await (async () => {
|
|
39
|
+
const ops = [];
|
|
40
|
+
for (let i = 0, n = chan.writes.length + chan.queue.length; i < n; i++) {
|
|
41
|
+
ops.push(chan.read());
|
|
42
|
+
}
|
|
43
|
+
return Promise.all(ops);
|
|
44
|
+
})();
|
|
45
|
+
const fromAsyncIterable = (src, close = true) => {
|
|
46
|
+
const chan = new Channel();
|
|
47
|
+
(async () => {
|
|
48
|
+
for await (let x of src) {
|
|
49
|
+
await chan.write(x);
|
|
50
|
+
if (!chan.writable())
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
close && chan.close();
|
|
54
|
+
})();
|
|
55
|
+
return chan;
|
|
56
|
+
};
|
|
57
|
+
const merge = (src, dest, close = true) => {
|
|
58
|
+
assert(src.length > 0, "no inputs given");
|
|
59
|
+
dest = dest || new Channel();
|
|
60
|
+
(async () => {
|
|
61
|
+
while (true) {
|
|
62
|
+
const [x, ch] = await select(...src);
|
|
63
|
+
if (x === void 0) {
|
|
64
|
+
src.splice(src.indexOf(ch), 1);
|
|
65
|
+
if (!src.length) {
|
|
66
|
+
close && dest.close();
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
await dest.write(x);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
})();
|
|
74
|
+
return dest;
|
|
75
|
+
};
|
|
76
|
+
const pipe = (src, dest, close = true) => {
|
|
77
|
+
(async () => {
|
|
78
|
+
for await (let x of src) {
|
|
79
|
+
await dest.write(x);
|
|
80
|
+
if (!dest.writable())
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
close && dest.close();
|
|
84
|
+
})();
|
|
85
|
+
return dest;
|
|
86
|
+
};
|
|
87
|
+
const select = async (input, ...xs) => {
|
|
88
|
+
const inputs = [input, ...xs];
|
|
89
|
+
const sel = await Promise.race(inputs.map((x) => x.race()));
|
|
90
|
+
for (let chan of inputs) {
|
|
91
|
+
if (chan !== sel)
|
|
92
|
+
chan.races.shift();
|
|
93
|
+
}
|
|
94
|
+
if (sel.writes.readable()) {
|
|
95
|
+
const [msg, write] = sel.writes.read();
|
|
96
|
+
write(true);
|
|
97
|
+
return [msg, sel];
|
|
98
|
+
}
|
|
99
|
+
return [void 0, sel];
|
|
100
|
+
};
|
|
101
|
+
const timeout = (delay) => {
|
|
102
|
+
const ch = new Channel();
|
|
103
|
+
setTimeout(() => ch.close(), delay);
|
|
104
|
+
return ch;
|
|
105
|
+
};
|
|
106
|
+
export {
|
|
107
|
+
broadcast,
|
|
108
|
+
concat,
|
|
109
|
+
consume,
|
|
110
|
+
consumeWith,
|
|
111
|
+
drain,
|
|
112
|
+
fromAsyncIterable,
|
|
113
|
+
merge,
|
|
114
|
+
pipe,
|
|
115
|
+
select,
|
|
116
|
+
timeout
|
|
117
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/csp",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "Primitives & operators for Communicating Sequential Processes based on async/await and async iterables",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
7
7
|
"typings": "./index.d.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"build": "yarn build:esbuild && yarn build:decl",
|
|
28
28
|
"build:decl": "tsc --declaration --emitDeclarationOnly",
|
|
29
29
|
"build:esbuild": "esbuild --format=esm --platform=neutral --target=es2022 --tsconfig=tsconfig.json --outdir=. src/**/*.ts",
|
|
30
|
-
"clean": "
|
|
30
|
+
"clean": "bun ../../tools/src/clean-package.ts",
|
|
31
31
|
"doc": "typedoc --excludePrivate --excludeInternal --out doc src/index.ts",
|
|
32
32
|
"doc:ae": "mkdir -p .ae/doc .ae/temp && api-extractor run --local --verbose",
|
|
33
33
|
"doc:readme": "bun ../../tools/src/module-stats.ts && bun ../../tools/src/readme.ts",
|
|
@@ -40,31 +40,31 @@
|
|
|
40
40
|
"tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@thi.ng/api": "^8.11.
|
|
44
|
-
"@thi.ng/
|
|
45
|
-
"@thi.ng/checks": "^3.6.
|
|
46
|
-
"@thi.ng/
|
|
47
|
-
"@thi.ng/errors": "^2.5.5",
|
|
48
|
-
"@thi.ng/transducers": "^9.0.2"
|
|
43
|
+
"@thi.ng/api": "^8.11.1",
|
|
44
|
+
"@thi.ng/buffers": "^0.1.2",
|
|
45
|
+
"@thi.ng/checks": "^3.6.3",
|
|
46
|
+
"@thi.ng/errors": "^2.5.6"
|
|
49
47
|
},
|
|
50
48
|
"devDependencies": {
|
|
51
49
|
"@microsoft/api-extractor": "^7.43.0",
|
|
52
50
|
"esbuild": "^0.20.2",
|
|
53
|
-
"rimraf": "^5.0.5",
|
|
54
51
|
"typedoc": "^0.25.12",
|
|
55
52
|
"typescript": "^5.4.3"
|
|
56
53
|
},
|
|
57
54
|
"keywords": [
|
|
58
55
|
"async",
|
|
56
|
+
"blocking",
|
|
59
57
|
"channel",
|
|
60
58
|
"communication",
|
|
61
59
|
"csp",
|
|
62
60
|
"datastructure",
|
|
61
|
+
"iterator",
|
|
62
|
+
"merge",
|
|
63
63
|
"multiplex",
|
|
64
|
+
"multitasking",
|
|
64
65
|
"pipeline",
|
|
65
66
|
"promise",
|
|
66
67
|
"pubsub",
|
|
67
|
-
"transducer",
|
|
68
68
|
"typescript"
|
|
69
69
|
],
|
|
70
70
|
"publishConfig": {
|
|
@@ -84,25 +84,27 @@
|
|
|
84
84
|
"./api": {
|
|
85
85
|
"default": "./api.js"
|
|
86
86
|
},
|
|
87
|
-
"./buffer": {
|
|
88
|
-
"default": "./buffer.js"
|
|
89
|
-
},
|
|
90
87
|
"./channel": {
|
|
91
88
|
"default": "./channel.js"
|
|
92
89
|
},
|
|
93
90
|
"./mult": {
|
|
94
91
|
"default": "./mult.js"
|
|
95
92
|
},
|
|
93
|
+
"./ops": {
|
|
94
|
+
"default": "./ops.js"
|
|
95
|
+
},
|
|
96
96
|
"./pubsub": {
|
|
97
97
|
"default": "./pubsub.js"
|
|
98
98
|
}
|
|
99
99
|
},
|
|
100
100
|
"thi.ng": {
|
|
101
101
|
"related": [
|
|
102
|
-
"
|
|
102
|
+
"fibers",
|
|
103
|
+
"rstream",
|
|
104
|
+
"transducers-async"
|
|
103
105
|
],
|
|
104
|
-
"status": "
|
|
106
|
+
"status": "beta",
|
|
105
107
|
"year": 2016
|
|
106
108
|
},
|
|
107
|
-
"gitHead": "
|
|
109
|
+
"gitHead": "aed3421c21044c005fbcb7cc37965ccf85a870d2\n"
|
|
108
110
|
}
|
package/pubsub.d.ts
CHANGED
|
@@ -1,35 +1,29 @@
|
|
|
1
1
|
import type { IObjectOf } from "@thi.ng/api";
|
|
2
|
-
import type {
|
|
3
|
-
import type { IWriteableChannel, TopicFn } from "./api.js";
|
|
2
|
+
import type { IClosable, IWriteable, TopicFn } from "./api.js";
|
|
4
3
|
import { Channel } from "./channel.js";
|
|
5
4
|
import { Mult } from "./mult.js";
|
|
6
|
-
export declare
|
|
7
|
-
|
|
5
|
+
export declare function pubsub<T>(fn: TopicFn<T>): PubSub<T>;
|
|
6
|
+
export declare function pubsub<T>(src: Channel<T>, fn: TopicFn<T>): PubSub<T>;
|
|
7
|
+
export declare class PubSub<T> implements IWriteable<T>, IClosable {
|
|
8
8
|
protected src: Channel<T>;
|
|
9
9
|
protected fn: TopicFn<T>;
|
|
10
10
|
protected topics: IObjectOf<Mult<T>>;
|
|
11
11
|
constructor(fn: TopicFn<T>);
|
|
12
12
|
constructor(src: Channel<T>, fn: TopicFn<T>);
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
close(flush?: boolean): Promise<void> | undefined;
|
|
13
|
+
writable(): boolean;
|
|
14
|
+
write(val: T): Promise<boolean>;
|
|
15
|
+
close(): void;
|
|
16
|
+
closed(): boolean;
|
|
18
17
|
/**
|
|
19
|
-
* Creates a new topic subscription channel and returns it.
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* only be applied to the new subscription channel.
|
|
23
|
-
*
|
|
24
|
-
* The special "*" topic can be used to subscribe to all messages and
|
|
25
|
-
* acts as multiplexed pass-through of the source channel.
|
|
18
|
+
* Creates a new topic subscription channel and returns it. Each topic is
|
|
19
|
+
* managed by its own {@link Mult} and can have arbitrary number of
|
|
20
|
+
* subscribers.
|
|
26
21
|
*
|
|
27
22
|
* @param id - topic id
|
|
28
|
-
* @param tx - transducer for new subscription
|
|
29
23
|
*/
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
subscribeTopic(id: string): Channel<T>;
|
|
25
|
+
unsubscribeTopic(id: string, ch: Channel<T>): boolean;
|
|
26
|
+
unsubscribeAll(id: string, close?: boolean): void;
|
|
33
27
|
protected process(): Promise<void>;
|
|
34
28
|
}
|
|
35
29
|
//# sourceMappingURL=pubsub.d.ts.map
|
package/pubsub.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { illegalArity } from "@thi.ng/errors/illegal-arity";
|
|
2
2
|
import { Channel } from "./channel.js";
|
|
3
3
|
import { Mult } from "./mult.js";
|
|
4
|
+
function pubsub(...args) {
|
|
5
|
+
return new PubSub(...args);
|
|
6
|
+
}
|
|
4
7
|
class PubSub {
|
|
5
|
-
static NEXT_ID = 0;
|
|
6
8
|
src;
|
|
7
9
|
fn;
|
|
8
10
|
topics;
|
|
@@ -13,7 +15,7 @@ class PubSub {
|
|
|
13
15
|
this.fn = args[1];
|
|
14
16
|
break;
|
|
15
17
|
case 1:
|
|
16
|
-
this.src = new Channel(
|
|
18
|
+
this.src = new Channel();
|
|
17
19
|
this.fn = args[0];
|
|
18
20
|
break;
|
|
19
21
|
default:
|
|
@@ -22,74 +24,55 @@ class PubSub {
|
|
|
22
24
|
this.topics = {};
|
|
23
25
|
this.process();
|
|
24
26
|
}
|
|
25
|
-
|
|
26
|
-
return this.src
|
|
27
|
-
}
|
|
28
|
-
set id(id) {
|
|
29
|
-
this.src && (this.src.id = id);
|
|
30
|
-
}
|
|
31
|
-
channel() {
|
|
32
|
-
return this.src;
|
|
27
|
+
writable() {
|
|
28
|
+
return this.src.writable();
|
|
33
29
|
}
|
|
34
30
|
write(val) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return
|
|
31
|
+
return this.src.write(val);
|
|
32
|
+
}
|
|
33
|
+
close() {
|
|
34
|
+
return this.src.close();
|
|
39
35
|
}
|
|
40
|
-
|
|
41
|
-
return this.src
|
|
36
|
+
closed() {
|
|
37
|
+
return this.src.closed();
|
|
42
38
|
}
|
|
43
39
|
/**
|
|
44
|
-
* Creates a new topic subscription channel and returns it.
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* only be applied to the new subscription channel.
|
|
48
|
-
*
|
|
49
|
-
* The special "*" topic can be used to subscribe to all messages and
|
|
50
|
-
* acts as multiplexed pass-through of the source channel.
|
|
40
|
+
* Creates a new topic subscription channel and returns it. Each topic is
|
|
41
|
+
* managed by its own {@link Mult} and can have arbitrary number of
|
|
42
|
+
* subscribers.
|
|
51
43
|
*
|
|
52
44
|
* @param id - topic id
|
|
53
|
-
* @param tx - transducer for new subscription
|
|
54
45
|
*/
|
|
55
|
-
|
|
46
|
+
subscribeTopic(id) {
|
|
56
47
|
let topic = this.topics[id];
|
|
57
48
|
if (!topic) {
|
|
58
|
-
this.topics[id] = topic = new Mult(this.src.id
|
|
49
|
+
this.topics[id] = topic = new Mult(`${this.src.id}-${id}`);
|
|
59
50
|
}
|
|
60
|
-
return topic.
|
|
51
|
+
return topic.subscribe();
|
|
61
52
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return topic.untap(ch);
|
|
66
|
-
}
|
|
67
|
-
return false;
|
|
53
|
+
unsubscribeTopic(id, ch) {
|
|
54
|
+
const topic = this.topics[id];
|
|
55
|
+
return topic?.unsubscribe(ch) ?? false;
|
|
68
56
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return topic.untapAll(close);
|
|
73
|
-
}
|
|
74
|
-
return false;
|
|
57
|
+
unsubscribeAll(id, close = true) {
|
|
58
|
+
const topic = this.topics[id];
|
|
59
|
+
topic?.unsubscribeAll(close);
|
|
75
60
|
}
|
|
76
61
|
async process() {
|
|
77
62
|
let x;
|
|
78
|
-
while ((x =
|
|
79
|
-
const id =
|
|
63
|
+
while ((x = await this.src.read()) !== void 0) {
|
|
64
|
+
const id = this.fn(x);
|
|
80
65
|
let topic = this.topics[id];
|
|
81
66
|
topic && await topic.write(x);
|
|
82
|
-
|
|
83
|
-
topic && await topic.write(x);
|
|
67
|
+
x = null;
|
|
84
68
|
}
|
|
85
|
-
for (let
|
|
86
|
-
|
|
69
|
+
for (let t of Object.values(this.topics)) {
|
|
70
|
+
t.close();
|
|
87
71
|
}
|
|
88
|
-
|
|
89
|
-
delete this.topics;
|
|
90
|
-
delete this.fn;
|
|
72
|
+
this.topics = {};
|
|
91
73
|
}
|
|
92
74
|
}
|
|
93
75
|
export {
|
|
94
|
-
PubSub
|
|
76
|
+
PubSub,
|
|
77
|
+
pubsub
|
|
95
78
|
};
|
package/buffer.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { DCons } from "@thi.ng/dcons/dcons";
|
|
2
|
-
import type { ChannelItem, IBuffer } from "./api.js";
|
|
3
|
-
export declare class FixedBuffer<T> implements IBuffer<T> {
|
|
4
|
-
buf: DCons<ChannelItem<T>>;
|
|
5
|
-
limit: number;
|
|
6
|
-
constructor(limit?: number);
|
|
7
|
-
get length(): number;
|
|
8
|
-
isEmpty(): boolean;
|
|
9
|
-
isFull(): boolean;
|
|
10
|
-
release(): boolean;
|
|
11
|
-
push(x: ChannelItem<T>): boolean;
|
|
12
|
-
drop(): ChannelItem<T> | undefined;
|
|
13
|
-
}
|
|
14
|
-
export declare class DroppingBuffer<T> extends FixedBuffer<T> {
|
|
15
|
-
constructor(limit?: number);
|
|
16
|
-
isFull(): boolean;
|
|
17
|
-
push(x: ChannelItem<T>): boolean;
|
|
18
|
-
}
|
|
19
|
-
export declare class SlidingBuffer<T> extends FixedBuffer<T> {
|
|
20
|
-
constructor(limit?: number);
|
|
21
|
-
isFull(): boolean;
|
|
22
|
-
push(x: ChannelItem<T>): boolean;
|
|
23
|
-
}
|
|
24
|
-
//# sourceMappingURL=buffer.d.ts.map
|