@player-ui/pubsub-plugin 0.8.0--canary.307.9645 → 0.8.0-next.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/dist/PubSubPlugin.native.js +479 -0
- package/dist/PubSubPlugin.native.js.map +1 -0
- package/dist/cjs/index.cjs +270 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/{index.cjs.js → index.legacy-esm.js} +97 -35
- package/dist/{index.esm.js → index.mjs} +97 -29
- package/dist/index.mjs.map +1 -0
- package/package.json +24 -61
- package/src/__test__/handler.test.ts +89 -0
- package/src/__test__/plugin.test.ts +163 -0
- package/src/__test__/pubsub.test.ts +309 -0
- package/src/handler.ts +5 -5
- package/src/index.ts +3 -3
- package/src/plugin.ts +11 -11
- package/src/pubsub.ts +9 -9
- package/src/symbols.ts +1 -1
- package/src/utils.ts +3 -3
- package/types/handler.d.ts +13 -0
- package/types/index.d.ts +4 -0
- package/types/plugin.d.ts +50 -0
- package/types/pubsub.d.ts +53 -0
- package/types/symbols.d.ts +2 -0
- package/types/utils.d.ts +7 -0
- package/dist/index.d.ts +0 -116
- package/dist/pubsub-plugin.dev.js +0 -289
- package/dist/pubsub-plugin.prod.js +0 -1
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { describe, test, it, beforeEach, expect, vitest } from "vitest";
|
|
2
|
+
import { pubsub } from "../pubsub";
|
|
3
|
+
|
|
4
|
+
describe("pubsub", () => {
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
pubsub.clear();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("should call subscriber with single argument", () => {
|
|
10
|
+
const type = "test";
|
|
11
|
+
const message = "this is a test message";
|
|
12
|
+
const spy = vitest.fn();
|
|
13
|
+
|
|
14
|
+
pubsub.subscribe(type, spy);
|
|
15
|
+
pubsub.publish(type, message);
|
|
16
|
+
|
|
17
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
18
|
+
expect(spy).toHaveBeenCalledWith(type, message);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("should increment uuid with each subscribe", () => {
|
|
22
|
+
const type = "test";
|
|
23
|
+
const message = "this is a test message";
|
|
24
|
+
const spy = vitest.fn();
|
|
25
|
+
|
|
26
|
+
const sub1 = pubsub.subscribe(type, spy);
|
|
27
|
+
const sub2 = pubsub.subscribe(type, spy);
|
|
28
|
+
const sub3 = pubsub.subscribe(type, spy);
|
|
29
|
+
pubsub.publish(type, message);
|
|
30
|
+
|
|
31
|
+
expect(sub1).not.toStrictEqual(sub2);
|
|
32
|
+
expect(sub1).not.toStrictEqual(sub3);
|
|
33
|
+
expect(sub2).not.toStrictEqual(sub3);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should call subscriber with multiple argument", () => {
|
|
37
|
+
const type = "test";
|
|
38
|
+
const spy = vitest.fn();
|
|
39
|
+
|
|
40
|
+
pubsub.subscribe(type, spy);
|
|
41
|
+
pubsub.publish(type, 1, "two", "three");
|
|
42
|
+
|
|
43
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
44
|
+
expect(spy).toHaveBeenCalledWith(type, 1, "two", "three");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("should handle different argument types", () => {
|
|
48
|
+
const type = "test";
|
|
49
|
+
const spy = vitest.fn();
|
|
50
|
+
|
|
51
|
+
pubsub.subscribe(type, spy);
|
|
52
|
+
pubsub.publish(type, "one", 2, undefined, null, true, false);
|
|
53
|
+
|
|
54
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
55
|
+
expect(spy).toHaveBeenCalledWith(
|
|
56
|
+
type,
|
|
57
|
+
"one",
|
|
58
|
+
2,
|
|
59
|
+
undefined,
|
|
60
|
+
null,
|
|
61
|
+
true,
|
|
62
|
+
false,
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("should call all subscribers only once", () => {
|
|
67
|
+
const type = "test";
|
|
68
|
+
const message = "this is a test message";
|
|
69
|
+
const first = vitest.fn();
|
|
70
|
+
const second = vitest.fn();
|
|
71
|
+
|
|
72
|
+
pubsub.subscribe(type, first);
|
|
73
|
+
pubsub.subscribe(type, second);
|
|
74
|
+
|
|
75
|
+
pubsub.publish(type, message);
|
|
76
|
+
|
|
77
|
+
expect(first).toHaveBeenCalledTimes(1);
|
|
78
|
+
expect(first).toHaveBeenCalledWith(type, message);
|
|
79
|
+
expect(second).toHaveBeenCalledTimes(1);
|
|
80
|
+
expect(second).toHaveBeenCalledWith(type, message);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("should call only subscribers of event", () => {
|
|
84
|
+
const message = "this is a test message";
|
|
85
|
+
const first = vitest.fn();
|
|
86
|
+
const second = vitest.fn();
|
|
87
|
+
|
|
88
|
+
pubsub.subscribe("first", first);
|
|
89
|
+
pubsub.subscribe("second", second);
|
|
90
|
+
|
|
91
|
+
pubsub.publish("first", message);
|
|
92
|
+
|
|
93
|
+
expect(first).toHaveBeenCalledTimes(1);
|
|
94
|
+
expect(first).toHaveBeenCalledWith("first", message);
|
|
95
|
+
expect(second).not.toHaveBeenCalled();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("should call subscriber for all publish types", () => {
|
|
99
|
+
const spy = vitest.fn();
|
|
100
|
+
|
|
101
|
+
pubsub.subscribe("*", spy);
|
|
102
|
+
|
|
103
|
+
pubsub.publish("one", "one");
|
|
104
|
+
pubsub.publish("two", "two");
|
|
105
|
+
pubsub.publish("three", "three");
|
|
106
|
+
|
|
107
|
+
expect(spy).toHaveBeenCalledTimes(3);
|
|
108
|
+
expect(spy).toHaveBeenNthCalledWith(1, "one", "one");
|
|
109
|
+
expect(spy).toHaveBeenNthCalledWith(2, "two", "two");
|
|
110
|
+
expect(spy).toHaveBeenNthCalledWith(3, "three", "three");
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("should call all levels of subscribers only once", () => {
|
|
114
|
+
const level1 = vitest.fn();
|
|
115
|
+
const level2 = vitest.fn();
|
|
116
|
+
const level3 = vitest.fn();
|
|
117
|
+
|
|
118
|
+
pubsub.subscribe("foo", level1);
|
|
119
|
+
pubsub.subscribe("foo.bar", level2);
|
|
120
|
+
pubsub.subscribe("foo.bar.baz", level3);
|
|
121
|
+
|
|
122
|
+
pubsub.publish("foo.bar.baz", "one", "two", "three");
|
|
123
|
+
|
|
124
|
+
expect(level1).toHaveBeenCalledTimes(1);
|
|
125
|
+
expect(level2).toHaveBeenCalledTimes(1);
|
|
126
|
+
expect(level3).toHaveBeenCalledTimes(1);
|
|
127
|
+
expect(level1).toHaveBeenCalledWith("foo.bar.baz", "one", "two", "three");
|
|
128
|
+
expect(level2).toHaveBeenCalledWith("foo.bar.baz", "one", "two", "three");
|
|
129
|
+
expect(level3).toHaveBeenCalledWith("foo.bar.baz", "one", "two", "three");
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("should return unique symbols for each subscribe", () => {
|
|
133
|
+
const spy = vitest.fn();
|
|
134
|
+
const spy2 = vitest.fn();
|
|
135
|
+
|
|
136
|
+
const token1 = pubsub.subscribe("test", spy);
|
|
137
|
+
const token2 = pubsub.subscribe("test", spy);
|
|
138
|
+
const token3 = pubsub.subscribe("test", spy2);
|
|
139
|
+
|
|
140
|
+
const symbols = new Set([token1, token2, token3]);
|
|
141
|
+
expect(symbols.size).toBe(3);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it(`shouldn't error if subscribing to non string value`, () => {
|
|
145
|
+
const spy = vitest.fn();
|
|
146
|
+
pubsub.subscribe(true as any, spy);
|
|
147
|
+
pubsub.publish(true as any, "test");
|
|
148
|
+
|
|
149
|
+
expect(spy).not.toHaveBeenCalled();
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it("should remove handler with token", () => {
|
|
153
|
+
const type = "test";
|
|
154
|
+
const spy = vitest.fn();
|
|
155
|
+
const token = pubsub.subscribe(type, spy);
|
|
156
|
+
|
|
157
|
+
expect(pubsub.count()).toBe(1);
|
|
158
|
+
expect(pubsub.count(type)).toBe(1);
|
|
159
|
+
|
|
160
|
+
pubsub.unsubscribe(token);
|
|
161
|
+
|
|
162
|
+
expect(pubsub.count()).toBe(0);
|
|
163
|
+
expect(pubsub.count(type)).toBe(0);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it("should only remove handler with passed token", () => {
|
|
167
|
+
const type = "test";
|
|
168
|
+
const spy1 = vitest.fn();
|
|
169
|
+
const spy2 = vitest.fn();
|
|
170
|
+
const token1 = pubsub.subscribe(type, spy1);
|
|
171
|
+
const token2 = pubsub.subscribe(type, spy2);
|
|
172
|
+
|
|
173
|
+
expect(pubsub.count()).toBe(2);
|
|
174
|
+
expect(pubsub.count(type)).toBe(2);
|
|
175
|
+
|
|
176
|
+
pubsub.unsubscribe(token1);
|
|
177
|
+
|
|
178
|
+
expect(pubsub.count()).toBe(1);
|
|
179
|
+
expect(pubsub.count(type)).toBe(1);
|
|
180
|
+
|
|
181
|
+
pubsub.unsubscribe(token2);
|
|
182
|
+
|
|
183
|
+
expect(pubsub.count()).toBe(0);
|
|
184
|
+
expect(pubsub.count(type)).toBe(0);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it("should remove all handlers for type", () => {
|
|
188
|
+
const type = "test";
|
|
189
|
+
const spy1 = vitest.fn();
|
|
190
|
+
const spy2 = vitest.fn();
|
|
191
|
+
pubsub.subscribe(type, spy1);
|
|
192
|
+
pubsub.subscribe(type, spy2);
|
|
193
|
+
|
|
194
|
+
expect(pubsub.count()).toBe(2);
|
|
195
|
+
expect(pubsub.count(type)).toBe(2);
|
|
196
|
+
|
|
197
|
+
expect(pubsub.tokens.size).toBe(2);
|
|
198
|
+
|
|
199
|
+
pubsub.unsubscribe(type);
|
|
200
|
+
|
|
201
|
+
expect(pubsub.count()).toBe(0);
|
|
202
|
+
expect(pubsub.count(type)).toBe(0);
|
|
203
|
+
|
|
204
|
+
expect(pubsub.tokens.size).toBe(0);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it("should remove all nested handlers for type", () => {
|
|
208
|
+
const spy1 = vitest.fn();
|
|
209
|
+
const spy2 = vitest.fn();
|
|
210
|
+
const spy3 = vitest.fn();
|
|
211
|
+
pubsub.subscribe("foo", spy1);
|
|
212
|
+
pubsub.subscribe("foo.bar", spy2);
|
|
213
|
+
pubsub.subscribe("foo.bar.baz", spy3);
|
|
214
|
+
|
|
215
|
+
expect(pubsub.count()).toBe(3);
|
|
216
|
+
expect(pubsub.count("foo")).toBe(1);
|
|
217
|
+
expect(pubsub.count("foo.bar")).toBe(1);
|
|
218
|
+
expect(pubsub.count("foo.bar.baz")).toBe(1);
|
|
219
|
+
|
|
220
|
+
expect(pubsub.tokens.size).toBe(3);
|
|
221
|
+
|
|
222
|
+
pubsub.unsubscribe("foo");
|
|
223
|
+
|
|
224
|
+
expect(pubsub.count()).toBe(0);
|
|
225
|
+
expect(pubsub.count("foo")).toBe(0);
|
|
226
|
+
expect(pubsub.count("foo.bar")).toBe(0);
|
|
227
|
+
expect(pubsub.count("foo.bar.baz")).toBe(0);
|
|
228
|
+
|
|
229
|
+
expect(pubsub.tokens.size).toBe(0);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it("should keep top layer for type", () => {
|
|
233
|
+
const spy1 = vitest.fn();
|
|
234
|
+
const spy2 = vitest.fn();
|
|
235
|
+
const spy3 = vitest.fn();
|
|
236
|
+
pubsub.subscribe("foo", spy1);
|
|
237
|
+
pubsub.subscribe("foo.bar", spy2);
|
|
238
|
+
pubsub.subscribe("foo.bar.baz", spy3);
|
|
239
|
+
|
|
240
|
+
expect(pubsub.count()).toBe(3);
|
|
241
|
+
expect(pubsub.count("foo")).toBe(1);
|
|
242
|
+
expect(pubsub.count("foo.bar")).toBe(1);
|
|
243
|
+
expect(pubsub.count("foo.bar.baz")).toBe(1);
|
|
244
|
+
|
|
245
|
+
expect(pubsub.tokens.size).toBe(3);
|
|
246
|
+
|
|
247
|
+
pubsub.unsubscribe("foo.bar");
|
|
248
|
+
|
|
249
|
+
expect(pubsub.count()).toBe(1);
|
|
250
|
+
expect(pubsub.count("foo")).toBe(1);
|
|
251
|
+
expect(pubsub.count("foo.bar")).toBe(0);
|
|
252
|
+
expect(pubsub.count("foo.bar.baz")).toBe(0);
|
|
253
|
+
|
|
254
|
+
expect(pubsub.tokens.size).toBe(1);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it("should only delete deeply nested type", () => {
|
|
258
|
+
const spy1 = vitest.fn();
|
|
259
|
+
const spy2 = vitest.fn();
|
|
260
|
+
const spy3 = vitest.fn();
|
|
261
|
+
pubsub.subscribe("foo", spy1);
|
|
262
|
+
pubsub.subscribe("foo.bar", spy2);
|
|
263
|
+
pubsub.subscribe("foo.bar.baz", spy3);
|
|
264
|
+
|
|
265
|
+
expect(pubsub.count()).toBe(3);
|
|
266
|
+
expect(pubsub.count("foo")).toBe(1);
|
|
267
|
+
expect(pubsub.count("foo.bar")).toBe(1);
|
|
268
|
+
expect(pubsub.count("foo.bar.baz")).toBe(1);
|
|
269
|
+
|
|
270
|
+
expect(pubsub.tokens.size).toBe(3);
|
|
271
|
+
|
|
272
|
+
pubsub.unsubscribe("foo.bar.baz");
|
|
273
|
+
|
|
274
|
+
expect(pubsub.count()).toBe(2);
|
|
275
|
+
expect(pubsub.count("foo")).toBe(1);
|
|
276
|
+
expect(pubsub.count("foo.bar")).toBe(1);
|
|
277
|
+
expect(pubsub.count("foo.bar.baz")).toBe(0);
|
|
278
|
+
|
|
279
|
+
expect(pubsub.tokens.size).toBe(2);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it(`should gracefully handle when token doesn't exist anymore`, () => {
|
|
283
|
+
const spy = vitest.fn();
|
|
284
|
+
|
|
285
|
+
const token = pubsub.subscribe("foo", spy);
|
|
286
|
+
expect(pubsub.count()).toBe(1);
|
|
287
|
+
|
|
288
|
+
pubsub.clear();
|
|
289
|
+
expect(pubsub.count()).toBe(0);
|
|
290
|
+
|
|
291
|
+
pubsub.unsubscribe(token);
|
|
292
|
+
|
|
293
|
+
expect(pubsub.tokens.size).toBe(0);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it(`should gracefully handle when unsubscribe isn't string or symbol`, () => {
|
|
297
|
+
const spy = vitest.fn();
|
|
298
|
+
|
|
299
|
+
pubsub.subscribe("foo", spy);
|
|
300
|
+
expect(pubsub.count()).toBe(1);
|
|
301
|
+
|
|
302
|
+
pubsub.clear();
|
|
303
|
+
expect(pubsub.count()).toBe(0);
|
|
304
|
+
|
|
305
|
+
pubsub.unsubscribe(false as any);
|
|
306
|
+
|
|
307
|
+
expect(pubsub.tokens.size).toBe(0);
|
|
308
|
+
});
|
|
309
|
+
});
|
package/src/handler.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Player, PlayerPlugin, InProgressState } from
|
|
2
|
-
import { getPubSubPlugin } from
|
|
1
|
+
import type { Player, PlayerPlugin, InProgressState } from "@player-ui/player";
|
|
2
|
+
import { getPubSubPlugin } from "./utils";
|
|
3
3
|
|
|
4
4
|
export type PubSubHandler<T extends unknown[]> = (
|
|
5
5
|
context: InProgressState,
|
|
@@ -12,7 +12,7 @@ export type SubscriptionMap = Map<string, PubSubHandler<any>>;
|
|
|
12
12
|
* Plugin to easily add subscribers to the PubSubPlugin
|
|
13
13
|
*/
|
|
14
14
|
export class PubSubHandlerPlugin implements PlayerPlugin {
|
|
15
|
-
name =
|
|
15
|
+
name = "pubsub-handler";
|
|
16
16
|
private subscriptions: SubscriptionMap;
|
|
17
17
|
|
|
18
18
|
constructor(subscriptions: SubscriptionMap) {
|
|
@@ -27,12 +27,12 @@ export class PubSubHandlerPlugin implements PlayerPlugin {
|
|
|
27
27
|
pubsub.subscribe(key, (_, ...args) => {
|
|
28
28
|
const state = player.getState();
|
|
29
29
|
|
|
30
|
-
if (state.status ===
|
|
30
|
+
if (state.status === "in-progress") {
|
|
31
31
|
return handler(state, ...args);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
player.logger.info(
|
|
35
|
-
`[PubSubHandlerPlugin] subscriber for ${key} was called when player was not in-progress
|
|
35
|
+
`[PubSubHandlerPlugin] subscriber for ${key} was called when player was not in-progress`,
|
|
36
36
|
);
|
|
37
37
|
});
|
|
38
38
|
});
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
1
|
+
export * from "./plugin";
|
|
2
|
+
export * from "./symbols";
|
|
3
|
+
export * from "./handler";
|
package/src/plugin.ts
CHANGED
|
@@ -2,10 +2,10 @@ import type {
|
|
|
2
2
|
Player,
|
|
3
3
|
PlayerPlugin,
|
|
4
4
|
ExpressionContext,
|
|
5
|
-
} from
|
|
6
|
-
import type { SubscribeHandler, TinyPubSub } from
|
|
7
|
-
import { pubsub } from
|
|
8
|
-
import { PubSubPluginSymbol } from
|
|
5
|
+
} from "@player-ui/player";
|
|
6
|
+
import type { SubscribeHandler, TinyPubSub } from "./pubsub";
|
|
7
|
+
import { pubsub } from "./pubsub";
|
|
8
|
+
import { PubSubPluginSymbol } from "./symbols";
|
|
9
9
|
|
|
10
10
|
export interface PubSubConfig {
|
|
11
11
|
/** A custom expression name to register */
|
|
@@ -22,7 +22,7 @@ export interface PubSubConfig {
|
|
|
22
22
|
*
|
|
23
23
|
*/
|
|
24
24
|
export class PubSubPlugin implements PlayerPlugin {
|
|
25
|
-
name =
|
|
25
|
+
name = "pub-sub";
|
|
26
26
|
|
|
27
27
|
static Symbol = PubSubPluginSymbol;
|
|
28
28
|
public readonly symbol = PubSubPlugin.Symbol;
|
|
@@ -32,7 +32,7 @@ export class PubSubPlugin implements PlayerPlugin {
|
|
|
32
32
|
private expressionName: string;
|
|
33
33
|
|
|
34
34
|
constructor(config?: PubSubConfig) {
|
|
35
|
-
this.expressionName = config?.expressionName ??
|
|
35
|
+
this.expressionName = config?.expressionName ?? "publish";
|
|
36
36
|
this.pubsub = pubsub;
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -46,21 +46,21 @@ export class PubSubPlugin implements PlayerPlugin {
|
|
|
46
46
|
|
|
47
47
|
player.hooks.expressionEvaluator.tap(this.name, (expEvaluator) => {
|
|
48
48
|
const existingExpression = expEvaluator.operators.expressions.get(
|
|
49
|
-
this.expressionName
|
|
49
|
+
this.expressionName,
|
|
50
50
|
);
|
|
51
51
|
|
|
52
52
|
if (existingExpression) {
|
|
53
53
|
player.logger.warn(
|
|
54
|
-
`[PubSubPlugin] expression ${this.expressionName} is already registered
|
|
54
|
+
`[PubSubPlugin] expression ${this.expressionName} is already registered.`,
|
|
55
55
|
);
|
|
56
56
|
} else {
|
|
57
57
|
expEvaluator.addExpressionFunction(
|
|
58
58
|
this.expressionName,
|
|
59
59
|
(_ctx: ExpressionContext, event: unknown, ...args: unknown[]) => {
|
|
60
|
-
if (typeof event ===
|
|
60
|
+
if (typeof event === "string") {
|
|
61
61
|
this.publish(event, ...args);
|
|
62
62
|
}
|
|
63
|
-
}
|
|
63
|
+
},
|
|
64
64
|
);
|
|
65
65
|
}
|
|
66
66
|
});
|
|
@@ -89,7 +89,7 @@ export class PubSubPlugin implements PlayerPlugin {
|
|
|
89
89
|
*/
|
|
90
90
|
subscribe<T extends string, A extends unknown[]>(
|
|
91
91
|
event: T,
|
|
92
|
-
handler: SubscribeHandler<T, A
|
|
92
|
+
handler: SubscribeHandler<T, A>,
|
|
93
93
|
) {
|
|
94
94
|
return this.pubsub.subscribe(event, handler);
|
|
95
95
|
}
|
package/src/pubsub.ts
CHANGED
|
@@ -14,7 +14,7 @@ export type PubSubUUID = `uuid_${number}`;
|
|
|
14
14
|
* Split a string into an array of event layers
|
|
15
15
|
*/
|
|
16
16
|
function splitEvent(event: string) {
|
|
17
|
-
return event.split(
|
|
17
|
+
return event.split(".").reduce<string[]>((prev, curr, index) => {
|
|
18
18
|
if (index === 0) {
|
|
19
19
|
return [curr];
|
|
20
20
|
}
|
|
@@ -41,11 +41,11 @@ export class TinyPubSub {
|
|
|
41
41
|
* Publish an event with any number of additional arguments
|
|
42
42
|
*/
|
|
43
43
|
publish(event: string, ...args: unknown[]) {
|
|
44
|
-
if (typeof event !==
|
|
44
|
+
if (typeof event !== "string") {
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
if (event.includes(
|
|
48
|
+
if (event.includes(".")) {
|
|
49
49
|
const eventKeys = splitEvent(event);
|
|
50
50
|
|
|
51
51
|
eventKeys.forEach((key) => {
|
|
@@ -55,7 +55,7 @@ export class TinyPubSub {
|
|
|
55
55
|
this.deliver(event, event, ...args);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
this.deliver(
|
|
58
|
+
this.deliver("*", event, ...args);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
/**
|
|
@@ -74,7 +74,7 @@ export class TinyPubSub {
|
|
|
74
74
|
subscribe(event: string, handler: SubscribeHandler<any, any>) {
|
|
75
75
|
const uuid = `uuid_${++count}`;
|
|
76
76
|
|
|
77
|
-
if (typeof event ===
|
|
77
|
+
if (typeof event === "string") {
|
|
78
78
|
if (!this.events.has(event)) {
|
|
79
79
|
this.events.set(event, new Map());
|
|
80
80
|
}
|
|
@@ -96,10 +96,10 @@ export class TinyPubSub {
|
|
|
96
96
|
* & 'a.b.c' will be unsubscribed as well.
|
|
97
97
|
*/
|
|
98
98
|
unsubscribe(value: string | symbol) {
|
|
99
|
-
if (typeof value ===
|
|
99
|
+
if (typeof value === "string" && value.startsWith("uuid")) {
|
|
100
100
|
const path = this.tokens.get(value as PubSubUUID);
|
|
101
101
|
|
|
102
|
-
if (typeof path ===
|
|
102
|
+
if (typeof path === "undefined") {
|
|
103
103
|
return;
|
|
104
104
|
}
|
|
105
105
|
|
|
@@ -109,7 +109,7 @@ export class TinyPubSub {
|
|
|
109
109
|
return;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
if (typeof value ===
|
|
112
|
+
if (typeof value === "string") {
|
|
113
113
|
for (const key of this.events.keys()) {
|
|
114
114
|
if (key.indexOf(value) === 0) {
|
|
115
115
|
const tokens = this.events.get(key);
|
|
@@ -134,7 +134,7 @@ export class TinyPubSub {
|
|
|
134
134
|
count(event?: string) {
|
|
135
135
|
let counter = 0;
|
|
136
136
|
|
|
137
|
-
if (typeof event ===
|
|
137
|
+
if (typeof event === "undefined") {
|
|
138
138
|
for (const handlers of this.events.values()) {
|
|
139
139
|
counter += handlers.size;
|
|
140
140
|
}
|
package/src/symbols.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const PubSubPluginSymbol = Symbol.for(
|
|
1
|
+
export const PubSubPluginSymbol = Symbol.for("PubSubPlugin");
|
package/src/utils.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Player } from
|
|
2
|
-
import { PubSubPlugin } from
|
|
3
|
-
import { PubSubPluginSymbol } from
|
|
1
|
+
import type { Player } from "@player-ui/player";
|
|
2
|
+
import { PubSubPlugin } from "./plugin";
|
|
3
|
+
import { PubSubPluginSymbol } from "./symbols";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Returns the existing PubSubPlugin or creates and registers a new plugin
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Player, PlayerPlugin, InProgressState } from "@player-ui/player";
|
|
2
|
+
export type PubSubHandler<T extends unknown[]> = (context: InProgressState, ...args: T) => void;
|
|
3
|
+
export type SubscriptionMap = Map<string, PubSubHandler<any>>;
|
|
4
|
+
/**
|
|
5
|
+
* Plugin to easily add subscribers to the PubSubPlugin
|
|
6
|
+
*/
|
|
7
|
+
export declare class PubSubHandlerPlugin implements PlayerPlugin {
|
|
8
|
+
name: string;
|
|
9
|
+
private subscriptions;
|
|
10
|
+
constructor(subscriptions: SubscriptionMap);
|
|
11
|
+
apply(player: Player): void;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=handler.d.ts.map
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Player, PlayerPlugin } from "@player-ui/player";
|
|
2
|
+
import type { SubscribeHandler, TinyPubSub } from "./pubsub";
|
|
3
|
+
export interface PubSubConfig {
|
|
4
|
+
/** A custom expression name to register */
|
|
5
|
+
expressionName: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The PubSubPlugin is a great way to enable your FRF content to publish events back to your app
|
|
9
|
+
* It injects a publish() function into the expression language, and will forward all events back to any subscribers.
|
|
10
|
+
*
|
|
11
|
+
* Published/Subscribed events support a hierarchy:
|
|
12
|
+
* - publish('foo', 'data') -- will trigger any listeners for 'foo'
|
|
13
|
+
* - publish('foo.bar', 'data') -- will trigger any listeners for 'foo' or 'foo.bar'
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
export declare class PubSubPlugin implements PlayerPlugin {
|
|
17
|
+
name: string;
|
|
18
|
+
static Symbol: symbol;
|
|
19
|
+
readonly symbol: symbol;
|
|
20
|
+
protected pubsub: TinyPubSub;
|
|
21
|
+
private expressionName;
|
|
22
|
+
constructor(config?: PubSubConfig);
|
|
23
|
+
apply(player: Player): void;
|
|
24
|
+
/**
|
|
25
|
+
* A way of publishing an event, notifying any listeners
|
|
26
|
+
*
|
|
27
|
+
* @param event - The name of the event to publish. Can take sub-topics like: foo.bar
|
|
28
|
+
* @param data - Any additional data to attach to the event
|
|
29
|
+
*/
|
|
30
|
+
publish(event: string, ...args: unknown[]): void;
|
|
31
|
+
/**
|
|
32
|
+
* Subscribe to an event with the given name. The handler will get called for any published event
|
|
33
|
+
*
|
|
34
|
+
* @param event - The name of the event to subscribe to
|
|
35
|
+
* @param handler - A function to be called when the event is triggered
|
|
36
|
+
* @returns A token to be used to unsubscribe from the event
|
|
37
|
+
*/
|
|
38
|
+
subscribe<T extends string, A extends unknown[]>(event: T, handler: SubscribeHandler<T, A>): string;
|
|
39
|
+
/**
|
|
40
|
+
* Remove any subscriptions using the given token
|
|
41
|
+
*
|
|
42
|
+
* @param token - A token from a `subscribe` call
|
|
43
|
+
*/
|
|
44
|
+
unsubscribe(token: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* Remove all subscriptions
|
|
47
|
+
*/
|
|
48
|
+
clear(): void;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Based off the pubsub-js library and rewritten to match the same used APIs but modified so that
|
|
3
|
+
* multiple arguments could be passed into the publish and subscription handlers.
|
|
4
|
+
*/
|
|
5
|
+
export type SubscribeHandler<T extends string, A extends unknown[]> = (type: T, ...args: A) => void;
|
|
6
|
+
export type PubSubUUID = `uuid_${number}`;
|
|
7
|
+
/**
|
|
8
|
+
* Tiny pubsub maker
|
|
9
|
+
*/
|
|
10
|
+
export declare class TinyPubSub {
|
|
11
|
+
private events;
|
|
12
|
+
private tokens;
|
|
13
|
+
constructor();
|
|
14
|
+
/**
|
|
15
|
+
* Publish an event with any number of additional arguments
|
|
16
|
+
*/
|
|
17
|
+
publish(event: string, ...args: unknown[]): void;
|
|
18
|
+
/**
|
|
19
|
+
* Subscribe to an event
|
|
20
|
+
*
|
|
21
|
+
* Events are also heirarchical when separated by a period. Given the following:
|
|
22
|
+
*
|
|
23
|
+
* publish('a.b.c', 'one', 'two', 'three)
|
|
24
|
+
*
|
|
25
|
+
* The subscribe event will be called when the event is passed as 'a', 'a.b', or 'a.b.c'.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* // subscribes to the top level 'a' publish
|
|
29
|
+
* subscribe('a', (event, ...args) => console.log(event, ...args))
|
|
30
|
+
*/
|
|
31
|
+
subscribe(event: string, handler: SubscribeHandler<any, any>): string;
|
|
32
|
+
/**
|
|
33
|
+
* Unsubscribes to a specific subscription given it's symbol or an entire
|
|
34
|
+
* event when passed as a string.
|
|
35
|
+
*
|
|
36
|
+
* When existing subscriptions exist for heirarchical events such as 'a.b.c',
|
|
37
|
+
* when passing an event 'a' to unsubscribe, all subscriptions for 'a', 'a.b',
|
|
38
|
+
* & 'a.b.c' will be unsubscribed as well.
|
|
39
|
+
*/
|
|
40
|
+
unsubscribe(value: string | symbol): void;
|
|
41
|
+
/**
|
|
42
|
+
* Get the number of subscriptions for a specific event, or when left blank
|
|
43
|
+
* will return the overall number of subscriptions for the entire pubsub.
|
|
44
|
+
*/
|
|
45
|
+
count(event?: string): number;
|
|
46
|
+
/**
|
|
47
|
+
* Deletes all existing subscriptions
|
|
48
|
+
*/
|
|
49
|
+
clear(): void;
|
|
50
|
+
private deliver;
|
|
51
|
+
}
|
|
52
|
+
export declare const pubsub: TinyPubSub;
|
|
53
|
+
//# sourceMappingURL=pubsub.d.ts.map
|
package/types/utils.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Player } from "@player-ui/player";
|
|
2
|
+
import { PubSubPlugin } from "./plugin";
|
|
3
|
+
/**
|
|
4
|
+
* Returns the existing PubSubPlugin or creates and registers a new plugin
|
|
5
|
+
*/
|
|
6
|
+
export declare function getPubSubPlugin(player: Player): PubSubPlugin;
|
|
7
|
+
//# sourceMappingURL=utils.d.ts.map
|