@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
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/pubsub/core/src/pubsub.ts
|
|
1
2
|
function splitEvent(event) {
|
|
2
3
|
return event.split(".").reduce((prev, curr, index) => {
|
|
3
4
|
if (index === 0) {
|
|
@@ -6,12 +7,15 @@ function splitEvent(event) {
|
|
|
6
7
|
return [...prev, `${prev[index - 1]}.${curr}`];
|
|
7
8
|
}, []);
|
|
8
9
|
}
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
var count = 1;
|
|
11
|
+
var TinyPubSub = class {
|
|
11
12
|
constructor() {
|
|
12
|
-
this.events = new Map();
|
|
13
|
-
this.tokens = new Map();
|
|
13
|
+
this.events = /* @__PURE__ */ new Map();
|
|
14
|
+
this.tokens = /* @__PURE__ */ new Map();
|
|
14
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Publish an event with any number of additional arguments
|
|
18
|
+
*/
|
|
15
19
|
publish(event, ...args) {
|
|
16
20
|
if (typeof event !== "string") {
|
|
17
21
|
return;
|
|
@@ -26,11 +30,24 @@ class TinyPubSub {
|
|
|
26
30
|
}
|
|
27
31
|
this.deliver("*", event, ...args);
|
|
28
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Subscribe to an event
|
|
35
|
+
*
|
|
36
|
+
* Events are also heirarchical when separated by a period. Given the following:
|
|
37
|
+
*
|
|
38
|
+
* publish('a.b.c', 'one', 'two', 'three)
|
|
39
|
+
*
|
|
40
|
+
* The subscribe event will be called when the event is passed as 'a', 'a.b', or 'a.b.c'.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* // subscribes to the top level 'a' publish
|
|
44
|
+
* subscribe('a', (event, ...args) => console.log(event, ...args))
|
|
45
|
+
*/
|
|
29
46
|
subscribe(event, handler) {
|
|
30
47
|
const uuid = `uuid_${++count}`;
|
|
31
48
|
if (typeof event === "string") {
|
|
32
49
|
if (!this.events.has(event)) {
|
|
33
|
-
this.events.set(event, new Map());
|
|
50
|
+
this.events.set(event, /* @__PURE__ */ new Map());
|
|
34
51
|
}
|
|
35
52
|
const handlers = this.events.get(event);
|
|
36
53
|
handlers.set(uuid, handler);
|
|
@@ -38,6 +55,14 @@ class TinyPubSub {
|
|
|
38
55
|
}
|
|
39
56
|
return uuid;
|
|
40
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Unsubscribes to a specific subscription given it's symbol or an entire
|
|
60
|
+
* event when passed as a string.
|
|
61
|
+
*
|
|
62
|
+
* When existing subscriptions exist for heirarchical events such as 'a.b.c',
|
|
63
|
+
* when passing an event 'a' to unsubscribe, all subscriptions for 'a', 'a.b',
|
|
64
|
+
* & 'a.b.c' will be unsubscribed as well.
|
|
65
|
+
*/
|
|
41
66
|
unsubscribe(value) {
|
|
42
67
|
if (typeof value === "string" && value.startsWith("uuid")) {
|
|
43
68
|
const path = this.tokens.get(value);
|
|
@@ -45,7 +70,7 @@ class TinyPubSub {
|
|
|
45
70
|
return;
|
|
46
71
|
}
|
|
47
72
|
const innerPath = this.events.get(path);
|
|
48
|
-
innerPath
|
|
73
|
+
innerPath?.delete(value);
|
|
49
74
|
this.tokens.delete(value);
|
|
50
75
|
return;
|
|
51
76
|
}
|
|
@@ -63,6 +88,10 @@ class TinyPubSub {
|
|
|
63
88
|
}
|
|
64
89
|
}
|
|
65
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Get the number of subscriptions for a specific event, or when left blank
|
|
93
|
+
* will return the overall number of subscriptions for the entire pubsub.
|
|
94
|
+
*/
|
|
66
95
|
count(event) {
|
|
67
96
|
let counter = 0;
|
|
68
97
|
if (typeof event === "undefined") {
|
|
@@ -72,11 +101,14 @@ class TinyPubSub {
|
|
|
72
101
|
return counter;
|
|
73
102
|
}
|
|
74
103
|
const handlers = this.events.get(event);
|
|
75
|
-
if (handlers
|
|
104
|
+
if (handlers?.size) {
|
|
76
105
|
return handlers.size;
|
|
77
106
|
}
|
|
78
107
|
return counter;
|
|
79
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Deletes all existing subscriptions
|
|
111
|
+
*/
|
|
80
112
|
clear() {
|
|
81
113
|
this.events.clear();
|
|
82
114
|
this.tokens.clear();
|
|
@@ -89,17 +121,18 @@ class TinyPubSub {
|
|
|
89
121
|
}
|
|
90
122
|
}
|
|
91
123
|
}
|
|
92
|
-
}
|
|
93
|
-
|
|
124
|
+
};
|
|
125
|
+
var pubsub = new TinyPubSub();
|
|
94
126
|
|
|
95
|
-
|
|
127
|
+
// ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/pubsub/core/src/symbols.ts
|
|
128
|
+
var PubSubPluginSymbol = Symbol.for("PubSubPlugin");
|
|
96
129
|
|
|
97
|
-
|
|
130
|
+
// ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/pubsub/core/src/plugin.ts
|
|
131
|
+
var _PubSubPlugin = class _PubSubPlugin {
|
|
98
132
|
constructor(config) {
|
|
99
133
|
this.name = "pub-sub";
|
|
100
134
|
this.symbol = _PubSubPlugin.Symbol;
|
|
101
|
-
|
|
102
|
-
this.expressionName = (_a = config == null ? void 0 : config.expressionName) != null ? _a : "publish";
|
|
135
|
+
this.expressionName = config?.expressionName ?? "publish";
|
|
103
136
|
this.pubsub = pubsub;
|
|
104
137
|
}
|
|
105
138
|
apply(player) {
|
|
@@ -108,37 +141,66 @@ const _PubSubPlugin = class {
|
|
|
108
141
|
this.pubsub = existing.pubsub;
|
|
109
142
|
}
|
|
110
143
|
player.hooks.expressionEvaluator.tap(this.name, (expEvaluator) => {
|
|
111
|
-
const existingExpression = expEvaluator.operators.expressions.get(
|
|
144
|
+
const existingExpression = expEvaluator.operators.expressions.get(
|
|
145
|
+
this.expressionName
|
|
146
|
+
);
|
|
112
147
|
if (existingExpression) {
|
|
113
|
-
player.logger.warn(
|
|
148
|
+
player.logger.warn(
|
|
149
|
+
`[PubSubPlugin] expression ${this.expressionName} is already registered.`
|
|
150
|
+
);
|
|
114
151
|
} else {
|
|
115
|
-
expEvaluator.addExpressionFunction(
|
|
116
|
-
|
|
117
|
-
|
|
152
|
+
expEvaluator.addExpressionFunction(
|
|
153
|
+
this.expressionName,
|
|
154
|
+
(_ctx, event, ...args) => {
|
|
155
|
+
if (typeof event === "string") {
|
|
156
|
+
this.publish(event, ...args);
|
|
157
|
+
}
|
|
118
158
|
}
|
|
119
|
-
|
|
159
|
+
);
|
|
120
160
|
}
|
|
121
161
|
});
|
|
122
162
|
player.hooks.onEnd.tap(this.name, () => {
|
|
123
163
|
this.clear();
|
|
124
164
|
});
|
|
125
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* A way of publishing an event, notifying any listeners
|
|
168
|
+
*
|
|
169
|
+
* @param event - The name of the event to publish. Can take sub-topics like: foo.bar
|
|
170
|
+
* @param data - Any additional data to attach to the event
|
|
171
|
+
*/
|
|
126
172
|
publish(event, ...args) {
|
|
127
173
|
this.pubsub.publish(event, ...args);
|
|
128
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Subscribe to an event with the given name. The handler will get called for any published event
|
|
177
|
+
*
|
|
178
|
+
* @param event - The name of the event to subscribe to
|
|
179
|
+
* @param handler - A function to be called when the event is triggered
|
|
180
|
+
* @returns A token to be used to unsubscribe from the event
|
|
181
|
+
*/
|
|
129
182
|
subscribe(event, handler) {
|
|
130
183
|
return this.pubsub.subscribe(event, handler);
|
|
131
184
|
}
|
|
185
|
+
/**
|
|
186
|
+
* Remove any subscriptions using the given token
|
|
187
|
+
*
|
|
188
|
+
* @param token - A token from a `subscribe` call
|
|
189
|
+
*/
|
|
132
190
|
unsubscribe(token) {
|
|
133
191
|
this.pubsub.unsubscribe(token);
|
|
134
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Remove all subscriptions
|
|
195
|
+
*/
|
|
135
196
|
clear() {
|
|
136
197
|
this.pubsub.clear();
|
|
137
198
|
}
|
|
138
199
|
};
|
|
139
|
-
|
|
140
|
-
PubSubPlugin
|
|
200
|
+
_PubSubPlugin.Symbol = PubSubPluginSymbol;
|
|
201
|
+
var PubSubPlugin = _PubSubPlugin;
|
|
141
202
|
|
|
203
|
+
// ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/pubsub/core/src/utils.ts
|
|
142
204
|
function getPubSubPlugin(player) {
|
|
143
205
|
const existing = player.findPlugin(PubSubPluginSymbol);
|
|
144
206
|
const plugin = existing || new PubSubPlugin();
|
|
@@ -148,26 +210,32 @@ function getPubSubPlugin(player) {
|
|
|
148
210
|
return plugin;
|
|
149
211
|
}
|
|
150
212
|
|
|
151
|
-
|
|
213
|
+
// ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/pubsub/core/src/handler.ts
|
|
214
|
+
var PubSubHandlerPlugin = class {
|
|
152
215
|
constructor(subscriptions) {
|
|
153
216
|
this.name = "pubsub-handler";
|
|
154
217
|
this.subscriptions = subscriptions;
|
|
155
218
|
}
|
|
156
219
|
apply(player) {
|
|
157
|
-
const
|
|
220
|
+
const pubsub2 = getPubSubPlugin(player);
|
|
158
221
|
player.hooks.onStart.tap(this.name, () => {
|
|
159
222
|
this.subscriptions.forEach((handler, key) => {
|
|
160
|
-
|
|
223
|
+
pubsub2.subscribe(key, (_, ...args) => {
|
|
161
224
|
const state = player.getState();
|
|
162
225
|
if (state.status === "in-progress") {
|
|
163
226
|
return handler(state, ...args);
|
|
164
227
|
}
|
|
165
|
-
player.logger.info(
|
|
228
|
+
player.logger.info(
|
|
229
|
+
`[PubSubHandlerPlugin] subscriber for ${key} was called when player was not in-progress`
|
|
230
|
+
);
|
|
166
231
|
});
|
|
167
232
|
});
|
|
168
233
|
});
|
|
169
234
|
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
235
|
+
};
|
|
236
|
+
export {
|
|
237
|
+
PubSubHandlerPlugin,
|
|
238
|
+
PubSubPlugin,
|
|
239
|
+
PubSubPluginSymbol
|
|
240
|
+
};
|
|
241
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/pubsub/core/src/pubsub.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/pubsub/core/src/symbols.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/pubsub/core/src/plugin.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/pubsub/core/src/utils.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/pubsub/core/src/handler.ts"],"sourcesContent":["/**\n * Based off the pubsub-js library and rewritten to match the same used APIs but modified so that\n * multiple arguments could be passed into the publish and subscription handlers.\n */\n\nexport type SubscribeHandler<T extends string, A extends unknown[]> = (\n type: T,\n ...args: A\n) => void;\n\nexport type PubSubUUID = `uuid_${number}`;\n\n/**\n * Split a string into an array of event layers\n */\nfunction splitEvent(event: string) {\n return event.split(\".\").reduce<string[]>((prev, curr, index) => {\n if (index === 0) {\n return [curr];\n }\n\n return [...prev, `${prev[index - 1]}.${curr}`];\n }, []);\n}\n\nlet count = 1;\n\n/**\n * Tiny pubsub maker\n */\nexport class TinyPubSub {\n private events: Map<string, Map<PubSubUUID, SubscribeHandler<any, any>>>;\n private tokens: Map<PubSubUUID, string>;\n\n constructor() {\n this.events = new Map();\n this.tokens = new Map();\n }\n\n /**\n * Publish an event with any number of additional arguments\n */\n publish(event: string, ...args: unknown[]) {\n if (typeof event !== \"string\") {\n return;\n }\n\n if (event.includes(\".\")) {\n const eventKeys = splitEvent(event);\n\n eventKeys.forEach((key) => {\n this.deliver(key, event, ...args);\n });\n } else {\n this.deliver(event, event, ...args);\n }\n\n this.deliver(\"*\", event, ...args);\n }\n\n /**\n * Subscribe to an event\n *\n * Events are also heirarchical when separated by a period. Given the following:\n *\n * publish('a.b.c', 'one', 'two', 'three)\n *\n * The subscribe event will be called when the event is passed as 'a', 'a.b', or 'a.b.c'.\n *\n * @example\n * // subscribes to the top level 'a' publish\n * subscribe('a', (event, ...args) => console.log(event, ...args))\n */\n subscribe(event: string, handler: SubscribeHandler<any, any>) {\n const uuid = `uuid_${++count}`;\n\n if (typeof event === \"string\") {\n if (!this.events.has(event)) {\n this.events.set(event, new Map());\n }\n\n const handlers = this.events.get(event);\n handlers!.set(uuid as PubSubUUID, handler);\n this.tokens.set(uuid as PubSubUUID, event);\n }\n\n return uuid;\n }\n\n /**\n * Unsubscribes to a specific subscription given it's symbol or an entire\n * event when passed as a string.\n *\n * When existing subscriptions exist for heirarchical events such as 'a.b.c',\n * when passing an event 'a' to unsubscribe, all subscriptions for 'a', 'a.b',\n * & 'a.b.c' will be unsubscribed as well.\n */\n unsubscribe(value: string | symbol) {\n if (typeof value === \"string\" && value.startsWith(\"uuid\")) {\n const path = this.tokens.get(value as PubSubUUID);\n\n if (typeof path === \"undefined\") {\n return;\n }\n\n const innerPath = this.events.get(path);\n innerPath?.delete(value as PubSubUUID);\n this.tokens.delete(value as PubSubUUID);\n return;\n }\n\n if (typeof value === \"string\") {\n for (const key of this.events.keys()) {\n if (key.indexOf(value) === 0) {\n const tokens = this.events.get(key);\n\n if (tokens && tokens.size) {\n // eslint-disable-next-line max-depth\n for (const token of tokens.keys()) {\n this.tokens.delete(token);\n }\n }\n\n this.events.delete(key);\n }\n }\n }\n }\n\n /**\n * Get the number of subscriptions for a specific event, or when left blank\n * will return the overall number of subscriptions for the entire pubsub.\n */\n count(event?: string) {\n let counter = 0;\n\n if (typeof event === \"undefined\") {\n for (const handlers of this.events.values()) {\n counter += handlers.size;\n }\n\n return counter;\n }\n\n const handlers = this.events.get(event);\n\n if (handlers?.size) {\n return handlers.size;\n }\n\n return counter;\n }\n\n /**\n * Deletes all existing subscriptions\n */\n clear() {\n this.events.clear();\n this.tokens.clear();\n }\n\n private deliver(path: string, event: string, ...args: unknown[]) {\n const handlers = this.events.get(path);\n\n if (handlers && handlers.size) {\n for (const handler of handlers.values()) {\n handler(event, ...args);\n }\n }\n }\n}\n\nexport const pubsub = new TinyPubSub();\n","export const PubSubPluginSymbol = Symbol.for(\"PubSubPlugin\");\n","import type {\n Player,\n PlayerPlugin,\n ExpressionContext,\n} from \"@player-ui/player\";\nimport type { SubscribeHandler, TinyPubSub } from \"./pubsub\";\nimport { pubsub } from \"./pubsub\";\nimport { PubSubPluginSymbol } from \"./symbols\";\n\nexport interface PubSubConfig {\n /** A custom expression name to register */\n expressionName: string;\n}\n\n/**\n * The PubSubPlugin is a great way to enable your FRF content to publish events back to your app\n * It injects a publish() function into the expression language, and will forward all events back to any subscribers.\n *\n * Published/Subscribed events support a hierarchy:\n * - publish('foo', 'data') -- will trigger any listeners for 'foo'\n * - publish('foo.bar', 'data') -- will trigger any listeners for 'foo' or 'foo.bar'\n *\n */\nexport class PubSubPlugin implements PlayerPlugin {\n name = \"pub-sub\";\n\n static Symbol = PubSubPluginSymbol;\n public readonly symbol = PubSubPlugin.Symbol;\n\n protected pubsub: TinyPubSub;\n\n private expressionName: string;\n\n constructor(config?: PubSubConfig) {\n this.expressionName = config?.expressionName ?? \"publish\";\n this.pubsub = pubsub;\n }\n\n apply(player: Player) {\n // if there is already a pubsub plugin, reuse its pubsub instance\n // to maintain the singleton across bundles for iOS/Android\n const existing = player.findPlugin<PubSubPlugin>(PubSubPluginSymbol);\n if (existing !== undefined) {\n this.pubsub = existing.pubsub;\n }\n\n player.hooks.expressionEvaluator.tap(this.name, (expEvaluator) => {\n const existingExpression = expEvaluator.operators.expressions.get(\n this.expressionName,\n );\n\n if (existingExpression) {\n player.logger.warn(\n `[PubSubPlugin] expression ${this.expressionName} is already registered.`,\n );\n } else {\n expEvaluator.addExpressionFunction(\n this.expressionName,\n (_ctx: ExpressionContext, event: unknown, ...args: unknown[]) => {\n if (typeof event === \"string\") {\n this.publish(event, ...args);\n }\n },\n );\n }\n });\n\n player.hooks.onEnd.tap(this.name, () => {\n this.clear();\n });\n }\n\n /**\n * A way of publishing an event, notifying any listeners\n *\n * @param event - The name of the event to publish. Can take sub-topics like: foo.bar\n * @param data - Any additional data to attach to the event\n */\n publish(event: string, ...args: unknown[]) {\n this.pubsub.publish(event, ...args);\n }\n\n /**\n * Subscribe to an event with the given name. The handler will get called for any published event\n *\n * @param event - The name of the event to subscribe to\n * @param handler - A function to be called when the event is triggered\n * @returns A token to be used to unsubscribe from the event\n */\n subscribe<T extends string, A extends unknown[]>(\n event: T,\n handler: SubscribeHandler<T, A>,\n ) {\n return this.pubsub.subscribe(event, handler);\n }\n\n /**\n * Remove any subscriptions using the given token\n *\n * @param token - A token from a `subscribe` call\n */\n unsubscribe(token: string) {\n this.pubsub.unsubscribe(token);\n }\n\n /**\n * Remove all subscriptions\n */\n clear() {\n this.pubsub.clear();\n }\n}\n","import type { Player } from \"@player-ui/player\";\nimport { PubSubPlugin } from \"./plugin\";\nimport { PubSubPluginSymbol } from \"./symbols\";\n\n/**\n * Returns the existing PubSubPlugin or creates and registers a new plugin\n */\nexport function getPubSubPlugin(player: Player) {\n const existing = player.findPlugin<PubSubPlugin>(PubSubPluginSymbol);\n const plugin = existing || new PubSubPlugin();\n\n if (!existing) {\n player.registerPlugin(plugin);\n }\n\n return plugin;\n}\n","import type { Player, PlayerPlugin, InProgressState } from \"@player-ui/player\";\nimport { getPubSubPlugin } from \"./utils\";\n\nexport type PubSubHandler<T extends unknown[]> = (\n context: InProgressState,\n ...args: T\n) => void;\n\nexport type SubscriptionMap = Map<string, PubSubHandler<any>>;\n\n/**\n * Plugin to easily add subscribers to the PubSubPlugin\n */\nexport class PubSubHandlerPlugin implements PlayerPlugin {\n name = \"pubsub-handler\";\n private subscriptions: SubscriptionMap;\n\n constructor(subscriptions: SubscriptionMap) {\n this.subscriptions = subscriptions;\n }\n\n apply(player: Player) {\n const pubsub = getPubSubPlugin(player);\n\n player.hooks.onStart.tap(this.name, () => {\n this.subscriptions.forEach((handler, key) => {\n pubsub.subscribe(key, (_, ...args) => {\n const state = player.getState();\n\n if (state.status === \"in-progress\") {\n return handler(state, ...args);\n }\n\n player.logger.info(\n `[PubSubHandlerPlugin] subscriber for ${key} was called when player was not in-progress`,\n );\n });\n });\n });\n }\n}\n"],"mappings":"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","names":["handlers","pubsub"]}
|
package/package.json
CHANGED
|
@@ -1,69 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@player-ui/pubsub-plugin",
|
|
3
|
-
"version": "0.8.0
|
|
4
|
-
"
|
|
5
|
-
"publishConfig": {
|
|
6
|
-
"registry": "https://registry.npmjs.org"
|
|
7
|
-
},
|
|
3
|
+
"version": "0.8.0-next.2",
|
|
4
|
+
"main": "dist/cjs/index.cjs",
|
|
8
5
|
"peerDependencies": {
|
|
9
|
-
"@player-ui/player": "0.8.0
|
|
6
|
+
"@player-ui/player": "0.8.0-next.2"
|
|
10
7
|
},
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"@types/pubsub-js": "^1.8.3",
|
|
15
|
-
"@babel/runtime": "7.15.4"
|
|
16
|
-
},
|
|
17
|
-
"main": "dist/index.cjs.js",
|
|
18
|
-
"module": "dist/index.esm.js",
|
|
19
|
-
"typings": "dist/index.d.ts",
|
|
8
|
+
"module": "dist/index.legacy-esm.js",
|
|
9
|
+
"types": "types/index.d.ts",
|
|
10
|
+
"bundle": "dist/PubSubPlugin.native.js",
|
|
20
11
|
"sideEffects": false,
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
},
|
|
29
|
-
"homepage": "https://player-ui.github.io",
|
|
30
|
-
"contributors": [
|
|
31
|
-
{
|
|
32
|
-
"name": "Adam Dierkens",
|
|
33
|
-
"url": "https://github.com/adierkens"
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
"name": "Spencer Hamm",
|
|
37
|
-
"url": "https://github.com/spentacular"
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
"name": "Harris Borawski",
|
|
41
|
-
"url": "https://github.com/hborawski"
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
"name": "Jeremiah Zucker",
|
|
45
|
-
"url": "https://github.com/sugarmanz"
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
"name": "Ketan Reddy",
|
|
49
|
-
"url": "https://github.com/KetanReddy"
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
"name": "Brocollie08",
|
|
53
|
-
"url": "https://github.com/brocollie08"
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
"name": "Kelly Harrop",
|
|
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"
|
|
12
|
+
"exports": {
|
|
13
|
+
"./package.json": "./package.json",
|
|
14
|
+
"./dist/index.css": "./dist/index.css",
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./types/index.d.ts",
|
|
17
|
+
"import": "./dist/index.mjs",
|
|
18
|
+
"default": "./dist/cjs/index.cjs"
|
|
66
19
|
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"src",
|
|
24
|
+
"types"
|
|
67
25
|
],
|
|
68
|
-
"
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@types/pubsub-js": "^1.8.3",
|
|
28
|
+
"pubsub-js": "^1.9.3",
|
|
29
|
+
"tapable-ts": "^0.2.3",
|
|
30
|
+
"tslib": "^2.6.2"
|
|
31
|
+
}
|
|
69
32
|
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { describe, expect, vitest, beforeEach, it } from "vitest";
|
|
2
|
+
import type { InProgressState } from "@player-ui/player";
|
|
3
|
+
import { Player } from "@player-ui/player";
|
|
4
|
+
import { PubSubPlugin } from "../plugin";
|
|
5
|
+
import type { PubSubHandler } from "../handler";
|
|
6
|
+
import { PubSubHandlerPlugin } from "../handler";
|
|
7
|
+
import { pubsub as pubsubimpl } from "../pubsub";
|
|
8
|
+
|
|
9
|
+
const customEventFlow = {
|
|
10
|
+
id: "customEventFlow",
|
|
11
|
+
views: [
|
|
12
|
+
{
|
|
13
|
+
id: "view-1",
|
|
14
|
+
type: "info",
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
navigation: {
|
|
18
|
+
BEGIN: "FLOW_1",
|
|
19
|
+
FLOW_1: {
|
|
20
|
+
onStart: 'publish("customEvent", {{foo.bar}}, "daisy")',
|
|
21
|
+
startState: "VIEW_1",
|
|
22
|
+
VIEW_1: {
|
|
23
|
+
ref: "view-1",
|
|
24
|
+
state_type: "VIEW",
|
|
25
|
+
transitions: {
|
|
26
|
+
Next: "VIEW_2",
|
|
27
|
+
"*": "END_Done",
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
data: {
|
|
33
|
+
foo: {
|
|
34
|
+
bar: "ginger",
|
|
35
|
+
baz: "",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
describe("PubSubHandlerPlugin", () => {
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
pubsubimpl.clear();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("registers a new subscription handler", () => {
|
|
46
|
+
const pubsub = new PubSubPlugin();
|
|
47
|
+
const spy = vitest.fn();
|
|
48
|
+
|
|
49
|
+
const player = new Player({
|
|
50
|
+
plugins: [
|
|
51
|
+
pubsub,
|
|
52
|
+
new PubSubHandlerPlugin(new Map([["customEvent", spy]])),
|
|
53
|
+
],
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
player.start(customEventFlow as any);
|
|
57
|
+
|
|
58
|
+
expect(spy).toHaveBeenCalledWith(expect.anything(), "ginger", "daisy");
|
|
59
|
+
expect(pubsubimpl.count("customEvent")).toBe(1);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("sets data in subscription", () => {
|
|
63
|
+
const pubsub = new PubSubPlugin();
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
*
|
|
67
|
+
*/
|
|
68
|
+
const customEventHandler: PubSubHandler<string[]> = (
|
|
69
|
+
context,
|
|
70
|
+
pet1,
|
|
71
|
+
pet2,
|
|
72
|
+
) => {
|
|
73
|
+
context.controllers.data.set([["foo.baz", pet2]]);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const subscriptions = new Map([["customEvent", customEventHandler]]);
|
|
77
|
+
|
|
78
|
+
const player = new Player({
|
|
79
|
+
plugins: [pubsub, new PubSubHandlerPlugin(subscriptions)],
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
player.start(customEventFlow as any);
|
|
83
|
+
|
|
84
|
+
expect(pubsubimpl.count("customEvent")).toBe(1);
|
|
85
|
+
|
|
86
|
+
const state = player.getState() as InProgressState;
|
|
87
|
+
expect(state.controllers.data.get("foo.baz")).toBe("daisy");
|
|
88
|
+
});
|
|
89
|
+
});
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { test, expect, vitest } from "vitest";
|
|
2
|
+
import { Player } from "@player-ui/player";
|
|
3
|
+
import { PubSubPlugin } from "../plugin";
|
|
4
|
+
import { PubSubPluginSymbol } from "../symbols";
|
|
5
|
+
|
|
6
|
+
const minimal = {
|
|
7
|
+
id: "minimal",
|
|
8
|
+
views: [
|
|
9
|
+
{
|
|
10
|
+
id: "view-1",
|
|
11
|
+
type: "info",
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
navigation: {
|
|
15
|
+
BEGIN: "FLOW_1",
|
|
16
|
+
FLOW_1: {
|
|
17
|
+
onStart: 'publish("pet.names", ["ginger", "daisy"])',
|
|
18
|
+
startState: "VIEW_1",
|
|
19
|
+
VIEW_1: {
|
|
20
|
+
ref: "view-1",
|
|
21
|
+
state_type: "VIEW",
|
|
22
|
+
transitions: {
|
|
23
|
+
Next: "VIEW_2",
|
|
24
|
+
"*": "END_Done",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const multistart = {
|
|
32
|
+
id: "minimal",
|
|
33
|
+
views: [
|
|
34
|
+
{
|
|
35
|
+
id: "view-1",
|
|
36
|
+
type: "info",
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
navigation: {
|
|
40
|
+
BEGIN: "FLOW_1",
|
|
41
|
+
FLOW_1: {
|
|
42
|
+
onStart: [
|
|
43
|
+
'publish("pet", ["ginger", "daisy"])',
|
|
44
|
+
'customPublish("pet", ["ginger", "daisy"])',
|
|
45
|
+
],
|
|
46
|
+
startState: "VIEW_1",
|
|
47
|
+
VIEW_1: {
|
|
48
|
+
ref: "view-1",
|
|
49
|
+
state_type: "VIEW",
|
|
50
|
+
transitions: {
|
|
51
|
+
Next: "VIEW_2",
|
|
52
|
+
"*": "END_Done",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const customName = {
|
|
60
|
+
id: "custom",
|
|
61
|
+
views: [
|
|
62
|
+
{
|
|
63
|
+
id: "view-1",
|
|
64
|
+
type: "info",
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
navigation: {
|
|
68
|
+
BEGIN: "FLOW_1",
|
|
69
|
+
FLOW_1: {
|
|
70
|
+
onStart: 'customPublish("pet.names", "ginger", "daisy")',
|
|
71
|
+
startState: "VIEW_1",
|
|
72
|
+
VIEW_1: {
|
|
73
|
+
ref: "view-1",
|
|
74
|
+
state_type: "VIEW",
|
|
75
|
+
transitions: {
|
|
76
|
+
Next: "VIEW_2",
|
|
77
|
+
"*": "END_Done",
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
test("loads an expression", () => {
|
|
85
|
+
const pubsub = new PubSubPlugin();
|
|
86
|
+
|
|
87
|
+
const player = new Player({
|
|
88
|
+
plugins: [pubsub],
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const topLevel = vitest.fn();
|
|
92
|
+
const nested = vitest.fn();
|
|
93
|
+
pubsub.subscribe("pet", topLevel);
|
|
94
|
+
pubsub.subscribe("pet.names", nested);
|
|
95
|
+
|
|
96
|
+
player.start(minimal as any);
|
|
97
|
+
|
|
98
|
+
expect(topLevel).toBeCalledTimes(1);
|
|
99
|
+
expect(topLevel).toBeCalledWith("pet.names", ["ginger", "daisy"]);
|
|
100
|
+
|
|
101
|
+
expect(nested).toBeCalledTimes(1);
|
|
102
|
+
expect(nested).toBeCalledWith("pet.names", ["ginger", "daisy"]);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test("handles custom expression names", () => {
|
|
106
|
+
const pubsub = new PubSubPlugin({ expressionName: "customPublish" });
|
|
107
|
+
|
|
108
|
+
const player = new Player({
|
|
109
|
+
plugins: [pubsub],
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const topLevel = vitest.fn();
|
|
113
|
+
const nested = vitest.fn();
|
|
114
|
+
pubsub.subscribe("pet", topLevel);
|
|
115
|
+
pubsub.subscribe("pet.names", nested);
|
|
116
|
+
|
|
117
|
+
player.start(customName as any);
|
|
118
|
+
|
|
119
|
+
expect(topLevel).toBeCalledTimes(1);
|
|
120
|
+
expect(topLevel).toBeCalledWith("pet.names", "ginger", "daisy");
|
|
121
|
+
|
|
122
|
+
expect(nested).toBeCalledTimes(1);
|
|
123
|
+
expect(nested).toBeCalledWith("pet.names", "ginger", "daisy");
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("finds plugin", () => {
|
|
127
|
+
const pubsub = new PubSubPlugin();
|
|
128
|
+
|
|
129
|
+
const player = new Player({ plugins: [pubsub] });
|
|
130
|
+
|
|
131
|
+
expect(player.findPlugin<PubSubPlugin>(PubSubPluginSymbol)).toBe(pubsub);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("only calls subscription once if multiple pubsub plugins are registered", () => {
|
|
135
|
+
const pubsub = new PubSubPlugin();
|
|
136
|
+
const pubsub2 = new PubSubPlugin();
|
|
137
|
+
|
|
138
|
+
const player = new Player({ plugins: [pubsub, pubsub2] });
|
|
139
|
+
|
|
140
|
+
const topLevel = vitest.fn();
|
|
141
|
+
pubsub.subscribe("pet", topLevel);
|
|
142
|
+
|
|
143
|
+
player.start(minimal as any);
|
|
144
|
+
|
|
145
|
+
expect(topLevel).toBeCalledTimes(1);
|
|
146
|
+
expect(topLevel).toBeCalledWith("pet.names", ["ginger", "daisy"]);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("calls subscription for each pubsub registered through pubsubplugin", () => {
|
|
150
|
+
const pubsub = new PubSubPlugin();
|
|
151
|
+
const pubsub2 = new PubSubPlugin({ expressionName: "customPublish" });
|
|
152
|
+
|
|
153
|
+
const player = new Player({ plugins: [pubsub, pubsub2] });
|
|
154
|
+
|
|
155
|
+
const spy = vitest.fn();
|
|
156
|
+
pubsub.subscribe("pet", spy);
|
|
157
|
+
|
|
158
|
+
player.start(multistart as any);
|
|
159
|
+
|
|
160
|
+
expect(spy).toBeCalledTimes(2);
|
|
161
|
+
expect(spy).toHaveBeenNthCalledWith(1, "pet", ["ginger", "daisy"]);
|
|
162
|
+
expect(spy).toHaveBeenNthCalledWith(2, "pet", ["ginger", "daisy"]);
|
|
163
|
+
});
|