@player-ui/pubsub-plugin 0.4.0 → 0.4.1-next.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.
package/dist/index.cjs.js CHANGED
@@ -2,11 +2,99 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var pubsub = require('pubsub-js');
6
-
7
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
-
9
- var pubsub__default = /*#__PURE__*/_interopDefaultLegacy(pubsub);
5
+ function splitEvent(event) {
6
+ return event.split(".").reduce((prev, curr, index) => {
7
+ if (index === 0) {
8
+ return [curr];
9
+ }
10
+ return [...prev, `${prev[index - 1]}.${curr}`];
11
+ }, []);
12
+ }
13
+ let count = 1;
14
+ class TinyPubSub {
15
+ constructor() {
16
+ this.events = new Map();
17
+ this.tokens = new Map();
18
+ }
19
+ publish(event, ...args) {
20
+ if (typeof event !== "string") {
21
+ return;
22
+ }
23
+ if (event.includes(".")) {
24
+ const eventKeys = splitEvent(event);
25
+ eventKeys.forEach((key) => {
26
+ this.deliver(key, event, ...args);
27
+ });
28
+ } else {
29
+ this.deliver(event, event, ...args);
30
+ }
31
+ this.deliver("*", event, ...args);
32
+ }
33
+ subscribe(event, handler) {
34
+ const uuid = `uuid_${++count}`;
35
+ if (typeof event === "string") {
36
+ if (!this.events.has(event)) {
37
+ this.events.set(event, new Map());
38
+ }
39
+ const handlers = this.events.get(event);
40
+ handlers.set(uuid, handler);
41
+ this.tokens.set(uuid, event);
42
+ }
43
+ return uuid;
44
+ }
45
+ unsubscribe(value) {
46
+ if (typeof value === "string" && value.startsWith("uuid")) {
47
+ const path = this.tokens.get(value);
48
+ if (typeof path === "undefined") {
49
+ return;
50
+ }
51
+ const innerPath = this.events.get(path);
52
+ innerPath == null ? void 0 : innerPath.delete(value);
53
+ this.tokens.delete(value);
54
+ return;
55
+ }
56
+ if (typeof value === "string") {
57
+ for (const key of this.events.keys()) {
58
+ if (key.indexOf(value) === 0) {
59
+ const tokens = this.events.get(key);
60
+ if (tokens && tokens.size) {
61
+ for (const token of tokens.keys()) {
62
+ this.tokens.delete(token);
63
+ }
64
+ }
65
+ this.events.delete(key);
66
+ }
67
+ }
68
+ }
69
+ }
70
+ count(event) {
71
+ let counter = 0;
72
+ if (typeof event === "undefined") {
73
+ for (const handlers2 of this.events.values()) {
74
+ counter += handlers2.size;
75
+ }
76
+ return counter;
77
+ }
78
+ const handlers = this.events.get(event);
79
+ if (handlers == null ? void 0 : handlers.size) {
80
+ return handlers.size;
81
+ }
82
+ return counter;
83
+ }
84
+ clear() {
85
+ this.events.clear();
86
+ this.tokens.clear();
87
+ }
88
+ deliver(path, event, ...args) {
89
+ const handlers = this.events.get(path);
90
+ if (handlers && handlers.size) {
91
+ for (const handler of handlers.values()) {
92
+ handler(event, ...args);
93
+ }
94
+ }
95
+ }
96
+ }
97
+ const pubsub = new TinyPubSub();
10
98
 
11
99
  const PubSubPluginSymbol = Symbol.for("PubSubPlugin");
12
100
 
@@ -16,29 +104,76 @@ const _PubSubPlugin = class {
16
104
  this.symbol = _PubSubPlugin.Symbol;
17
105
  var _a;
18
106
  this.expressionName = (_a = config == null ? void 0 : config.expressionName) != null ? _a : "publish";
107
+ this.pubsub = pubsub;
19
108
  }
20
109
  apply(player) {
110
+ const existing = player.findPlugin(PubSubPluginSymbol);
111
+ if (existing !== void 0) {
112
+ this.pubsub = existing.pubsub;
113
+ }
21
114
  player.hooks.expressionEvaluator.tap(this.name, (expEvaluator) => {
22
- expEvaluator.addExpressionFunction(this.expressionName, (_ctx, event, data) => {
23
- if (typeof event === "string") {
24
- this.publish(event, data);
25
- }
26
- });
115
+ const existingExpression = expEvaluator.operators.expressions.get(this.expressionName);
116
+ if (existingExpression) {
117
+ player.logger.warn(`[PubSubPlugin] expression ${this.expressionName} is already registered.`);
118
+ } else {
119
+ expEvaluator.addExpressionFunction(this.expressionName, (_ctx, event, ...args) => {
120
+ if (typeof event === "string") {
121
+ this.publish(event, ...args);
122
+ }
123
+ });
124
+ }
125
+ });
126
+ player.hooks.onEnd.tap(this.name, () => {
127
+ this.clear();
27
128
  });
28
129
  }
29
- publish(event, data) {
30
- pubsub__default["default"].publishSync(event, data);
130
+ publish(event, ...args) {
131
+ this.pubsub.publish(event, ...args);
31
132
  }
32
133
  subscribe(event, handler) {
33
- return pubsub__default["default"].subscribe(event, handler);
134
+ return this.pubsub.subscribe(event, handler);
34
135
  }
35
136
  unsubscribe(token) {
36
- pubsub__default["default"].unsubscribe(token);
137
+ this.pubsub.unsubscribe(token);
138
+ }
139
+ clear() {
140
+ this.pubsub.clear();
37
141
  }
38
142
  };
39
143
  let PubSubPlugin = _PubSubPlugin;
40
144
  PubSubPlugin.Symbol = PubSubPluginSymbol;
41
145
 
146
+ function getPubSubPlugin(player) {
147
+ const existing = player.findPlugin(PubSubPluginSymbol);
148
+ const plugin = existing || new PubSubPlugin();
149
+ if (!existing) {
150
+ player.registerPlugin(plugin);
151
+ }
152
+ return plugin;
153
+ }
154
+
155
+ class PubSubHandlerPlugin {
156
+ constructor(subscriptions) {
157
+ this.name = "pubsub-handler";
158
+ this.subscriptions = subscriptions;
159
+ }
160
+ apply(player) {
161
+ const pubsub = getPubSubPlugin(player);
162
+ player.hooks.onStart.tap(this.name, () => {
163
+ this.subscriptions.forEach((handler, key) => {
164
+ pubsub.subscribe(key, (_, ...args) => {
165
+ const state = player.getState();
166
+ if (state.status === "in-progress") {
167
+ return handler(state, ...args);
168
+ }
169
+ player.logger.info(`[PubSubHandlerPlugin] subscriber for ${key} was called when player was not in-progress`);
170
+ });
171
+ });
172
+ });
173
+ }
174
+ }
175
+
176
+ exports.PubSubHandlerPlugin = PubSubHandlerPlugin;
42
177
  exports.PubSubPlugin = PubSubPlugin;
43
178
  exports.PubSubPluginSymbol = PubSubPluginSymbol;
44
179
  //# sourceMappingURL=index.cjs.js.map
package/dist/index.d.ts CHANGED
@@ -1,11 +1,62 @@
1
- import { PlayerPlugin, Player } from '@player-ui/player';
1
+ import { PlayerPlugin, Player, InProgressState } from '@player-ui/player';
2
+
3
+ /**
4
+ * Based off the pubsub-js library and rewritten to match the same used APIs but modified so that
5
+ * multiple arguments could be passed into the publish and subscription handlers.
6
+ */
7
+ declare type SubscribeHandler<T extends string, A extends unknown[]> = (type: T, ...args: A) => void;
8
+ /**
9
+ * Tiny pubsub maker
10
+ */
11
+ declare class TinyPubSub {
12
+ private events;
13
+ private tokens;
14
+ constructor();
15
+ /**
16
+ * Publish an event with any number of additional arguments
17
+ */
18
+ publish(event: string, ...args: unknown[]): void;
19
+ /**
20
+ * Subscribe to an event
21
+ *
22
+ * Events are also heirarchical when separated by a period. Given the following:
23
+ *
24
+ * publish('a.b.c', 'one', 'two', 'three)
25
+ *
26
+ * The subscribe event will be called when the event is passed as 'a', 'a.b', or 'a.b.c'.
27
+ *
28
+ * @example
29
+ * // subscribes to the top level 'a' publish
30
+ * subscribe('a', (event, ...args) => console.log(event, ...args))
31
+ */
32
+ subscribe(event: string, handler: SubscribeHandler<any, any>): string;
33
+ /**
34
+ * Unsubscribes to a specific subscription given it's symbol or an entire
35
+ * event when passed as a string.
36
+ *
37
+ * When existing subscriptions exist for heirarchical events such as 'a.b.c',
38
+ * when passing an event 'a' to unsubscribe, all subscriptions for 'a', 'a.b',
39
+ * & 'a.b.c' will be unsubscribed as well.
40
+ */
41
+ unsubscribe(value: string | symbol): void;
42
+ /**
43
+ * Get the number of subscriptions for a specific event, or when left blank
44
+ * will return the overall number of subscriptions for the entire pubsub.
45
+ */
46
+ count(event?: string): number;
47
+ /**
48
+ * Deletes all existing subscriptions
49
+ */
50
+ clear(): void;
51
+ private deliver;
52
+ }
2
53
 
3
54
  interface PubSubConfig {
4
55
  /** A custom expression name to register */
5
56
  expressionName: string;
6
57
  }
7
58
  /**
8
- * The PubSubPlugin is a great way to enable your Content content to publish events back to your app
59
+ * The PubSubPlugin is a great way to enable your FRF content to publish events back to your app
9
60
  * It injects a publish() function into the expression language, and will forward all events back to any subscribers.
10
61
  *
11
62
  * Published/Subscribed events support a hierarchy:
@@ -17,6 +68,7 @@ declare class PubSubPlugin implements PlayerPlugin {
17
68
  name: string;
18
69
  static Symbol: symbol;
19
70
  readonly symbol: symbol;
71
+ protected pubsub: TinyPubSub;
20
72
  private expressionName;
21
73
  constructor(config?: PubSubConfig);
22
74
  apply(player: Player): void;
@@ -26,7 +78,7 @@ declare class PubSubPlugin implements PlayerPlugin {
26
78
  * @param event - The name of the event to publish. Can take sub-topics like: foo.bar
27
79
  * @param data - Any additional data to attach to the event
28
80
  */
29
- publish(event: string, data: unknown): void;
81
+ publish(event: string, ...args: unknown[]): void;
30
82
  /**
31
83
  * Subscribe to an event with the given name. The handler will get called for any published event
32
84
  *
@@ -34,15 +86,31 @@ declare class PubSubPlugin implements PlayerPlugin {
34
86
  * @param handler - A function to be called when the event is triggered
35
87
  * @returns A token to be used to unsubscribe from the event
36
88
  */
37
- subscribe(event: string, handler: (e: string, data: unknown) => void): string;
89
+ subscribe<T extends string, A extends unknown[]>(event: T, handler: SubscribeHandler<T, A>): string;
38
90
  /**
39
91
  * Remove any subscriptions using the given token
40
92
  *
41
93
  * @param token - A token from a `subscribe` call
42
94
  */
43
95
  unsubscribe(token: string): void;
96
+ /**
97
+ * Remove all subscriptions
98
+ */
99
+ clear(): void;
44
100
  }
45
101
 
46
102
  declare const PubSubPluginSymbol: unique symbol;
47
103
 
48
- export { PubSubConfig, PubSubPlugin, PubSubPluginSymbol };
104
+ declare type PubSubHandler<T extends unknown[]> = (context: InProgressState, ...args: T) => void;
105
+ declare type SubscriptionMap = Map<string, PubSubHandler<any>>;
106
+ /**
107
+ * Plugin to easily add subscribers to the PubSubPlugin
108
+ */
109
+ declare class PubSubHandlerPlugin implements PlayerPlugin {
110
+ name: string;
111
+ private subscriptions;
112
+ constructor(subscriptions: SubscriptionMap);
113
+ apply(player: Player): void;
114
+ }
115
+
116
+ export { PubSubConfig, PubSubHandler, PubSubHandlerPlugin, PubSubPlugin, PubSubPluginSymbol, SubscriptionMap };
package/dist/index.esm.js CHANGED
@@ -1,4 +1,96 @@
1
- import pubsub from 'pubsub-js';
1
+ function splitEvent(event) {
2
+ return event.split(".").reduce((prev, curr, index) => {
3
+ if (index === 0) {
4
+ return [curr];
5
+ }
6
+ return [...prev, `${prev[index - 1]}.${curr}`];
7
+ }, []);
8
+ }
9
+ let count = 1;
10
+ class TinyPubSub {
11
+ constructor() {
12
+ this.events = new Map();
13
+ this.tokens = new Map();
14
+ }
15
+ publish(event, ...args) {
16
+ if (typeof event !== "string") {
17
+ return;
18
+ }
19
+ if (event.includes(".")) {
20
+ const eventKeys = splitEvent(event);
21
+ eventKeys.forEach((key) => {
22
+ this.deliver(key, event, ...args);
23
+ });
24
+ } else {
25
+ this.deliver(event, event, ...args);
26
+ }
27
+ this.deliver("*", event, ...args);
28
+ }
29
+ subscribe(event, handler) {
30
+ const uuid = `uuid_${++count}`;
31
+ if (typeof event === "string") {
32
+ if (!this.events.has(event)) {
33
+ this.events.set(event, new Map());
34
+ }
35
+ const handlers = this.events.get(event);
36
+ handlers.set(uuid, handler);
37
+ this.tokens.set(uuid, event);
38
+ }
39
+ return uuid;
40
+ }
41
+ unsubscribe(value) {
42
+ if (typeof value === "string" && value.startsWith("uuid")) {
43
+ const path = this.tokens.get(value);
44
+ if (typeof path === "undefined") {
45
+ return;
46
+ }
47
+ const innerPath = this.events.get(path);
48
+ innerPath == null ? void 0 : innerPath.delete(value);
49
+ this.tokens.delete(value);
50
+ return;
51
+ }
52
+ if (typeof value === "string") {
53
+ for (const key of this.events.keys()) {
54
+ if (key.indexOf(value) === 0) {
55
+ const tokens = this.events.get(key);
56
+ if (tokens && tokens.size) {
57
+ for (const token of tokens.keys()) {
58
+ this.tokens.delete(token);
59
+ }
60
+ }
61
+ this.events.delete(key);
62
+ }
63
+ }
64
+ }
65
+ }
66
+ count(event) {
67
+ let counter = 0;
68
+ if (typeof event === "undefined") {
69
+ for (const handlers2 of this.events.values()) {
70
+ counter += handlers2.size;
71
+ }
72
+ return counter;
73
+ }
74
+ const handlers = this.events.get(event);
75
+ if (handlers == null ? void 0 : handlers.size) {
76
+ return handlers.size;
77
+ }
78
+ return counter;
79
+ }
80
+ clear() {
81
+ this.events.clear();
82
+ this.tokens.clear();
83
+ }
84
+ deliver(path, event, ...args) {
85
+ const handlers = this.events.get(path);
86
+ if (handlers && handlers.size) {
87
+ for (const handler of handlers.values()) {
88
+ handler(event, ...args);
89
+ }
90
+ }
91
+ }
92
+ }
93
+ const pubsub = new TinyPubSub();
2
94
 
3
95
  const PubSubPluginSymbol = Symbol.for("PubSubPlugin");
4
96
 
@@ -8,28 +100,74 @@ const _PubSubPlugin = class {
8
100
  this.symbol = _PubSubPlugin.Symbol;
9
101
  var _a;
10
102
  this.expressionName = (_a = config == null ? void 0 : config.expressionName) != null ? _a : "publish";
103
+ this.pubsub = pubsub;
11
104
  }
12
105
  apply(player) {
106
+ const existing = player.findPlugin(PubSubPluginSymbol);
107
+ if (existing !== void 0) {
108
+ this.pubsub = existing.pubsub;
109
+ }
13
110
  player.hooks.expressionEvaluator.tap(this.name, (expEvaluator) => {
14
- expEvaluator.addExpressionFunction(this.expressionName, (_ctx, event, data) => {
15
- if (typeof event === "string") {
16
- this.publish(event, data);
17
- }
18
- });
111
+ const existingExpression = expEvaluator.operators.expressions.get(this.expressionName);
112
+ if (existingExpression) {
113
+ player.logger.warn(`[PubSubPlugin] expression ${this.expressionName} is already registered.`);
114
+ } else {
115
+ expEvaluator.addExpressionFunction(this.expressionName, (_ctx, event, ...args) => {
116
+ if (typeof event === "string") {
117
+ this.publish(event, ...args);
118
+ }
119
+ });
120
+ }
121
+ });
122
+ player.hooks.onEnd.tap(this.name, () => {
123
+ this.clear();
19
124
  });
20
125
  }
21
- publish(event, data) {
22
- pubsub.publishSync(event, data);
126
+ publish(event, ...args) {
127
+ this.pubsub.publish(event, ...args);
23
128
  }
24
129
  subscribe(event, handler) {
25
- return pubsub.subscribe(event, handler);
130
+ return this.pubsub.subscribe(event, handler);
26
131
  }
27
132
  unsubscribe(token) {
28
- pubsub.unsubscribe(token);
133
+ this.pubsub.unsubscribe(token);
134
+ }
135
+ clear() {
136
+ this.pubsub.clear();
29
137
  }
30
138
  };
31
139
  let PubSubPlugin = _PubSubPlugin;
32
140
  PubSubPlugin.Symbol = PubSubPluginSymbol;
33
141
 
34
- export { PubSubPlugin, PubSubPluginSymbol };
142
+ function getPubSubPlugin(player) {
143
+ const existing = player.findPlugin(PubSubPluginSymbol);
144
+ const plugin = existing || new PubSubPlugin();
145
+ if (!existing) {
146
+ player.registerPlugin(plugin);
147
+ }
148
+ return plugin;
149
+ }
150
+
151
+ class PubSubHandlerPlugin {
152
+ constructor(subscriptions) {
153
+ this.name = "pubsub-handler";
154
+ this.subscriptions = subscriptions;
155
+ }
156
+ apply(player) {
157
+ const pubsub = getPubSubPlugin(player);
158
+ player.hooks.onStart.tap(this.name, () => {
159
+ this.subscriptions.forEach((handler, key) => {
160
+ pubsub.subscribe(key, (_, ...args) => {
161
+ const state = player.getState();
162
+ if (state.status === "in-progress") {
163
+ return handler(state, ...args);
164
+ }
165
+ player.logger.info(`[PubSubHandlerPlugin] subscriber for ${key} was called when player was not in-progress`);
166
+ });
167
+ });
168
+ });
169
+ }
170
+ }
171
+
172
+ export { PubSubHandlerPlugin, PubSubPlugin, PubSubPluginSymbol };
35
173
  //# sourceMappingURL=index.esm.js.map