@player-ui/pubsub-plugin 0.3.1-next.0 → 0.3.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
@@ -0,0 +1,289 @@
1
+ (function webpackUniversalModuleDefinition(root, factory) {
2
+ if(typeof exports === 'object' && typeof module === 'object')
3
+ module.exports = factory();
4
+ else if(typeof define === 'function' && define.amd)
5
+ define([], factory);
6
+ else if(typeof exports === 'object')
7
+ exports["PubSubPlugin"] = factory();
8
+ else
9
+ root["PubSubPlugin"] = factory();
10
+ })(this, function() {
11
+ return /******/ (function(modules) { // webpackBootstrap
12
+ /******/ // The module cache
13
+ /******/ var installedModules = {};
14
+ /******/
15
+ /******/ // The require function
16
+ /******/ function __webpack_require__(moduleId) {
17
+ /******/
18
+ /******/ // Check if module is in cache
19
+ /******/ if(installedModules[moduleId]) {
20
+ /******/ return installedModules[moduleId].exports;
21
+ /******/ }
22
+ /******/ // Create a new module (and put it into the cache)
23
+ /******/ var module = installedModules[moduleId] = {
24
+ /******/ i: moduleId,
25
+ /******/ l: false,
26
+ /******/ exports: {}
27
+ /******/ };
28
+ /******/
29
+ /******/ // Execute the module function
30
+ /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
31
+ /******/
32
+ /******/ // Flag the module as loaded
33
+ /******/ module.l = true;
34
+ /******/
35
+ /******/ // Return the exports of the module
36
+ /******/ return module.exports;
37
+ /******/ }
38
+ /******/
39
+ /******/
40
+ /******/ // expose the modules object (__webpack_modules__)
41
+ /******/ __webpack_require__.m = modules;
42
+ /******/
43
+ /******/ // expose the module cache
44
+ /******/ __webpack_require__.c = installedModules;
45
+ /******/
46
+ /******/ // define getter function for harmony exports
47
+ /******/ __webpack_require__.d = function(exports, name, getter) {
48
+ /******/ if(!__webpack_require__.o(exports, name)) {
49
+ /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
50
+ /******/ }
51
+ /******/ };
52
+ /******/
53
+ /******/ // define __esModule on exports
54
+ /******/ __webpack_require__.r = function(exports) {
55
+ /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
56
+ /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
57
+ /******/ }
58
+ /******/ Object.defineProperty(exports, '__esModule', { value: true });
59
+ /******/ };
60
+ /******/
61
+ /******/ // create a fake namespace object
62
+ /******/ // mode & 1: value is a module id, require it
63
+ /******/ // mode & 2: merge all properties of value into the ns
64
+ /******/ // mode & 4: return value when already ns object
65
+ /******/ // mode & 8|1: behave like require
66
+ /******/ __webpack_require__.t = function(value, mode) {
67
+ /******/ if(mode & 1) value = __webpack_require__(value);
68
+ /******/ if(mode & 8) return value;
69
+ /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
70
+ /******/ var ns = Object.create(null);
71
+ /******/ __webpack_require__.r(ns);
72
+ /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
73
+ /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
74
+ /******/ return ns;
75
+ /******/ };
76
+ /******/
77
+ /******/ // getDefaultExport function for compatibility with non-harmony modules
78
+ /******/ __webpack_require__.n = function(module) {
79
+ /******/ var getter = module && module.__esModule ?
80
+ /******/ function getDefault() { return module['default']; } :
81
+ /******/ function getModuleExports() { return module; };
82
+ /******/ __webpack_require__.d(getter, 'a', getter);
83
+ /******/ return getter;
84
+ /******/ };
85
+ /******/
86
+ /******/ // Object.prototype.hasOwnProperty.call
87
+ /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
88
+ /******/
89
+ /******/ // __webpack_public_path__
90
+ /******/ __webpack_require__.p = "";
91
+ /******/
92
+ /******/
93
+ /******/ // Load entry module and return exports
94
+ /******/ return __webpack_require__(__webpack_require__.s = "./bazel-out/k8-fastbuild/bin/plugins/pubsub/core/dist/index.esm.js");
95
+ /******/ })
96
+ /************************************************************************/
97
+ /******/ ({
98
+
99
+ /***/ "./bazel-out/k8-fastbuild/bin/plugins/pubsub/core/dist/index.esm.js":
100
+ /*!**************************************************************************!*\
101
+ !*** ./bazel-out/k8-fastbuild/bin/plugins/pubsub/core/dist/index.esm.js ***!
102
+ \**************************************************************************/
103
+ /*! exports provided: PubSubHandlerPlugin, PubSubPlugin, PubSubPluginSymbol */
104
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
105
+
106
+ "use strict";
107
+ __webpack_require__.r(__webpack_exports__);
108
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PubSubHandlerPlugin", function() { return PubSubHandlerPlugin; });
109
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PubSubPlugin", function() { return PubSubPlugin; });
110
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PubSubPluginSymbol", function() { return PubSubPluginSymbol; });
111
+ function splitEvent(event) {
112
+ return event.split(".").reduce((prev, curr, index) => {
113
+ if (index === 0) {
114
+ return [curr];
115
+ }
116
+ return [...prev, `${prev[index - 1]}.${curr}`];
117
+ }, []);
118
+ }
119
+ let count = 1;
120
+ class TinyPubSub {
121
+ constructor() {
122
+ this.events = new Map();
123
+ this.tokens = new Map();
124
+ }
125
+ publish(event, ...args) {
126
+ if (typeof event !== "string") {
127
+ return;
128
+ }
129
+ if (event.includes(".")) {
130
+ const eventKeys = splitEvent(event);
131
+ eventKeys.forEach((key) => {
132
+ this.deliver(key, event, ...args);
133
+ });
134
+ } else {
135
+ this.deliver(event, event, ...args);
136
+ }
137
+ this.deliver("*", event, ...args);
138
+ }
139
+ subscribe(event, handler) {
140
+ const uuid = `uuid_${++count}`;
141
+ if (typeof event === "string") {
142
+ if (!this.events.has(event)) {
143
+ this.events.set(event, new Map());
144
+ }
145
+ const handlers = this.events.get(event);
146
+ handlers.set(uuid, handler);
147
+ this.tokens.set(uuid, event);
148
+ }
149
+ return uuid;
150
+ }
151
+ unsubscribe(value) {
152
+ if (typeof value === "string" && value.startsWith("uuid")) {
153
+ const path = this.tokens.get(value);
154
+ if (typeof path === "undefined") {
155
+ return;
156
+ }
157
+ const innerPath = this.events.get(path);
158
+ innerPath == null ? void 0 : innerPath.delete(value);
159
+ this.tokens.delete(value);
160
+ return;
161
+ }
162
+ if (typeof value === "string") {
163
+ for (const key of this.events.keys()) {
164
+ if (key.indexOf(value) === 0) {
165
+ const tokens = this.events.get(key);
166
+ if (tokens && tokens.size) {
167
+ for (const token of tokens.keys()) {
168
+ this.tokens.delete(token);
169
+ }
170
+ }
171
+ this.events.delete(key);
172
+ }
173
+ }
174
+ }
175
+ }
176
+ count(event) {
177
+ let counter = 0;
178
+ if (typeof event === "undefined") {
179
+ for (const handlers2 of this.events.values()) {
180
+ counter += handlers2.size;
181
+ }
182
+ return counter;
183
+ }
184
+ const handlers = this.events.get(event);
185
+ if (handlers == null ? void 0 : handlers.size) {
186
+ return handlers.size;
187
+ }
188
+ return counter;
189
+ }
190
+ clear() {
191
+ this.events.clear();
192
+ this.tokens.clear();
193
+ }
194
+ deliver(path, event, ...args) {
195
+ const handlers = this.events.get(path);
196
+ if (handlers && handlers.size) {
197
+ for (const handler of handlers.values()) {
198
+ handler(event, ...args);
199
+ }
200
+ }
201
+ }
202
+ }
203
+ const pubsub = new TinyPubSub();
204
+
205
+ const PubSubPluginSymbol = Symbol.for("PubSubPlugin");
206
+
207
+ const _PubSubPlugin = class {
208
+ constructor(config) {
209
+ this.name = "pub-sub";
210
+ this.symbol = _PubSubPlugin.Symbol;
211
+ var _a;
212
+ this.expressionName = (_a = config == null ? void 0 : config.expressionName) != null ? _a : "publish";
213
+ this.pubsub = pubsub;
214
+ }
215
+ apply(player) {
216
+ const existing = player.findPlugin(PubSubPluginSymbol);
217
+ if (existing !== void 0) {
218
+ this.pubsub = existing.pubsub;
219
+ }
220
+ player.hooks.expressionEvaluator.tap(this.name, (expEvaluator) => {
221
+ const existingExpression = expEvaluator.operators.expressions.get(this.expressionName);
222
+ if (existingExpression) {
223
+ player.logger.warn(`[PubSubPlugin] expression ${this.expressionName} is already registered.`);
224
+ } else {
225
+ expEvaluator.addExpressionFunction(this.expressionName, (_ctx, event, ...args) => {
226
+ if (typeof event === "string") {
227
+ this.publish(event, ...args);
228
+ }
229
+ });
230
+ }
231
+ });
232
+ player.hooks.onEnd.tap(this.name, () => {
233
+ this.clear();
234
+ });
235
+ }
236
+ publish(event, ...args) {
237
+ this.pubsub.publish(event, ...args);
238
+ }
239
+ subscribe(event, handler) {
240
+ return this.pubsub.subscribe(event, handler);
241
+ }
242
+ unsubscribe(token) {
243
+ this.pubsub.unsubscribe(token);
244
+ }
245
+ clear() {
246
+ this.pubsub.clear();
247
+ }
248
+ };
249
+ let PubSubPlugin = _PubSubPlugin;
250
+ PubSubPlugin.Symbol = PubSubPluginSymbol;
251
+
252
+ function getPubSubPlugin(player) {
253
+ const existing = player.findPlugin(PubSubPluginSymbol);
254
+ const plugin = existing || new PubSubPlugin();
255
+ if (!existing) {
256
+ player.registerPlugin(plugin);
257
+ }
258
+ return plugin;
259
+ }
260
+
261
+ class PubSubHandlerPlugin {
262
+ constructor(subscriptions) {
263
+ this.name = "pubsub-handler";
264
+ this.subscriptions = subscriptions;
265
+ }
266
+ apply(player) {
267
+ const pubsub = getPubSubPlugin(player);
268
+ player.hooks.onStart.tap(this.name, () => {
269
+ this.subscriptions.forEach((handler, key) => {
270
+ pubsub.subscribe(key, (_, ...args) => {
271
+ const state = player.getState();
272
+ if (state.status === "in-progress") {
273
+ return handler(state, ...args);
274
+ }
275
+ player.logger.info(`[PubSubHandlerPlugin] subscriber for ${key} was called when player was not in-progress`);
276
+ });
277
+ });
278
+ });
279
+ }
280
+ }
281
+
282
+
283
+ //# sourceMappingURL=index.esm.js.map
284
+
285
+
286
+ /***/ })
287
+
288
+ /******/ });
289
+ });
@@ -0,0 +1 @@
1
+ !function(e,t){"object"===typeof exports&&"object"===typeof module?module.exports=t():"function"===typeof define&&define.amd?define([],t):"object"===typeof exports?exports.PubSubPlugin=t():e.PubSubPlugin=t()}(this,(function(){return function(e){var t={};function s(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,s),i.l=!0,i.exports}return s.m=e,s.c=t,s.d=function(e,t,n){s.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},s.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},s.t=function(e,t){if(1&t&&(e=s(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(s.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)s.d(n,i,function(t){return e[t]}.bind(null,i));return n},s.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return s.d(t,"a",t),t},s.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},s.p="",s(s.s=0)}([function(e,t,s){"use strict";s.r(t),s.d(t,"PubSubHandlerPlugin",(function(){return l})),s.d(t,"PubSubPlugin",(function(){return u})),s.d(t,"PubSubPluginSymbol",(function(){return r}));let n=1;const i=new class{constructor(){this.events=new Map,this.tokens=new Map}publish(e,...t){if("string"===typeof e){if(e.includes(".")){const s=function(e){return e.split(".").reduce(((e,t,s)=>0===s?[t]:[...e,`${e[s-1]}.${t}`]),[])}(e);s.forEach((s=>{this.deliver(s,e,...t)}))}else this.deliver(e,e,...t);this.deliver("*",e,...t)}}subscribe(e,t){const s="uuid_"+ ++n;if("string"===typeof e){this.events.has(e)||this.events.set(e,new Map);this.events.get(e).set(s,t),this.tokens.set(s,e)}return s}unsubscribe(e){if("string"===typeof e&&e.startsWith("uuid")){const t=this.tokens.get(e);if("undefined"===typeof t)return;const s=this.events.get(t);return null==s||s.delete(e),void this.tokens.delete(e)}if("string"===typeof e)for(const t of this.events.keys())if(0===t.indexOf(e)){const e=this.events.get(t);if(e&&e.size)for(const t of e.keys())this.tokens.delete(t);this.events.delete(t)}}count(e){let t=0;if("undefined"===typeof e){for(const e of this.events.values())t+=e.size;return t}const s=this.events.get(e);return(null==s?void 0:s.size)?s.size:t}clear(){this.events.clear(),this.tokens.clear()}deliver(e,t,...s){const n=this.events.get(e);if(n&&n.size)for(const i of n.values())i(t,...s)}},r=Symbol.for("PubSubPlugin"),o=class{constructor(e){var t;this.name="pub-sub",this.symbol=o.Symbol,this.expressionName=null!=(t=null==e?void 0:e.expressionName)?t:"publish",this.pubsub=i}apply(e){const t=e.findPlugin(r);void 0!==t&&(this.pubsub=t.pubsub),e.hooks.expressionEvaluator.tap(this.name,(t=>{t.operators.expressions.get(this.expressionName)?e.logger.warn(`[PubSubPlugin] expression ${this.expressionName} is already registered.`):t.addExpressionFunction(this.expressionName,((e,t,...s)=>{"string"===typeof t&&this.publish(t,...s)}))})),e.hooks.onEnd.tap(this.name,(()=>{this.clear()}))}publish(e,...t){this.pubsub.publish(e,...t)}subscribe(e,t){return this.pubsub.subscribe(e,t)}unsubscribe(e){this.pubsub.unsubscribe(e)}clear(){this.pubsub.clear()}};let u=o;u.Symbol=r;class l{constructor(e){this.name="pubsub-handler",this.subscriptions=e}apply(e){const t=function(e){const t=e.findPlugin(r),s=t||new u;return t||e.registerPlugin(s),s}(e);e.hooks.onStart.tap(this.name,(()=>{this.subscriptions.forEach(((s,n)=>{t.subscribe(n,((t,...i)=>{const r=e.getState();if("in-progress"===r.status)return s(r,...i);e.logger.info(`[PubSubHandlerPlugin] subscriber for ${n} was called when player was not in-progress`)}))}))}))}}}])}));
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@player-ui/pubsub-plugin",
3
- "version": "0.3.1-next.0",
3
+ "version": "0.3.1",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org"
7
7
  },
8
8
  "peerDependencies": {
9
- "@player-ui/player": "0.3.1-next.0"
9
+ "@player-ui/player": "0.3.1"
10
10
  },
11
11
  "dependencies": {
12
- "tapable-ts": "^0.1.0",
12
+ "tapable-ts": "^0.2.3",
13
13
  "pubsub-js": "^1.9.3",
14
14
  "@types/pubsub-js": "^1.8.3",
15
15
  "@babel/runtime": "7.15.4"
@@ -55,6 +55,15 @@
55
55
  {
56
56
  "name": "Kelly Harrop",
57
57
  "url": "https://github.com/kharrop"
58
+ },
59
+ {
60
+ "name": "Alejandro Fimbres",
61
+ "url": "https://github.com/lexfm"
62
+ },
63
+ {
64
+ "name": "Rafael Campos",
65
+ "url": "https://github.com/rafbcampos"
58
66
  }
59
- ]
67
+ ],
68
+ "bundle": "./dist/pubsub-plugin.prod.js"
60
69
  }
package/src/handler.ts ADDED
@@ -0,0 +1,41 @@
1
+ import type { Player, PlayerPlugin, InProgressState } from '@player-ui/player';
2
+ import { getPubSubPlugin } from './utils';
3
+
4
+ export type PubSubHandler<T extends unknown[]> = (
5
+ context: InProgressState,
6
+ ...args: T
7
+ ) => void;
8
+
9
+ export type SubscriptionMap = Map<string, PubSubHandler<any>>;
10
+
11
+ /**
12
+ * Plugin to easily add subscribers to the PubSubPlugin
13
+ */
14
+ export class PubSubHandlerPlugin implements PlayerPlugin {
15
+ name = 'pubsub-handler';
16
+ private subscriptions: SubscriptionMap;
17
+
18
+ constructor(subscriptions: SubscriptionMap) {
19
+ this.subscriptions = subscriptions;
20
+ }
21
+
22
+ apply(player: Player) {
23
+ const pubsub = getPubSubPlugin(player);
24
+
25
+ player.hooks.onStart.tap(this.name, () => {
26
+ this.subscriptions.forEach((handler, key) => {
27
+ pubsub.subscribe(key, (_, ...args) => {
28
+ const state = player.getState();
29
+
30
+ if (state.status === 'in-progress') {
31
+ return handler(state, ...args);
32
+ }
33
+
34
+ player.logger.info(
35
+ `[PubSubHandlerPlugin] subscriber for ${key} was called when player was not in-progress`
36
+ );
37
+ });
38
+ });
39
+ });
40
+ }
41
+ }
package/src/index.ts CHANGED
@@ -1,2 +1,3 @@
1
- export * from './pubsub';
1
+ export * from './plugin';
2
2
  export * from './symbols';
3
+ export * from './handler';
package/src/plugin.ts ADDED
@@ -0,0 +1,112 @@
1
+ import type {
2
+ Player,
3
+ PlayerPlugin,
4
+ ExpressionContext,
5
+ } from '@player-ui/player';
6
+ import type { SubscribeHandler, TinyPubSub } from './pubsub';
7
+ import { pubsub } from './pubsub';
8
+ import { PubSubPluginSymbol } from './symbols';
9
+
10
+ export interface PubSubConfig {
11
+ /** A custom expression name to register */
12
+ expressionName: string;
13
+ }
14
+
15
+ /**
16
+ * The PubSubPlugin is a great way to enable your FRF content to publish events back to your app
17
+ * It injects a publish() function into the expression language, and will forward all events back to any subscribers.
18
+ *
19
+ * Published/Subscribed events support a hierarchy:
20
+ * - publish('foo', 'data') -- will trigger any listeners for 'foo'
21
+ * - publish('foo.bar', 'data') -- will trigger any listeners for 'foo' or 'foo.bar'
22
+ *
23
+ */
24
+ export class PubSubPlugin implements PlayerPlugin {
25
+ name = 'pub-sub';
26
+
27
+ static Symbol = PubSubPluginSymbol;
28
+ public readonly symbol = PubSubPlugin.Symbol;
29
+
30
+ protected pubsub: TinyPubSub;
31
+
32
+ private expressionName: string;
33
+
34
+ constructor(config?: PubSubConfig) {
35
+ this.expressionName = config?.expressionName ?? 'publish';
36
+ this.pubsub = pubsub;
37
+ }
38
+
39
+ apply(player: Player) {
40
+ // if there is already a pubsub plugin, reuse its pubsub instance
41
+ // to maintain the singleton across bundles for iOS/Android
42
+ const existing = player.findPlugin<PubSubPlugin>(PubSubPluginSymbol);
43
+ if (existing !== undefined) {
44
+ this.pubsub = existing.pubsub;
45
+ }
46
+
47
+ player.hooks.expressionEvaluator.tap(this.name, (expEvaluator) => {
48
+ const existingExpression = expEvaluator.operators.expressions.get(
49
+ this.expressionName
50
+ );
51
+
52
+ if (existingExpression) {
53
+ player.logger.warn(
54
+ `[PubSubPlugin] expression ${this.expressionName} is already registered.`
55
+ );
56
+ } else {
57
+ expEvaluator.addExpressionFunction(
58
+ this.expressionName,
59
+ (_ctx: ExpressionContext, event: unknown, ...args: unknown[]) => {
60
+ if (typeof event === 'string') {
61
+ this.publish(event, ...args);
62
+ }
63
+ }
64
+ );
65
+ }
66
+ });
67
+
68
+ player.hooks.onEnd.tap(this.name, () => {
69
+ this.clear();
70
+ });
71
+ }
72
+
73
+ /**
74
+ * A way of publishing an event, notifying any listeners
75
+ *
76
+ * @param event - The name of the event to publish. Can take sub-topics like: foo.bar
77
+ * @param data - Any additional data to attach to the event
78
+ */
79
+ publish(event: string, ...args: unknown[]) {
80
+ this.pubsub.publish(event, ...args);
81
+ }
82
+
83
+ /**
84
+ * Subscribe to an event with the given name. The handler will get called for any published event
85
+ *
86
+ * @param event - The name of the event to subscribe to
87
+ * @param handler - A function to be called when the event is triggered
88
+ * @returns A token to be used to unsubscribe from the event
89
+ */
90
+ subscribe<T extends string, A extends unknown[]>(
91
+ event: T,
92
+ handler: SubscribeHandler<T, A>
93
+ ) {
94
+ return this.pubsub.subscribe(event, handler);
95
+ }
96
+
97
+ /**
98
+ * Remove any subscriptions using the given token
99
+ *
100
+ * @param token - A token from a `subscribe` call
101
+ */
102
+ unsubscribe(token: string) {
103
+ this.pubsub.unsubscribe(token);
104
+ }
105
+
106
+ /**
107
+ * Remove all subscriptions
108
+ */
109
+ clear() {
110
+ this.pubsub.clear();
111
+ }
112
+ }
package/src/pubsub.ts CHANGED
@@ -1,77 +1,173 @@
1
- import pubsub from 'pubsub-js';
2
- import type {
3
- Player,
4
- PlayerPlugin,
5
- ExpressionContext,
6
- } from '@player-ui/player';
7
- import { PubSubPluginSymbol } from './symbols';
8
-
9
- export interface PubSubConfig {
10
- /** A custom expression name to register */
11
- expressionName: string;
12
- }
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
+
6
+ export type SubscribeHandler<T extends string, A extends unknown[]> = (
7
+ type: T,
8
+ ...args: A
9
+ ) => void;
10
+
11
+ export type PubSubUUID = `uuid_${number}`;
13
12
 
14
13
  /**
15
- * The PubSubPlugin is a great way to enable your Content content to publish events back to your app
16
- * It injects a publish() function into the expression language, and will forward all events back to any subscribers.
17
- *
18
- * Published/Subscribed events support a hierarchy:
19
- * - publish('foo', 'data') -- will trigger any listeners for 'foo'
20
- * - publish('foo.bar', 'data') -- will trigger any listeners for 'foo' or 'foo.bar'
21
- *
14
+ * Split a string into an array of event layers
22
15
  */
23
- export class PubSubPlugin implements PlayerPlugin {
24
- name = 'pub-sub';
16
+ function splitEvent(event: string) {
17
+ return event.split('.').reduce<string[]>((prev, curr, index) => {
18
+ if (index === 0) {
19
+ return [curr];
20
+ }
25
21
 
26
- static Symbol = PubSubPluginSymbol;
27
- public readonly symbol = PubSubPlugin.Symbol;
22
+ return [...prev, `${prev[index - 1]}.${curr}`];
23
+ }, []);
24
+ }
28
25
 
29
- private expressionName: string;
26
+ let count = 1;
30
27
 
31
- constructor(config?: PubSubConfig) {
32
- this.expressionName = config?.expressionName ?? 'publish';
28
+ /**
29
+ * Tiny pubsub maker
30
+ */
31
+ export class TinyPubSub {
32
+ private events: Map<string, Map<PubSubUUID, SubscribeHandler<any, any>>>;
33
+ private tokens: Map<PubSubUUID, string>;
34
+
35
+ constructor() {
36
+ this.events = new Map();
37
+ this.tokens = new Map();
33
38
  }
34
39
 
35
- apply(player: Player) {
36
- player.hooks.expressionEvaluator.tap(this.name, (expEvaluator) => {
37
- expEvaluator.addExpressionFunction(
38
- this.expressionName,
39
- (_ctx: ExpressionContext, event: unknown, data: unknown) => {
40
- if (typeof event === 'string') {
41
- this.publish(event, data);
42
- }
43
- }
44
- );
45
- });
40
+ /**
41
+ * Publish an event with any number of additional arguments
42
+ */
43
+ publish(event: string, ...args: unknown[]) {
44
+ if (typeof event !== 'string') {
45
+ return;
46
+ }
47
+
48
+ if (event.includes('.')) {
49
+ const eventKeys = splitEvent(event);
50
+
51
+ eventKeys.forEach((key) => {
52
+ this.deliver(key, event, ...args);
53
+ });
54
+ } else {
55
+ this.deliver(event, event, ...args);
56
+ }
57
+
58
+ this.deliver('*', event, ...args);
46
59
  }
47
60
 
48
61
  /**
49
- * A way of publishing an event, notifying any listeners
62
+ * Subscribe to an event
63
+ *
64
+ * Events are also heirarchical when separated by a period. Given the following:
50
65
  *
51
- * @param event - The name of the event to publish. Can take sub-topics like: foo.bar
52
- * @param data - Any additional data to attach to the event
66
+ * publish('a.b.c', 'one', 'two', 'three)
67
+ *
68
+ * The subscribe event will be called when the event is passed as 'a', 'a.b', or 'a.b.c'.
69
+ *
70
+ * @example
71
+ * // subscribes to the top level 'a' publish
72
+ * subscribe('a', (event, ...args) => console.log(event, ...args))
53
73
  */
54
- publish(event: string, data: unknown) {
55
- pubsub.publishSync(event, data);
74
+ subscribe(event: string, handler: SubscribeHandler<any, any>) {
75
+ const uuid = `uuid_${++count}`;
76
+
77
+ if (typeof event === 'string') {
78
+ if (!this.events.has(event)) {
79
+ this.events.set(event, new Map());
80
+ }
81
+
82
+ const handlers = this.events.get(event);
83
+ handlers!.set(uuid as PubSubUUID, handler);
84
+ this.tokens.set(uuid as PubSubUUID, event);
85
+ }
86
+
87
+ return uuid;
56
88
  }
57
89
 
58
90
  /**
59
- * Subscribe to an event with the given name. The handler will get called for any published event
91
+ * Unsubscribes to a specific subscription given it's symbol or an entire
92
+ * event when passed as a string.
60
93
  *
61
- * @param event - The name of the event to subscribe to
62
- * @param handler - A function to be called when the event is triggered
63
- * @returns A token to be used to unsubscribe from the event
94
+ * When existing subscriptions exist for heirarchical events such as 'a.b.c',
95
+ * when passing an event 'a' to unsubscribe, all subscriptions for 'a', 'a.b',
96
+ * & 'a.b.c' will be unsubscribed as well.
64
97
  */
65
- subscribe(event: string, handler: (e: string, data: unknown) => void) {
66
- return pubsub.subscribe(event, handler);
98
+ unsubscribe(value: string | symbol) {
99
+ if (typeof value === 'string' && value.startsWith('uuid')) {
100
+ const path = this.tokens.get(value as PubSubUUID);
101
+
102
+ if (typeof path === 'undefined') {
103
+ return;
104
+ }
105
+
106
+ const innerPath = this.events.get(path);
107
+ innerPath?.delete(value as PubSubUUID);
108
+ this.tokens.delete(value as PubSubUUID);
109
+ return;
110
+ }
111
+
112
+ if (typeof value === 'string') {
113
+ for (const key of this.events.keys()) {
114
+ if (key.indexOf(value) === 0) {
115
+ const tokens = this.events.get(key);
116
+
117
+ if (tokens && tokens.size) {
118
+ // eslint-disable-next-line max-depth
119
+ for (const token of tokens.keys()) {
120
+ this.tokens.delete(token);
121
+ }
122
+ }
123
+
124
+ this.events.delete(key);
125
+ }
126
+ }
127
+ }
67
128
  }
68
129
 
69
130
  /**
70
- * Remove any subscriptions using the given token
71
- *
72
- * @param token - A token from a `subscribe` call
131
+ * Get the number of subscriptions for a specific event, or when left blank
132
+ * will return the overall number of subscriptions for the entire pubsub.
73
133
  */
74
- unsubscribe(token: string) {
75
- pubsub.unsubscribe(token);
134
+ count(event?: string) {
135
+ let counter = 0;
136
+
137
+ if (typeof event === 'undefined') {
138
+ for (const handlers of this.events.values()) {
139
+ counter += handlers.size;
140
+ }
141
+
142
+ return counter;
143
+ }
144
+
145
+ const handlers = this.events.get(event);
146
+
147
+ if (handlers?.size) {
148
+ return handlers.size;
149
+ }
150
+
151
+ return counter;
152
+ }
153
+
154
+ /**
155
+ * Deletes all existing subscriptions
156
+ */
157
+ clear() {
158
+ this.events.clear();
159
+ this.tokens.clear();
160
+ }
161
+
162
+ private deliver(path: string, event: string, ...args: unknown[]) {
163
+ const handlers = this.events.get(path);
164
+
165
+ if (handlers && handlers.size) {
166
+ for (const handler of handlers.values()) {
167
+ handler(event, ...args);
168
+ }
169
+ }
76
170
  }
77
171
  }
172
+
173
+ export const pubsub = new TinyPubSub();
package/src/utils.ts ADDED
@@ -0,0 +1,17 @@
1
+ import type { Player } from '@player-ui/player';
2
+ import { PubSubPlugin } from './plugin';
3
+ import { PubSubPluginSymbol } from './symbols';
4
+
5
+ /**
6
+ * Returns the existing PubSubPlugin or creates and registers a new plugin
7
+ */
8
+ export function getPubSubPlugin(player: Player) {
9
+ const existing = player.findPlugin<PubSubPlugin>(PubSubPluginSymbol);
10
+ const plugin = existing || new PubSubPlugin();
11
+
12
+ if (!existing) {
13
+ player.registerPlugin(plugin);
14
+ }
15
+
16
+ return plugin;
17
+ }